function GameFieldFunc(message)
	if message == "Game field options credits button pressed" then
		SendMessage("Game field alpha changer", "change alpha to 0.0")
		MoveGamefieldPanels("out")
		SendMessage("Credits modal dialog", "instantiate GameFieldCreditsZGlassTemplate")
	elseif message == "5 pressed" then
		PermanentStorage.SetLocalBool("Shown message [ispy_diver_intro]", false)
	elseif message == "Game field credits click" then
		SendMessage("Credits modal dialog", "hide")
		SendMessage("Game field alpha changer", "change alpha to 1.0")
		MoveGamefieldPanels("in")
	elseif message == "Game field eye button pressed" then
		SendMessage("Game field panel mover", "move to out")
		SendMessage("Game field alpha changer", "change alpha to 0.0")
		SendMessage("GameField", "Pause")
		SendMessage("Screen", "template GameFieldBackgroundZGlassTemplate")
		SendMessage("Screen", "create top instance")
	elseif message == "Game field background to game field" then
		SendMessage("Game field panel mover", "move to in")
		SendMessage("Game field alpha changer", "change alpha to 1.0")
		SendMessage("GameField", "Continue")
		SendMessage("Screen", "erase top child")
	elseif message == "Game field menu button pressed" then
		SendMessage("Game field modal dialog", "instantiate GameFieldMenuTemplate")
		SendMessage("Game field menu mover", "move to in")
		SendMessage("GameField", "Pause")
	elseif message == "Game field menu resume button pressed" then
		SendMessage("Game field menu mover", "move to out")
		SendMessage("Game field modal dialog", "hide")
		SendMessage("GameField", "Continue")
	elseif message == "Game field restart confirmation dialog yes button pressed" then
		SendMessage("Game field menu mover", "move to out")
		SendMessage("Game field modal dialog", "hide")
		SendMessage("GameField", "Restart")
		SendMessage("Exit and restart modal dialog", "hide")
	elseif message == "Game field exit confirmation dialog yes button pressed" then
		SendMessage("Screen", "template ZGlassTemplate")
		SendMessage("Screen", "create top instance")
			-- защита от повторного выхода
		SendMessage("Screen", "template DarkeningTemplate")
		SendMessage("Screen", "defineText [receiver] post:lua:GameFieldFunc")
		SendMessage("Screen", "defineText [message] Game field darkened for main screen")
		SendMessage("Screen", "create top instance")
	elseif message == "Game field darkened for main screen" then
		Sound:FadeOutTrack(PermanentStorage.GetLocalString("Track in game"), 1.0)
		if PermanentStorage.GetLocalString("Track in game") == "Game1" then
			PermanentStorage.SetLocalString("Track in game", "Game2")
		elseif PermanentStorage.GetLocalString("Track in game") == "Game2" then
			PermanentStorage.SetLocalString("Track in game", "Game3")
		elseif PermanentStorage.GetLocalString("Track in game") == "Game3" then
			PermanentStorage.SetLocalString("Track in game", "Game1")
		end
		Sound:FadeInTrack("Menu"..PermanentStorage.GetLocalString("Current Tank"), 1.0, true)
		SendMessage("Screen", "clear children list")
		--SendMessage("lua:TutorialFunc", "Game field to main screen")
		PermanentStorage.SetLocalString("temp:Tutorial main screen panels in after", "game field")
		SendMessage("lua:MainScreenFunc", "Enter main screen")
		SendMessage("Screen", "template BrighteningTemplate")
		SendMessage("Screen", "create top instance")

		SendMessage("lua:BetaFunc", "Game field to main screen")
		SendMessage("post:lua:BetaFunc", "Commit")
	elseif message == "Game field menu options button pressed" then
		SendMessage("Game field menu mover", "report arrival to post:lua:GameFieldFunc")
		SendMessage("Game field menu mover", "set arrival message Game field menu out for options")
		SendMessage("Game field menu mover", "move to out")
	elseif message == "Game field menu out for options" then
		SendMessage("Above game field menu", "template GameFieldOptionsDialogTemplate")
		SendMessage("Above game field menu", "create top instance")
		SendMessage("Options dispatcher", "report finish to post:lua:GameFieldFunc")
		SendMessage("Options dispatcher", "set finish message Game field menu options finished")
		SendMessage("Options dispatcher", "Show dialog")
	elseif message == "Game field menu options finished" then
		SendMessage("Options mover", "report arrival to post:lua:GameFieldFunc")
		SendMessage("Options mover", "set arrival message Game field menu options out")
		SendMessage("Options mover", "move to out")
	elseif message == "Game field menu options out" then
		SendMessage("Above game field menu", "clear children list")
		SendMessage("Game field menu mover", "move to in")
	elseif message == "Game field help button pressed" then
		SendMessage("Above game field modal dialog", "instantiate GameFieldHelpTemplate")
		SendMessage("Help mover", "move to in")
		SendMessage("GameField", "Pause")
	elseif message == "Game field help ok button pressed" then
		SendMessage("Above game field modal dialog", "hide")
		SendMessage("Help mover", "move to out")
		SendMessage("GameField", "Continue")
	elseif message == "Game field menu restart button pressed" then
		SendMessage("Exit and restart modal dialog", "instantiate ConfirmGameRestartTemplate")
	elseif message == "Game field menu exit button pressed" then
		SendMessage("Exit and restart modal dialog", "instantiate ConfirmGameExitTemplate")
	elseif message == "Game field exit confirmation dialog no button pressed" then
		SendMessage("Exit and restart modal dialog", "hide")
	elseif message == "Game field restart confirmation dialog no button pressed" then
		SendMessage("Exit and restart modal dialog", "hide")
	else
		assert(false, "Unknown message "..message)
	end
end

function ISpyFunc(message)
	if message == "Game field menu button pressed" then
		SendMessage("GameField", "Pause")
		SendMessage("ISpy modal dialog", "instantiate GameFieldMenuTemplate")
		SendMessage("Game field menu mover", "move to in")
		Sound:PlaySample("window_moving")
		--SendMessage("Game field modal dialog", "instantiate ISpyFieldMenuTemplate")
		--SendMessage("Game field menu mover", "report arrival to null")
		--SendMessage("Game field menu mover", "set arrival message null")
		--SendMessage("Game field menu mover", "move to in")		
	elseif message == "Exit" then
		FinishGameMusic()
		MoveGamefieldPanels("out")
		SendMessage("Screen", "template DarkeningTemplate")
		SendMessage("Screen", "defineText [receiver] post:lua:ISpyFunc")
		SendMessage("Screen", "defineText [message] Game field darkened for shop")
		SendMessage("Screen", "create top instance")
	elseif message == "Game field menu exit button pressed" then
		SendMessage("Game field menu mover", "report arrival to post:lua:ISpyFunc")
		SendMessage("Game field menu mover", "set arrival message Game field menu out for exit confirm")
		SendMessage("Game field menu mover", "move to out")
		Sound:PlaySample("window_moving")
	elseif message == "Game field menu resume button pressed" then
		SendMessage("Game field menu mover", "report arrival to lua:ISpyFunc")
		SendMessage("Game field menu mover", "set arrival message Game field menu out for gamefield")
		SendMessage("Game field menu mover", "move to out")
		Sound:PlaySample("window_moving")
		SendMessage("ISpy modal dialog", "hide")
	elseif message == "Game field menu out for gamefield" then
		SendMessage("GameField", "Continue")
	elseif message == "Game field menu options button pressed" then
		SendMessage("Game field menu mover", "report arrival to post:lua:ISpyFunc")
		SendMessage("Game field menu mover", "set arrival message Game field menu out for options")
		SendMessage("Game field menu mover", "move to out")
		Sound:PlaySample("window_moving")
		WriteToLogIfBetaLog("Press Options - I Spy")
		--SendMessage("Main menu modal dialog", "instantiate MainMenuOptionsDialogTemplate")
		--SendMessage("Options dispatcher", "report finish to lua:MainMenuFunc")
		--SendMessage("Options dispatcher", "set finish message Main menu options dialog finished")
		--SendMessage("Options dispatcher", "Show dialog")

	elseif message == "Game field menu out for options" then
		SendMessage("Above game field menu", "template GameFieldOptionsDialogTemplate")
		SendMessage("Above game field menu", "create top instance")
		SendMessage("Options dispatcher", "report finish to post:lua:ISpyFunc")
		SendMessage("Options dispatcher", "set finish message Game field menu options finished")
		SendMessage("Options dispatcher", "Show dialog")
		Sound:PlaySample("window_moving")
	elseif message == "Game field menu options finished" then
		SendMessage("Options mover", "report arrival to post:lua:ISpyFunc")
		SendMessage("Options mover", "set arrival message Game field menu options out")
		SendMessage("Options mover", "move to out")
		Sound:PlaySample("window_moving")
	elseif message == "Game field menu options out" then
		SendMessage("Above game field menu", "clear children list")
		SendMessage("Game field menu mover", "move to in")
		Sound:PlaySample("window_moving")
	elseif message == "Game field menu help button pressed" then
		SendMessage("Game field menu mover", "report arrival to post:lua:ISpyFunc")
		SendMessage("Game field menu mover", "set arrival message Game field menu out for help")
		SendMessage("Game field menu mover", "move to out")
		Sound:PlaySample("window_moving")
	elseif message == "Game field menu out for help" then
		SendMessage("Above game field menu", "clear children list")
		SendMessage("Above game field menu", "template GameFieldHelpTemplate")
		SendMessage("Above game field menu", "create top instance")
		SendMessage("Help mover", "move to in")
		Sound:PlaySample("window_moving")
		local gameMode = PermanentStorage.GetLocalString("CurrentMode");
		if gameMode == "submersion" then
			SendMessage("post:Game screen help scroll", "set 0")
		elseif gameMode == "collector" then
			SendMessage("post:Game screen help scroll", "set -490")
		elseif gameMode == "diver" then
			SendMessage("post:Game screen help scroll", "set -980")
		elseif gameMode == "goldrush" then
			SendMessage("post:Game screen help scroll", "set -1470")
		end
	--elseif message == "Game field menu out for help" then
	--	SendMessage("Above game field menu", "instantiate GameFieldHelpTemplate")
	--	SendMessage("Game field menu mover", "move to in")
	elseif message == "Game field menu out for exit confirm" then
		SendMessage("StatisticsControl", "CountMoney")
		SendMessage("Above game field menu", "template ExitToShopConfirmTemplate")
		SendMessage("Above game field menu", "create top instance")
		SendMessage("Exit to shop confirmation mover", "move to in")
		Sound:PlaySample("window_moving")
	elseif message == "Game field darkened for shop" then
		SendMessage("Locations", "Next");
		SendMessage("Locations", "Release");
		SendMessage("Screen", "clear children list")
		SendMessage("Screen", "template AnyShopTemplate")
		SendMessage("Screen", "create top instance")
		SendMessage("Screen", "template BrighteningTemplate")
		SendMessage("Screen", "create top instance")
		SendMessage("lua:BetaFunc", "Commit")
		MoveShopPanels("in")
		if PermanentStorage.IsLocalNameDefined("inTutorial") and not PermanentStorage.GetLocalBool("inTutorial") then
			PermanentStorage.SetLocalInt("ExitToTankCounter", PermanentStorage.GetLocalIntOrDef("ExitToTankCounter", 0) + 1)
			if not PermanentStorage.IsLocalNameDefined("EyeHintsShown") then
				SendMessage("Timed messages", "lua:Hints, create EyeHint, 0.5")
			elseif not PermanentStorage.IsLocalNameDefined("NeedMyTanksShown") then
				if PermanentStorage.GetLocalInt("ExitToTankCounter") == 4 then
					SendMessage("Timed messages", "lua:Hints, create MyTanksHint, 0.5")
					PermanentStorage.SetLocalBool("NeedMyTanksShown", false)
				end
			end
		end
	elseif message == "Load level" then
		--SendMessage("Screen", "clear children list")
		SendMessage("Screen", "template LevelLoadingTemplate")
		SendMessage("Screen", "create top instance")
	elseif message == "Load level start" then
		SendMessage("Screen", "erase bottom child")
		SendMessage("Locations", "Upload");
		SendMessage("LevelLoading", "animate");
		SendMessage("Screen", "template ISpyTemplate")
		SendMessage("Screen", "create bottom instance")
	elseif message == "Load level done" then
		SendMessage("Screen", "erase top child")
		SendMessage("GameField", "it's time to show panel")
		--SendMessage("Screen", "template ISpyTemplate")
		--SendMessage("Screen", "create top instance")
		--SendMessage("Screen", "template BrighteningTemplate")
		--SendMessage("Screen", "create top instance")
		StartGameMusic()
	elseif message == "Show gamefield" then
	elseif message == "LevelInfoPanel continue pressed" then
		SendMessage("Welcome ispy modal dialog", "hide")
		SendMessage("GameField", "start timer");
		-- SendMessage("GameField", "Start")
		SendMessage("info panel clock", "hide")
		SendMessage("post:lua:MoveGamefieldPanels", "in")
	elseif message == "Help button pressed" then
		SendMessage("ISpy modal dialog", "instantiate GameFieldHelpTemplate")
		SendMessage("Help mover", "move to in")
		Sound:PlaySample("window_moving")
		SendMessage("GameField", "Pause")
		local gameMode = PermanentStorage.GetLocalString("CurrentMode");
		if gameMode == "submersion" then
			SendMessage("post:Game screen help scroll", "set 0")
		elseif gameMode == "collector" then
			SendMessage("post:Game screen help scroll", "set -490")
		elseif gameMode == "diver" then
			SendMessage("post:Game screen help scroll", "set -980")
		elseif gameMode == "goldrush" then
			SendMessage("post:Game screen help scroll", "set -1470")
		end
	elseif message == "Help ok button pressed" then
		SendMessage("Help mover", "move to out")
		Sound:PlaySample("window_moving")
		SendMessage("GameField", "Continue")
		SendMessage("ISpy modal dialog", "hide")
	elseif message == "hint is active" then
		SendMessage("ISpy vessel background", "Change texture to ispy_hint_bg_active")
		SendMessage("HintVesselCoverControl", "set texture to active");
	elseif message == "hint is pressed" then
		SendMessage("ISpy vessel background", "Change texture to ispy_hint_bg_active")
		SendMessage("HintVesselCoverControl", "set texture to active");
	elseif message == "hint is normal" then
		SendMessage("ISpy vessel background", "Change texture to ispy_hint_bg")
		SendMessage("HintVesselCoverControl", "set texture to normal");
	elseif message == "hint is disabled" then
		SendMessage("ISpy vessel background", "Change texture to ispy_hint_bg")
		SendMessage("HintVesselCoverControl", "set texture to normal")
	elseif message == "Statistics continue pressed" then
		SendMessage("GameField", "Exit")
	elseif message == "exit confirm ok pressed" then
		SendMessage("GameField", "Exit")
	elseif message == "exit confirm cancel pressed" then
		SendMessage("Exit to shop confirmation mover", "report arrival to post:lua:ISpyFunc")
		SendMessage("Exit to shop confirmation mover", "set arrival message exit to shop confirmation out for menu")
		SendMessage("Exit to shop confirmation mover", "move to out")
		Sound:PlaySample("window_moving")
	elseif message == "exit to shop confirmation out for menu" then
		SendMessage("Above game field menu", "clear children list")
		SendMessage("Game field menu mover", "move to in")
		Sound:PlaySample("window_moving")
	else
		assert(false, "Unknown message "..message)
	end
end

function MoveGamefieldPanels(where)
	SendMessage("Gamefield left top panel mover", "move to "..where)
	SendMessage("Gamefield right top panel mover", "move to "..where)
	Sound:PlaySample("panel_moving")
end

--
-- Возвращает скорость штрафной рыбки в зависимости от времени
--
function GetPenaltyFishSpeed(time)
	if time < 1 then
		-- плаваем очень быстро
		return 17
	elseif time < 2 then
		-- замедляемся
		return lerp(17, 3, (time - 1) / 1)
	else
		-- теперь плаваем более-менее медленно, чтобы в нас смогли попасть
		return 3
	end
end

--
-- Получение размера таблицы table
-- Замена документированного оператора #, который почему-то не работает :(
--
function GetTableSize(table)
	local i = 1;
	while table[i] ~= nil do
		i = i + 1
	end
	return i - 1;
end

--
-- Класс :) информации о кликах
--
Clicks = {}


--
-- Инициализировать информацию о кликах
--
function Clicks_Init()
	Clicks.clicks = {}
	Clicks.hits = {}
	Clicks.n = 0
	Clicks.nMisses = 0
	Clicks.nHits = 0
	Clicks.isExpensive = false
end

--
-- Добавить попадание в момент времени time
--
function Clicks_AddHit(time)
	Clicks.n = Clicks.n + 1
	Clicks.nHits = Clicks.nHits + 1
	local clickInfo = {
		["type"] = "hit",
		["time"] = time
	}
	Clicks.clicks[Clicks.n] = clickInfo
	Clicks.hits[Clicks.nHits] = clickInfo
	local currentMode = PermanentStorage.GetLocalString("CurrentMode")
	if currentMode == "goldrush" then
		--if math.random(10) == 1 then
		--	Clicks.isExpensive = true
		--else
			Clicks.isExpensive = false
		--end 
	end
end

--
-- Добавить промах в момент времени time
--
function Clicks_AddMiss(time)
	Clicks.n = Clicks.n + 1
	Clicks.nMisses = Clicks.nMisses + 1
	Clicks.clicks[Clicks.n] = {
		["type"] = "miss",
		["time"] = time
	}
end

--
-- Вернуть спид бонус за последний клик
--
function Clicks_GetLastClickSpeedBonus()
	if PermanentStorage.GetLocalBoolOrDef("IsRelaxedMode", false) then
		local mode = PermanentStorage.GetLocalString("CurrentMode")
		-- if mode == "submersion" or mode == "diver" then
		if mode == "submersion" then
			assert(Clicks.nHits > 0)
			local prevClickTime = 0
			if Clicks.nHits > 1 then
				prevClickTime = Clicks.hits[Clicks.nHits - 1].time;
			end
			local dt = Clicks.hits[Clicks.nHits].time - prevClickTime
			if (dt < 3) then
				local curTableSize = GetTableSize(ISpyPrices[mode])
				local n = Clicks.nHits
				if n > curTableSize then
					n = curTableSize
				end
				local price = ISpyPrices[mode][n]
				local currentN = PermanentStorage.GetLocalIntOrDef("CurrentN", 0) + 1
				price = math.sqrt(currentN) * price
				price = price / 3;
				price = math.ceil( price / 5) * 5
				return price;
			else
				return 0
			end
		end
	end
	return 0
end

--
-- Вернуть время до следующего подсказочного блика
-- restTime - сколько осталось до следующего (0, если он только что был, или инициализация, >0, если нашли предмет)
-- Возвращает число, как бы заменяющее restTime
--
function Clicks_GetTimeToHintFlash(restTime)
	local mode = PermanentStorage.GetLocalString("CurrentMode")
	local alreadyDiver = SendMessageReply("Locations", "Get current location usings in submersion")
	alreadyDiver = alreadyDiver + SendMessageReply("Locations", "Get current location usings in diver")
	local alreadyLvl = PermanentStorage.GetLocalInt("CurrentStage")
	if mode == "diver" then
		if PermanentStorage.GetLocalBoolOrDef("IsRelaxedMode", false) then
			return 10 + Clicks.nHits * 3 + alreadyDiver + alreadyLvl;
		else 
			return 2 + 3 * math.floor(Clicks.nHits / 3) + alreadyDiver + math.floor(alreadyLvl / 40);
		end
	elseif mode == "submersion" or mode == "collector" then
		if PermanentStorage.GetLocalBoolOrDef("IsRelaxedMode", false) then
			if alreadyLvl < 2 then
				if Clicks.nHits == 0 then
					return 15
				else
					return 20	
				end
			elseif alreadyLvl < 20 then
				return 45
			else	
				return 90
			end
		else 
			if alreadyLvl < 2 then
				if Clicks.nHits == 0 then
					return 15
				else
					return 20	
				end
			elseif alreadyLvl < 20 then
				return 30
			else	
				return 60
			end
		end
	elseif mode == "goldrush" then
		if Clicks.nHits == 0 then
			if alreadyLvl < 20 then
				return 20
			elseif alreadyLvl < 40 then
				return 25
			else	
				return 28
			end
			return 25
		elseif restTime == 0 then
			return 1
			-- далее мигаем каждые 2 секунды невзирая на попадания
		else
			-- случай, когда время блика пересчитывается после успешного попадания
			-- не изменяем оставшееся время
			return 1
		end
	else
		assert(false)
	end
end

function GetGameTrackName()
	local mode = PermanentStorage.GetLocalStringOrDef("CurrentMode", "submersion")
	if mode == "submersion" then
		return "Game1"
	elseif mode == "collector" then
		return "Game2"
	elseif mode == "goldrush" then
		return "Game3"
	elseif mode == "diver" then
		return "Game4"
	else
		assert(false)
	end
end

function StartGameMusic()
	Sound:FadeOutTrack("Menu"..PermanentStorage.GetLocalString("Current Tank"), 1)
	Sound:FadeInTrack(GetGameTrackName(), 1, true)
	Sound:FadeInTrack("underwater_amb", 1, true)
end

function FinishGameMusic()
	Sound:FadeOutTrack(GetGameTrackName(), 1)
	Sound:FadeOutTrack("underwater_amb", 1)
	Sound:FadeInTrack("Menu"..PermanentStorage.GetLocalString("Current Tank"), 1, true)
end

--
-- Настройки скоростей рыб
--

--
-- Возвращает скорость _напуганной_ штрафной рыбки в зависимости от времени (прошедшего с пугания)
--
function GetPenaltyFishInScareSpeed(time)
	if time < 1 then
		return lerp(3, 100, time / 1)
	else
		return 100
	end
end

-- Разгон при нахождении
function GetSwimInTimeScale1(time)
	if time < 0.05 then
		return lerp(1, 30, time / 0.05)
	elseif time < 0.95 then
		return 30
	else
		return lerp(30, 10, (time - 0.95) / 0.05)
	end
end

-- Торможение при нахождении
function GetSwimInTimeScale2(time)
	if time < 0.95 then
		return 10
	else
		return lerp(10, 4, (time - 0.95) / 0.05)
	end
end

-- Разгон при применении - здесь time не нормализованный
function GetSwimOutTimeScale1(time)
	if time < 0.4 then
		return lerp(1, 40, time / 0.4)
	else
		return 40
	end
end

-- Конец разгона при применении
function GetSwimOutTimeScale2(time)
	return 40
end

-- Торможение при применении
function GetSwimOutTimeScale3(time)
	if time < 0.9 then
		return 40
	else
		return lerp(40, 1, (time - 0.9) / 0.1)
	end 
end

-- Разгон при улёте
function GetSwimOutTimeScale4(time)
	if time < 1 then
		return lerp(1, 40, time / 1)
	else 
		return 40
	end
end

-- Вернуть ускорение в зависимости от расстояния
function GetSpeedupByDistance(d)
	d = d / 300
	if (d < 1) then
		d = 1
	end
	return d
end

-- Вернуть коэффициент видимости объекта (вроде от 0 до 1)
function GetVisibilityOfObject(id)
	local opaquePixels = SendMessageReply("ObjectsVisibility", "Get opaque pixels of "..id)
	local visiblePixels = SendMessageReply("ObjectsVisibility", "Get visible pixels of "..id)
	local k = visiblePixels * visiblePixels * visiblePixels / opaquePixels / 6250000
	if k > 1 then
		k = 1;
	end
	return k;
end

-- Вернуть минимальную и максимальную видимость для текущего уровня
function GetVisibilityMinMax()
	local min = 0
	local max = 1
	local alreadyLvl = PermanentStorage.GetLocalInt("CurrentStage")
	local ostatok = alreadyLvl - math.floor( alreadyLvl / 2 ) * 2
	local alreadyLoc = SendMessageReply("Locations", "Get current location usings in diver")
	local currentMode = PermanentStorage.GetLocalString("CurrentMode")
	if alreadyLvl < 10 then
		max = 1
		min = 1
	elseif alreadyLvl < 30 then
		max = 0.75
		min = 0.25
	elseif alreadyLvl < 60 then
		max = 0.25
		min = 0
	else 
		max = 1
		min = 0
	end
	if currentMode == "diver" then
		if PermanentStorage.GetLocalBoolOrDef("IsRelaxedMode", false) then
			max = max
		else
			if alreadyLoc == 0 then 
				alreadyLoc = 0.5
			elseif alreadyLoc == 1 then 
				alreadyLoc = 0.2
			else
				alreadyLoc = 0
			end
			max = max + alreadyLoc
			if max > 1 then 
				max = 1
			end
			min = min + alreadyLoc
			if min > 1 then 
				min = 1
			end
		end
	end

	return min, max
end

function GetVisibilityMin()
	local min, max = GetVisibilityMinMax()
	return min
end

function GetVisibilityMax()
	local min, max = GetVisibilityMinMax()
	return max
end

