---@diagnostic disable: lowercase-global

local player = dota.GetLocalPlayer()
local Enum = GetEnums()
local sleepDB = {}
local vec3_origin = dota.Vector(0,0,0)
local CastOrderMethod

--MouseSimulate
mouseSim = {}

mouseSim.cast_via_minimap = false
mouseSim.cast_only_minimap = false
mouseSim.cast_priority = false
mouseSim.cast_without_sim = false
mouseSim.cast_next_tick = false
mouseSim.is_vector_spell = false
mouseSim.cast_smooth_ticks = 1
mouseSim.last_cast_pos = nil

BLOCK = {}

--// LastOrder
local lastOrderInfo = {all={target=0,vec=vec3_origin,order=0,ability=0},filter={target=0,vec=vec3_origin,order=0,ability=0},pike=0}
function DumpLastOrder(order,target,vec,ability)
	lastOrderInfo.all = {target=target,order=order,vec=vec,ability=ability}
	if (order > Enum.ORDER_TAKERUNE and order < Enum.ORDER_AUTOCAST) or order == Enum.ORDER_UPDGRADEABILITY or order == Enum.ORDER_CAST_TOGGLE_ALT then
		return
	elseif ability > 1 then 
		local spell = dota.GlobalInstanceManager:GetClientEntityList():GetClientAbility(ability)
		if spell then 
			local behavior = spell:GetBehavior()
			if (HasFlag(behavior,Enum.BEHAVIOR_IMMEDIATE) and HasFlag(behavior,Enum.BEHAVIOR_NO_TARGET)) or HasFlag(behavior,Enum.BEHAVIOR_TOGGLE) then 
				return
			end
			if spell:GetName() == "item_hurricane_pike" then
				lastOrderInfo.pike = target
			end
		end
	end
	lastOrderInfo.filter = lastOrderInfo.all
end 
function IsLastOrder(order, ent, ability, all)
	if all then
		local order_f = lastOrderInfo.all
		return order_f.order == order and (not ent or order_f.target == ent:GetIndex()) and (not ability or order_f.ability==ability:GetIndex())
	else
		local order_f = lastOrderInfo.filter
		return order_f.order == order and (not ent or order_f.target == ent:GetIndex()) and (not ability or order_f.ability==ability:GetIndex())
	end
end
function GetLastOrderInfoFilter()
	return lastOrderInfo.filter
end
function IsLastPike(self,target)
	return HaveModifier(self,"modifier_item_hurricane_pike_range") and lastOrderInfo.pike == target:GetIndex()
end 

--// Orders Wrappers

--// Sleep
function SleepCheck(id)
	if not id then id = "NAN" end
	return not sleepDB[id] or dota.GetTick() > sleepDB[id]
end

function GetSleepTime(id)
	if sleepDB[id] then
		return math.max(0,sleepDB[id]-dota.GetTick())
	else 
		return 0
	end 
end

function Sleep(ms,id)
	if not id then id = "NAN" end
	if not sleepDB[id] or sleepDB[id] < dota.GetTick() + ms then
		sleepDB[id] = dota.GetTick() + ms
	end
end

function RemoveSleep(id)
	sleepDB[id] = nil
end 

local function GetIssuer(self)
	-- if not self or type(self) == "table" then 
		-- return Enum.ISSUER_SELECTED_UNITS
	-- else 
		-- return Enum.ISSUER_PASSED_UNIT_ONLY
	-- end 
	return Enum.ISSUER_PASSED_UNIT_ONLY
end 

local function GetSelf(self)
	return self
end 

--// Selection

function SelectUnit(unit)
	if not unit or type(unit) == "table" then 
		return {}
	end
	local _prevSelect = {}	
	local selection = player:GetSelection()	
	if #selection >0 and selection[1]:GetIndex() ~= unit:GetIndex() then
		_prevSelect = selection
		player:SelectUnit(unit)
	end
	return _prevSelect
end

function SelectUnits(units)
	local _prevSelect = player:GetSelection()	
	local first = false 
	for i,v in ipairs(units) do
		if not first then
			player:SelectUnit(v)
			first = true
		else 
			player:SelectAdd(v)
		end 
	end
	return _prevSelect
end

function SelectBack(units)
	if units and #units > 0 then
		for i,v in ipairs(units) do
			if i == 1 then
				player:SelectUnit(v)
			else
				player:SelectAdd(v)
			end
		end
	end
end

function SelectionRemove(index)
	local first = false
	local selection = player:GetSelection()
	for i,v in ipairs(selection) do
		if v:GetIndex()~=index then
			if not first then
				player:SelectUnit(v)
				first = true
			else
				player:SelectAdd(v)
			end
		end
	end
end 

function IsSelected(index,source)
	local selection = player:GetSelection()
	for i,v in ipairs(selection) do
		if v:GetIndex() == index then
			return true
		end
	end
	-- if source then 
		-- return source:GetIndex()==index
	-- end 
	return false
end

function IsSelectedOne(index,source)	
	-- if source then 
		-- return source:GetIndex() == index
	-- else
		local selection = player:GetSelection()
		return selection[1] and selection[1]:GetIndex()==index
	--end
end

--// Order Helper 
local function OffSimStatus()
	mouseSim.cast_via_minimap = false
	mouseSim.cast_only_minimap = false
	mouseSim.cast_priority = false
	mouseSim.cast_without_sim = false
	mouseSim.cast_next_tick = false
	mouseSim.is_vector_spell = false
	mouseSim.cast_smooth_ticks = 1
end

local function GetSimInfo(target,save_states)
	local extra =  {
		target = target, 
		cast_via_minimap = mouseSim.cast_via_minimap,
		cast_only_minimap = mouseSim.cast_only_minimap,
		cast_priority = mouseSim.cast_priority, 
		cast_without_sim = mouseSim.cast_without_sim,
		cast_next_tick = mouseSim.cast_next_tick,
		is_vector_spell = mouseSim.is_vector_spell,
		cast_smooth_ticks = mouseSim.cast_smooth_ticks
	}
	if target then
		mouseSim.last_cast_pos = target.x and target or target:GetAbsOrigin()
	else
		mouseSim.last_cast_pos = nil
	end
	if not save_states then
		OffSimStatus()
	end
	return extra
end 

--// Orders  (Move(nil,pos)-> move currents entity, Move(ents[],pos) -> move array of entity)
function Move(self,vec,ex,direct)
	local ord = direct and Enum.ORDER_MOVE_TO_DIRECTION or Enum.ORDER_MOVETOPOSITION
	CastOrderMethod(ord, 0, vec, 0, GetIssuer(self), GetSelf(self), ex, 	GetSimInfo(vec))
end

function MoveOne(self,vec,ex,direct)
	local ord = direct and Enum.ORDER_MOVE_TO_DIRECTION or Enum.ORDER_MOVETOPOSITION
	CastOrderMethod(ord, 0, vec, 0, Enum.ISSUER_CURRENT_UNIT_ONLY, GetSelf(self), ex, 	GetSimInfo(vec))
end

function MoveIn(self,vec,time)
	if SleepCheck("move_in") then
		Sleep(time or 90,"move_in")
		Move(self,vec or dota.Get3dPositionUnderCursor())
		return 1
	else
		OffSimStatus()
	end 
end 

function MoveToDirection(self,vec,ex)
	Move(self,vec,ex,true)
end


function AttackMove(self,vec,ex)
	CastOrderMethod(Enum.ORDER_ATTACKPOSITION, 0, vec, 0, GetIssuer(self), GetSelf(self), ex, 	GetSimInfo(vec))
end


function Attack(self,unit,ex)

	local is_array = not self or type(self) == "table"

	if ex and not is_array and not CanAttack(self) then
		OffSimStatus()
		return 
	end

	if not unit:IsDotaNPC() or (not IsInvul(unit) and (not IsAttackImmune(unit) or (not is_array and CanAttackInGhost(dota.EntityToBaseNPC(self)))))  then
		DumpLastOrder(Enum.ORDER_ATTACKENTITY,unit:GetIndex(),vec3_origin,0)
		CastOrderMethod(Enum.ORDER_ATTACKENTITY, unit:GetIndex(), vec3_origin, 0, GetIssuer(self), GetSelf(self), ex, 	GetSimInfo(unit))
	else 
		OffSimStatus()
	end 
	return true
end

function AttackSafe(self,unit,ex)
	if not unit or not CanAttack(self) then
		OffSimStatus()
		return
	end
	return Attack(self,unit,ex)
end


function Follow(self,unit,ex)
	CastOrderMethod(Enum.ORDER_MOVETOENTITY, unit:GetIndex(), vec3_origin, 0, GetIssuer(self), GetSelf(self), ex, 	GetSimInfo(unit))
end


function DropItem(self,item,pos,ex)
	CastOrderMethod(Enum.ORDER_DROPITEM, 0, pos, item:GetIndex(), GetIssuer(self), GetSelf(self), ex, 	GetSimInfo(pos))
end

function SendItem(self,item, target, ex)
	CastOrderMethod(Enum.ORDER_GIVEITEM, target:GetIndex(), vec3_origin, item:GetIndex(), GetIssuer(self), GetSelf(self), ex, GetSimInfo(target))
end

function PickItem(self,item,ex)
	CastOrderMethod(Enum.ORDER_TAKEITEM, item:GetIndex(), vec3_origin, 0, GetIssuer(self), GetSelf(self), ex, 	GetSimInfo(item))
end

function PickRune(self,item,ex)
	CastOrderMethod(Enum.ORDER_TAKERUNE, item:GetIndex(), vec3_origin, 0, GetIssuer(self), GetSelf(self), ex, 	GetSimInfo(item))
end

function PickItemSafe(self,item,ex)
	if item:IsValid() then
		PickItem(self,item,ex)
	else
		OffSimStatus()
	end
end


function Stop(self)
	mouseSim.cast_without_sim = true
	CastOrderMethod(Enum.ORDER_STOP, 0, vec3_origin, 0, GetIssuer(self), GetSelf(self), false,	GetSimInfo())
end

function HoldPosition(self,ex)
	mouseSim.cast_without_sim = true
	CastOrderMethod(Enum.ORDER_HOLDPOSITION, 0, vec3_origin, 0, GetIssuer(self), GetSelf(self), ex,	GetSimInfo())
end

function EmptyOrder(self)
	mouseSim.cast_without_sim = true
	CastOrderMethod(Enum.ORDER_CONTINUE, 0, vec3_origin, 0, GetIssuer(self), GetSelf(self), false, GetSimInfo())
end


--// Ignore
function CastToggleAbility(self,ability,ex)
	CastOrderMethod(Enum.ORDER_TOGGLEABILITY, 0, vec3_origin, ability:GetIndex(), GetIssuer(self), GetSelf(self), ex, GetSimInfo())
end

function CastAltAbility(self,ability,ex)
	CastOrderMethod(Enum.ORDER_CAST_TOGGLE_ALT, 0, vec3_origin, ability:GetIndex(), GetIssuer(self), GetSelf(self), ex, GetSimInfo())
end

function PingOnAbility(ability)
	ability:AbilityAlert()
	-- CastOrderMethod(Enum.ORDER_PING_ABILITY,0,vec3_origin,		index,0, GetSelf(self), false, GetSimInfo())
end

function MoveItem(self,item, slot)
	CastOrderMethod(Enum.ORDER_MOVEITEM, slot, vec3_origin, item:GetIndex(), GetIssuer(self), GetSelf(self), false, GetSimInfo())
end

--[[ function MoveNeutralToStash(self,slot)
	CastOrderMethod(Enum.ORDER_DROP_ITEM_AT_FOUNTAIN, slot, vec3_origin, 0, GetIssuer(self), GetSelf(self), false, GetSimInfo())
end 

function PickNeutralFromStash(self,item)
	CastOrderMethod(Enum.ORDER_TAKE_ITEM_FROM_NEUTRAL_ITEM_STASH, 0, vec3_origin, item:GetIndex(), GetIssuer(self), GetSelf(self), false, 	GetSimInfo())
end ]]

function DisassembleItem(self,item)
	CastOrderMethod(Enum.ORDER_DISASSEMBLEITEM, 0, vec3_origin, item:GetIndex(), GetIssuer(self), GetSelf(self), false, GetSimInfo())
end

function BuyItem(self,id)
	CastOrderMethod(Enum.ORDER_BUYITEM, 0, vec3_origin, id, GetIssuer(self), GetSelf(self), false, GetSimInfo())
	return true
end

function SellItem(self,item)
	CastOrderMethod(Enum.ORDER_SELLITEM, 0, vec3_origin, item:GetIndex(), GetIssuer(self), GetSelf(self), false, GetSimInfo())
end

function UnlockItem(self,item)
	CastOrderMethod(Enum.ORDER_SET_ITEM_COMBINE_LOCK, 0, vec3_origin, item:GetIndex(), GetIssuer(self), GetSelf(self), false, GetSimInfo())
end

function ChangePT(self,item,state)	
	local curent
	if item:GetName() == "item_power_treads" then 
		curent = item:GetPowerTreadsType()
	else 
		curent = item:GetPropertyInt("C_DOTA_Item_Vambrace","m_iStat")
	end 
	for i = 1, (state - curent) % Enum.PT_LAST do	
		CastAbility(self,item)	
	end
	return curent
end

function Buyback(self)
	CastOrderMethod(Enum.ORDER_BUYBACK, 0, vec3_origin, 0, GetIssuer(self), GetSelf(self), false, GetSimInfo())
end

function LearnAbility(self,spell)
	CastOrderMethod(Enum.ORDER_UPDGRADEABILITY, 0, vec3_origin, spell:GetIndex(), GetIssuer(self), GetSelf(self), false, GetSimInfo())
end 


--// Now Orders (выполнятся всегда первыми)
function StopNow()
	player:Stop()
end

--// Cast Ability
function CastAbility(self,ability,target,ex)	
	if not target then 
		CastOrderMethod(Enum.ORDER_USEABILITY, 0, 			vec3_origin, ability:GetIndex(), GetIssuer(self), GetSelf(self), ex, GetSimInfo())
	elseif target.x then
		CastOrderMethod(Enum.ORDER_USEABILITYPOSITION, 0, 	target, ability:GetIndex(), GetIssuer(self), GetSelf(self), ex, GetSimInfo(target))
	else
		local is_me = (self:GetIndex() == target:GetIndex())
		if is_me or not IsUntargetable(target) then
			local sim = target
			if is_me then sim = nil	end		
			CastOrderMethod(Enum.ORDER_USEABILITYENTITY, target:GetIndex(), vec3_origin, ability:GetIndex(), GetIssuer(self), GetSelf(self), ex,	GetSimInfo(sim))
		else 
			OffSimStatus()
		end
	end
	return true
end

function CastAbilityEx(self,ability,target)
	return CastAbility(self,ability,target, true)
end

function CastAbilityTree(self,ability,target,ex)
	CastOrderMethod(Enum.ORDER_USEABILITTREE,dota.GetTreeId(target:GetIndex()),vec3_origin,ability:GetIndex(), GetIssuer(self), GetSelf(self), ex , GetSimInfo(target))
	return true
end

function SafeCastAbility(self,ability,target)
	if ability and CanBeCasted(ability) then
		return CastAbility(self,ability,target)
	else
		OffSimStatus()
	end 
end

function CastDotaAbility(self,numb,smart)
	local prev = SelectUnit(self)	
	if not smart then 
		dota.ExecuteCommand("dota_ability_execute "..(numb-1).." 1")
	else 
		dota.ExecuteCommand("dota_ability_quickcast "..(numb-1).." 1")		
	end 
	for z,x in ipairs(prev) do					
		player:SelectAdd(x)
	end	
end

function CastVectorAbility(self,ability,pos2,pos)	
	pos2.z = dota.GetGroundHeight(pos2)
	MoveCameraIfNotOnScreen(pos2)
	pos = Otrezok(pos,pos2,75)		
	CastOrderMethod(Enum.ORDER_VECTOR_TARGET_POSITION, 0, pos, ability:GetIndex(), GetIssuer(self), GetSelf(self), false, GetSimInfo(nil,true))
	mouseSim.is_vector_spell = true	
	return CastAbility(self,ability,pos2)	
end

function CastVectorTargetAbility(self,ability,target,pos)
	CastOrderMethod(Enum.ORDER_VECTOR_TARGET_POSITION, target:GetIndex(), pos, ability:GetIndex(), GetIssuer(self), GetSelf(self), false, GetSimInfo()) 
	mouseSim.is_vector_spell = true
	return CastAbility(self,ability,target)
end 

function CastVectorTargetAbilityTree(self,ability,target,pos)
	pos = Otrezok(pos,target,75)
	CastOrderMethod(Enum.ORDER_VECTOR_TARGET_POSITION, 0, pos, ability:GetIndex(), GetIssuer(self), GetSelf(self), false, GetSimInfo()) 
	mouseSim.is_vector_spell = true
	return CastAbilityTree(self,ability,target)
end 

function AutoCastAbility(self,ability)
	CastOrderMethod(Enum.ORDER_AUTOCAST,0,vec3_origin,ability:GetIndex(),GetIssuer(self), GetSelf(self), false, GetSimInfo())
end

function CastAbilityMaxRange(self,ability,pos,range)
	if GetDistance2D(self,pos)>range then 
		return CastAbility(self,ability,Otrezok(pos,self:GetAbsOrigin(),range))
	else 
		return CastAbility(self,ability,pos)
	end 
end

--врапер для функции выше
function CastVectorVectorAbility(self,ability,target,range,time,anlgle)
	local new2,new1 = GetVectorVectorAbility(self,target,range,time,anlgle)
	CastVectorAbility(self,ability,new2,new1)
end

function FreeSlots(self,start,maximum)
	local count = 0
	local inventory = self:GetInventory()
	for i = start, maximum do
        local item = inventory:GetItemInSlot(i)
        if not item then
			count = count + 1
        end
	end
	return count
end 

--// Evader
function ExportAutoEvade(setting, info, linear)

    if setting["AutoEvade"] then
        return
    end
	
    if linear and linear.self:IsAlive() then
        if info.AbilityName == "shadow_demon_shadow_poison" and dota.GetGameTime() > 600 then
            return
        end
		
		local enabled = (info.IsDisable or info.UltNuke or info.MuertaQ or dota.GetGameTime()<600) and not setting["block_"..info.AbilityName]

		local hull = linear.self:GetHullRadius()+16
        local time = EvadeLinearSpell(linear.self, linear.pos, linear.pos2, linear.radius+hull, linear.time, enabled, info)

		if enabled then 
			BlockOrders()
		end
		
        if (time == false) then
            if (info.LinearBlock) then
                MarsQCHeck(info, {origin=linear.pos,radius=linear.radius},linear.pos2)
            end
			return true
        elseif (time and not info.OnlyMoveDodge) then			
            BlockOrders(time, {pos1=linear.pos, pos2=linear.pos2, radius=(linear.radius or linear.range), 
			linearId=linear.linearId, particleId=linear.particleId, via_bkb=info.MagicImmunityPierce})
        end
    end
end

function BlockOrders(time, data)
	BLOCK = {}
	if time then 
		BLOCK.last_id = newHum.LastOrderId()
		BLOCK.time = dota.GetTick() + time
		BLOCK.CheckOrder = function(IsCheatOrder)
			return not IsCheatOrder or newHum.CurrentOrderId() == 0 or newHum.CurrentOrderId() > BLOCK.last_id
		end
	else 
		BLOCK.time = nil
	end 
	if data then
		BLOCK.pos1 = data.pos1
		BLOCK.pos2 = data.pos2
		BLOCK.radius = data.radius
		BLOCK.linearId = data.linearId
		BLOCK.particleId = data.particleId
		BLOCK.via_bkb = data.via_bkb
	end
end

function EvadeLinearSpell(self,pos,pos2,range,time,setting,mgc_check)

	if (mgc_check and not mgc_check.MagicImmunityPierce and GetBKBTime(self) > time) or not self:IsAlive() then
		return nil
	end

	local fly = IsFlying(self)
	local mySpeed= self:GetMoveSpeed()
	if HaveModifier(self,"modifier_invoker_ice_wall_slow_debuff") then mySpeed = 100 end 
	local myPos = self:GetNetworkOrigin()
	local dis_to_segment = distToSegment(myPos,pos,pos2)
	if dis_to_segment < range then
		local bestTime = 100
		local goTo = nil						
		for i = 0,360,45 do
			for a = 24, time*mySpeed, 24 do
				local newVec = dota.Vector(myPos.x + a * math.cos(GetRotR(self)), myPos.y + a * math.sin(GetRotR(self)), 0)
				local rVec= RotatePosition(myPos, i, newVec)
				
				local newVec2 = dota.Vector(myPos.x + (a+24) * math.cos(GetRotR(self)), myPos.y + (a+24) * math.sin(GetRotR(self)), 0)
				local rVec2= RotatePosition(myPos,i, newVec2)
				
				if fly or dota.IsFreePosition(rVec2) then --or GetDistance2D(rVec2,dota.Vector(-2306,1778,0))<300
					if distToSegment(rVec,pos,pos2) > range and bestTime > GetTurnTime(self,rVec)/1000+GetDistance2D(myPos,rVec)/mySpeed and OnScreen(rVec) then
						bestTime = GetTurnTime(self,rVec)/1000+GetDistance2D(myPos,rVec)/mySpeed
						goTo = rVec
					end
				else
					break
				end
				
			end
		end
		if goTo and bestTime < time and CanMove(self) then --and not HaveModifier(self,"modfiier")	
			if setting then
				Msg("✓ ",Enum.COLOR_SUCCESS,"action_move",750)
				Move(self,goTo)				 
				return ((GetDistance2D(self,goTo)+150)/mySpeed+0.25)*1000
			end 
		end 
		return false
	else
		local is_running = IsRunning(self)
		if is_running then						
			local newVec = dota.Vector(myPos.x + mySpeed*time * math.cos(GetRotR(self)), myPos.y + mySpeed*time * math.sin(GetRotR(self)), 0)
			dis_to_segment = distToSegment(newVec,pos,pos2)
			if dis_to_segment < range then 
				if setting then 
					Msg("✓ ",Enum.COLOR_SUCCESS,"action_stop",750)
					Stop(self) 
					return (time+0.27)*1000
				end 
			end
		end
		if dis_to_segment < range + 600 then 
			Msg("✓ ",Enum.COLOR_SUCCESS,"action_stop",450)
			return (time+0.27)*1000
		end
	end 
end 

function EvadeCircleSpell(self,pos,range,time,setting,mgc_check)

	if (mgc_check and not mgc_check.MagicImmunityPierce and GetBKBTime(self) > time) or not self:IsAlive() then
		return false
	end 
	local mySpeed= self:GetMoveSpeed()
	local fly = IsFlying(self)
	if HaveModifier(self,"modifier_invoker_ice_wall_slow_debuff") then mySpeed = 100 end 
	local myPos = self:GetNetworkOrigin()
	local dis_to_segment = GetDistance2D(myPos,pos)
	local rotR = GetRotR(self)+GetTurnRad(self)
	if dis_to_segment < range and GetDistance2D(GetSimplePrediction(self,time),pos) < range then
		local bestTime = 100
		local goTo = nil	
		for i = 0,360,45 do
			for a = 24, time*mySpeed, 24 do
				local newVec = dota.Vector(myPos.x + a * math.cos(rotR), myPos.y + a * math.sin(rotR), 0)
				local rVec= RotatePosition(myPos, i, newVec)
				
				local newVec2 = dota.Vector(myPos.x + (a+24) * math.cos(rotR), myPos.y + (a+24) * math.sin(rotR), 0)
				local rVec2= RotatePosition(myPos, i, newVec2)
				
				if fly or dota.IsFreePosition(rVec2) then --or GetDistance2D(rVec2,dota.Vector(-2306,1778,0))<300
					if GetDistance2D(rVec,pos) > range and bestTime > GetTurnTime(self,rVec)/1000+GetDistance2D(myPos,rVec)/mySpeed and OnScreen(rVec) then
						bestTime = GetTurnTime(self,rVec)/1000+GetDistance2D(myPos,rVec)/mySpeed
						goTo = rVec
					end
				else
					break
				end
				
			end
		end
		if goTo and bestTime < time and CanMove(self) then --and not HaveModifier(self,"modfiier")	
			if setting then 
				Msg("✓ ",Enum.COLOR_SUCCESS,"action_stop",750)
				Move(self,goTo)				 
				return ((GetDistance2D(self,goTo)+150)/mySpeed+0.25)*1000
			end 
		else 
			return false
		end
	elseif IsRunning(self) then						
		local newVec = dota.Vector(myPos.x + mySpeed*time * math.cos(rotR), myPos.y + mySpeed*time * math.sin(rotR), 0)
		dis_to_segment = GetDistance2D(newVec,pos)	
		if dis_to_segment < range then 
			if setting then 
				Msg("✓ ",Enum.COLOR_SUCCESS,"action_stop",750)
				Stop(self) 
				return (time+0.27)*1000
			end 
		end 			
	end		
end 


--// NEW HUM 
function PrepareOrderFnVirtual(order, target, vec, ability, order_issuer, self, queue, custom)
	-- aaa("pre"..Print(order,ability))
	-- aaa(debug.traceback())

	if dota.GameRules.IsPaused() then 
		return
	end

	local sim = ((not custom.target and {}) or (custom.target.x and {vec=custom.target}) or {target=custom.target})
	
	local new_order = {
		order=order,
		target=target,
		vec=(vec or vec3_origin),
		ability=ability,
		queue = queue,
		order_issuer = order_issuer,
		self = self,
		sim=sim,

		cast_via_minimap=custom.cast_via_minimap,
		cast_only_minimap=custom.cast_only_minimap,
		cast_priority=custom.cast_priority,
		cast_without_sim=custom.cast_without_sim,
		cast_next_tick=custom.cast_next_tick,
		cast_smooth=custom.cast_smooth_ticks,
		
		is_vector = (order == Enum.ORDER_VECTOR_TARGET_POSITION or custom.is_vector_spell)
	}

	newHum.SetOrderFromLua(new_order)
end 


--// Cast Helper
function GetVectorVectorAbility(self,target,range,time,anlgle)
	local pos = (not target.x and time and GetSimplePrediction(target,time)) or target
	local new = Otrezok(pos,self:GetNetworkOrigin(),GetDistance2D(pos,self:GetNetworkOrigin())+0)
	local newE = Otrezok(pos,self:GetNetworkOrigin(),GetDistance2D(pos,self:GetNetworkOrigin())+range)
	local new1 = RotatePosition(pos, -1*(anlgle or 90), newE)
	local new2 = RotatePosition(pos, (anlgle or 90), new)
	return new2,new1
end 

function MoveCameraIfNotOnScreen(position)
	
	if not position then 
		return 
	end
	if not position.x then 
		position = position:GetAbsOrigin()
	end
	
	if not OnScreen(position) then 
		MoveCamera(position)
	end
	
	
end

function MoveCameraSmooth(position)

	if OnScreen(position) then 
		return true
	else
		local cam_pos = camera.GetPosition()
		local split = math.max(450, GetDistance2D(cam_pos,position)/10)
		local new_pos = Otrezok(position,cam_pos,split)
		MoveCamera(new_pos)
		return false
	end
	
end

function InNearCursor(ent,range)
	return GetDistance2D(ent,dota.Get3dPositionUnderCursor()) < (range or Enum.MAX_MOUSE_RANGE)
end 

function MapToMinimapEnt(v)
	local pos = v:GetAbsOrigin()
	return dota.WorldToMinimap(pos) 
end

function MapToMinimap(x, y)
	return dota.WorldToMinimap(dota.Vector(x,y,0)) 
end

function MinimapToMap()

	local vec_result = dota.MinimapToWorld(dota.GetMousePosition())
	if vec_result.z == 0 then 
		return nil  
	else 
		vec_result.z = dota.GetGroundHeight(vec_result)
		return vec_result
	end 	

end

function RefreshCast()
	sleepDB = {}
	BLOCK = {}

	OffSimStatus()
end

function CreateTime(ent,time)
	return dota.GetMapTime() - ent:GetCreateTime() > (time or 0.5)
end



--// Helper Cast Functions
function IsOrderNotBreakMove(order)
	return Enum.ORDER_TOGGLEABILITY == order or
	Enum.ORDER_UPDGRADEABILITY == order or
	Enum.ORDER_BUYITEM == order or
	Enum.ORDER_SELLITEM == order or
	Enum.ORDER_DISASSEMBLEITEM == order or
	Enum.ORDER_MOVEITEM == order or
	Enum.ORDER_AUTOCAST == order or
	Enum.ORDER_GLYPH == order or
	Enum.ORDER_PING_ABILITY == order or
	Enum.ORDER_RADAR == order or
	Enum.ORDER_DISASSEMBLEITEM == order or
	Enum.ORDER_MOVEITEM == order or
	Enum.ORDER_CAST_TOGGLE_ALT == order
end 
function Print(order,ability)
	local time = SecondsToClock(dota.GetGameTime(),true).." "..dota.GetTick()
	if ability and ability ~= 0 then 
		local spell = dota.GlobalInstanceManager:GetClientEntityList():GetClientAbility(ability)
		if spell and spell:GetName() then 					
			return "order "..spell:GetName().." - "..time
		end 
	elseif order ==  Enum.ORDER_MOVETOPOSITION then 
		return "order move".." - "..time
	elseif order ==  Enum.ORDER_MOVE_TO_DIRECTION then 
		return "order move direct".." - "..time
	elseif order == Enum.ORDER_MOVETOENTITY then 
		return "order follow".." - "..time
	elseif order == Enum.ORDER_ATTACKPOSITION then 
		return "order attack pos".." - "..time
	elseif order == Enum.ORDER_ATTACKENTITY then 
		return "order attack".." - "..time
	else 
		return "order "..order.." - "..time
	end 
end 

--// Cast Without Hum
function PrepareOrderFnOld(order, target, vec, ability, order_issuer, self, queue, custom)

	OffSimStatus()

	if dota.GameRules.IsPaused() or order == Enum.ORDER_NONE then 
		return
	end

	local prev = nil
	if self then 
		prev = type(self) == "table" and SelectUnits(self) or SelectUnit(self)
	end 
	player:PrepareUnitOrders(order, target, vec, ability, order_issuer, nil, queue or false)
	if prev then 
		SelectBack(prev)
	end

end 

--= Выбор между новым и старым
function SelectHumOrder() 
	if not newHum.IsNewHum() then
		CastOrderMethod = PrepareOrderFnOld
	else
		CastOrderMethod = PrepareOrderFnVirtual
	end
end

SelectHumOrder() 