function getcode(num,nums)
	local hm = ""
	
	for i=1,nums do
		hm = hm .. "0"
	end
	
	local result = string.sub(hm .. tostring(num), 0-nums)
	
	return result
end

function codepos(code,nums)
	local hm = string.sub(code, 0-nums*2)
	
	local x = tonumber(string.sub(hm, 1, nums))
	local y = tonumber(string.sub(hm, 0-nums))
	
	return x,y
end

function inbounds(x,y)
	return (x >= 0) and (y >= 0) and (x < map.width) and (y < map.height)
end

function gettileid(x,y)
	local result = x + y * map.width
	return result
end

function dirtopos(dir)
	local drs = dirs[tonumber(dir) + 1]
	
	local x = drs[1]
	local y = drs[2]
	
	return x,y
end

function findstruct(x,y,structtype,minstatus_)
	local opts = {}
	local pointers = {}
	local minstatus = minstatus_ or 0
	
	for i,struct in ipairs(structs) do
		local stype = MF_getstring(struct.id,TYPE)
		local user = MF_getvalue(struct.id,USER)
		local disabled = MF_getvalue(struct.id,DISABLED)
		
		if (stype == structtype) and (user == 0) and (disabled == 0) and (struct.status >= minstatus) then
			local sx,sy = MF_getvalue(struct.id,XTILE),MF_getvalue(struct.id,YTILE)
			local dist = math.abs(sy - y) + math.abs(sx - x)
			
			local code = getcode(dist,3) .. tostring(struct.id)
			
			table.insert(opts, code)
			pointers[code] = struct
		end
	end
	
	table.sort(opts)
	
	for i,code in ipairs(opts) do
		local struct = pointers[code]
		local sx,sy = MF_getvalue(struct.id,XTILE),MF_getvalue(struct.id,YTILE)
		
		local nearby = MF_getvalue(struct.id,NEARBY)
		if (nearby == 0) then
			nearby = 1
		end
		
		if (x ~= sx) or (y ~= sy) then
			local path,success,uw = astar(x,y,sx,sy,searchlimit,nearby)
			
			if success then
				return struct,nearby,uw
			end
		else
			return struct,nearby,uw
		end
	end
	
	return nil,nil,nil
end

function finditem(x,y,itemtype)
	local opts = {}
	local pointers = {}
	
	for i,item in ipairs(items) do
		local stype = MF_getstring(item.id,TYPE)
		local carry = MF_getvalue(item.id,CARRY)
		local disabled = MF_getvalue(item.id,DISABLED)
		local equip = MF_getvalue(item.id,EQUIP)
		local rx,ry = MF_getpos(item.id)
		
		if (stype == itemtype) and (disabled == 0) and (carry == 0) and (equip == 0) and (rx >= 0) and (ry >= 0) and (rx < screenw) and (ry < screenh) then
			local sx,sy = MF_getvalue(item.id,XTILE),MF_getvalue(item.id,YTILE)
			local dist = math.abs(sy - y) + math.abs(sx - x)
			
			local code = getcode(dist,3) .. tostring(item.id)
			
			table.insert(opts, code)
			pointers[code] = item
		end
	end
	
	table.sort(opts)
	
	for i,code in ipairs(opts) do
		local item = pointers[code]
		local sx,sy = MF_getvalue(item.id,XTILE),MF_getvalue(item.id,YTILE)
		
		if (x ~= sx) or (y ~= sy) then
			local path,success,uw = astar(x,y,sx,sy,searchlimit)
			
			if success then
				return item,uw
			end
		else
			return item,uw
		end
	end
	
	return nil,nil
end

function findfoe(unit)
	local x,y = MF_getvalue(unit.id,XPOS),MF_getvalue(unit.id,YPOS)
	local opts = {}
	local pointers = {}
	
	for i,foe in ipairs(foes) do
		local sx,sy = MF_getvalue(foe.id,XPOS),MF_getvalue(foe.id,YPOS)
		local rx,ry = MF_getpos(foe.id)
		
		if (rx >= 0) and (ry >= 0) and (rx < screenw) and (ry < screenh) then
			local dist = math.floor(math.sqrt((sy - y) ^ 2 + (sx - x) ^ 2))
			
			if (dist < 360) then
				local code = getcode(dist,6) .. tostring(foe.id)
				table.insert(opts, code)
				pointers[code] = foe
			end
		end
	end
	
	table.sort(opts)
	
	for i,code in ipairs(opts) do
		local foe = pointers[code]
		
		return foe
	end
	
	return nil
end

function fireat(unit,foe)
	local laserid = MF_create("laser")
	
	local x,y = MF_getvalue(unit.id,XPOS),MF_getvalue(unit.id,YPOS)
	local sx,sy = MF_getvalue(foe.id,XPOS),MF_getvalue(foe.id,YPOS)
	
	local dir = 0 - math.atan2(sy - y, sx - x)
	local xvel = math.cos(dir) * 40
	local yvel = 0 - math.sin(dir) * 40
	
	MF_setvalue(laserid,XVEL,xvel)
	MF_setvalue(laserid,YVEL,yvel)
	MF_setvalue(laserid,ONLINE,1)
	MF_setvalue(laserid,XPOS,x)
	MF_setvalue(laserid,YPOS,y)
end

function finddamaged(x,y)
	local opts = {}
	local pointers = {}
	local minstatus = minstatus_ or 0
	
	for i,room in ipairs(rooms) do
		local damage = MF_getvalue(room.id,HP)
		
		if (damage > 30) then
			local sx,sy = MF_getvalue(room.id,XTILE),MF_getvalue(room.id,YTILE)
			local dist = math.abs(sy - y) + math.abs(sx - x)
			
			local code = getcode(dist,3) .. tostring(room.id)
			
			table.insert(opts, code)
			pointers[code] = room
		end
	end
	
	table.sort(opts)
	
	for i,code in ipairs(opts) do
		local struct = pointers[code]
		local sx,sy = MF_getvalue(struct.id,XTILE),MF_getvalue(struct.id,YTILE)
		
		if (x ~= sx) or (y ~= sy) then
			local path,success,uw = astar(x,y,sx,sy,searchlimit,2)
			
			if success then
				return struct,uw
			end
		else
			return struct,uw
		end
	end
	
	return nil,nil
end

function delete(id)
	for i,v in ipairs(units) do
		local target = MF_getvalue(v.id,TARGET)
		local equip = MF_getvalue(v.id,EQUIP)
		
		if (target == id) then
			cancel(v)
		end
		
		if (equip == id) then
			MF_setvalue(v.id,EQUIP,0)
			cancel(v)
		end
		
		if (v.id == id) then
			table.remove(units, i)
			break
		end
	end
	
	for i,v in ipairs(items) do
		if (v.id == id) then
			table.remove(items, i)
			break
		end
	end
	
	for i,v in ipairs(structs) do
		if (v.id == id) then
			table.remove(structs, i)
			break
		end
	end
	
	cancel_id(id)
	MF_delete(id)
end

function button(id,name,x,y,dis_)
	local unitid = MF_create("hud_button")
	local dis = dis_ or 0
	
	MF_setpos(unitid,x,y)
	MF_setlayer(unitid,1)
	MF_setstring(unitid,TYPE,id)
	MF_setstring(unitid,NAME,name)
	MF_setvalue(unitid,B_DISABLED,dis)
	
	return unitid
end

function isnearby(x1,y1,x2,y2)
	local xdist = math.abs(x1 - x2)
	local ydist = math.abs(y1 - y2)
	
	if (xdist == 0) and (ydist == 0) then
		return 1
	elseif (xdist <= 1) and (ydist <= 1) then
		return 2
	end
	
	return 0
end

function returntotask(unit)
	if (string.len(unit.actualtask) > 0) then
		MF_setstring(unit.id,TASK,unit.actualtask)
	else
		cancel(unit)
		MF_setstring(unit.id,TASK,"IDLE")
	end
	
	unit.actualtask = ""
end

function deletefoe(id)
	for i,v in ipairs(foes) do
		if (v.id == id) then
			table.remove(foes, i)
			break
		end
	end
	
	MF_delete(id)
end