local B_NONE = 11
local B_SQUESTUPGRADE = 21
local B_REPAIR = 13

local RE2A_01_localCitizen = avatar:create("ParrotGuy")
---------------------------------------------------------------------------------------------------
-- Подсказка на лут, который вот-вот пропадет
---------------------------------------------------------------------------------------------------
function RE2A_AllLootWillDisappearSoonHint(message)
	-- Показываем стрелку на лут, который вот-вот забликует
	if message:is("LootIsAboutToBlink") then
		if not IsLocked() then
			tutorial:targetLoot(message:getIntegerParam(), "RE2_AllLootAlmostBlinkHint_Arrow", 0.5, IPoint(0, 10), 0.0)
			tutorial:setObjectsAllowType(allowPass)
			tutorial:variables():setBool("TutorialArrowAlphaBind", true)
			tutorial:variables():setBool("TutorialArrowsNoBind", true);
			tutorial:variables():setFloat("TutorialShowDelayTime", -1.0)
			tutorial:show(0.25)
		end
	-- Лут собран или прощелкан
	elseif message:is("LootGathered") or message:is("LootLost") then
		tutorial:hideBindedArrow("RE2_AllLootAlmostBlinkHint_Arrow", message:getIntegerParam(), 0.25)
	end
end

---------------------------------------------------------------------------------------------------
-- Подсказка на пропажу трех лутов
---------------------------------------------------------------------------------------------------
local RE2A_ThreeLootsLost = hint:create("RE2A_ThreeLootsLostHint")
function RE2A_ThreeLootsLost:setCount(count) tutSetInt(self.hintId.."Count", count) end
function RE2A_ThreeLootsLost:getCount() return tutGetInt(self.hintId.."Count") end
function RE2A_ThreeLootsLost:incCount() self:setCount(self:getCount() + 1) end
function RE2A_ThreeLootsLost:onInit()
	self:setCount(0)
end
function RE2A_ThreeLootsLost:onProcessMessage(message)
	if self:isShown() then return end

	if not self:isActive() then
		if message:is("LootLost") then
			self:incCount()
			if self:getCount() > 2 and self:getState() == 0 then
				self:start()
				self:setState(1)
				avatar:show("RE2A_MoneyLootLoseHint")
				avatar:setOffset(IPoint(10, 150), false)
			end
		end
	else
		if self:getState() == 1 then
			if self:isPassed(message) then
				avatar:hide()
				self:setShown(true)
				self:goToFinish()
			end
		end
	end
end
function RE2A_ThreeLootsLostHint(message)
	RE2A_ThreeLootsLost:processMessage(message)
end

---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
function Lock()
	tutSetBool("TutorialLock", true)
end

function Unlock()
	tutSetBool("TutorialLock", false)
end

function IsLocked()
	return tutGetBool("TutorialLock")
end

function IsBaseSelected()
	return tutorial:getSelectedBuildingType() == BaseBuildingType
end

---------------------------------------------------------------------------------------------------
-- Подсказа на постройку первой хижины
---------------------------------------------------------------------------------------------------
function RE2A_Build1HouseHint(message)
	local housesPos = IPoint(617, 100)
	local backPos = IPoint(950, 100)
	local house1Pos = IPoint(549, 100)
	------------------------------------------ Дополнительные функции ------------------------------------------
	-- Инициализация переменных
	local function Reset()	
		tutSetBool("RE2_BuildFirstHouseHint_Active", false)				-- активность подсказки
		tutSetFloat("RE2_BuildFirstHouseHint_HintAppearTime", 1.5)		-- время появления подсказки
		tutSetFloat("RE2_BuildFirstHouseHint_Time", 0.0)				-- общее время подсказки
		tutSetInt("RE2_BuildFirstHouseHint_State", -1)
		tutSetBool("RE2_BuildFirstHouseHint_Ready", false)				-- готов ли первый дом
		tutSetInt("RE2_BuildFirstHouseHint_Arrow", -1)					-- Идентификатор стрелочки
		tutSetBool("RE2_BuildFirstHouseHint_BuildingStarted", false)	-- Строительство первого дома началось
		tutSetBool("RE2_BuildFirstHouseHint_ArrowHidden", true)			-- Стрелка скрыта
	end

	local function IsArrowHidden()
		return tutGetBool("RE2_BuildFirstHouseHint_ArrowHidden")
	end
	
	local function SetArrowHidden(hidden)
		tutSetBool("RE2_BuildFirstHouseHint_ArrowHidden", hidden)
	end
	
	-- Начали строить дом?
	local function IsBuildingStarted()
		return tutGetBool("RE2_BuildFirstHouseHint_BuildingStarted")
	end
	
	-- Устанавливает, начали ли строить дом
	local function SetBuildingStarted(started)
		tutSetBool("RE2_BuildFirstHouseHint_BuildingStarted", started)
	end
	
	-- Построили дом, подсказка больше не нужна
	local function IsReady()
		return tutGetBool("RE2_BuildFirstHouseHint_Ready")
	end
	
	-- Устанавливает, нужно ли отображать подсказку
	local function SetReady(ready)
		tutSetBool("RE2_BuildFirstHouseHint_Ready", ready)
	end
	
	-- Обновляет таймер
	local function Update()
		if message:is("Update") then
			tutSetFloat("RE2_BuildFirstHouseHint_Time", tutGetFloat("RE2_BuildFirstHouseHint_Time") + message:getVariables():getFloat("TimeDelta"))
		end
	end
	
	-- Возвращает true, если пора показывать подсказку
	local function ItsTime()
		return tutGetFloat("RE2_BuildFirstHouseHint_Time") > tutGetFloat("RE2_BuildFirstHouseHint_HintAppearTime")
	end
	
	local function Time()
		return tutGetFloat("RE2_BuildFirstHouseHint_Time")
	end
	
	-- Обнуляет таймер
	local function NullTimer()
		tutSetFloat("RE2_BuildFirstHouseHint_Time", 0.0)
	end
	
	-- Возвращает состояние
	local function GetState()
		return tutGetInt("RE2_BuildFirstHouseHint_State")
	end
	
	-- Устанавливает новое состояние
	local function SetState(newState)
		if newState == GetState() then
			return
		end
		tutSetInt("RE2_BuildFirstHouseHint_State", newState)
	end

	-- Активна ли подсказка
	local function IsActive()
		return tutGetBool("RE2_BuildFirstHouseHint_Active")
	end
	
	-- Устанавливает активность подсказки
	local function SetActive(newActive)
		tutSetBool("RE2_BuildFirstHouseHint_Active", newActive)
	end
	
	-- Нужно ли указывать стрелкой на пустую площадку?
	-- Нужно, если ничего не выделено или выделено, но не пустая площадка
	local function ShouldPointAtFreeLargeField()
		if (not tutorial:game():getSelected()) or (tutorial:game():getSelected() and not tutorial:isLargeFieldFree(tutorial:game():getSelected():id())) then
			return true
		else
			return false
		end
	end
	
	-- Возвращает стрелку (если нет - создает)
	local function GetArrow()
		local arrowId = tutGetInt("RE2_BuildFirstHouseHint_Arrow")
		-- Стрелки нет - создаем
		if arrowId == -1 then
			arrowId = tutorial:addArrow()
			tutSetInt("RE2_BuildFirstHouseHint_Arrow", arrowId)
		end
		
		return arrowId
	end
	
	-- Шаманский код для отображения стрелки
	local function ShowArrow()
		SetArrowHidden(false)
		
		Lock()
		tutorial:setObjectsAllowType(allowPass)
		tutorial:variables():setBool("TutorialArrowsNoBind", true);
		tutorial:variables():setFloat("TutorialShowDelayTime", -1.0)
		tutorial:show(0.25)
	end
	
	-- Прячет стрелку, завершает подсказку
	local function HideArrow()
		tutorial:hideArrows(0.25)
		tutorial:hide(0.25)
		SetArrowHidden(true)
	end
	
	-- Удаляет стрелку
	local function RemoveArrow()
		local arrowId = GetArrow()
		tutorial:removeArrow(arrowId)
		tutSetInt("RE2_BuildFirstHouseHint_Arrow", -1)
	end
	
	-- Указывает на площадку
	local function PointAtField()
		local arrowId = GetArrow()
		
		local middleFieldId = 131694
		local fieldPos
		
		-- Если площадка в центре свободна - тычем в нее
		if tutorial:isLargeFieldFree(middleFieldId) then
			fieldPos = tutorial:game():getObject(middleFieldId):getScreenPosition()
		else
			-- Иначе - тычем в произвольную пустую площадку
			local fieldId = tutorial:getRandomFreeLargeFieldId()
			if fieldId ~= -1 then
				fieldPos = tutorial:game():getObject(fieldId):getScreenPosition()
			else
				return
			end
		end

		tutorial:getArrow(arrowId):setPosition(fieldPos.x, fieldPos.y + 40)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)

		ShowArrow()
	end
	
	-- Указывает на кнопку "Назад"
	local function PointAtBack()
		local arrowId = GetArrow()
		
		tutorial:getArrow(arrowId):setPosition(backPos.x, backPos.y)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)

		ShowArrow()
	end
	
	-- Указывает на кнопку "Дома"
	local function PointAtHouses()
		local arrowId = GetArrow()
		
		tutorial:getArrow(arrowId):setPosition(housesPos.x, housesPos.y)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.25)

		ShowArrow()
	end
	
	-- Указывает на кнопку "Дом1"
	local function PointAtHouse1()
		local arrowId = GetArrow()
		
		tutorial:getArrow(arrowId):setPosition(house1Pos.x, house1Pos.y)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)
		
		ShowArrow()
	end
	
	-- Указывает на соответствующую точку в зависимости от ситуации
	local function PointAtAppropriatePoint()
		local arrowId = GetArrow()
		local arrowPos = IPoint(tutorial:getArrow(arrowId):getPosition().x, tutorial:getArrow(arrowId):getPosition().y)
		
		-- Кнопки "Дома" и "Здания"
		if tutorial:isLargeFieldInterface() then
			local pointAtRightPlace = (housesPos.x == arrowPos.x and housesPos.y == arrowPos.y)
			if not IsArrowHidden() and not pointAtRightPlace then
				HideArrow()
				NullTimer()
			else
				Update()
				if Time() > 0.25 then
					PointAtHouses()
				end
			end
		-- Интерфейс постройки зданий
		elseif tutorial:isLargeFieldInterfaceBuildings() then
			local pointAtRightPlace = (backPos.x == arrowPos.x and backPos.y == arrowPos.y)

			if not IsArrowHidden() and not pointAtRightPlace then
				HideArrow()
				NullTimer()
			else
				Update()
				if Time() > 0.25 then
					PointAtBack()
				end
			end
		-- Интерфейс постройки домов
		elseif tutorial:isLargeFieldInterfaceHouses() then
			local pointAtRightPlace = (house1Pos.x == arrowPos.x and house1Pos.y == arrowPos.y)
			
			if not IsArrowHidden() and not pointAtRightPlace then
				HideArrow()
				NullTimer()
			else
				Update()
				if Time() > 0.25 then
					PointAtHouse1()
				end
			end
		end
	end	
	
	------------------------------------------ Начало основной функции ------------------------------------------
	-- Инициализация
	if message:is("LoadLevel") then
		Reset()
	end

	-- Если активна другая подсказка - ничего не делаем
	if IsLocked() and not IsActive() then
		return
	end
	
	if message:is("House1", "press") and not IsBuildingStarted() then
		SetBuildingStarted(true)
	elseif message:is("Cancel", "press") and IsBuildingStarted() then
		SetBuildingStarted(false)
	elseif message:is("BuildingBuilt") and IsBuildingStarted() then
		SetReady(true)
		Unlock()
	end

	if tutorial:game():getHouses1Count() > 1 or IsReady() then
		return
	end
	
	--[[
		-1 - начальное состояние - стрелки нет
		0 - стрелка тычет в площадку
		1 - стрелка тычет в кнопку панель
		111 - прячем стрелку - переинициализация
	]]--
	-- Подсказка не активна
	if not IsActive() then
		-- Обновляем таймер
		if message:is("Update") and not IsBuildingStarted() then
			Update()
			
			-- Пора
			if ItsTime() then
				-- Проверим на предмет начального состояния
				if GetState() == -1 then
					-- Если ничего не выделено или выделено, но не пустая площадка - укажем на площадку
					if ShouldPointAtFreeLargeField() then
						SetActive(true)
						NullTimer()
						PointAtField()
						SetState(0)
					-- Если выделена пустая площадка - проверим, какие кнопки интерфейса доступны
					else
						SetActive(true)
						SetState(1)
					end
				end
			end
		end
	-- Подсказка активна
	else
		-- Стрелочка тычет в площадку
		if GetState() == 0 then
			-- Чтобы стрелка обновлялась
			if message:is("Update") then
				-- Выделена площадка
				if tutorial:game():getSelected() and tutorial:isLargeFieldFree(tutorial:game():getSelected():id()) then
					PointAtAppropriatePoint()
					SetState(1)
				end
			end
		-- Стрелка тычет в панель
		elseif GetState() == 1 then
			-- Чтобы стрелка обновлялась
			if message:is("Update") then
				-- Сняли выделение - все прячем
				if ShouldPointAtFreeLargeField() then
					HideArrow()
					SetState(111)
				else
					PointAtAppropriatePoint()
				end
			end
		elseif GetState() == 111 then
			if (message:is("TutorialPop")) then
				Unlock()
				tutorial:variables():setBool("TutorialArrowsNoBind", false)

				local isBuildingStarted = IsBuildingStarted()
				RemoveArrow()
				Reset()
				SetBuildingStarted(isBuildingStarted)
			end
		end
	end
end

---------------------------------------------------------------------------------------------------
-- Подсказка на постройку второго дома
---------------------------------------------------------------------------------------------------
function RE2A_Build2HouseHint(message)
	local housesPos = IPoint(617, 100)
	local backPos = IPoint(950, 100)
	local house1Pos = IPoint(549, 100)
	------------------------------------------ Дополнительные функции ------------------------------------------
	-- Инициализация переменных
	local function Reset()	
		tutSetBool("RE2_BuildSecondHouseHint_Active", false)				-- активность подсказки
		tutSetFloat("RE2_BuildSecondHouseHint_HintAppearTime", 15.0)		-- время появления подсказки
		tutSetFloat("RE2_BuildSecondHouseHint_Time", 0.0)				-- общее время подсказки
		tutSetInt("RE2_BuildSecondHouseHint_State", -1)
		tutSetBool("RE2_BuildSecondHouseHint_Ready", false)				-- готов ли первый дом
		tutSetInt("RE2_BuildSecondHouseHint_Arrow", -1)					-- Идентификатор стрелочки
		tutSetBool("RE2_BuildSecondHouseHint_BuildingStarted", false)	-- Строительство первого дома началось
		tutSetBool("RE2_BuildSecondHouseHint_ArrowHidden", true)			-- Стрелка скрыта
	end

	local function IsArrowHidden()
		return tutGetBool("RE2_BuildSecondHouseHint_ArrowHidden")
	end
	
	local function SetArrowHidden(hidden)
		tutSetBool("RE2_BuildSecondHouseHint_ArrowHidden", hidden)
	end
	
	-- Начали строить дом?
	local function IsBuildingStarted()
		return tutGetBool("RE2_BuildSecondHouseHint_BuildingStarted")
	end
	
	-- Устанавливает, начали ли строить дом
	local function SetBuildingStarted(started)
		tutSetBool("RE2_BuildSecondHouseHint_BuildingStarted", started)
	end
	
	-- Построили дом, подсказка больше не нужна
	local function IsReady()
		return tutGetBool("RE2_BuildSecondHouseHint_Ready")
	end
	
	-- Устанавливает, нужно ли отображать подсказку
	local function SetReady(ready)
		tutSetBool("RE2_BuildSecondHouseHint_Ready", ready)
	end
	
	-- Обновляет таймер
	local function Update()
		if message:is("Update") then
			tutSetFloat("RE2_BuildSecondHouseHint_Time", tutGetFloat("RE2_BuildSecondHouseHint_Time") + message:getVariables():getFloat("TimeDelta"))
		end
	end
	
	-- Возвращает true, если пора показывать подсказку
	local function ItsTime()
		return tutGetFloat("RE2_BuildSecondHouseHint_Time") > tutGetFloat("RE2_BuildSecondHouseHint_HintAppearTime")
	end

	local function Time()
		return tutGetFloat("RE2_BuildSecondHouseHint_Time")
	end
	
	local function SetAppearTime(newTime)
		tutSetFloat("RE2_BuildSecondHouseHint_HintAppearTime", newTime)
	end
	
	-- Обнуляет таймер
	local function NullTimer()
		tutSetFloat("RE2_BuildSecondHouseHint_Time", 0.0)
	end
	
	-- Возвращает состояние
	local function GetState()
		return tutGetInt("RE2_BuildSecondHouseHint_State")
	end
	
	-- Устанавливает новое состояние
	local function SetState(newState)
		if newState == GetState() then
			return
		end
		tutSetInt("RE2_BuildSecondHouseHint_State", newState)
	end

	-- Активна ли подсказка
	local function IsActive()
		return tutGetBool("RE2_BuildSecondHouseHint_Active")
	end
	
	-- Устанавливает активность подсказки
	local function SetActive(newActive)
		tutSetBool("RE2_BuildSecondHouseHint_Active", newActive)
	end
	
	-- Нужно ли указывать стрелкой на пустую площадку?
	-- Нужно, если ничего не выделено или выделено, но не пустая площадка
	local function ShouldPointAtFreeLargeField()
		if (not tutorial:game():getSelected()) or (tutorial:game():getSelected() and not tutorial:isLargeFieldFree(tutorial:game():getSelected():id())) then
			return true
		else
			return false
		end
	end
	
	-- Возвращает стрелку (если нет - создает)
	local function GetArrow()
		local arrowId = tutGetInt("RE2_BuildSecondHouseHint_Arrow")
		-- Стрелки нет - создаем
		if arrowId == -1 then
			arrowId = tutorial:addArrow()
			tutSetInt("RE2_BuildSecondHouseHint_Arrow", arrowId)
		end
		
		return arrowId
	end
	
	-- Шаманский код для отображения стрелки
	local function ShowArrow()
		SetArrowHidden(false)

		Lock()
		tutorial:setObjectsAllowType(allowPass)
		tutorial:variables():setBool("TutorialArrowsNoBind", true);
		tutorial:variables():setFloat("TutorialShowDelayTime", -1.0)
		tutorial:show(0.25)
	end
	
	-- Прячет стрелку, завершает подсказку
	local function HideArrow()
		tutorial:hideArrows(0.25)
		tutorial:hide(0.25)
		SetArrowHidden(true)
	end
	
	-- Удаляет стрелку
	local function RemoveArrow()
		local arrowId = GetArrow()
		tutorial:removeArrow(arrowId)
		tutSetInt("RE2_BuildSecondHouseHint_Arrow", -1)
	end
	
	-- Указывает на площадку
	local function PointAtField()
		local arrowId = GetArrow()
		
		local middleFieldId = 131694
		local fieldPos
		
		-- Если площадка в центре свободна - тычем в нее
		if tutorial:isLargeFieldFree(middleFieldId) then
			fieldPos = tutorial:game():getObject(middleFieldId):getScreenPosition()
		else
			-- Иначе - тычем в произвольную пустую площадку
			local fieldId = tutorial:getRandomFreeLargeFieldId()
			if fieldId ~= -1 then
				fieldPos = tutorial:game():getObject(fieldId):getScreenPosition()
			else
				return
			end
		end

		tutorial:getArrow(arrowId):setPosition(fieldPos.x, fieldPos.y + 40)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)

		ShowArrow()
	end
	
	-- Указывает на кнопку "Назад"
	local function PointAtBack()
		local arrowId = GetArrow()
		
		tutorial:getArrow(arrowId):setPosition(backPos.x, backPos.y)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)

		ShowArrow()
	end
	
	-- Указывает на кнопку "Дома"
	local function PointAtHouses()
		local arrowId = GetArrow()
		
		tutorial:getArrow(arrowId):setPosition(housesPos.x, housesPos.y)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)

		ShowArrow()
	end
	
	-- Указывает на кнопку "Дом1"
	local function PointAtHouse1()
		local arrowId = GetArrow()
		
		tutorial:getArrow(arrowId):setPosition(house1Pos.x, house1Pos.y)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)
		
		ShowArrow()
	end
	
	-- Указывает на соответствующую точку в зависимости от ситуации
	local function PointAtAppropriatePoint()
		local arrowId = GetArrow()
		local arrowPos = IPoint(tutorial:getArrow(arrowId):getPosition().x, tutorial:getArrow(arrowId):getPosition().y)
		
		-- Кнопки "Дома" и "Здания"
		if tutorial:isLargeFieldInterface() then
			local pointAtRightPlace = (housesPos.x == arrowPos.x and housesPos.y == arrowPos.y)
			if not IsArrowHidden() and not pointAtRightPlace then
				HideArrow()
				NullTimer()
			else
				Update()
				if Time() > 0.25 then
					PointAtHouses()
				end
			end
		-- Интерфейс постройки зданий
		elseif tutorial:isLargeFieldInterfaceBuildings() then
			local pointAtRightPlace = (backPos.x == arrowPos.x and backPos.y == arrowPos.y)

			if not IsArrowHidden() and not pointAtRightPlace then
				HideArrow()
				NullTimer()
			else
				Update()
				if Time() > 0.25 then
					PointAtBack()
				end
			end
		-- Интерфейс постройки домов
		elseif tutorial:isLargeFieldInterfaceHouses() then
			local pointAtRightPlace = (house1Pos.x == arrowPos.x and house1Pos.y == arrowPos.y)
			
			if not IsArrowHidden() and not pointAtRightPlace then
				HideArrow()
				NullTimer()
			else
				Update()
				if Time() > 0.25 then
					PointAtHouse1()
				end
			end
		end
	end	
	
	------------------------------------------ Начало основной функции ------------------------------------------
	-- Инициализация
	if message:is("LoadLevel") then
		Reset()
	end

	-- Еще не построили второй дом - ничего не делаем
	if tutorial:game():getHouses1Count() < 2 then
		return
	end

	-- Если активна другая подсказка - ничего не делаем
	if IsLocked() and not IsActive() then
		return
	end
	
	if message:is("House1", "press") and not IsBuildingStarted() then
		SetBuildingStarted(true)
	elseif message:is("Cancel", "press") and IsBuildingStarted() then
		SetBuildingStarted(false)
	elseif message:is("BuildingBuilt") and IsBuildingStarted() then
		SetReady(true)
		Unlock()
	end
	
	-- Построили третий дом - ничего не делаем
	if tutorial:game():getHouses1Count() > 2 or IsReady() then
		return
	end

	--[[
		-1 - начальное состояние - стрелки нет
		0 - стрелка тычет в площадку
		1 - стрелка тычет в кнопку панель
		111 - прячем стрелку - переинициализация
	]]--
	-- Подсказка не активна
	if not IsActive() then
		-- Обновляем таймер
		if message:is("Update") and not IsBuildingStarted() then
			Update()
			
			-- Пора
			if ItsTime() then
				-- Проверим на предмет начального состояния
				if GetState() == -1 then
					-- Если ничего не выделено или выделено, но не пустая площадка - укажем на площадку
					if ShouldPointAtFreeLargeField() then
						SetActive(true)
						NullTimer()
						PointAtField()
						SetState(0)
					-- Если выделена пустая площадка - проверим, какие кнопки интерфейса доступны
					else
						SetActive(true)
						SetState(1)
					end
				end
			end
		end
	-- Подсказка активна
	else
		-- Стрелочка тычет в площадку
		if GetState() == 0 then
			-- Чтобы стрелка обновлялась
			if message:is("Update") then
				-- Выделена площадка
				if tutorial:game():getSelected() and tutorial:isLargeFieldFree(tutorial:game():getSelected():id()) then
					PointAtAppropriatePoint()
					SetState(1)
				end
			end
		-- Стрелка тычет в панель
		elseif GetState() == 1 then
			-- Чтобы стрелка обновлялась
			if message:is("Update") then
				-- Сняли выделение - все прячем
				if ShouldPointAtFreeLargeField() then
					HideArrow()
					SetState(111)
				else
					PointAtAppropriatePoint()
				end
			end
		elseif GetState() == 111 then
			if (message:is("TutorialPop")) then
				Unlock()
				tutorial:variables():setBool("TutorialArrowsNoBind", false)

				local isBuildingStarted = IsBuildingStarted()
				local appearTime = tutGetFloat("RE2_BuildSecondHouseHint_HintAppearTime")
				
				RemoveArrow()
				Reset()
				
				SetBuildingStarted(isBuildingStarted)
				SetAppearTime(appearTime)
			end
		end
	end
end

---------------------------------------------------------------------------------------------------
-- Подсказка после постройки двух домов (общее число домов 3), если игрок тупит 15 секунд
---------------------------------------------------------------------------------------------------
function RE2A_Build3HouseHint(message)
	-- Инициализация
	if (message:is("LoadLevel")) then
		tutSetBool("RE2_HouseBuildHint_Active", false)			-- активность подсказки
		tutSetFloat("RE2_HouseBuildHint_HintAppearTime", 15.0)	-- время появления подсказки
		tutSetFloat("RE2_HouseBuildHint_Time", 0.0)				-- общее время подсказки
		tutSetBool("RE2_HouseBuildHint_HouseStarted", false)
		tutSetBool("RE2_HouseBuildHint_Shown", false)
		tutSetInt("RE2_HouseBuildHint_State", -1)
	end
	
	-- Еще не построили второй дом - ничего не делаем
	if tutorial:game():getHouses1Count() < 3 then
		return
	end

	-- Если активна другая подсказка, то с этой мы ничего не делаем
	if (IsLocked() and not tutGetBool("RE2_HouseBuildHint_Active")) then
		-- Тоже небольшое исключение из правил, если в другой подсказке будет построен дом, то эта подсказка уже будет не нужна
		if (message:is("House1", "press")) then
			tutSetBool("RE2_HouseBuildHint_HouseStarted", true)
		end
		return
	end
	-- Логика подсказки при неактивном состоянии
	if (not tutGetBool("RE2_HouseBuildHint_Active")) then
		if (message:is("House1", "press")) then
			tutSetBool("RE2_HouseBuildHint_HouseStarted", true)
		end
		-- Обновляем время
		if (message:is("Update") and not tutGetBool("RE2_HouseBuildHint_HouseStarted") and tutorial:hasFreeLargeFields() and not tutGetBool("RE2_HouseBuildHint_Shown")) then
			tutSetFloat("RE2_HouseBuildHint_Time", tutGetFloat("RE2_HouseBuildHint_Time") + message:getVariables():getFloat("TimeDelta"))
			
			if (tutGetFloat("RE2_HouseBuildHint_Time") > tutGetFloat("RE2_HouseBuildHint_HintAppearTime")) then
			
				tutSetBool("RE2_HouseBuildHint_Active", true)
				Lock()
				tutSetInt("RE2_HouseBuildHint_State", 0)
				avatar:show("RE2_HouseBuildHint_01")
				avatar:setOffset(IPoint(10, 150), false)

				arrow = tutorial:addArrow()
				tutorial:getArrow(arrow):setPosition(690, 710)
				tutorial:getArrow(arrow):setAngle(45)
				tutorial:getArrow(arrow):setShowTimer(1.0)
				tutorial:getArrow(arrow):show(0.5)
				tutorial:show(0.25)

				tutSetBool("RE2_HouseBuildHint_Shown", true)
			end
		end
	-- Логика подсказки при активном состоянии
	else
		-- Логика при показе стрелок
		if (tutGetInt("RE2_HouseBuildHint_State") == 0) then
			if (message:is("TutorialOk", "press")) then
				avatar:hide()
				tutorial:hideArrows(0.25)
				tutSetFloat("RE2_HouseBuildHint_Time", 0.0)
				tutSetInt("RE2_HouseBuildHint_State", 1)
			end
		elseif (tutGetInt("RE2_HouseBuildHint_State") == 1) then
			if (message:is("MapTutorialDidHide")) then
				Unlock()
				tutorial:hideArrows(0.25)
				tutorial:hide(0.25)
				DialogResumeGame()
			end
		end
	end
end

---------------------------------------------------------------------------------------------------
-- Подсказка на постройку третьего и четвертого дома после подсказки на таски
---------------------------------------------------------------------------------------------------
function RE2A_Build4HouseHint(message)
	local housesPos = IPoint(617, 100)
	local backPos = IPoint(950, 100)
	local house1Pos = IPoint(549, 100)
	------------------------------------------ Дополнительные функции ------------------------------------------
	-- Инициализация переменных
	local function Reset()	
		tutSetBool("RE2_Build4HouseHint_Active", false)				-- активность подсказки
		tutSetFloat("RE2_Build4HouseHint_HintAppearTime", 15.0)		-- время появления подсказки
		tutSetFloat("RE2_Build4HouseHint_Time", 0.0)				-- общее время подсказки
		tutSetInt("RE2_Build4HouseHint_State", -1)
		tutSetBool("RE2_Build4HouseHint_Ready", false)				-- готов ли первый дом
		tutSetInt("RE2_Build4HouseHint_Arrow", -1)					-- Идентификатор стрелочки
		tutSetBool("RE2_Build4HouseHint_BuildingStarted", false)	-- Строительство первого дома началось
		tutSetBool("RE2_Build4HouseHint_ArrowHidden", true)			-- Стрелка скрыта
	end

	local function IsArrowHidden()
		return tutGetBool("RE2_Build4HouseHint_ArrowHidden")
	end
	
	local function SetArrowHidden(hidden)
		tutSetBool("RE2_Build4HouseHint_ArrowHidden", hidden)
	end

	-- Начали строить дом?
	local function IsBuildingStarted()
		return tutGetBool("RE2_Build4HouseHint_BuildingStarted")
	end
	
	-- Устанавливает, начали ли строить дом
	local function SetBuildingStarted(started)
		tutSetBool("RE2_Build4HouseHint_BuildingStarted", started)
	end
	
	-- Построили дом, подсказка больше не нужна
	local function IsReady()
		return tutGetBool("RE2_Build4HouseHint_Ready")
	end
	
	-- Устанавливает, нужно ли отображать подсказку
	local function SetReady(ready)
		tutSetBool("RE2_Build4HouseHint_Ready", ready)
	end
	
	-- Обновляет таймер
	local function Update()
		if message:is("Update") then
			tutSetFloat("RE2_Build4HouseHint_Time", tutGetFloat("RE2_Build4HouseHint_Time") + message:getVariables():getFloat("TimeDelta"))
		end
	end
	
	-- Возвращает true, если пора показывать подсказку
	local function ItsTime()
		return tutGetFloat("RE2_Build4HouseHint_Time") > tutGetFloat("RE2_Build4HouseHint_HintAppearTime")
	end
	
	local function Time()
		return tutGetFloat("RE2_Build4HouseHint_Time")
	end
	
	local function SetAppearTime(newTime)
		tutSetFloat("RE2_Build4HouseHint_HintAppearTime", newTime)
	end
	
	-- Обнуляет таймер
	local function NullTimer()
		tutSetFloat("RE2_Build4HouseHint_Time", 0.0)
	end
	
	-- Возвращает состояние
	local function GetState()
		return tutGetInt("RE2_Build4HouseHint_State")
	end
	
	-- Устанавливает новое состояние
	local function SetState(newState)
		if newState == GetState() then
			return
		end
		tutSetInt("RE2_Build4HouseHint_State", newState)
	end

	-- Активна ли подсказка
	local function IsActive()
		return tutGetBool("RE2_Build4HouseHint_Active")
	end
	
	-- Устанавливает активность подсказки
	local function SetActive(newActive)
		tutSetBool("RE2_Build4HouseHint_Active", newActive)
	end
	
	-- Нужно ли указывать стрелкой на пустую площадку?
	-- Нужно, если ничего не выделено или выделено, но не пустая площадка
	local function ShouldPointAtFreeLargeField()
		if (not tutorial:game():getSelected()) or (tutorial:game():getSelected() and not tutorial:isLargeFieldFree(tutorial:game():getSelected():id())) then
			return true
		else
			return false
		end
	end
	
	-- Возвращает стрелку (если нет - создает)
	local function GetArrow()
		local arrowId = tutGetInt("RE2_Build4HouseHint_Arrow")
		-- Стрелки нет - создаем
		if arrowId == -1 then
			arrowId = tutorial:addArrow()
			tutSetInt("RE2_Build4HouseHint_Arrow", arrowId)
		end
		
		return arrowId
	end
	
	-- Шаманский код для отображения стрелки
	local function ShowArrow()
		SetArrowHidden(false)

		Lock()
		tutorial:setObjectsAllowType(allowPass)
		tutorial:variables():setBool("TutorialArrowsNoBind", true);
		tutorial:variables():setFloat("TutorialShowDelayTime", -1.0)
		tutorial:show(0.25)
	end
	
	-- Прячет стрелку, завершает подсказку
	local function HideArrow()
		SetArrowHidden(true)

		tutorial:hideArrows(0.25)
		tutorial:hide(0.25)
	end
	
	-- Удаляет стрелку
	local function RemoveArrow()
		local arrowId = GetArrow()
		tutorial:removeArrow(arrowId)
		tutSetInt("RE2_Build4HouseHint_Arrow", -1)
	end
	
	-- Указывает на площадку
	local function PointAtField()
		local arrowId = GetArrow()
		
		local middleFieldId = 131694
		local fieldPos
		
		-- Если площадка в центре свободна - тычем в нее
		if tutorial:isLargeFieldFree(middleFieldId) then
			fieldPos = tutorial:game():getObject(middleFieldId):getScreenPosition()
		else
			-- Иначе - тычем в произвольную пустую площадку
			local fieldId = tutorial:getRandomFreeLargeFieldId()
			if fieldId ~= -1 then
				fieldPos = tutorial:game():getObject(fieldId):getScreenPosition()
			else
				return
			end
		end

		tutorial:getArrow(arrowId):setPosition(fieldPos.x, fieldPos.y + 40)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)

		ShowArrow()
	end
	
	-- Указывает на кнопку "Назад"
	local function PointAtBack()
		local arrowId = GetArrow()
		
		tutorial:getArrow(arrowId):setPosition(backPos.x, backPos.y)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)

		ShowArrow()
	end
	
	-- Указывает на кнопку "Дома"
	local function PointAtHouses()
		local arrowId = GetArrow()
		
		tutorial:getArrow(arrowId):setPosition(housesPos.x, housesPos.y)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)

		ShowArrow()
	end
	
	-- Указывает на кнопку "Дом1"
	local function PointAtHouse1()
		local arrowId = GetArrow()
		
		tutorial:getArrow(arrowId):setPosition(house1Pos.x, house1Pos.y)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)
		
		ShowArrow()
	end
	
	-- Указывает на соответствующую точку в зависимости от ситуации
	local function PointAtAppropriatePoint()
		local arrowId = GetArrow()
		local arrowPos = IPoint(tutorial:getArrow(arrowId):getPosition().x, tutorial:getArrow(arrowId):getPosition().y)
		
		-- Кнопки "Дома" и "Здания"
		if tutorial:isLargeFieldInterface() then
			local pointAtRightPlace = (housesPos.x == arrowPos.x and housesPos.y == arrowPos.y)
			if not IsArrowHidden() and not pointAtRightPlace then
				HideArrow()
				NullTimer()
			else
				Update()
				if Time() > 0.25 then
					PointAtHouses()
				end
			end
		-- Интерфейс постройки зданий
		elseif tutorial:isLargeFieldInterfaceBuildings() then
			local pointAtRightPlace = (backPos.x == arrowPos.x and backPos.y == arrowPos.y)

			if not IsArrowHidden() and not pointAtRightPlace then
				HideArrow()
				NullTimer()
			else
				Update()
				if Time() > 0.25 then
					PointAtBack()
				end
			end
		-- Интерфейс постройки домов
		elseif tutorial:isLargeFieldInterfaceHouses() then
			local pointAtRightPlace = (house1Pos.x == arrowPos.x and house1Pos.y == arrowPos.y)
			
			if not IsArrowHidden() and not pointAtRightPlace then
				HideArrow()
				NullTimer()
			else
				Update()
				if Time() > 0.25 then
					PointAtHouse1()
				end
			end
		end
	end	
	
	------------------------------------------ Начало основной функции ------------------------------------------
	-- Инициализация
	if message:is("LoadLevel") then
		Reset()
	end

	-- Еще не построили второй дом - ничего не делаем
	if tutorial:game():getHouses1Count() < 3 then
		return
	end
	
	-- Подсказки на задачи не было
	if not tutGetBool("RE2_HouseBuildHint_Shown") then
		return
	end

	-- Если активна другая подсказка - ничего не делаем
	if IsLocked() and not IsActive() then
		return
	end
	
	-- Построили третий дом - ничего не делаем
	if IsReady() then
		return
	end
	
	
	if message:is("House1", "press") and not IsBuildingStarted() then
		SetBuildingStarted(true)
	elseif message:is("Cancel", "press") and IsBuildingStarted() then
		SetBuildingStarted(false)
	elseif message:is("BuildingBuilt") and IsBuildingStarted() then
		SetReady(true)
	end
	
	--[[
		-1 - начальное состояние - стрелки нет
		0 - стрелка тычет в площадку
		1 - стрелка тычет в кнопку панель
		111 - прячем стрелку - переинициализация
	]]--
	-- Подсказка не активна
	if not IsActive() then
		-- Обновляем таймер
		if message:is("Update") and not IsBuildingStarted() then
			Update()
			
			-- Пора
			if ItsTime() then
				-- Проверим на предмет начального состояния
				if GetState() == -1 then
					-- Если ничего не выделено или выделено, но не пустая площадка - укажем на площадку
					if ShouldPointAtFreeLargeField() then
						SetActive(true)
						NullTimer()
						PointAtField()
						SetState(0)
					-- Если выделена пустая площадка - проверим, какие кнопки интерфейса доступны
					else
						SetActive(true)
						SetState(1)
					end
				end
			end
		end
	-- Подсказка активна
	else
		-- Стрелочка тычет в площадку
		if GetState() == 0 then
			-- Чтобы стрелка обновлялась
			if message:is("Update") then
				-- Выделена площадка
				if tutorial:game():getSelected() and tutorial:isLargeFieldFree(tutorial:game():getSelected():id()) then
					PointAtAppropriatePoint()
					SetState(1)
				end
			end
		-- Стрелка тычет в панель
		elseif GetState() == 1 then
			-- Чтобы стрелка обновлялась
			if message:is("Update") then
				-- Сняли выделение - все прячем
				if ShouldPointAtFreeLargeField() then
					HideArrow()
					SetState(111)
				else
					PointAtAppropriatePoint()
				end
			end
		elseif GetState() == 111 then
			if (message:is("TutorialPop")) then
				Unlock()
				tutorial:variables():setBool("TutorialArrowsNoBind", false)

				local isBuildingStarted = IsBuildingStarted()
				local appearTime = tutGetFloat("RE2_Build4HouseHint_HintAppearTime")
				
				RemoveArrow()
				Reset()
				
				SetBuildingStarted(isBuildingStarted)
				SetAppearTime(appearTime)
			end
		end
	end
end

---------------------------------------------------------------------------------------------------
-- Подсказка на постройку 5 дома
---------------------------------------------------------------------------------------------------
function RE2A_Build5HouseHint(message)
	local housesPos = IPoint(617, 100)
	local backPos = IPoint(950, 100)
	local house1Pos = IPoint(549, 100)
	------------------------------------------ Дополнительные функции ------------------------------------------
	-- Инициализация переменных
	local function Reset()	
		tutSetBool("RE2_Build5HouseHint_Active", false)				-- активность подсказки
		tutSetFloat("RE2_Build5HouseHint_HintAppearTime", 15.0)		-- время появления подсказки
		tutSetFloat("RE2_Build5HouseHint_Time", 0.0)				-- общее время подсказки
		tutSetInt("RE2_Build5HouseHint_State", -1)
		tutSetBool("RE2_Build5HouseHint_Ready", false)				-- готов ли первый дом
		tutSetInt("RE2_Build5HouseHint_Arrow", -1)					-- Идентификатор стрелочки
		tutSetBool("RE2_Build5HouseHint_BuildingStarted", false)	-- Строительство первого дома началось
		tutSetBool("RE2_Build5HouseHint_ArrowHidden", true)			-- Стрелка скрыта
	end

	local function IsArrowHidden()
		return tutGetBool("RE2_Build5HouseHint_ArrowHidden")
	end
	
	local function SetArrowHidden(hidden)
		tutSetBool("RE2_Build5HouseHint_ArrowHidden", hidden)
	end
	
	-- Начали строить дом?
	local function IsBuildingStarted()
		return tutGetBool("RE2_Build5HouseHint_BuildingStarted")
	end
	
	-- Устанавливает, начали ли строить дом
	local function SetBuildingStarted(started)
		tutSetBool("RE2_Build5HouseHint_BuildingStarted", started)
	end
	
	-- Построили дом, подсказка больше не нужна
	local function IsReady()
		return tutGetBool("RE2_Build5HouseHint_Ready")
	end
	
	-- Устанавливает, нужно ли отображать подсказку
	local function SetReady(ready)
		tutSetBool("RE2_Build5HouseHint_Ready", ready)
	end
	
	-- Обновляет таймер
	local function Update()
		tutSetFloat("RE2_Build5HouseHint_Time", tutGetFloat("RE2_Build5HouseHint_Time") + message:getVariables():getFloat("TimeDelta"))
	end
	
	-- Возвращает true, если пора показывать подсказку
	local function ItsTime()
		return tutGetFloat("RE2_Build5HouseHint_Time") > tutGetFloat("RE2_Build5HouseHint_HintAppearTime")
	end
	
	local function Time()
		return tutGetFloat("RE2_Build5HouseHint_Time")
	end

	local function SetAppearTime(newTime)
		tutSetFloat("RE2_Build5HouseHint_HintAppearTime", newTime)
	end
	
	-- Обнуляет таймер
	local function NullTimer()
		tutSetFloat("RE2_Build5HouseHint_Time", 0.0)
	end
	
	-- Возвращает состояние
	local function GetState()
		return tutGetInt("RE2_Build5HouseHint_State")
	end
	
	-- Устанавливает новое состояние
	local function SetState(newState)
		if newState == GetState() then
			return
		end
		tutSetInt("RE2_Build5HouseHint_State", newState)
	end

	-- Активна ли подсказка
	local function IsActive()
		return tutGetBool("RE2_Build5HouseHint_Active")
	end
	
	-- Устанавливает активность подсказки
	local function SetActive(newActive)
		tutSetBool("RE2_Build5HouseHint_Active", newActive)
	end
	
	-- Нужно ли указывать стрелкой на пустую площадку?
	-- Нужно, если ничего не выделено или выделено, но не пустая площадка
	local function ShouldPointAtFreeLargeField()
		if (not tutorial:game():getSelected()) or (tutorial:game():getSelected() and not tutorial:isLargeFieldFree(tutorial:game():getSelected():id())) then
			return true
		else
			return false
		end
	end
	
	-- Возвращает стрелку (если нет - создает)
	local function GetArrow()
		local arrowId = tutGetInt("RE2_Build5HouseHint_Arrow")
		-- Стрелки нет - создаем
		if arrowId == -1 then
			arrowId = tutorial:addArrow()
			tutSetInt("RE2_Build5HouseHint_Arrow", arrowId)
		end
		
		return arrowId
	end
	
	-- Шаманский код для отображения стрелки
	local function ShowArrow()
		SetArrowHidden(false)

		Lock()
		tutorial:setObjectsAllowType(allowPass)
		tutorial:variables():setBool("TutorialArrowsNoBind", true);
		tutorial:variables():setFloat("TutorialShowDelayTime", -1.0)
		--tutorial:setCharacter("Sedrik")
		--tutorial:setWidgetVisible("TutorialOk", true)
		tutorial:show(0.25)
	end
	
	-- Прячет стрелку, завершает подсказку
	local function HideArrow()
		SetArrowHidden(true)

		tutorial:hideArrows(0.25)
		tutorial:hide(0.25)
	end
	
	-- Удаляет стрелку
	local function RemoveArrow()
		local arrowId = GetArrow()
		tutorial:removeArrow(arrowId)
		tutSetInt("RE2_Build5HouseHint_Arrow", -1)
	end
	
	-- Указывает на площадку
	local function PointAtField()
		local arrowId = GetArrow()
		
		local middleFieldId = 131694
		local fieldPos
		
		-- Если площадка в центре свободна - тычем в нее
		if tutorial:isLargeFieldFree(middleFieldId) then
			fieldPos = tutorial:game():getObject(middleFieldId):getScreenPosition()
		else
			-- Иначе - тычем в произвольную пустую площадку
			local fieldId = tutorial:getRandomFreeLargeFieldId()
			if fieldId ~= -1 then
				fieldPos = tutorial:game():getObject(fieldId):getScreenPosition()
			else
				return
			end
		end

		tutorial:getArrow(arrowId):setPosition(fieldPos.x, fieldPos.y + 40)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)

		ShowArrow()
	end
	
	-- Указывает на кнопку "Назад"
	local function PointAtBack()
		local arrowId = GetArrow()
		
		tutorial:getArrow(arrowId):setPosition(backPos.x, backPos.y)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)

		ShowArrow()
	end
	
	-- Указывает на кнопку "Дома"
	local function PointAtHouses()
		local arrowId = GetArrow()
		
		tutorial:getArrow(arrowId):setPosition(housesPos.x, housesPos.y)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)

		ShowArrow()
	end
	
	-- Указывает на кнопку "Дом1"
	local function PointAtHouse1()
		local arrowId = GetArrow()
		
		tutorial:getArrow(arrowId):setPosition(house1Pos.x, house1Pos.y)
		tutorial:getArrow(arrowId):setAngle(270)
		tutorial:getArrow(arrowId):setIgnoreContext(true)
		tutorial:getArrow(arrowId):show(0.5)
		
		ShowArrow()
	end
	
	-- Указывает на соответствующую точку в зависимости от ситуации
	local function PointAtAppropriatePoint()
		local arrowId = GetArrow()
		local arrowPos = IPoint(tutorial:getArrow(arrowId):getPosition().x, tutorial:getArrow(arrowId):getPosition().y)
		
		-- Кнопки "Дома" и "Здания"
		if tutorial:isLargeFieldInterface() then
			local pointAtRightPlace = (housesPos.x == arrowPos.x and housesPos.y == arrowPos.y)
			if not IsArrowHidden() and not pointAtRightPlace then
				HideArrow()
				NullTimer()
			else
				Update()
				if Time() > 0.25 then
					PointAtHouses()
				end
			end
		-- Интерфейс постройки зданий
		elseif tutorial:isLargeFieldInterfaceBuildings() then
			local pointAtRightPlace = (backPos.x == arrowPos.x and backPos.y == arrowPos.y)

			if not IsArrowHidden() and not pointAtRightPlace then
				HideArrow()
				NullTimer()
			else
				Update()
				if Time() > 0.25 then
					PointAtBack()
				end
			end
		-- Интерфейс постройки домов
		elseif tutorial:isLargeFieldInterfaceHouses() then
			local pointAtRightPlace = (house1Pos.x == arrowPos.x and house1Pos.y == arrowPos.y)
			
			if not IsArrowHidden() and not pointAtRightPlace then
				HideArrow()
				NullTimer()
			else
				Update()
				if Time() > 0.25 then
					PointAtHouse1()
				end
			end
		end
	end	
	
	------------------------------------------ Начало основной функции ------------------------------------------
	-- Инициализация
	if message:is("LoadLevel") then
		Reset()
	end

	-- Еще не построили второй дом - ничего не делаем
	if tutorial:game():getHouses1Count() < 4 then
		return
	end
	
	-- Если активна другая подсказка - ничего не делаем
	if IsLocked() and not IsActive() then
		return
	end
	
	-- Построили третий дом - ничего не делаем
	if IsReady() then
		return
	end
	
	if message:is("House1", "press") and not IsBuildingStarted() then
		SetBuildingStarted(true)
	elseif message:is("Cancel", "press") and IsBuildingStarted() then
		SetBuildingStarted(false)
	elseif message:is("BuildingBuilt") and IsBuildingStarted() then
		SetReady(true)
	end
	
	--[[
		-1 - начальное состояние - стрелки нет
		0 - стрелка тычет в площадку
		1 - стрелка тычет в кнопку панель
		111 - прячем стрелку - переинициализация
	]]--
	-- Подсказка не активна
	if not IsActive() then
		-- Обновляем таймер
		if message:is("Update") and not IsBuildingStarted() then
			Update()
			
			-- Пора
			if ItsTime() then
				-- Проверим на предмет начального состояния
				if GetState() == -1 then
					-- Если ничего не выделено или выделено, но не пустая площадка - укажем на площадку
					if ShouldPointAtFreeLargeField() then
						SetActive(true)
						NullTimer()
						PointAtField()
						SetState(0)
					-- Если выделена пустая площадка - проверим, какие кнопки интерфейса доступны
					else
						SetActive(true)
						SetState(1)
					end
				end
			end
		end
	-- Подсказка активна
	else
		-- Стрелочка тычет в площадку
		if GetState() == 0 then
			-- Чтобы стрелка обновлялась
			if message:is("Update") then
				-- Выделена площадка
				if tutorial:game():getSelected() and tutorial:isLargeFieldFree(tutorial:game():getSelected():id()) then
					PointAtAppropriatePoint()
					SetState(1)
				end
			end
		-- Стрелка тычет в панель
		elseif GetState() == 1 then
			-- Чтобы стрелка обновлялась
			if message:is("Update") then
				-- Сняли выделение - все прячем
				if ShouldPointAtFreeLargeField() then
					HideArrow()
					SetState(111)
				else
					PointAtAppropriatePoint()
				end
			end
		elseif GetState() == 111 then
			if (message:is("TutorialPop")) then
				Unlock()
				tutorial:variables():setBool("TutorialArrowsNoBind", false)

				local isBuildingStarted = IsBuildingStarted()
				local appearTime = tutGetFloat("RE2_Build5HouseHint_HintAppearTime")
				
				RemoveArrow()
				Reset()
				
				SetBuildingStarted(isBuildingStarted)
				SetAppearTime(appearTime)
			end
		end
	end
end

---------------------------------------------------------------------------------------------------
-- Подсказка после постройки первого дома
---------------------------------------------------------------------------------------------------
function RE2A_FirstHouseWasBuilt(message)
	local active = "RE2_FirstHouseWasBuilt_Active"
	local shown = "RE2_FirstHouseWasBuilt_Shown"
	local allow = "RE2_FirstHouseWasBuilt_Allow"
	local time = "RE2_FirstHouseWasBuilt_Time"
	-- Инициализация
	if (message:is("LoadLevel")) then
		tutSetBool(active, false)			-- активность подсказки
		tutSetBool(shown, false)
		tutSetBool(active, false)
		tutSetFloat(time, 0.0)
		tutSetInt("RE2_FirstHouseWasBuilt_State", -1)
	end
	
	-- Еще не построили первый дом - ничего не делаем
	if message:is("BuildingBuilt") and not tutGetBool(allow) then
		tutSetBool(allow, true)
	end
	
	if not tutGetBool(allow) then
		return
	end

	if tutGetBool(shown) then
		return
	end

	-- Если активна другая подсказка, то с этой мы ничего не делаем
	if (tutGetBool("TutorialLock") and not tutGetBool(active)) then
		return
	end
	
	-- Логика подсказки при неактивном состоянии
	if not tutGetBool(active) and not tutGetBool(shown) then
		if message:is("Update") then
			tutSetFloat(time, tutGetFloat(time) + message:getVariables():getFloat("TimeDelta"))
			if tutGetFloat(time) >= 1.0 then
				tutSetFloat(time, 0.0)

				tutSetBool(active, true)
				tutSetInt("RE2_FirstHouseWasBuilt_State", 0)

				avatar:show("RE2_FirstHouseWasBuilt")
				avatar:setOffset(IPoint(520, 450), false)
				arrow = tutorial:addArrow()
				tutorial:getArrow(arrow):setPosition(690, 710)
				tutorial:getArrow(arrow):setAngle(45)
				tutorial:getArrow(arrow):setShowTimer(1.0)
				tutorial:getArrow(arrow):show(0.5)
				tutorial:show(0.25)
			end
		end
	-- Логика подсказки при активном состоянии
	else
		-- Логика при показе стрелок
		if (tutGetInt("RE2_FirstHouseWasBuilt_State") == 0) then
			if message:is("Update") then
				tutSetFloat(time, tutGetFloat(time) + message:getVariables():getFloat("TimeDelta"))
			elseif tutGetFloat(time) >= 1.0 and message:is("TutorialOk", "press") then
				tutorial:hideArrows(0.25)
				avatar:hide()
				tutSetInt("RE2_FirstHouseWasBuilt_State", 1)
			end
		elseif (tutGetInt("RE2_FirstHouseWasBuilt_State") == 1) then
			if (message:is("MapTutorialDidHide")) then
				Unlock()
				tutSetBool(shown, true)
				DialogResumeGame()
				avatar:setOffset(LeftAvatarPosition, false)
			end
		end
	end
end

---------------------------------------------------------------------------------------------------
-- Подсказка на пропажу пяти лутов
---------------------------------------------------------------------------------------------------
local RE2A_FiveLootsLost = hint:create("RE2A_FiveLootsLost")
function RE2A_FiveLootsLost:setCount(count) tutSetInt(self.hintId.."Count", count) end
function RE2A_FiveLootsLost:getCount() return tutGetInt(self.hintId.."Count") end
function RE2A_FiveLootsLost:incCount() self:setCount(self:getCount() + 1) end
function RE2A_FiveLootsLost:onInit()
	self:setCount(0)
end
function RE2A_FiveLootsLost:onProcessMessage(message)
	if not self:isActive() then
		if message:is("LootLost") then
			self:incCount()
			if self:getCount() > 4 and self:getState() == 0 then
				self:start()
				self:setState(1)
				avatar:show("RE2_AllLootHint_01")
				avatar:setOffset(IPoint(10, 150), false)
			end
		end
	else
		if self:getState() == 1 then
			if self:isPassed(message) then
				avatar:hide()
				self:setShown(true)
				self:goToFinish()
			end
		end
	end
end
function RE2A_FiveLootsLostHint(message)
	RE2A_FiveLootsLost:processMessage(message)
end


---------------------------------------------------------------------------------------------------
-- Подсказка на пропажу пяти лутов
---------------------------------------------------------------------------------------------------
local SedrikFishing = avatar:create("SedrikFishing")
local RE2A_FiveLootsLostSedrikFishing = hint:create("RE2A_FiveLootsLostSedrikFishing")
function RE2A_FiveLootsLostSedrikFishing:setCount(count) tutSetInt(self.hintId.."Count", count) end
function RE2A_FiveLootsLostSedrikFishing:getCount() return tutGetInt(self.hintId.."Count") end
function RE2A_FiveLootsLostSedrikFishing:incCount() self:setCount(self:getCount() + 1) end
function RE2A_FiveLootsLostSedrikFishing:onInit()
	self:setCount(0)
end
function RE2A_FiveLootsLostSedrikFishing:onProcessMessage(message)
	if not self:isActive() then
		if message:is("LootLost") then
			self:incCount()
			if self:getCount() > 4 and self:getState() == 0 then
				self:start()
				self:setState(1)
				SedrikFishing:show("RE2_AllLootHint_01")
				avatar:setOffset(IPoint(10, 150), false)
			end
		end
	else
		if self:getState() == 1 then
			if self:isPassed(message) then
				SedrikFishing:hide()
				self:setShown(true)
				self:goToFinish()
			end
		end
	end
end
function RE2A_FiveLootsLostSedrikFishingHint(message)
	RE2A_FiveLootsLostSedrikFishing:processMessage(message)
end


---------------------------------------------------------------------------------------------------
-- Если в течение 7 секунд не отправили рабочего рубить пальму - покажем на нее стрелкой
---------------------------------------------------------------------------------------------------
local RE2A_StartCuttingTrees = hint:create("RE2A_StartCuttingTrees")
function RE2A_StartCuttingTrees:isReady() return tutGetBool(self.hintId.."Ready") end
function RE2A_StartCuttingTrees:setReady(ready) tutSetBool(self.hintId.."Ready", ready) end
function RE2A_StartCuttingTrees:onInit()
	self:setReady(false)
end

function RE2A_StartCuttingTrees:onProcessMessageRegardlessLock(message)
	if message:is("ForestLand", "press") then
		self:setReady(true)
	end
end

function RE2A_StartCuttingTrees:onProcessMessage(message)
	if not self:isActive() then
		if not self:isReady() and message:is("Update") then
			self:updateTime(message)
			if self:getTime() > 7.0 then
				self:start()
				tutorial:targetForestLand("RE2_ForestLandHint_Arrow", 0.5, IPoint(0, 50), 0.0)
			end
		end
	else
		if self:getState() == 0 then
			if message:is("ForestLand", "press") then
				self:arrowHideAll()
				self:setShown(true)
				self:goToFinish()
			end
		end
	end
end
function RE2A_StartCuttingTreesHint(message)
	RE2A_StartCuttingTrees:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Если не хватает рабочих - покажем стрелками, как их покупать
---------------------------------------------------------------------------------------------------
local RE2A_LackOfWorkers = hint:create("RE2A_LackOfWorkers")
function RE2A_LackOfWorkers:setTextShown(shown) tutSetBool(self.hintId.."TextShown", shown) end
function RE2A_LackOfWorkers:isTextShown() return tutGetBool(self.hintId.."TextShown") end
function RE2A_LackOfWorkers:setTextVisible(visible) tutSetBool(self.hintId.."TextVisible", visible) end
function RE2A_LackOfWorkers:isTextVisible() return tutGetBool(self.hintId.."TextVisible") end
function RE2A_LackOfWorkers:setStartedByTimer(started) tutSetBool(self.hintId.."StartedByTimer", started) end
function RE2A_LackOfWorkers:isStartedByTimer() return tutGetBool(self.hintId.."StartedByTimer") end
function RE2A_LackOfWorkers:hideAll()
	self:arrowHideAll()
	if self:isTextVisible() then
		avatar:hide()
	end
end
function RE2A_LackOfWorkers:onInit()
	self:setTextShown(false)
	self:setStartedByTimer(false)
end
function RE2A_LackOfWorkers:onReset()
	self:setTextVisible(false)
end

function RE2A_LackOfWorkers:onStart()
	self:setStartedByTimer(true)
end

function RE2A_LackOfWorkers:pointAtButton()
	if self:getArrowIndex() == 0 then
		self:arrowSave(self:arrowAdd(IPoint(705, 100), -90))
	end

	local arrow = self:arrowGet(0)
	arrow:setPosition(705, 100)
	self:arrowShow(0, 0.25)
end

function RE2A_LackOfWorkers:onProcessMessage(message)
	if tutorial:game():getWorkersCount() > 1 then return end
	if not self:isActive() then
		-- Если в течение 20 секунд не построили рабочего - тоже вызовем подсказку
		local timeToStart = false
		-- Если подсказку уже показывали - не показываем
		if not self:isStartedByTimer() then
			if message:is("Worker", "press") then
				self:setStartedByTimer(true)
			elseif message:is("Update") then
				timeToStart = false
				self:updateTime(message)
				if self:getTime() >= 20.0 then
					timeToStart = true
					self:setStartedByTimer(true)
				end
			end
		end

		-- Клик в объект - и не хватает рабочих
		if (message:is("WorkersBlock") and tutorial:game():getWorkersCount() < 5 and not tutorial:isBaseBusy()) or timeToStart then
			self:decClickCounter()
			-- Пора показывать подсказку
			if self:getClickCounter() <= 0 then
				-- Количество кликов для вызова подсказки меняется
				if self:getClickCount() == 1 then
					self:setClickCount(2)
				elseif self:getClickCount() == 2 then
					self:setClickCount(3)
				end
				self:setClickCounter(self:getClickCount())
				self:start()

				-- Стрелка - на кнопку "Купить рабочего"
				if IsBaseSelected() then
					self:setState(1)
				else
					-- Стрелка - на базу
					local arrowId = tutorial:targetBase(0.5, IPoint(0, 50), 0.25)
					self:arrowSave(arrowId)
					self:setState(0)
					if not self:isTextShown() then
						avatar:show("RE2_NoMoreWorkersDuring30Sec")
						avatar:setOffset(IPoint(10, 150), false)
						self:setTextVisible(true)
						self:setTextShown(true)
					else
						self:setTextVisible(false)
					end
				end

				self:setTime(0.0)
			end
		end		
	else
		-- Стрелка указывает на базу
		if self:getState() == 0 then
			-- Обновляем таймер
			if message:is("Update") then
				-- Ткнули в базу
				if IsBaseSelected() then
					self:setTime(0.0)
					self:hideAll()
					self:setState(1)
				else
					self:updateTime(message)
					-- Базу не выделили - скрываем стрелку
					if self:isTextShown() and self:getTime() > 7.0 then
						self:hideAll()
						self:goToFinish()
					end
				end
			-- Игрок кликнул - прячем подсказку, но стрелку оставляем. Она сама пропадет через 7 секунд, если не выделить базу
			elseif self:isPassed(message) then
				if self:isTextVisible() then
					avatar:hide()
				end
			end
		elseif self:getState() == 1 then
			if message:is("Update") then
				self:updateTime(message)
				if self:getTime() >= 0.25 then
					self:pointAtButton()
					self:setState(2)
				end
			end
		-- Стрелка указыват на кнопку
		elseif self:getState() == 2 then
			-- Построили рабочего
			if message:is("Worker", "press") then
				-- Пячем все
				self:hideAll()
				-- Больше подсказку не показываем
				self:setShown(true)
				self:goToFinish()
			elseif message:is("Update") then
				-- База больше не выделена - прячем все
				if not IsBaseSelected() then
					self:hideAll()
					self:goToFinish()
				end
			end
		end
	end
end

function RE2A_LackOfWorkersHint(message)
	RE2A_LackOfWorkers:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Если не хватает рабочих - покажем стрелками, как их покупать
---------------------------------------------------------------------------------------------------
local RE2A_LackOfMaterials = hint:create("RE2A_LackOfMaterials")
function RE2A_LackOfMaterials:setTextShown(shown) tutSetBool(self.hintId.."TextShown", shown) end
function RE2A_LackOfMaterials:isTextShown() return tutGetBool(self.hintId.."TextShown") end
function RE2A_LackOfMaterials:setTextVisible(visible) tutSetBool(self.hintId.."TextVisible", visible) end
function RE2A_LackOfMaterials:isTextVisible() return tutGetBool(self.hintId.."TextVisible") end
function RE2A_LackOfMaterials:hideAll()
	self:arrowHideAll()
	if self:isTextVisible() then
		avatar:hide()
	end
end
function RE2A_LackOfMaterials:onInit()
	self:setTextShown(false)
end
function RE2A_LackOfMaterials:onReset()
	self:setTextVisible(false)
end

function RE2A_LackOfMaterials:onProcessMessage(message)
	if not self:isActive() then
		if message:is("MaterialsBlock") and tutorial:getForestLandsWithMaterialsCount() > 0 then
			self:setClickAccepted(true)
			self:decClickCounter()
			if self:getClickCounter() <= 0 then
				-- Количество кликов для вызова подсказки меняется
				if self:getClickCount() == 1 then
					self:setClickCount(2)
				elseif self:getClickCount() == 2 then
					self:setClickCount(3)
				end
				self:setClickCounter(self:getClickCount())
				self:start()
				self:arrowSave(tutorial:targetRandomForestLand(0.5, IPoint(0, 50), 0.0))
				if not self:isTextShown() then
					avatar:show("RE2_MaterialsAllHint_01")
					avatar:setOffset(IPoint(10, 150), false)
					self:setTextVisible(true)
					self:setTextShown(true)
				else
					self:setTextVisible(false)
				end
				self:setTime(0.0)
			end
		elseif message:is("Update") then
			self:setClickAccepted(false)
		end
	else
		if self:getState() == 0 then
			-- Игрок кликнул - прячем подсказку, но стрелку оставляем. Она сама пропадет через 7 секунд, если не выделить базу
			if self:isPassed(message) or message:is("ForestLand", "click") then
				self:hideAll()
				self:goToFinish()
			end
		end
	end
end

function RE2A_LackOfMaterialsHint(message)
	RE2A_LackOfMaterials:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Если игрок кликает по недоступным объектам - покажем на мосты
---------------------------------------------------------------------------------------------------
local RE2A_ClickOnUnreachableObjects = hint:create("RE2A_ClickOnUnreachableObjects")
function RE2A_ClickOnUnreachableObjects:setTextShown(shown) tutSetBool(self.hintId.."TextShown", shown) end
function RE2A_ClickOnUnreachableObjects:isTextShown() return tutGetBool(self.hintId.."TextShown") end
function RE2A_ClickOnUnreachableObjects:setTextVisible(visible) tutSetBool(self.hintId.."TextVisible", visible) end
function RE2A_ClickOnUnreachableObjects:isTextVisible() return tutGetBool(self.hintId.."TextVisible") end
function RE2A_ClickOnUnreachableObjects:hideAll()
	self:arrowHideAll()
	if self:isTextVisible() then
		avatar:hide()
	end
end
function RE2A_ClickOnUnreachableObjects:onInit()
	self:setTextShown(false)
end
function RE2A_ClickOnUnreachableObjects:onReset()
	self:setTextVisible(false)
end

function RE2A_ClickOnUnreachableObjects:onProcessMessage(message)
	if not self:isActive() then
		if message:is("UnreachableClick") and not self:isClickAccepted() then
			self:setClickAccepted(true)
			local fieldId = message:getIntegerParam()
			local field = tutorial:game():getObject(fieldId)
			local blockingObjectId = field:getBlockingObject():id()
			local blockingObject = tutorial:game():getBuilding(blockingObjectId)
			PrintDebug("blockingObjectId = "..tostring(blockingObjectId)..", state = "..tostring(blockingObject:getState()).."\n")
			if blockingObject ~= nil and blockingObject:getState() ~= 21 then
				self:decClickCounter()
				if self:getClickCounter() <= 0 then
					-- Количество кликов для вызова подсказки меняется
					if self:getClickCount() == 1 then
						self:setClickCount(2)
					elseif self:getClickCount() == 2 then
						self:setClickCount(3)
					end
					self:setClickCounter(self:getClickCount())
					self:start()
					self:arrowSave(tutorial:targetBlockingObjectForField(fieldId, 0.5, IPoint(0, 0), 0.0))
					if not self:isTextShown() then
						avatar:show("RE2_UnreachableHint_01")
						avatar:setOffset(IPoint(10, 150), false)
						self:setTextVisible(true)
						self:setTextShown(true)
					else
						self:setTextVisible(false)
					end

					self:setTime(0.0)
				end
			end
		elseif message:is("Update") then
			self:setClickAccepted(false)
		end
	else
		if self:getState() == 0 then
			local publisher = message:getPublisher()
			if publisher ~= "Update" then
				PrintDebug("message is "..publisher.."\n")
			end
			if self:isPassed(message) or message:is("RoadBridge", "press") then
				self:hideAll()
				self:goToFinish()
			elseif message:is("Update") then
				if not tutorial:game():getSelected() then
					self:updateTime(message)
					if self:getTime() >= 7.0 then
						self:hideAll()
						self:goToFinish()
					end
				end
			end
		end
	end
end

function RE2A_ClickOnUnreachableObjectsHint(message)
	RE2A_ClickOnUnreachableObjects:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Подсказка на постройку лесопилки, если игрок не начал ее строить в течение 15 секунд
---------------------------------------------------------------------------------------------------
local RE2A_BuildSawmill = hint:create("RE2A_BuildSawmill")
function RE2A_BuildSawmill:setReady(ready) tutSetBool(self.hintId.."Ready", ready) end
function RE2A_BuildSawmill:isReady() return tutGetBool(self.hintId.."Ready") end
function RE2A_BuildSawmill:setArrowHidden(hidden) tutSetBool(self.hintId.."ArrowHidden", hidden) end
function RE2A_BuildSawmill:isArrowHidden() return tutGetBool(self.hintId.."ArrowHidden") end
function RE2A_BuildSawmill:setBuildingStarted(started) tutSetBool(self.hintId.."BuildingStarted", started) end
function RE2A_BuildSawmill:isBuildingStarted() return tutGetBool(self.hintId.."BuildingStarted") end
function RE2A_BuildSawmill:isTextShown() return tutGetBool(self.hintId.."TextShown") end
function RE2A_BuildSawmill:setTextShown(shown) tutSetBool(self.hintId.."TextShown", shown) end

function RE2A_BuildSawmill:onReset()
end

function RE2A_BuildSawmill:onInit()
	self:setBuildingStarted(false)
	self:setArrowHidden(true)
	self:setTextShown(false)
end

function RE2A_BuildSawmill:onStart()
	self:addArrow()
end

function RE2A_BuildSawmill:addArrow()
	self:arrowSave(self:arrowAdd(IPoint(0, 0), 270))
end

function RE2A_BuildSawmill:getArrow()
	return self:arrowGet(0)
end

function RE2A_BuildSawmill:showArrow()
	local arrow = self:getArrow()
	self:setArrowHidden(false)
	arrow:show(0.5)
end

function RE2A_BuildSawmill:hideArrow()
	local arrow = self:getArrow()
	self:setArrowHidden(true)
	arrow:hide(0.25)
end

function RE2A_BuildSawmill:update(message)
	if message:is("Update") then
		self:updateTime(message)
	end
end

function RE2A_BuildSawmill:pointAtField()
	local fieldId = tutorial:getRandomFreeLargeFieldId()
	local fieldPos = tutorial:game():getObject(fieldId):getScreenPosition()

	local arrow = self:getArrow()
	arrow:setPosition(fieldPos.x, fieldPos.y + 40)
	self:showArrow()
end

function RE2A_BuildSawmill:pointAtBack()
	local arrow = self:getArrow()
	arrow:setPosition(950, 100)
	self:showArrow()
end

function RE2A_BuildSawmill:pointAtBuildings()
	local arrow = self:getArrow()
	arrow:setPosition(767, 100)
	self:showArrow()
end

function RE2A_BuildSawmill:pointAtSawmill()
	local arrow = self:getArrow()
	arrow:setPosition(500, 100)
	self:showArrow()
end

function RE2A_BuildSawmill:pointAtAppropriatePoint(message)
	local arrow = self:getArrow()
	local arrowPos = IPoint(arrow:getPosition().x, arrow:getPosition().y)
	local buildingsPos = IPoint(767, 100)
	local backPos = IPoint(950, 100)
	local sawmillPos = IPoint(500, 100)

	-- Кнопки "Дома" и "Здания"
	if tutorial:isLargeFieldInterface() then
		local pointAtRightPlace = (buildingsPos.x == arrowPos.x and buildingsPos.y == arrowPos.y)
		if not self:isArrowHidden() and not pointAtRightPlace then
			self:hideArrow()
			self:setTime(0.0)
		else
			self:update(message)
			if self:getTime() > 0.25 then
				self:pointAtBuildings()
			end
		end
	elseif tutorial:isLargeFieldInterfaceBuildings() then
		local pointAtRightPlace = (sawmillPos.x == arrowPos.x and sawmillPos.y == arrowPos.y)
		
		if not self:isArrowHidden() and not pointAtRightPlace then
			self:hideArrow()
			self:setTime(0.0)
		else
			self:update(message)
			if self:getTime() > 0.25 then
				self:pointAtSawmill()
			end
		end
	elseif tutorial:isLargeFieldInterfaceHouses() then
		local pointAtRightPlace = (backPos.x == arrowPos.x and backPos.y == arrowPos.y)
		if not self:isArrowHidden() and not pointAtRightPlace then
			self:hideArrow()
			self:setTime(0.0)
		else
			self:update(message)
			if self:getTime() > 0.25 then
				self:pointAtBack()
			end
		end
	end
end

function RE2A_BuildSawmill:shouldPointAtFreeLargeField()
	if (not tutorial:game():getSelected()) or (tutorial:game():getSelected() and not tutorial:isLargeFieldFree(tutorial:game():getSelected():id())) then
		return true
	else
		return false
	end
end

function RE2A_BuildSawmill:startHint()
	self:start()
	if not self:isTextShown() then
		avatar:show("RE2_SawmillHint_01")
		avatar:setOffset(IPoint(10, 150), false)
		self:setTextShown(true)
	end
	if self:shouldPointAtFreeLargeField() then
		self:pointAtField()
		self:setState(0)
	else
		self:setState(1)
	end					
end

function RE2A_BuildSawmill:onProcessMessageRegardlessLock(message)
	if message:is("Sawmill", "press") and not self:isBuildingStarted() then
		avatar:hide()
		self:setBuildingStarted(true)
	elseif message:is("Cancel", "press") and self:isBuildingStarted() then
		self:setBuildingStarted(false)
	elseif message:is("BuildingBuilt") and self:isBuildingStarted() then
		self:setReady(true)
	end
end

function RE2A_BuildSawmill:onProcessMessage(message)
	if tutorial:getSawmillsCount() > 0 or self:isReady() then return end

	if not self:isActive() then
		if message:is("Update") and not self:isBuildingStarted() then
			self:updateTime(message)
			if self:getTime() > 15.0 then
				self:startHint()
			end
		elseif message:is("MaterialsBlock") and not self:isBuildingStarted() then
			self:startHint()
		end
	else
		if self:getState() == 0 then
			if message:is("Update") then
				-- Выделена площадка
				if tutorial:game():getSelected() and tutorial:isLargeFieldFree(tutorial:game():getSelected():id()) then
					self:pointAtAppropriatePoint(message)
					self:setState(1)
				end
			elseif self:isPassed(message) then
				avatar:hide()
			end
		elseif self:getState() == 1 then
			if message:is("Update") then
				if self:shouldPointAtFreeLargeField() then
					self:hideArrow()
					self:goToFinish()
				else
					self:pointAtAppropriatePoint(message)
				end
			end
		end
	end
end

function RE2A_BuildSawmillHint(message)
	RE2A_BuildSawmill:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Недостаточно дерева, но есть лесопилка
---------------------------------------------------------------------------------------------------
local RE2A_ProduceMoreWoodInSawmill = hint:create("RE2A_ProduceMoreWoodInSawmill")
function RE2A_ProduceMoreWoodInSawmill:setBuildingStarted(started) tutSetBool(self.hintId.."BuildingStarted", started) end
function RE2A_ProduceMoreWoodInSawmill:isBuildingStarted() return tutGetBool(self.hintId.."BuildingStarted") end
function RE2A_ProduceMoreWoodInSawmill:setSawmillReady(ready) tutSetBool(self.hintId.."SawmillReady", ready) end
function RE2A_ProduceMoreWoodInSawmill:isSawmillReady() return tutGetBool(self.hintId.."SawmillReady") end
function RE2A_ProduceMoreWoodInSawmill:setTextShown(shown) tutSetBool(self.hintId.."TextShown", shown) end
function RE2A_ProduceMoreWoodInSawmill:isTextShown() return tutGetBool(self.hintId.."TextShown") end
function RE2A_ProduceMoreWoodInSawmill:setTextVisible(visible) tutSetBool(self.hintId.."TextVisible", visible) end
function RE2A_ProduceMoreWoodInSawmill:isTextVisible() return tutGetBool(self.hintId.."TextVisible") end

function RE2A_ProduceMoreWoodInSawmill:hideAll()
	self:arrowHideAll()
	if self:isTextVisible() then
		avatar:hide()
	end
end
function RE2A_ProduceMoreWoodInSawmill:onInit()
	self:setTextShown(false)
	self:setSawmillReady(false)
end
function RE2A_ProduceMoreWoodInSawmill:onReset()
	self:setTextVisible(false)
end

function RE2A_ProduceMoreWoodInSawmill:onProcessMessageRegardlessLock(message)
	if message:is("Sawmill", "press") and not self:isBuildingStarted() then
		self:setBuildingStarted(true)
	elseif message:is("Cancel", "press") and self:isBuildingStarted() then
		self:setBuildingStarted(false)
	elseif message:is("BuildingBuilt") and self:isBuildingStarted() then
		self:setSawmillReady(true)
	end
end

function RE2A_ProduceMoreWoodInSawmill:onProcessMessage(message)
	if not self:isActive() and self:isBuildingStarted() then
		if message:is("MaterialsBlock") then
			self:setClickAccepted(true)
			self:decClickCounter()
			if self:getClickCounter() <= 0 then
				-- Количество кликов для вызова подсказки меняется
				if self:getClickCount() == 1 then
					self:setClickCount(2)
				elseif self:getClickCount() == 2 then
					self:setClickCount(3)
				end
				self:setClickCounter(self:getClickCount())
				self:start()
				self:arrowSave(tutorial:targetAllSawmills(0.5, IPoint(0, 50), 0.0))
				if not self:isTextShown() then
					avatar:show("RE2A_ProduceMaterialsInSawmillHint")
					avatar:setOffset(IPoint(10, 150), false)
					self:setTextVisible(true)
					self:setTextShown(true)
				else
					self:setTextVisible(false)
				end
				self:setTime(0.0)
			end
		elseif message:is("Update") then
			self:setClickAccepted(false)
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) then
				self:hideAll()
				self:goToFinish()
			elseif message:is("Update") then
				self:updateTime(message)
				if self:getTime() >= 5.0 then
					self:hideAll()
					self:goToFinish()
				end
			elseif message:is("SawmillOffer", "press") then
				self:hideAll()
				self:goToFinish()
			end
		end
	end	
end

function RE2A_ProduceMoreWoodInSawmillHint(message)
	RE2A_ProduceMoreWoodInSawmill:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- В течение 30 секунд игрок ни разу не собирал еду
---------------------------------------------------------------------------------------------------
local RE2A_DidNotGatherFoodFor30Seconds = hint:create("RE2A_DidNotGatherFoodFor30Seconds")
function RE2A_DidNotGatherFoodFor30Seconds:isFoodWasGathered() return tutGetBool(self.hintId.."FoodWasGathered") end
function RE2A_DidNotGatherFoodFor30Seconds:setFoodWasGathered(was) tutSetBool(self.hintId.."FoodWasGathered", was) end
function RE2A_DidNotGatherFoodFor30Seconds:onProcessMessageRegardlessLock(message)
	if message:is("Bush", "press") then
		self:setFoodWasGathered(true)
	end
end

function RE2A_DidNotGatherFoodFor30Seconds:onProcessMessage(message)
	if not self:isActive() and not self:isFoodWasGathered() then
		if message:is("Update") then
			self:updateTime(message)
			if self:getTime() >= 30.0 then
				self:start()
				self:arrowSave(tutorial:targetAllBushes(0.5, IPoint(10, 40), 0.0))
				avatar:show("RE2_LookItIsFood")
				avatar:setOffset(IPoint(10, 150), false)
			end
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) then
				avatar:hide()
				self:arrowHideAll()
				self:goToFinish()
				self:setShown(true)
			end
		end
	end
end

function RE2A_DidNotGatherFoodFor30SecondsHint(message)
	RE2A_DidNotGatherFoodFor30Seconds:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Недостаточно еды - нужно собирать ее с кустов и стрелка на кусты (любые)
---------------------------------------------------------------------------------------------------
local RE2A_GatherFoodFromBushes = hint:create("RE2A_GatherFoodFromBushes")
function RE2A_GatherFoodFromBushes:setTextShown(shown) tutSetBool(self.hintId.."TextShown", shown) end
function RE2A_GatherFoodFromBushes:isTextShown() return tutGetBool(self.hintId.."TextShown") end
function RE2A_GatherFoodFromBushes:setTextVisible(visible) tutSetBool(self.hintId.."TextVisible", visible) end
function RE2A_GatherFoodFromBushes:isTextVisible() return tutGetBool(self.hintId.."TextVisible") end
function RE2A_GatherFoodFromBushes:hideAll()
	self:arrowHideAll()
	if self:isTextVisible() then
		avatar:hide()
	end
end
function RE2A_GatherFoodFromBushes:onInit()
	self:setTextShown(false)
	--self:arrowSave(self:arrowAdd(IPoint(0, 0), 270))
end
function RE2A_GatherFoodFromBushes:onReset()
	self:setTextVisible(false)
end
function RE2A_GatherFoodFromBushes:getArrow()
	if self:getArrowIndex() == 0 then
		self:arrowSave(self:arrowAdd(IPoint(0, 0), 270))
	end

	return self:arrowGet(0)
end
function RE2A_GatherFoodFromBushes:targetBushGroup()
	PrintDebug("targetBushGroup\n")
	local groupNearBase = false
	local groupLeftBottom = false
	local groupRightUp = false
	local theId = nil

	local nearBase = { 68323, 68321, 68313 }
	local leftBottom = { 74853, 70547, 76981 }
	local rightUp = { 59519, 52523, 68319, 59730, 68309 }
	for k, v in ipairs(nearBase) do
		if not groupNearBase and tutorial:bushHasFoodOnFieldWithId(v) then
			theId = v
			groupNearBase = true
		end
	end

	if not groupNearBase then
		for k, v in ipairs(leftBottom) do
			if not groupLeftBottom and tutorial:bushHasFoodOnFieldWithId(v) then
				theId = v
				groupLeftBottom = true
			end
		end

		if not groupLeftBottom then
			for k, v in ipairs(rightUp) do
				if not groupRightUp and tutorial:bushHasFoodOnFieldWithId(v) then
					theId = v
					groupRightUp = true
				end
			end
		end

	end

	if theId ~= nil then
		local field = tutorial:game():getObject(theId)
		local pos = field:getScreenPosition()
		local arrow = self:getArrow()
		arrow:setPosition(pos.x + 10, pos.y + 25)
		self:arrowShow(0, 0.25)
	end
end

function RE2A_GatherFoodFromBushes:onProcessMessage(message)
	-- Подсказка не активна
	if not self:isActive() then
		if message:is("FoodBlock") and tutorial:getAllBushesWithFoodCount() > 0 then
			self:setClickAccepted(true)
			-- Обновляем количество кликов
			self:decClickCounter()
			-- Пора показывать подсказку
			if self:getClickCounter() <= 0 then
				-- Количество кликов для вызова подсказки меняется
				if self:getClickCount() == 1 then
					self:setClickCount(2)
				elseif self:getClickCount() == 2 then
					self:setClickCount(3)
				end
				self:setClickCounter(self:getClickCount())
				self:start()
				self:targetBushGroup()
				self:setState(0)
				if not self:isTextShown() then
					avatar:show("RE2A_CollectFoodFromBushesHint")
					avatar:setOffset(IPoint(10, 150), false)
					self:setTextVisible(true)
					self:setTextShown(true)
				else
					self:setTextVisible(false)
				end

				self:setTime(0.0)
			end
		elseif message:is("Update") then
			self:setClickAccepted(false)
		end
	else
		-- Стрелка указывает на базу
		if self:getState() == 0 then
			if message:is("TutorialOk", "press") or message:is("Bush", "click") then
				self:hideAll()
				self:goToFinish()
			end
		end
	end	
end

function RE2A_GatherFoodFromBushesHint(message)
	RE2A_GatherFoodFromBushes:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Если все таски выполнены кроме сбора еды со всех кустов - стрелка на куст
---------------------------------------------------------------------------------------------------
local RE2A_01_03_AllTasksAreReadyButGatherFood = hint:create("RE2A_01_03_AllTasksAreReadyButGatherFood")
function RE2A_01_03_AllTasksAreReadyButGatherFood:onProcessMessageRegardlessLock(message)
	if tutorial:isTaskReady(0) and tutorial:isTaskReady(1) and not tutorial:isTaskReady(2) then
		if message:is("Bush", "press") then
			self:setTime(0.0)
		end
		if not self:isActive() then
			if message:is("Update") then
				self:updateTime(message)
				if self:getTime() >= 10.0 then
					tutorial:targetAllBushes(0.5, IPoint(10, 40), 0.0)
					self:setActive(true)
				end
			end
		else
			if message:is("Bush", "press") then
				self:setTime(0.0)
				self:arrowHideAll()
				self:setActive(false)
			end
		end
	end
end

function RE2A_01_03_AllTasksAreReadyButGatherFoodHint(message)
	RE2A_01_03_AllTasksAreReadyButGatherFood:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Если все таски выполнены, кроме постройки апгрейженных домов - подскажем, что их надо сделать
---------------------------------------------------------------------------------------------------
local RE2A_01_03_AllTasksAreReadyButUpgradedCabins = hint:create("RE2A_01_03_AllTasksAreReadyButUpgradedCabins")
--function RE2A_01_03_AllTasksAreReadyButUpgradedCabins:setTextShown(shown) tutSetBool(self.hintId.."TextShown", shown) end
--function RE2A_01_03_AllTasksAreReadyButUpgradedCabins:isTextShown() return tutGetBool(self.hintId.."TextShown") end
--function RE2A_01_03_AllTasksAreReadyButUpgradedCabins:setTextVisible(visible) tutSetBool(self.hintId.."TextVisible", visible) end
--function RE2A_01_03_AllTasksAreReadyButUpgradedCabins:isTextVisible() return tutGetBool(self.hintId.."TextVisible") end
function RE2A_01_03_AllTasksAreReadyButUpgradedCabins:hideAll()
	self:arrowHideAll()
--	if self:isTextVisible() then
		avatar:hide()
--	end
end
function RE2A_01_03_AllTasksAreReadyButUpgradedCabins:onInit()
--	self:setTextShown(false)
end
function RE2A_01_03_AllTasksAreReadyButUpgradedCabins:onReset()
--	self:setTextVisible(false)
end

function RE2A_01_03_AllTasksAreReadyButUpgradedCabins:onProcessMessage(message)
	if tutorial:isTaskReady(0) and tutorial:isTaskReady(2) and not tutorial:isTaskReady(1) then
		if not self:isActive() then
			if message:is("House1", "press") or message:is("Upgrade", "press") then
				self:setTime(0.0)
			end
			if message:is("Update") then
				self:updateTime(message)
				if self:getTime() >= 15.0 then
					-- Есть непроапгрейженные дома (Первая ситуация)
					if tutorial:getHousesCountP(1, 0) > 0 then
						self:start()
						tutorial:targetAllHouses1WithNoUpgrade("RE2A_01_03_AllTasksAreReadyButUpgradedCabins_Arrow", 0.5, IPoint(0, 60), 0.5)
						avatar:show("RE2_UpgradeHousesHint")
						avatar:setOffset(IPoint(900, 400), true)
						self:setState(0)
					-- Есть пустые площадки (Вторая ситуация)
					elseif tutorial:hasFreeLargeFields() then
						self:start()
						self:arrowSave(self:arrowAdd(IPoint(690, 690), 45))
						avatar:setOffset(IPoint(10, 150), false)
						self:arrowShow(0, 0.25)
						avatar:show("RE2A_01_03_AllTasksAreReadyButUpgradedCabins_BuildMoreUpgradedCabins")
						self:setState(1)
					-- Лесопилок больше 1 (Третья ситуация)
					elseif tutorial:getSawmillsCount() > 1 then
						self:start()
						self:arrowSave(self:arrowAdd(IPoint(690, 690), 45))
						self:arrowShow(0, 0.25)
						avatar:show("RE2A_01_03_AllTasksAreReadyButUpgradedCabins_BuildMoreCabins")
						avatar:setOffset(IPoint(10, 150), false)
						self:setState(2)
					end
				end
			end
		else
			-- Первая ситуация
			if self:getState() == 0 then
				if self:isPassed(message) then
					self:hideAll()
					self:goToFinish()
				end
			-- Вторая ситуация
			elseif self:getState() == 1 then
				if self:isPassed(message) then
					self:hideAll()
					DialogResumeGame()
					self:setState(101)
					tutorial:targetAnySingleFreeLargeField("RE2A_01_03_AllTasksAreReadyButUpgradedCabins_Arrow", 0.5, IPoint(0, 40), 0.5)
					self:setTime(0.0)
				end
			elseif self:getState() == 101 then
				if message:is("Update") then
					self:updateTime(message)
					if self:getTime() >= 7.0 or tutorial:isFreeLargeFieldSelected() then
						self:hideAll()
						self:goToFinish()
					end
				end
			-- Третья ситуация
			elseif self:getState() == 2 then
				if self:isPassed(message) then
					self:arrowHideAll()
					DialogResumeGame()
					self:setState(201)
					self:arrowSave(tutorial:targetAnySawmillExceptForOnField(70246, 0.5, IPoint(0, 40), 0.5))
					avatar:switchText("RE2A_01_03_AllTasksAreReadyButUpgradedCabins_DestroySawmillBuildHouse1")
				end
			elseif self:getState() == 201 then
				if message:is("Update") then
					if tutorial:isSawmillInterface() then
						self:hideAll()
						arrowId = tutorial:addArrow()
						tutorial:getArrow(arrowId):setPosition(950, 100)
						tutorial:getArrow(arrowId):setAngle(270)
						tutorial:getArrow(arrowId):setIgnoreContext(true)
						tutorial:getArrow(arrowId):show(0.5)
						self:setState(202)
					end
				end
			elseif self:getState() == 202 then
				if self:isPassed(message) then
					self:hideAll()
					self:goToFinish()
				end
			end
		end
	end
end

function RE2A_01_03_AllTasksAreReadyButUpgradedCabinsHint(message)
	RE2A_01_03_AllTasksAreReadyButUpgradedCabins:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- В течение 30 секунд не кликали в пирсы
---------------------------------------------------------------------------------------------------
local RE2A_01_04_NoPierWasSelectedFor30Seconds = hint:create("RE2A_01_04_NoPierWasSelectedFor30Seconds")
function RE2A_01_04_NoPierWasSelectedFor30Seconds:onProcessMessageRegardlessLock(message)
	if message:is("Update") then
		if tutorial:getSelectedBuildingType() == self.pierType then
			self:setShown(true)
		end
	end
end
function RE2A_01_04_NoPierWasSelectedFor30Seconds:onProcessMessage(message)
	if not self:isActive() then
		if message:is("Update") then
			self:updateTime(message)
			if not self:isShown() and self:getTime() > 30 then
				local arrowId = self:arrowAdd(IPoint(915, 380), 270)
				tutorial:getArrow(arrowId):show(0.25)
				self:start()
				self:setTime(0.0)
			end
		end	
	else
		if self:getState() == 0 then
			if message:is("Update") then
				self:updateTime(message)
			end
			if tutorial:getSelectedBuildingType() == self.pierType or self:getTime() >= 20.0 then
				self:arrowHideAll()
				self:setShown(true)
				self:goToFinish()
			end
		end
	end
end

function RE2A_01_04_NoPierWasSelectedFor30Seconds:onInit()
	RE2A_01_04_NoPierWasSelectedFor30Seconds["pierType"] = tutorial:game():convertType("Pier")
end

function RE2A_01_04_NoPierWasSelectedFor30SecondsHint(message)
	RE2A_01_04_NoPierWasSelectedFor30Seconds:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- В течение минуты не чинился ни один пирс
---------------------------------------------------------------------------------------------------
local RE2A_01_04_NoPierWasRepairedFor60Seconds = hint:create("RE2A_01_04_NoPierWasRepairedFor60Seconds")
function RE2A_01_04_NoPierWasRepairedFor60Seconds:onProcessMessageRegardlessLock(message)
	if message:is("PierRepair") then
		self:setShown(true)
	end	
end
function RE2A_01_04_NoPierWasRepairedFor60Seconds:hideAll()
	self:arrowHideAll()
	RE2A_01_localCitizen:hide()
	self:setShown(true)
	self:goToFinish()
end
function RE2A_01_04_NoPierWasRepairedFor60Seconds:onProcessMessage(message)
	if not self:isActive() then
		if message:is("PierRepair") then
			self:setShown(true)
		elseif message:is("Update") then
			self:updateTime(message)
			if not self:isShown() and self:getTime() >= 60.0 then
				RE2A_01_localCitizen:setOffset(LeftAvatarPosition, false)
				RE2A_01_localCitizen:show("RE2A_01_04_RepairPiersToStartFishing")
				local arrowId = self:arrowAdd(IPoint(915, 380), 270)
				tutorial:getArrow(arrowId):show(0.25)
				self:setTime(0.0)
				self:start()
			end
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) then
				self:hideAll()
			elseif message:is("Update") then
				self:updateTime(message)
				if self:getTime() >= 3.0 and tutorial:getSelectedBuildingType() == self.pierType then
					self:hideAll()
				end
			end
		end
	end
end

function RE2A_01_04_NoPierWasRepairedFor60Seconds:onInit()
	RE2A_01_04_NoPierWasSelectedFor30Seconds["pierType"] = tutorial:game():convertType("Pier")
end

function RE2A_01_04_NoPierWasRepairedFor60SecondsHint(message)
	RE2A_01_04_NoPierWasRepairedFor60Seconds:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Вот еще не восстановленный пирс
---------------------------------------------------------------------------------------------------
local RE2A_01_04_ThereIsMoreBrokenPiers = hint:create("RE2A_01_04_ThereIsMoreBrokenPiers")
function RE2A_01_04_ThereIsMoreBrokenPiers:setTextShown(shown) tutSetBool(self.hintId.."TextShown", shown) end
function RE2A_01_04_ThereIsMoreBrokenPiers:isTextShown() return tutGetBool(self.hintId.."TextShown") end
function RE2A_01_04_ThereIsMoreBrokenPiers:setTextVisible(visible) tutSetBool(self.hintId.."TextVisible", visible) end
function RE2A_01_04_ThereIsMoreBrokenPiers:isTextVisible() return tutGetBool(self.hintId.."TextVisible") end
function RE2A_01_04_ThereIsMoreBrokenPiers:setLastPierRepairTime(time) tutSetFloat(self.hintId.."LastPierRepairTime", time) end
function RE2A_01_04_ThereIsMoreBrokenPiers:getLastPierRepairTime() return tutGetFloat(self.hintId.."LastPierRepairTime") end
function RE2A_01_04_ThereIsMoreBrokenPiers:hideAll()
	self:arrowHideAll()
	if self:isTextVisible() then
		RE2A_01_localCitizen:hide()
	end
end
function RE2A_01_04_ThereIsMoreBrokenPiers:onInit()
	self:setTextShown(false)
end
function RE2A_01_04_ThereIsMoreBrokenPiers:onReset()
	self:setTextVisible(false)
	self:setLastPierRepairTime(0.0)
end
function FilterBroken(building)
	if building:isBroken() and building:getState() ~= B_REPAIR then
		return true
	else
		return false
	end
end

function RE2A_01_04_ThereIsMoreBrokenPiers:onProcessMessage(message)
	if not self:isActive() then
		if message:is("Update") then
			self:updateTime(message)
			self:setLastPierRepairTime(self:getLastPierRepairTime() + message:getVariables():getFloat("TimeDelta"))

			local woodCount = tutorial:game():getWoodCount()
			local restoredPierCount = tutorial:getRestoredPierCount()
			local brokenPierCount = tutorial:getBrokenPierCount()
			local time = self:getTime()
			local lastPierRepairedTime = self:getLastPierRepairTime()

			--PrintDebug("woodCount = "..tostring(woodCount)..", restoredPierCount = "..tostring(restoredPierCount)..", brokenPierCount = "..tostring(brokenPierCount))
			--PrintDebug(", time = "..tostring(time)..", lastPierRepairedTime = "..tostring(lastPierRepairedTime).."\n")
			if woodCount > 50 and restoredPierCount > 3 and brokenPierCount > 0 and 
				(time > 120.0 or self:isTextShown()) and lastPierRepairedTime > 20.0 then

				self:start()
				if not self:isTextShown() then
					RE2A_01_localCitizen:setOffset(IPoint(200, 350), false)
					RE2A_01_localCitizen:show("RE2A_01_04_ThereIsMoreBrokenPiers")
					self:setTextVisible(true)
					self:setTextShown(true)
				else
					self:setTextVisible(false)
				end
				local piers = tutorial:filter(tutorial:collectBuildingsWithType("Pier"), "FilterBroken")
				tutorial:targetAny(piers, "RE2A_01_04_ThereIsMoreBrokenPiers", 0.5, IPoint(15, 10), 0.5)
			end
		elseif message:is("PierRepair") then
			self:setLastPierRepairTime(0.0)
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) or message:is("PierRepair") then
				self:hideAll()
				self:goToFinish()
			end
		end
	end
end

function RE2A_01_04_ThereIsMoreBrokenPiersHint(message)
	RE2A_01_04_ThereIsMoreBrokenPiers:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- В течение 20 секунд у игрока не было свободных рабочих
---------------------------------------------------------------------------------------------------
function FilterOccupied(pier)
	if not pier:isBroken() and pier:getState() == B_SQUESTUPGRADE and pier:getWorkingWorkers() == pier:getNeededWorkers() then
		return true
	else
		return false
	end
end
function selectedBuildingIsPierInFishingState()
	local pierIsSelected = tutorial:game():getSelected() and tutorial:getSelectedBuildingType() == tutorial:game():convertType("Pier")
	if pierIsSelected then
		local pier = tutorial:game():getSelected():getBuilding()
		if pier and pier:getState() == B_SQUESTUPGRADE then
			return true
		end
	end

	return false
end

function selectedBuildingIsPier()
	local pierIsSelected = tutorial:game():getSelected() and tutorial:getSelectedBuildingType() == tutorial:game():convertType("Pier")
	return pierIsSelected
end

local RE2A_01_04_NoFreeWorkersFor20Seconds = hint:create("RE2A_01_04_NoFreeWorkersFor20Seconds")
function RE2A_01_04_NoFreeWorkersFor20Seconds:setPierWasSelected(was) tutSetBool(self.hintId.."PierWasSelected", was) end
function RE2A_01_04_NoFreeWorkersFor20Seconds:isPierWasSelected() return tutGetBool(self.hintId.."PierWasSelected") end
function RE2A_01_04_NoFreeWorkersFor20Seconds:onProcessMessage(message)
	if not self:isActive() then
		if message:is("Update") then
			local totalWorkersCount = tutorial:game():getWorkersCount()
			local freeWorkersCount = tutorial:getFreeWorkersCount()
			if freeWorkersCount == 0 and totalWorkersCount < 7 then
				self:updateTime(message)
				if self:getTime() >= 25.0 then
					local occupiedPiers = tutorial:filter(tutorial:collectBuildingsWithType("Pier"), "FilterOccupied")
					local occupiedPiersCount = tutorial:count(occupiedPiers)
					
					if occupiedPiersCount > 0 then
						self:start()
						SedrikFishing:show("RE2A_01_04_NoFreeWorkersFor20Seconds")
						SedrikFishing:setOffset(IPoint(200, 350), false)

						if selectedBuildingIsPierInFishingState() then
							local arrowId = self:arrowAdd(IPoint(950, 100), 270)
							tutorial:getArrow(arrowId):show(0.25)
							self:setState(1)
						else
							tutorial:targetAny(occupiedPiers, "RE2A_01_04_NoFreeWorkersFor20Seconds", 0.5, IPoint(15, 30), 0.5)
							self:setState(0)
						end

						if selectedBuildingIsPier() then
							self:setPierWasSelected(true)
						else
							self:setPierWasSelected(false)
						end
					end
				end
			else
				self:setTime(0.0)
			end
		end
	else
		if self:getState() == 0 then
			if message:is("Update") then
				if selectedBuildingIsPierInFishingState() and not self:isPierWasSelected() then
					self:arrowHideAll()
					SedrikFishing:hide()
					DialogResumeGame()

					local arrowId = self:arrowAdd(IPoint(950, 100), 270)
					tutorial:getArrow(arrowId):show(0.25)
					self:setState(1)
				else
					if selectedBuildingIsPierInFishingState() then
						self:arrowHideAll()
						local arrowId = self:arrowAdd(IPoint(950, 100), 270)
						tutorial:getArrow(arrowId):show(0.25)
						self:setState(1)
					end
				end
			elseif self:isPassed(message) then
				self:arrowHideAll()
				SedrikFishing:hide()
				DialogResumeGame()
				
				if selectedBuildingIsPierInFishingState() then
					local arrowId = self:arrowAdd(IPoint(950, 100), 270)
					tutorial:getArrow(arrowId):show(0.25)
				end

				self:setState(1)
			end
		elseif self:getState() == 1 then
			if message:is("PierDismiss") then
				self:arrowHideAll()
				SedrikFishing:hide()
				self:goToFinish()
				self:setShown(true)
			elseif message:is("Update") then
				if selectedBuildingIsPierInFishingState() then
					local arrowId = self:arrowAdd(IPoint(950, 100), 270)
					tutorial:getArrow(arrowId):show(0.25)
					self:setState(2)
				elseif not tutorial:game():getSelected() then
					self:arrowHideAll()
					SedrikFishing:hide()
					self:goToFinish()
					self:setShown(true)
				end
			end
		elseif self:getState() == 2 then
			if message:is("PierDismiss") then
				self:arrowHideAll()
				SedrikFishing:hide()
				self:goToFinish()
				self:setShown(true)
			elseif message:is("Update") then
				if not tutorial:game():getSelected() then
					self:arrowHideAll()
					SedrikFishing:hide()
					self:goToFinish()
					self:setShown(true)
				end
			end
		end
	end
end
function RE2A_01_04_NoFreeWorkersFor20SecondsHint(message)
	RE2A_01_04_NoFreeWorkersFor20Seconds:processMessage(message)
end
---------------------------------------------------------------------------------------------------
-- Подсказка на лут, который вот-вот пропадет
---------------------------------------------------------------------------------------------------
function RE2A_FishLootLaysTooLongHint(message)
	-- Показываем стрелку на лут, который вот-вот забликует
	if message:is("LootLaysTooLong") then
		if not IsLocked() then
			tutorial:targetLoot(message:getIntegerParam(), "RE2A_FishLootLaysTooLongHint_Arrow", 0.5, IPoint(0, 10), 0.0)
			tutorial:setObjectsAllowType(allowPass)
			tutorial:variables():setBool("TutorialArrowAlphaBind", true)
			tutorial:variables():setBool("TutorialArrowsNoBind", true);
			tutorial:variables():setFloat("TutorialShowDelayTime", -1.0)
			tutorial:show(0.25)
		end
	-- Лут собран или прощелкан
	elseif message:is("LootGathered") then
		tutorial:hideBindedArrow("RE2A_FishLootLaysTooLongHint_Arrow", message:getIntegerParam(), 0.25)
	end
end

local RE2A_02_localCitizen = avatar:create("TropicGirl")
---------------------------------------------------------------------------------------------------
-- Клики в болото
---------------------------------------------------------------------------------------------------
local RE2A_02_01_SwampClick = hint:create("RE2A_02_01_SwampClick")
function RE2A_02_01_SwampClick:isSeduceStarted() return tutGetBool(self.hintId.."SeduceStarted") end
function RE2A_02_01_SwampClick:setSeduceStarted(started) tutSetBool(self.hintId.."SeduceStarted", started) end
function RE2A_02_01_SwampClick:setTextShown(shown) tutSetBool(self.hintId.."TextShown", shown) end
function RE2A_02_01_SwampClick:isTextShown() return tutGetBool(self.hintId.."TextShown") end

function RE2A_02_01_SwampClick:onProcessMessageRegardlessLock(message)
	if message:is("ElephantSeduce", "press") then
		self:setSeduceStarted(true)
	end
end
function RE2A_02_01_SwampClick:hideAll()
	self:arrowHideAll()
	RE2A_02_localCitizen:hide()
	self:goToFinish()
end

function RE2A_02_01_SwampClick:onProcessMessage(message)
	if not self:isActive() then
		if message:is("SwampClicked") and not self:isSeduceStarted() then
			self:decClickCounter()
			if self:getClickCounter() <= 0 then
				local showText = false
				if self:getClickCount() == 2 then
					showText = true
				end
				self:setClickCount(2)

				self:setClickCounter(self:getClickCount())
				self:start()
				tutorial:targetAll(tutorial:collectAllBuildingsWithType("Elephant"), "RE2A_02_01_SwampClick", 0.5, IPoint(0, 50), 0.5)
				if showText and not self:isSeduceStarted() and not self:isTextShown() then
					RE2A_02_localCitizen:setOffset(IPoint(265, 445), false)
					RE2A_02_localCitizen:show("RE2A_02_01_SeduceElephant")
					self:setTextShown(true)
					self:setState(1)
				else
					self:setState(0)
				end
				self:setTime(0.0)
			end
		end
	else
		if self:getState() == 0 then
			if message:is("Update") then
				self:updateTime(message)

				local elephant = tutorial:getElephant()
				if elephant and elephant:getState() ~= B_NONE and self:getTime() >= 2.0 then
					self:hideAll()
				end

				if self:getTime() >= 7.0 then
					self:hideAll()
				end
			elseif self:isPassed(message) then
				avatar:hide()
			elseif (message:is("SwampClicked") or message:is("ElephantSeduce", "press")) and self:getTime() >= 2.0 then
				self:hideAll()
			elseif message:is("ElephantSeduced") then
				self:hideAll()
			end
		elseif self:getState() == 1 then
			if self:isPassed(message) or (message:is("SwampClicked") and self:getTime() >= 2.0) then
				self:hideAll()
			elseif message:is("ElephantSeduced") then
				self:arrowHideAll()
			elseif message:is("Update") then
				self:updateTime(message)
				local elephant = tutorial:getElephant()
				if elephant and elephant:getState() ~= B_NONE then
					if self:getTime() >= 2.0 then
						self:arrowHideAll()
					end

					if self:getTime() >= 7.0 then
						self:hideAll()
					end
				end
			end
		end
	end
end

function RE2A_02_01_SwampClickHint(message)
	RE2A_02_01_SwampClick:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Все площадки застроены, но таски не выполнены - игрок чего-то напутал
---------------------------------------------------------------------------------------------------
local RE2A_02_01_GamerProbablyConfusedHoused = hint:create("RE2A_02_01_GamerProbablyConfusedHoused")
function RE2A_02_01_GamerProbablyConfusedHoused:onProcessMessage(message)
	if not self:isActive() then
		if message:is("Update") then
			local rightNumberOfHouses = (tutorial:game():getHouses1Count() + tutorial:game():getHouses2Count()) >= 7
			if not tutorial:hasFreeLargeFields() and rightNumberOfHouses then
				self:updateTime(message)
				if self:getTime() >= 20.0 and (not tutorial:isTaskReady(0) or not tutorial:isTaskReady(1)) then
					self:start()
					avatar:show("RE2A_02_01_GamerProbablyConfusedHouses")
					avatar:setOffset(IPoint(10, 150), false)
				end
			end
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) then
				if tutorial:game():getHouses1Count() < 3 then
					avatar:switchText("RE2A_02_01_BuildHouses1")
				else
					avatar:switchText("RE2A_02_01_BuildHouses2")
				end
				self:setState(1)
			end
		elseif self:getState() == 1 then
			if self:isPassed(message) then
				avatar:hide()
				self:goToFinish()
				self:setTime(0.0)
				self:setShown(true)
			end
		end
	end
end
function RE2A_02_01_GamerProbablyConfusedHousedHint(message)
	RE2A_02_01_GamerProbablyConfusedHoused:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Каждый второй клик по болоту - стрелка в слона
---------------------------------------------------------------------------------------------------
local RE2A_PointAtElephantEveryThirdClickAtSwamp = hint:create("RE2A_PointAtElephantEveryThirdClickAtSwamp")
function RE2A_PointAtElephantEveryThirdClickAtSwamp:onInit()
	self:setClickCount(3)
end
function RE2A_PointAtElephantEveryThirdClickAtSwamp:onProcessMessage(message)
	if not self:isActive() then
		if message:is("SwampClicked") then
			self:decClickCounter()
			if self:getClickCounter() <= 0 then
				self:setClickCount(2)
				self:setClickCounter(self:getClickCount())
				self:start()
				tutorial:targetAll(tutorial:collectAllBuildingsWithType("Elephant"), "RE2A_02_01_SwampClick", 0.5, IPoint(0, 50), 0.5)
				self:setTime(0.0)
			end
		elseif message:is("ElephantSeduce", "press") then
			self:setShown(true)
		end
	else
		if self:getState() == 0 then
			if message:is("Update") then
				self:updateTime(message)
				if self:getTime() >= 7.0 then
					self:arrowHideAll()
					self:goToFinish()
				end
			elseif message:is("ElephantSeduce", "press") then
				self:arrowHideAll()
				self:goToFinish()
			end
		end
	end
end

function RE2A_PointAtElephantEveryThirdClickAtSwampHint(message)
	RE2A_PointAtElephantEveryThirdClickAtSwamp:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Не начали восстанавливать ни одну золотую шахту
---------------------------------------------------------------------------------------------------
local RE2A_GoldMineWasNotRepairedFor60Seconds = hint:create("RE2A_GoldMineWasNotRepairedFor60Seconds")
function RE2A_GoldMineWasNotRepairedFor60Seconds:onProcessMessage(message)
	if not self:isActive() then
		if message:is("Update") then
			self:updateTime(message)
			if self:getTime() >= 60.0 and not self:isShown() then
				self:start()
				RE2A_02_localCitizen:setOffset(LeftAvatarPosition, false)
				RE2A_02_localCitizen:show("RE2A_RestoreGoldMineHint")
				local arrowId = self:arrowAdd(IPoint(700, 610), 270)
				tutorial:getArrow(arrowId):show(0.25)
			end
		elseif message:is("GoldMineRepair") then
			self:setShown(true)
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) then
				RE2A_02_localCitizen:hide()
				self:arrowHideAll()
				self:goToFinish()
			end
		end
	end
end
function RE2A_GoldMineWasNotRepairedFor60SecondsHint(message)
	RE2A_GoldMineWasNotRepairedFor60Seconds:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- не начали работу в шахте после восстановления в течение 15 секунд
---------------------------------------------------------------------------------------------------
local leftGoldMineId = 137321
local rightGoldMineId = 137313
local RE2A_02_02_SendWorkersToGoldMineLeft = hint:create("RE2A_02_02_SendWorkersToGoldMineLeft")
function RE2A_02_02_SendWorkersToGoldMineLeft:isReady() return tutGetBool(self.hintId.."Ready") end
function RE2A_02_02_SendWorkersToGoldMineLeft:setReady(ready) tutSetBool(self.hintId.."Ready", ready) end
function RE2A_02_02_SendWorkersToGoldMineLeft:onProcessMessage(message)
	--local id = 137321
	if not self:isActive() then
		if message:is("BuildingRepaired") then
			if message:getIntegerParam() == leftGoldMineId then
				self:setReady(true)
			end
		elseif self:isReady() and tutorial:getGoldMineOrderWorkers(leftGoldMineId) == 0 and message:is("Update") then
			self:updateTime(message)
			local waitTime = 15.0
			if tutorial:getGoldMineOrderWorkers(rightGoldMineId) == 2 then
				waitTime = 30.0
			end
			if self:getTime() >= waitTime then
				self:start()
				RE2A_02_localCitizen:setOffset(LeftAvatarPosition, false)
				RE2A_02_localCitizen:show("RE2A_SendWorkersToGoldMineHint")
				tutorial:getArrow(self:arrowAdd(IPoint(700, 610), 270)):show(0.25)
			end
		elseif message:is("GoldMineLeave", "press") then
			if message:getIntegerParam() == leftGoldMineId then
				self:setReady(false)
			end
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) or message:is("GoldMine") then
				RE2A_02_localCitizen:hide()
				self:arrowHideAll()
				self:setShown(true)
				self:goToFinish()
			end
		end
	end
end
function RE2A_02_02_SendWorkersToGoldMineLeftHint(message)
	RE2A_02_02_SendWorkersToGoldMineLeft:processMessage(message)
end

local RE2A_02_02_SendWorkersToGoldMineRight = hint:create("RE2A_02_02_SendWorkersToGoldMineRight")
function RE2A_02_02_SendWorkersToGoldMineRight:isReady() return tutGetBool(self.hintId.."Ready") end
function RE2A_02_02_SendWorkersToGoldMineRight:setReady(ready) tutSetBool(self.hintId.."Ready", ready) end
function RE2A_02_02_SendWorkersToGoldMineRight:onProcessMessage(message)
	--local id = 137313
	if not self:isActive() then
		if message:is("BuildingRepaired") then
			if message:getIntegerParam() == rightGoldMineId then
				self:setReady(true)
			end
		elseif self:isReady() and tutorial:getGoldMineOrderWorkers(rightGoldMineId) == 0 and message:is("Update") then
			self:updateTime(message)
			local waitTime = 15.0
			if tutorial:getGoldMineOrderWorkers(leftGoldMineId) == 2 then
				waitTime = 30.0
			end
			if self:getTime() >= waitTime then
				self:start()
				RE2A_02_localCitizen:setOffset(LeftAvatarPosition, false)
				RE2A_02_localCitizen:show("RE2A_SendWorkersToGoldMineHint")
				tutorial:getArrow(self:arrowAdd(IPoint(930, 600), 270)):show(0.25)
			end
		elseif message:is("GoldMineLeave", "press") then
			if message:getIntegerParam() == rightGoldMineId then
				self:setReady(false)
			end
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) or message:is("GoldMine") then
				RE2A_02_localCitizen:hide()
				self:arrowHideAll()
				self:setShown(true)
				self:goToFinish()
			end
		end
	end
end
function RE2A_02_02_SendWorkersToGoldMineRightHint(message)
	RE2A_02_02_SendWorkersToGoldMineRight:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- 
---------------------------------------------------------------------------------------------------
local RE2A_02_02_SendMoreWorkersToGoldMine = hint:create("RE2A_02_02_SendMoreWorkersToGoldMine")
function RE2A_02_02_SendMoreWorkersToGoldMine:isReady() return tutGetBool(self.hintId.."Ready") end
function RE2A_02_02_SendMoreWorkersToGoldMine:setReady(ready) tutSetBool(self.hintId.."Ready", ready) end
function RE2A_02_02_SendMoreWorkersToGoldMine:onProcessMessage(message)
	if not self:isActive() then
		if message:is("GoldMineWorkers") then
			local id = message:getIntegerParam()
			local paramName = "RE2A_02_02_SendMoreWorkersToGoldMine"..tostring(id)
			if not tutGetBool(paramName) then
				tutSetBool(paramName, true)
				self:start()
				RE2A_02_localCitizen:setOffset(LeftAvatarPosition, false)
				RE2A_02_localCitizen:show("RE2A_SendMoreWorkersToGoldMineHint")

				goldMine = tutorial:game():getObject(id)
				pos = goldMine:getScreenPosition()
				tutorial:getArrow(self:arrowAdd(pos, 270)):show(0.25)
			end
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) then
				RE2A_02_localCitizen:hide()
				self:arrowHideAll()
				self:goToFinish()
				self:setShown(true)
			end
		end

	end
end
function RE2A_02_02_SendMoreWorkersToGoldMineHint(message)
	RE2A_02_02_SendMoreWorkersToGoldMine:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Рабочий в лесничестве работает в течение 20 секунд один
---------------------------------------------------------------------------------------------------
local RE2A_SendMoreWorkersToForestArea = hint:create("RE2A_SendMoreWorkersToForestArea")
function RE2A_SendMoreWorkersToForestArea:onProcessMessage(message)
	if not self:isActive() then
		if message:is("ForestAreaWorkers") then
			self:start()
			RE2A_02_localCitizen:setOffset(LeftAvatarPosition, false)
			RE2A_02_localCitizen:show("RE2_ForestAreaWorkersHint_01")

			local id = message:getIntegerParam()
			PrintDebug("id = "..tostring(id).."\n")
			forestArea = tutorial:game():getObject(id)
			areaPos = forestArea:getScreenPosition()
			if id == 143966 then
				areaPos = IPoint(areaPos.x + 100, areaPos.y + 25)
				tutorial:getArrow(self:arrowAdd(areaPos, 225)):show(0.25)
			else
				tutorial:getArrow(self:arrowAdd(areaPos, 270)):show(0.25)
			end
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) then
				RE2A_02_localCitizen:hide()
				self:arrowHideAll()
				self:setShown(true)
				self:goToFinish()
			end
		end
	end
end
function RE2A_SendMoreWorkersToForestAreaHint(message)
	RE2A_SendMoreWorkersToForestArea:processMessage(message)
end

local RE2A_03_localCitizen = avatar:create("FeatherGirl")
---------------------------------------------------------------------------------------------------
-- В течение 10 секунда не отправили рабочего добывать клад
---------------------------------------------------------------------------------------------------
local RE2A_TreasureWasNotDiggedFor10Seconds = hint:create("RE2A_TreasureWasNotDiggedFor10Seconds")
function RE2A_TreasureWasNotDiggedFor10Seconds:onProcessMessage(message)
	if not self:isActive() then
		if message:is("TreasureStartedBeingDigged") then
			self:setShown(true)
		elseif message:is("Update") then
			self:updateTime(message)
			if self:getTime() >= 10.0 then
				self:start()
				tutorial:getArrow(self:arrowAdd(IPoint(195, 525), 270)):show(0.25)
			end
		end
	else
		if self:getState() == 0 then
			if message:is("TreasureStartedBeingDigged") then
				self:setShown(true)
				self:arrowHideAll()
				self:goToFinish()
			end
		end
	end
end
function RE2A_TreasureWasNotDiggedFor10SecondsHint(message)
	RE2A_TreasureWasNotDiggedFor10Seconds:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- 
---------------------------------------------------------------------------------------------------
local RE2A_SendWorkerToTrunk = hint:create("RE2A_SendWorkerToTrunk")
function RE2A_SendWorkerToTrunk:isReady() return tutGetBool(self.hintId.."Ready") end
function RE2A_SendWorkerToTrunk:setReady(ready) tutSetBool(self.hintId.."Ready", ready) end

function RE2A_SendWorkerToTrunk:onProcessMessage(message)
	if not self:isActive() then
		if message:is("RoadBridge", "press") then
			self:setReady(true)
		elseif message:is("Trunk", "press") then
			self:setShown(true)
		elseif self:isReady() and message:is("Update") then
			local trunks = tutorial:collectBuildingsWithType("Trunk")
			local count = tutorial:count(trunks)
			if count > 0 then
				self:updateTime(message)
				if self:getTime() >= 15.0 then
					self:start()
					tutorial:targetAny(trunks, "RE2A_SendWorkerToTrunk", 0.5, IPoint(0, 50), 0.5)
				end
			end
		end
	else
		if self:getState() == 0 then
			if message:is("Trunk", "press") then
				self:setShown(true)
				self:arrowHideAll()
				self:goToFinish()
			end
		end
	end
end
function RE2A_SendWorkerToTrunkHint(message)
	RE2A_SendWorkerToTrunk:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Клик в недоступные кликовые объекты
---------------------------------------------------------------------------------------------------
local RE2A_03_02_NoWorkerClick = hint:create("RE2A_03_02_NoWorkerClick")
function RE2A_03_02_NoWorkerClick:onProcessMessage(message)
	local messageData = message:getData()
	if messageData == "clickNoWorker" or messageData == "clickUnreachable" then
		local id = message:getIntegerParam()
		local building = tutorial:game():getBuilding(id)

		if not building:getField():belongsToBase() then
			local popupPos = building:getField():getScreenPosition()
			tutorial:game():addPopupText("RE2A_NoFreeWorkerOnIsland1", IPoint(popupPos.x, popupPos.y + 30), 4)
			tutorial:game():addPopupText("RE2A_NoFreeWorkerOnIsland2", IPoint(popupPos.x, popupPos.y + 10), 4)
		end
	end
end
function RE2A_03_02_NoWorkerClickHint(message)
	RE2A_03_02_NoWorkerClick:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Клик в недоступные кликовые объекты
---------------------------------------------------------------------------------------------------
local RE2A_03_03_NoWorkerClick = hint:create("RE2A_03_03_NoWorkerClick")
function RE2A_03_03_NoWorkerClick:getWorkersCount() return tutGetInt(self.hintId.."WorkersCount") end
function RE2A_03_03_NoWorkerClick:setWorkersCount(count) tutSetInt(self.hintId.."WorkersCount", count) end
function RE2A_03_03_NoWorkerClick:incWorkersCount() self:setWorkersCount(self:getWorkersCount() + 1) end
function RE2A_03_03_NoWorkerClick:decWorkersCount() self:setWorkersCount(self:getWorkersCount() - 1) end
function RE2A_03_03_NoWorkerClick:onInit()
	self:setWorkersCount(0)
end

function RE2A_03_03_NoWorkerClick:onProcessMessage(message)
	local fieldId = 162173
	local messageData = message:getData()
	if messageData == "clickNoWorker" or (messageData == "clickUnreachable" and tutorial:getPortalAssignedWorkersCount(fieldId) == 0) then
		local id = message:getIntegerParam()
		local building = tutorial:game():getBuilding(id)

		if not building:getField():belongsToBase() then
			local popupPos = building:getField():getScreenPosition()
			tutorial:game():addPopupText("RE2A_NoFreeWorkerOnIsland1", IPoint(popupPos.x, popupPos.y + 30), 4)
			tutorial:game():addPopupText("RE2A_NoFreeWorkerOnIsland2", IPoint(popupPos.x, popupPos.y + 10), 4)
		end
	end
end
function RE2A_03_03_NoWorkerClickHint(message)
	RE2A_03_03_NoWorkerClick:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Послать в ферму больше рабочих
---------------------------------------------------------------------------------------------------
local RE2A_SendMoreWorkersToFarm = hint:create("RE2A_SendMoreWorkersToFarm")
function RE2A_SendMoreWorkersToFarm:onProcessMessage(message)
	if not self:isActive() then
		if message:is("FarmWorkers") then
			local id = message:getIntegerParam()
			self:start()
			RE2A_03_localCitizen:setOffset(LeftAvatarPosition, false)
			RE2A_03_localCitizen:show("RE2_FarmWorkersHint_01")

			farm = tutorial:game():getObject(id)
			pos = farm:getScreenPosition()
			tutorial:getArrow(self:arrowAdd(pos, 270)):show(0.25)
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) then
				RE2A_03_localCitizen:hide()
				self:arrowHideAll()
				self:goToFinish()
				self:setShown(true)
			end
		end
	end
end
function RE2A_SendMoreWorkersToFarmHint(message)
	RE2A_SendMoreWorkersToFarm:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Построили два банка - а зачем?
---------------------------------------------------------------------------------------------------
local RE2A_YouDoNotNeedMoreThanOneBank = hint:create("RE2A_YouDoNotNeedMoreThanOneBank")
function RE2A_YouDoNotNeedMoreThanOneBank:onProcessMessage(message)
	if RE2A_YouDoNotNeedMoreThanOneBankAlreadyShowed() then return end
	if not self:isActive() then
		if message:is("BuildingBuilt") then
			if tutorial:count(tutorial:collectBuildingsWithType("Bank")) > 1 then
				self:start()
				avatar:show("RE2A_YouDoNotNeedMoreThanOneBank")
				avatar:setOffset(IPoint(10, 150), false)
			end
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) then
				tutSetBool("RE2A_YouDoNotNeedMoreThanOneBankShowed", true)
				gameInfo:setBoolData("RE2A_YouDoNotNeedMoreThanOneBankShowed", true)
				avatar:hide()
				self:goToFinish()
			end
		end
	end
end
function RE2A_YouDoNotNeedMoreThanOneBankHint(message)
	RE2A_YouDoNotNeedMoreThanOneBank:processMessage(message)
end
function RE2A_YouDoNotNeedMoreThanOneBankAlreadyShowed()
	if gameInfo:getBoolData("RE2A_YouDoNotNeedMoreThanOneBankShowed") then
		return true
	else
		return false
	end
end

---------------------------------------------------------------------------------------------------
-- 
---------------------------------------------------------------------------------------------------
local RE2A_03_06_Cedric = avatar:create("Sedrik")
local RE2A_ShowArrowsOnCaveSmokes = hint:create("RE2A_ShowArrowsOnCaveSmokes")
function RE2A_ShowArrowsOnCaveSmokes:setSmokesCount(count) tutSetInt(self.hintId.."SmokesCount", count) end
function RE2A_ShowArrowsOnCaveSmokes:getSmokesCount() return tutGetInt(self.hintId.."SmokesCount") end
function RE2A_ShowArrowsOnCaveSmokes:incSmokesCount() self:setSmokesCount(self:getSmokesCount() + 1) end
function RE2A_ShowArrowsOnCaveSmokes:onInit()
	self:setSmokesCount(0)
end
function RE2A_ShouldBoostCaveSmokeAppear(smokeId)
	if smokeId == 135067 or smokeId == 133845 or smokeId == 134455 then
		return true
	else
		return false
	end
end

function RE2A_ShowArrowsOnCaveSmokes:onProcessMessage(message)
	if not self:isActive() and not IsFinishTutShowed("RE2A_03_06") then
		if message:is("CaveDoorAppeared") then
			tutSetBool("BoostSmokeAppear", true)
			self:start()
			tutorial:showBlackScreen(0.0)
			tutorial:addHoleInBlackScreen(IPoint(635, 600), 250)
			RE2A_03_06_Cedric.pos = LeftAvatarPosition
			RE2A_03_06_Cedric:show("RE2A_03_06_SmartHint_01")

			self:arrowSave(self:arrowAdd(IPoint(635, 640), 270))
			self:arrowShow(0, 0.25)

			RE2A_03_localCitizen:addCharacter()
			RE2A_03_localCitizen:setOffset(RightAvatarPosition, true)
			RE2A_03_localCitizen:setFaded(true)
			tutorial:setObjectsAllowType(allowList)
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) then
				RE2A_03_06_Cedric:hideText()
				RE2A_03_06_Cedric:setFaded(true)
				self:arrowGet(0):hide(0.25)

				RE2A_03_localCitizen:show("RE2A_03_06_SmartHint_02")
				RE2A_03_localCitizen:setFaded(false)
				self:setState(1)
				tutorial:setObjectsAllowType(allowList)
			end
		elseif self:getState() == 1 then
			if self:isPassed(message) then
				RE2A_03_06_Cedric:show("RE2A_03_06_SmartHint_03")
				RE2A_03_06_Cedric:setFaded(false)

				RE2A_03_localCitizen:hideText()
				RE2A_03_localCitizen:setFaded(true)

				self:arrowSave(self:arrowAdd(IPoint(534, 560), 270))
				self:arrowGet(1):setScale(0.7)
				self:arrowShow(1, 0.25)

				self:arrowSave(self:arrowAdd(IPoint(602, 537), 270))
				self:arrowGet(2):setScale(0.7)
				self:arrowShow(2, 0.25)

				self:arrowSave(self:arrowAdd(IPoint(665, 537), 270))
				self:arrowGet(3):setScale(0.7)
				self:arrowShow(3, 0.25)

				self:setState(2)
				tutorial:setObjectsAllowType(allowList)
			end
		elseif self:getState() == 2 then
			if self:isPassed(message) then
				RE2A_03_06_Cedric:hideText()
				RE2A_03_localCitizen:hideText()
				tutorial:hideBlackScreen(0.25)
				DialogResumeGame()
				tutorial:setObjectsAllowType(allowPass)
				self:setState(3)
			end
		elseif self:getState() == 3 then
			if message:is("CaveSmoke", "press") and not self:isClickAccepted() then
				self:setClickAccepted(true)
				local id = message:getIntegerParam()
				--PrintDebug("CaveSmoke, id = "..tostring(id).."\n")
				self:incSmokesCount()
				if id == 135067 then
					self:arrowGet(1):hide(0.25)
				elseif id == 133845 then
					self:arrowGet(2):hide(0.25)
				elseif id == 134455 then
					self:arrowGet(3):hide(0.25)
				end
				if self:getSmokesCount() == 3 then
					self:setShown(true)
					self:arrowHideAll()
					self:goToFinish()
					tutSetBool("BoostSmokeAppear", false)
				end
			elseif message:is("Update") then
				self:setClickAccepted(false)
				self:updateTime(message)
				if self:getTime() >= 0.25 then
					RE2A_03_06_Cedric:hideCharacter()
					RE2A_03_localCitizen:hideCharacter()
				end

				local smoke1 = tutorial:game():getBuilding(135067)
				if smoke1 and smoke1:getState() == B_NONE then
					if smoke1:mouseOverObject() then
						self:arrowGet(1):hide(0.15)
					else
						self:arrowGet(1):showWithoutEffect(0.15)
					end
				end

				local smoke2 = tutorial:game():getBuilding(133845)
				if smoke2 and smoke2:getState() == B_NONE  then
					if smoke2:mouseOverObject() then
						self:arrowGet(2):hide(0.15)
					else
						self:arrowGet(2):showWithoutEffect(0.15)
					end
				end
				
				local smoke3 = tutorial:game():getBuilding(134455)
				if smoke3 and smoke3:getState() == B_NONE  then
					if smoke3:mouseOverObject() then
						self:arrowGet(3):hide(0.15)
					else
						self:arrowGet(3):showWithoutEffect(0.15)
					end
				end

			end
		end
	end
end
function RE2A_ShowArrowsOnCaveSmokesHint(message)
	RE2A_ShowArrowsOnCaveSmokes:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Дверь в пещеру открылась
---------------------------------------------------------------------------------------------------
local RE2A_03_06_CaveDoorWasOpen = hint:create("RE2A_03_06_CaveDoorWasOpen")
function RE2A_03_06_CaveDoorWasOpen:onProcessMessage(message)
	if not self:isActive() and not IsFinishTutShowed("RE2A_03_06") then
		if message:is("CaveDoorOpened") then
			self:start()
			avatar:show("RE2A_03_06_SmartHint_04")
			avatar:setOffset(IPoint(10, 150), false)
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) then
				self:setShown(true)
				avatar:hide()
				self:goToFinish()
			end
		end
	end
end
function RE2A_03_06_CaveDoorWasOpenHint(message)
	RE2A_03_06_CaveDoorWasOpen:processMessage(message)
end
Tippy = avatar:create("Tippy")
Pirat = avatar:create("Pirat")

---------------------------------------------------------------------------------------------------
-- Первая сцена в 15 уровне
---------------------------------------------------------------------------------------------------
RE2A_04_01_StartDialog = hint:create("RE2A_04_01_StartDialog")
function RE2A_04_01_StartDialog:isReady() return tutGetBool(self.hintId.."Ready") end
function RE2A_04_01_StartDialog:setReady(ready) tutSetBool(self.hintId.."Ready", ready) end
function RE2A_04_01_StartDialog:disableSelection()
	HideFAN()
	tutorial:setObjectsAllowType(allowList)
end
function RE2A_04_01_StartDialog:onFinish()
	SetTutShowed("RE2A_04_01")
	self:setShown(true)
	ShowFAN()
	tutorial:setObjectsAllowType(allowPass)
	--HideTutorialSkip()
end
function RE2A_04_01_StartDialog:onProcessMessage(message)
	if IsTutShowed("RE2A_04_01") then return end
	if not self:isActive() then
		if self:isReady() and message:is("Update") then
			--ShowTutorialSkip()

			tutorial:addParticleEffect("Tutorial_Babrokon_shadow", IPoint(373, 371))
			Sound:PlaySample("TutorialAir", false)
			Sound:PlaySample("TutorialBobrakonRoar", false)

			self:start()
			self:setTime(0.0)
			self:disableSelection()
		elseif message:is("LoadLevel") then
			tutorial:show(0.25)
			self:setReady(true)
		end
	else
		if self:getState() == 0 then
			if message:is("Update") then
				self:updateTime(message)
				if self:getTime() >= 2.0 then
					tutorial:targetAll(tutorial:collectBuildingsWithType("Robber"), "RE2A_04_01", 0.5, IPoint(0, 45), 0.5)
					self:setState(1)
					self:disableSelection()
					tutSetBool("TutorialSendClicksAsMessages", true)
				end
			end
		elseif self:getState() == 1 then
			if message:is("RobberSelected") or message:is("MouseClick") then
				tutSetBool("TutorialSendClicksAsMessages", false)
				local who = "Pirat"
				self:arrowHideAll()
				Pirat:setOffset(IPoint(930, 400), true)
				tutorial:nSetVisible(who, true)
				tutorial:nSetJumpAppear(who, true)
				self:setState(2)
				self:disableSelection()
				self:setTime(0.0)
			end
		elseif self:getState() == 2 then
			if message:is("Update") then
				self:updateTime(message)
				if self:getTime() >= 0.5 then
					Pirat:show("RE2A_04_01_01")
					self:setState(3)
					self:disableSelection()
				end
			end
		elseif self:getState() == 3 then
			if self:isPassed(message) then
				Pirat:hideText()
				Pirat:setFaded(true)

				avatar:setOffset(IPoint(100, 400), false)
				avatar:show("RE2A_04_01_02")
				self:setState(4)
				self:disableSelection()
			end
		elseif self:getState() == 4 then
			if self:isPassed(message) then
				avatar:hideText()
				avatar:setFaded(true)

				Pirat:show("RE2A_04_01_03")
				self:setState(5)
				self:setTime(0.0)
				self:disableSelection()
			end
		elseif self:getState() == 5 then
			if self:getTime() >= 0.5 and self:isPassed(message) then
				Pirat:switchText("RE2A_04_01_04")
				self:setState(6)
				self:setTime(0.0)
				self:disableSelection()
			elseif message:is("Update") then
				self:updateTime(message)
			end
		elseif self:getState() == 6 then
			if self:getTime() >= 0.5 and self:isPassed(message) then
				tutorial:nSetVisible("Pirat", false)

				avatar:show("RE2A_04_01_05")
				self:setState(7)
				self:setTime(0.0)
				self:disableSelection()
			elseif message:is("Update") then
				self:updateTime(message)
			end
		elseif self:getState() == 7 then
			if self:getTime() >= 1.0 and self:isPassed(message) then
				avatar:switchText("RE2A_04_01_06")
				self:setState(8)
				self:setTime(0.0)
				self:disableSelection()
			elseif message:is("Update") then
				self:updateTime(message)
			end
		elseif self:getState() == 8 then
			if self:getTime() >= 1.0 and self:isPassed(message) then
				avatar:hide()
				Pirat:hide()
				self:goToFinish()
				self:disableSelection()
			elseif message:is("Update") then
				self:updateTime(message)
			end
		end
	end
end
function RE2A_04_01_StartDialogHint(message)
	RE2A_04_01_StartDialog:processMessage(message)
end
---------------------------------------------------------------------------------------------------
-- Если в течение 10 секунд не начали строить фонарь - стрелки на все фонари и текст Типпи
---------------------------------------------------------------------------------------------------
function Filter_TorchIsNotReady(torch)
	if torch:isFired() then
		return false
	else
		return true
	end
end

local RE2A_04_02_DidNotStartRestoringTorchesFor10Seconds = hint:create("RE2A_04_02_DidNotStartRestoringTorchesFor10Seconds")
function RE2A_04_02_DidNotStartRestoringTorchesFor10Seconds:onProcessMessage(message)
	if not self:isActive() then
		if message:is("TorchBuildStarted") then
			self:setShown(true)
		elseif message:is("Update") then
			self:updateTime(message)
			if self:getTime() >= 10.0 then
				self:start()

				local allUnlitTorches = tutorial:filter(tutorial:collectBuildingsWithType("Torch"), "Filter_TorchIsNotReady")
				tutorial:targetAll(allUnlitTorches, "RE2A_04_02_DidNotStartRestoringTorchesFor10Seconds", 0.5, IPoint(0, 30), 0.5)
				Tippy:setOffset(LeftAvatarPosition, false)
				Tippy:show("RE2A_04_02_LetsStartWithTheseTorchesHint")
			end
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) or message:is("TorchBuildStarted") then
				self:setShown(true)
				self:arrowHideAll()
				Tippy:hide()
				self:goToFinish()
			end
		end
	end
end
function RE2A_04_02_DidNotStartRestoringTorchesFor10SecondsHint(message)
	RE2A_04_02_DidNotStartRestoringTorchesFor10Seconds:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Если зажгли 1 или 2 фонаря, есть доступные фонари для зажжения, а не разжигают в течении 30 секунд
---------------------------------------------------------------------------------------------------
function Filter_TorchIsReady(torch)
	if torch:isFired() then
		return true
	else
		return false
	end
end
local RE2A_04_02_LitMoreTorches = hint:create("RE2A_04_02_LitMoreTorches")
function RE2A_04_02_LitMoreTorches:onProcessMessage(message)
	if not self:isActive() then
		if message:is("Update") then
			-- Подсчитываем непостроенные фонари
			local restoredTorchesCount = tutorial:count(tutorial:filter(tutorial:collectBuildingsWithType("Torch"), "Filter_TorchIsReady"))
			if restoredTorchesCount == 3 or restoredTorchesCount == 4 then
				-- Считаем еще незажженые фонари
				local unlitTorches = tutorial:filter(tutorial:collectBuildingsWithType("Torch"), "Filter_TorchIsNotReady")
				local unlitTorchesCount = tutorial:count(unlitTorches)
				if unlitTorchesCount > 0 then
					self:updateTime(message)
					if self:getTime() >= 30.0 then
						self:start()
						tutorial:targetAll(unlitTorches, "RE2A_04_02_LitMoreTorches", 0.5, IPoint(0, 40), 0.5)
						Tippy:setOffset(IPoint(100, 180), false)
						Tippy:show("RE2A_04_02_LitMoreTorches")
					end
				end
			end
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) or message:is("TorchBuildStarted") then
				self:setShown(true)
				self:arrowHideAll()
				Tippy:hide()
				self:goToFinish()
			end
		end
	end
end
function RE2A_04_02_LitMoreTorchesHint(message)
	RE2A_04_02_LitMoreTorches:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Никто не выкапывает клад в течение 30 секунд
---------------------------------------------------------------------------------------------------
function Filter_TreasureIsUndigged(treasure) return (treasure:getUpgradeLevel() == 0) end

local RE2A_04_03_DigThatTreasureAlready = hint:create("RE2A_04_03_DigThatTreasureAlready")
function RE2A_04_03_DigThatTreasureAlready:onProcessMessageRegardlessLock(message)
	if message:is("TreasureDigged") then
		self:setTime(0.0)
	end
end
function RE2A_04_03_DigThatTreasureAlready:onProcessMessage(message)
	if not self:isActive() then
		if message:is("Update") then
			local undiggedTreasures = tutorial:filter(tutorial:collectBuildingsWithType("Treasure"), "Filter_TreasureIsUndigged")
			local undiggedTreasuresCount = tutorial:count(undiggedTreasures)
			if undiggedTreasuresCount > 0 then
				self:updateTime(message)
				if self:getTime() >= 20.0 then
					self:start()
					tutorial:targetAll(undiggedTreasures, "RE2A_04_03_DigThatTreasureAlready", 0.5, IPoint(0, 0), 0.5)
					self:setTime(0.0)
				end
			end
		end
	else
		if self:getState() == 0 then
			if message:is("Treasure", "press") then
				self:arrowHideAll()
				self:setTime(0.0)
				self:goToFinish()
			end
		end
	end
end
function RE2A_04_03_DigThatTreasureAlreadyHint(message)
	RE2A_04_03_DigThatTreasureAlready:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Погас фонарь - скажем, что надо платить еще
---------------------------------------------------------------------------------------------------
local RE2A_YouMustPayToTorchTimedPirateAgainAndAgain = hint:create("RE2A_YouMustPayToTorchTimedPirateAgainAndAgain")
function RE2A_YouMustPayToTorchTimedPirateAgainAndAgain:isReady() return tutGetBool(self.hintId.."Ready") end
function RE2A_YouMustPayToTorchTimedPirateAgainAndAgain:setReady(ready) tutSetBool(self.hintId.."Ready", ready) end
function RE2A_YouMustPayToTorchTimedPirateAgainAndAgain:onProcessMessageRegardlessLock(message)
	if message:is("TorchTimedSwitchedOff") then
		self:setReady(true)
	end
end
function RE2A_YouMustPayToTorchTimedPirateAgainAndAgain:onProcessMessage(message)
	if not self:isActive() then
		if self:isReady() and message:is("Update") then
			self:updateTime(message)
			if tutorial:game():getWorkersCount() >= 1 and tutorial:game():getMoneyCount() >= 500 and self:getTime() >= 15.0 then
				self:start()
				Tippy:setOffset(LeftAvatarPosition, false)
				Tippy:show("RE2A_PayToTimedPirateRegularly")

				self:arrowSave(self:arrowAdd(IPoint(821, 555), 270))
				self:arrowShow(0, 0.25)
			end
		elseif self:isReady() and (message:is("TorchTimedSwitchedOn") or message:is("TorchTimedPirate", "press")) then
			self:setReady(false)
		end
	else
		if self:getState() == 0 then
			if self:isPassed(message) then
				self:setShown(true)
				Tippy:hide()
				self:arrowHideAll()
				self:goToFinish()
			end
		end
	end
end
function RE2A_YouMustPayToTorchTimedPirateAgainAndAgainHint(message)
	RE2A_YouMustPayToTorchTimedPirateAgainAndAgain:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Подсказка на падающие камни
---------------------------------------------------------------------------------------------------
local RE2A_04_06_CoalStone = hint:create("RE2A_04_06_CoalStone")
function RE2A_04_06_CoalStone:onProcessMessageRegardlessLock(message)
	if message:is("CoalStone", "press") or message:is("CoalStoneEmptyed") then
		local id = message:getIntegerParam()
		local arrowId = tutGetInt("RE2A_04_06_CoalStone"..id)
		if arrowId == nil then return end
		
		local arrow = tutorial:getArrow(arrowId)
		if arrow == nil then return end

		arrow:hide(0.25)
	elseif message:is("FieldBecomeUnreachable") then
		local fieldId = message:getIntegerParam()
		local field = tutorial:game():getObject(fieldId)
		if field == nil then return end
		
		local building = field:getBuilding()
		if building == nil then return end

		if building:getType() == tutorial:game():convertType("CoalStone") then
			local buildingId = building:id()
			local arrowId = tutGetInt("RE2A_04_06_CoalStone"..buildingId)
			if arrowId == nil then return end
			
			local arrow = tutorial:getArrow(arrowId)
			if arrow == nil then return end

			arrow:hide(0.25)
		end
	end
end
function Map_TargetCoalStone(coalStone)
	local coalStonePosition = coalStone:getField():getScreenPosition()
	local offset = IPoint(8, 40)
	local arrowId = tutorial:addArrow()
	tutorial:getArrow(arrowId):setPosition(coalStonePosition.x + offset.x, coalStonePosition.y + offset.y)
	tutorial:getArrow(arrowId):setAngle(270)
	tutorial:getArrow(arrowId):setShowTimer(0.5)
	tutorial:getArrow(arrowId):show(0.25)
	tutorial:getArrow(arrowId):setScale(0.7)
	tutorial:show(0.25)
	tutSetInt("RE2A_04_06_CoalStone"..tostring(coalStone:id()), arrowId)
end
function RE2A_04_06_CoalStone:onProcessMessage(message)
	if not self:isActive() then
		if message:is("NeedMoreCoal") then
			self:start()
			self:setTime(0.0)
			self:setState(0)
		end
	else
		if self:getState() == 0 then
			if message:is("Update") then
				self:updateTime(message)
				if self:getTime() >= 3.0 then
					avatar.pos = IPoint(20, 160)
					avatar:show("RE2A_CoalStone1")

					Tippy:addCharacter()
					Tippy:setOffset(IPoint(915, 160), true)
					Tippy:setFaded(true)
					self:setState(1)
				end
			end
		elseif self:getState() == 1 then
			if self:isPassed(message) then
				avatar:hideText()
				avatar:setFaded(true)

				Tippy:show("RE2A_CoalStone2")
				Tippy:setFaded(false)
				self:setState(2)

				local coalStones = tutorial:collectBuildingsWithType("CoalStone")
				tutorial:map(coalStones, "Map_TargetCoalStone")
			end
		elseif self:getState() == 2 then
			if self:isPassed(message) then
				self:setShown(true)
				Tippy:hide()
				avatar:hide()
				self:goToFinish()
			end
		end
	end
end
function RE2A_04_06_CoalStoneHint(message)
	RE2A_04_06_CoalStone:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- У игрока достаточно материалов для строительства колодца
---------------------------------------------------------------------------------------------------
local RE2A_05_01_YouHaveEnoughWoodSoBuildTheWell = hint:create("RE2A_05_01_YouHaveEnoughWoodSoBuildTheWell")
function RE2A_05_01_YouHaveEnoughWoodSoBuildTheWell:onProcessMessage(message)
	if not self:isActive() then
		if message:is("Update") then
			if tutorial:game():getWoodCount() >= 50.0 then
				self:start()

				local arrowId = tutorial:addArrow()
				tutorial:getArrow(arrowId):setPosition(798, 555)
				tutorial:getArrow(arrowId):setAngle(270)
				tutorial:getArrow(arrowId):setShowTimer(0.5)
				tutorial:getArrow(arrowId):show(0.25)
				tutorial:getArrow(arrowId):setScale(0.7)
				tutorial:show(0.25)
			end
		end
	else
		if self:getState() == 0 then
			if message:is("WellBuildStarted") then
				self:arrowHideAll()
				self:setShown(true)
				self:goToFinish()
			end
		end
	end
end
function RE2A_05_01_YouHaveEnoughWoodSoBuildTheWellHint(message)
	RE2A_05_01_YouHaveEnoughWoodSoBuildTheWell:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Разогнан туман друидом
---------------------------------------------------------------------------------------------------
local Druid = avatar:create("Saruman")
local RE2A_07_03_DruidLitTheFire = hint:create("RE2A_07_03_DruidLitTheFire")
function RE2A_07_03_DruidLitTheFire:onProcessMessage(message)
	if IsTutShowed("RE2A_07_03") then return end
	if not self:isActive() then
		if message:is("FieldBecameReachable") then
			local id = message:getIntegerParam()
			local fieldId = 119543
			if id == fieldId then
				self:start()
			end
		end
	else
		if self:getState() == 0 then
			if message:is("Update") then
				self:updateTime(message)
				if self:getTime() >= 1.0 then
					avatar.pos = IPoint(100, 500)
					avatar:show("RE2A_DruidAppear1")

					Druid:addCharacter()
					Druid:setOffset(IPoint(950, 500), true)
					Druid:setFaded(true)

					self:arrowSave(self:arrowAdd(IPoint(363, 350), 270))
					self:arrowShow(0, 0.25)
					self:setState(1)
				end
			end
		elseif self:getState() == 1 then
			if self:isPassed(message) then
				avatar:hideText()
				avatar:setFaded(true)
				Druid:show("RE2A_DruidAppear2")
				Druid:setFaded(false)
				self:setState(2)

				if tutorial:getSelectedBuildingType() == tutorial:game():convertType("TorchTimedDruid") then
					self:arrowHideAll()
				end
			elseif message:is("TorchTimedDruid", "press") then
				if tutorial:getSelectedBuildingType() == tutorial:game():convertType("TorchTimedDruid") then
					self:arrowHideAll()
				end
			end
		elseif self:getState() == 2 then
			if self:isPassed(message) then
				SetTutShowed("RE2A_07_03")
				self:setShown(true)
				avatar:hide()
				Druid:hide()
				self:arrowHideAll()
				self:goToFinish()
			end
		end
	end
end
function RE2A_07_03_DruidLitTheFireHint(message)
	RE2A_07_03_DruidLitTheFire:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Разогнан туман над университетом
---------------------------------------------------------------------------------------------------
local RE2A_07_08_ThereIsTheUni = hint:create("RE2A_07_08_ThereIsTheUni")
function RE2A_07_08_ThereIsTheUni:onProcessMessage(message)
	if IsFinishTutShowed("RE2A_07_08") then return end
	if not self:isActive() then
		if message:is("FieldBecameReachable") then
			local id = message:getIntegerParam()
			local fieldId = 68338
			local field = tutorial:game():getObject(fieldId)
			if id == fieldId and field:isReachable() then
				self:start()
			end
		end
	else
		if self:getState() == 0 then
			if message:is("Update") then
				self:updateTime(message)
				if self:getTime() >= 0.5 then
					Druid:setOffset(LeftAvatarPosition)
					Druid:show("RE2A_07_08_03")
					self:arrowSave(self:arrowAdd(IPoint(470, 635), 270))
					self:arrowShow(0, 0.25)
					self:setState(1)
				end
			end
		elseif self:getState() == 1 then
			if self:isPassed(message) then
				Druid:switchText("RE2A_07_08_04")
				self:setState(2)
			end
		elseif self:getState() == 2 then
			if self:isPassed(message) then
				self:setShown(true)
				Druid:hide()
				self:arrowHideAll()
				self:goToFinish()
			end
		end
	end
end
function RE2A_07_08_ThereIsTheUniHint(message)
	RE2A_07_08_ThereIsTheUni:processMessage(message)
end

---------------------------------------------------------------------------------------------------
-- Разогнан туман над учителем
---------------------------------------------------------------------------------------------------
local RE2A_07_08_ThereIsTheTeacher = hint:create("RE2A_07_08_ThereIsTheTeacher")
function RE2A_07_08_ThereIsTheTeacher:onProcessMessage(message)
	if IsFinishTutShowed("RE2A_07_08") then return end
	if not self:isActive() then
		if message:is("FieldBecameReachable") then
			local id = message:getIntegerParam()
			local fieldId = 69265
			local field = tutorial:game():getObject(fieldId)
			if id == fieldId and field:isReachable() then
				self:start()
			end
		end
	else
		if self:getState() == 0 then
			if message:is("Update") then
				self:updateTime(message)
				if self:getTime() >= 0.5 then
					Druid:setOffset(LeftAvatarPosition)
					Druid:show("RE2A_07_08_05")
					self:setState(1)
				end
			end
		elseif self:getState() == 1 then
			if self:isPassed(message) then
				self:setShown(true)
				Druid:hide()
				self:goToFinish()
				SetFinishTutShowed("RE2A_07_08")
			end
		end
	end
end
function RE2A_07_08_ThereIsTheTeacherHint(message)
	RE2A_07_08_ThereIsTheTeacher:processMessage(message)
end
---------------------------------------------------------------------------------------------------
-- 
---------------------------------------------------------------------------------------------------
local TEST_ = hint:create("TEST_")
function TEST_:onProcessMessage(message)
	if not self:isActive() then
	else
		if self:getState() == 0 then
		end
	end
end
function TEST_Hint(message)
	TEST_:processMessage(message)
end