<?xml version="1.0" encoding="utf-8"?><waypoints>
<onLoad>
	--         Rock5's Element Converter
	--               Version 1.2
	--
	-- Thank's to Lisa for her original version

	-- User options ----------------------------

	local PauseBetweenCasts = 100			-- In ms
	local BallSizeToClick = 1.1 			-- Values between 0.5 and 2.5 (1.1 is optimal. Don't change)
	local GetFailureTitle = true			-- Set true to get title "There is nothing I cannot Break!" only if you don't have it.
	local ExchangeForCertificates = true	-- Auto exchanges Universal Components for Certificates.

	local When_Finished = "end"
		-- "end" to end script, "relog" to log next character, "charlist" to log next in 'charlist' and "waypointfilename" to load that waypointfile.

	local CharList = {}
		-- Character list to use when using the "charlist" option above. Requires my "userfunction_LoginNextChar" userfunction.
		-- Find it here. http://www.solarstrike.net/phpBB3/viewtopic.php?p=10350
		--		eg.
		--		CharList = {
		--			{account=4,chars={}},
		--			{account=8,chars={1}},
		--			{account=7,chars={1,2,5}},
		--		}

	--------------------------------------------

	local HaveFailureTitle = RoMScript("} for i = 0, GetTitleCount() do name, titleID, geted = GetTitleInfoByIndex(i) if titleID == 530897 then a = {geted} end end z= {")

	local Converters = {
		{
			Converter = {X = 3158, Z = -57},
			Balls = {{X = 3197, Z = 0}, {X = 3164, Z = 11}, {X = 3126, Z = 0}, {X = 3097, Z = -31}, {X = 3094, Z = -73}},
			CameraPos = {3084,203,60},
			Place = {{W = -0.333, H = 0.165}, {W = -0.226, H = 0.308}, {W = 0, H = 0.376}, {W = 0.255, H = 0.319},{W = 0.401, H = 0.157}},
		},
		{
			Converter = {X = 3002, Z = 123},
			Balls = {{X = 2982, Z = 60}, {X = 3015, Z = 66}, {X = 3048, Z = 86}, {X = 3062, Z = 116}, {X = 3061, Z = 149}},
			CameraPos = {3112,203,35},
			Place = {{W = -0.394, H = 0.157 }, {W = -0.248, H = 0.271}, {W = -0.023, H = 0.334}, {W = 0.172, H = 0.275}, {W = 0.308, H = 0.155}},
		},
		{
			Converter = {X = 3366, Z = 340},
			Balls = {{X = 3306, Z = 345}, {X = 3322, Z = 310}, {X = 3355, Z = 290}, {X = 3391, Z = 300}, {X = 3414, Z = 320}},
			CameraPos = {3340,203,204},
			Place = {{W = -0.364 , H = 0.077 }, {W = -0.243 , H = 0.230 }, {W = -0.027 , H = 0.296 }, {W = 0.161 , H = 0.195 }, {W = 0.259 , H = 0.077 }},
		},
		{
			Converter = {X = 3471, Z = 140},
			Balls = {{X = 3501, Z = 209}, {X = 3463, Z = 213}, {X = 3425, Z = 193}, {X = 3402, Z = 167}, {X = 3406, Z = 129}},
			CameraPos = {3365,203,259},
			Place = {{W = -0.405, H = 0.088 }, {W = -0.264, H = 0.236 }, {W = -0.018, H = 0.285 }, {W = 0.189, H = 0.265 }, {W = 0.306, H = 0.097 }},
		},
	}

	local settings

	function relog()
		if When_Finished == "relog" then
			ChangeChar()
			waitForLoadingScreen();
			yrest(3000)
			loadProfile()
			loadPaths(__WPL.FileName);
		elseif When_Finished == "charlist" then
			SetCharList(CharList)
			LoginNextChar()
			loadProfile()
			loadPaths(__WPL.FileName);
		elseif When_Finished == "end" then
			error("Ending script",2)
		else
			if not string.find(When_Finished,".", 1, true) then
				When_Finished = When_Finished .. ".xml"
			end
			local filename = getExecutionPath() .. "/waypoints/" .. When_Finished
			local file, err = io.open(filename, "r");
			if file then
				file:close();
				loadPaths(When_Finished)
			else
				error("'When_Finished' option is invalid",0)
			end
		end
	end

	function GetBalls()
		local objectList = CObjectList();
		objectList:update();
		local objSize = objectList:size()
		local obj
		local found = 0
		local Balls = {}
		for i = 0,objSize do
			obj = objectList:getObject(i);
			if (obj.Id == 120910 or obj.Id == 120911 or obj.Id == 120912) then
				local place
				if 5 > distance(obj.X, obj.Z, settings.Balls[1].X, settings.Balls[1].Z) then
					place = 1
				elseif 5 > distance(obj.X, obj.Z, settings.Balls[2].X, settings.Balls[2].Z) then
					place = 2
				elseif 5 > distance(obj.X, obj.Z, settings.Balls[3].X, settings.Balls[3].Z) then
					place = 3
				elseif 5 > distance(obj.X, obj.Z, settings.Balls[4].X, settings.Balls[4].Z) then
					place = 4
				elseif 5 > distance(obj.X, obj.Z, settings.Balls[5].X, settings.Balls[5].Z) then
					place = 5
				end

				if place then
					local tmpsize = memoryReadFloat(getProc(),obj.Address +0x74)
					local tmpcast = bitAnd(memoryReadByte(getProc(),obj.Address + 0xC8),0x8)
					if tmpsize >= BallSizeToClick and tmpcast == false then
						local tmpdata = {
							X = obj.X,
							Z = obj.Z,
							Id = obj.Id,
							Size = tmpsize,
							Place = place
							}
						table.insert(Balls,tmpdata)
					end
					found = found + 1
					if found > 4 then break end
				end
			end
		end
		table.sort(Balls,function (a,b) return a.Size > b.Size end)
		return Balls, found
	end

	function FindNearestConverterNotInUse()
		if distance(player.X,player.Z,3239,141) > 300 then
			return nil
		end
		local closest
		for i = 1,4 do
			settings = table.copy(Converters[i])
			local balls, found = GetBalls()
			if found == 0 then -- Available
				if closest == nil then
					closest = i
				else
					local last = Converters[closest].Converter
					local new  = Converters[i].Converter
					if distance(player.X,player.Z,last.X,last.Z) > distance(player.X,player.Z,new.X,new.Z) then
						closest = i
					end
				end
			end
		end
		return closest
	end

	function nomouse()
		-- x axis
		local addressX1 = addresses.functionMousePatchAddr
		local addressX2 = addresses.functionMousePatchAddr + addresses.mousePatchX2_offset
		local addressX3 = addresses.functionMousePatchAddr + addresses.mousePatchX3_offset
		memoryWriteString(getProc(), addressX1, string.rep(string.char(0x90),#addresses.functionMouseX1Bytes)); -- left of window
		memoryWriteString(getProc(), addressX2, string.rep(string.char(0x90),#addresses.functionMouseX2Bytes)); -- right of window
		memoryWriteString(getProc(), addressX3, string.rep(string.char(0x90),#addresses.functionMouseX3Bytes)); -- over window

		-- y axis
		local addressY1 = addresses.functionMousePatchAddr + addresses.mousePatchY1_offset
		local addressY2 = addresses.functionMousePatchAddr + addresses.mousePatchY2_offset
		local addressY3 = addresses.functionMousePatchAddr + addresses.mousePatchY3_offset
		memoryWriteString(getProc(), addressY1, string.rep(string.char(0x90),#addresses.functionMouseY1Bytes)); -- above window
		memoryWriteString(getProc(), addressY2, string.rep(string.char(0x90),#addresses.functionMouseY2Bytes)); -- below window
		memoryWriteString(getProc(), addressY3, string.rep(string.char(0x90),#addresses.functionMouseY3Bytes)); -- over window
	end

	-- Unfreeze mouse function
	function unnomouse()
		-- x axis
		local addressX1 = addresses.functionMousePatchAddr
		local addressX2 = addresses.functionMousePatchAddr + addresses.mousePatchX2_offset
		local addressX3 = addresses.functionMousePatchAddr + addresses.mousePatchX3_offset
		memoryWriteString(getProc(), addressX1, string.char(unpack(addresses.functionMouseX1Bytes)));
		memoryWriteString(getProc(), addressX2, string.char(unpack(addresses.functionMouseX2Bytes)));
		memoryWriteString(getProc(), addressX3, string.char(unpack(addresses.functionMouseX3Bytes)));

		-- y axis
		local addressY1 = addresses.functionMousePatchAddr + addresses.mousePatchY1_offset
		local addressY2 = addresses.functionMousePatchAddr + addresses.mousePatchY2_offset
		local addressY3 = addresses.functionMousePatchAddr + addresses.mousePatchY3_offset
		memoryWriteString(getProc(), addressY1, string.char(unpack(addresses.functionMouseY1Bytes)));
		memoryWriteString(getProc(), addressY2, string.char(unpack(addresses.functionMouseY2Bytes)));
		memoryWriteString(getProc(), addressY3, string.char(unpack(addresses.functionMouseY3Bytes)));
	end

	function useskill(target)
		local color = target.Id - 120909
		if GetFailureTitle and not HaveFailureTitle then
			color = color + 1
			if color == 4 then color = 1 end
		end
		SlashCommand("/script UseExtraAction("..color..")")

		local wwidth = settings.Place[target.Place].W
		local wheight = settings.Place[target.Place].H

		local www = memoryReadIntPtr(getProc(),addresses.staticbase_char,addresses.windowSizeX_offset)
		local wwh = memoryReadIntPtr(getProc(),addresses.staticbase_char,addresses.windowSizeY_offset)
		local clickXw = math.ceil(www/2 + wwh*wwidth)
		local clickYw = math.ceil(wwh*wheight)
		memoryWriteIntPtr(getProc(),addresses.staticbase_char,addresses.mouseX_offset,clickXw)
		memoryWriteIntPtr(getProc(),addresses.staticbase_char,addresses.mouseY_offset,clickYw)
		yrest(50)
		SlashCommand("/script SpellTargetUnit()")
	end

	--Start Converter
	repeat
		local conv = FindNearestConverterNotInUse()

		if not conv then
			print("You're not near any Element Converters or none are available. Go to one, then continue.")
			player:sleep()
		else
			settings = table.copy(Converters[conv])
			player:moveInRange(CWaypoint(settings.Converter.X,settings.Converter.Z),50,true)
			player:target_NPC(120905) yrest(2000) -- Element Converter
			break
		end
	until false
	RoMScript("ChoiceOption(1)") -- Activates Element Converter.

	-- set camera distance
	camera:update()
	local oDist = camera.Distance
	camera:setDistance(150)

	-- Wait for balls to appear
	repeat
		yrest(1000)
		local balls ,found = GetBalls()
	until found > 0

	player:update()

	-- Set camera angle
	RoMScript(string.format("SetCameraPosition(%d, %d, %d)",settings.CameraPos[1],settings.CameraPos[2],settings.CameraPos[3]))

	local StartTime = os.clock()
	nomouse()
	while true do
		local Balls, Found = GetBalls()
		if Found == 0 or (os.clock() - StartTime) > 100 then -- finished
			break
		end

		-- Cast to all needed balls
		if #Balls > 0 then
			for k,v in pairs(Balls) do
				useskill(v)
				yrest(PauseBetweenCasts)
			end
		else
			yrest(PauseBetweenCasts)
		end
	end

	camera:setDistance(oDist)
	unnomouse()
	if ExchangeForCertificates and inventory:itemTotalCount(241606) > 0 then
		player:moveTo(CWaypoint(3280,287),true)
		player:target_NPC(120924) yrest(1500) -- Myden Neil
		RoMScript("ChoiceOption(2)") yrest(500)
	end

	relog()
</onLoad>
</waypoints>
