<?xml version="1.0" encoding="utf-8"?><waypoints>
<onLoad>

--=== V 2.2 ===--

--=== User Options ===--
When_Finished = "end" -- "relog" to end script, "relog" to log next character and "waypointfilename" to load that waypointfile.
guardianrockspirit = "Guardian Rock Spirit" -- change name with language here, id doesn't work at the moment.
--guardianrockspirit = GetIdName()

--====================--

local attackdistance
if player.Class1 == CLASS_SCOUT or player.Class1 == CLASS_PRIEST or player.Class1 == CLASS_DRUID then
	attackdistance = 50
else
	attackdistance = 25
end

local orderlist = {}
if player.Class1 == CLASS_MAGE then
	orderlist = {6, 18, 30, 35, 33, 31, 19, 7, 2, 4}
else 
	orderlist = {6, 12, 18, 24, 30, 36, 35, 34, 33, 32, 31, 25, 19, 13, 7, 1, 2, 3, 4, 5}
end
local listsize = #orderlist

--=== Table numbering system ===--
--[[
	1 7 13 19 25 31
	2 8 14 20 26 32
	3 9 15 21 27 33
	4 10 16 22 28 34
	5 11 17 23 29 35
	6 12 18 24 30 36
* -- entrance to room.
]]
function trashhp()
	local target = player:getTarget()
	if target.Id == 101489 then
		if 10 > target.HP then
			player:clearTarget();
			return false
		end
		if arg1.Name == "MAGE_FLAME" then 
			return false
		end			
	end
end

--=== Turn off looting, wastes time ===--
settings.profile.options.LOOT = false
settings.profile.options.TARGET_LEVELDIF_ABOVE = "15" -- Need to try to kill anything in there or no point.
settings.profile.options.TARGET_LEVELDIF_BELOW = "60" --trash is lvl 15 which people won't allow for in profile.
settings.profile.events.onPreSkillCast = function() return trashhp() end -- deals with trash hp.

function checkRelog()
	if When_Finished == "relog" then
		sendMacro("}LoginNextToon=true;a={")
		sendMacro("Logout();");
		waitForLoadingScreen();
		loadPaths("survival");
	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 to sort tables, at angle ===--
local function SEsize(_x, _z)
   local X1 = 2622.1403808594
   local Z1 = 2900.1105957031
   local X2 = 2471.7895507813
   local Z2 = 2954.833984375

   return math.floor(((_x-X1)*(Z2-Z1)-(X2-X1)*(_z-Z1))/math.sqrt((X2-X1)^2 + (Z2-Z1)^2) + 0.5)
end

local function NEsize(_x, _z)
   local X1 = 2471.7895507813
   local Z1 = 2954.833984375
   local X2 = 2526.5126953125
   local Z2 = 3105.1848144531

   return math.floor(((_x-X1)*(Z2-Z1)-(X2-X1)*(_z-Z1))/math.sqrt((X2-X1)^2 + (Z2-Z1)^2) + 0.5)
end

function addToNE(_x, _z, _s)
   return _x + (_s * 0.9397), _z - (_s * 0.3420)
end

function addToSE(_x, _z, _s)
   return _x + (_s * 0.3420), _z + (_s * 0.9397)
end

function GetAttackPosition(_x, _z)
   local SEvalue = SEsize(_x, _z)
   local NEvalue = NEsize(_x, _z)
   if 1 > SEvalue then -- nw edge
      return addToSE(_x, _z, - attackdistance)
   elseif SEvalue > 159 then -- se edge
      return addToSE(_x, _z, attackdistance)
   elseif 1 > NEvalue then -- sw edge
      return addToNE(_x, _z, - attackdistance)
   elseif NEvalue > 159 then -- ne edge
      return addToNE(_x, _z, attackdistance)
   end
end



--=== Create table of tiles ===--
function createTileTable()

   tiles = {}

   local objectList = CObjectList();
   objectList:update();
   local objSize = objectList:size()

   for i = 0,objSize do
      local obj = objectList:getObject(i);
      if obj.Id == 111811 or obj.Id == 111812 then
         table.insert(tiles, table.copy(obj))
      end
   end

   -- Sort function
   local function sortfunc(a,b)
      if SEsize(a.X,a.Z) == SEsize(b.X,b.Z) then
         return NEsize(b.X,b.Z) > NEsize(a.X,a.Z)
      else
         return SEsize(b.X,b.Z) > SEsize(a.X,a.Z)
      end
   end
   
   -- Sort tiles
   table.sort(tiles, sortfunc)
end

--=== look for indicator that the tile is clickable ===--
function clicktile(address)
	local tmp = memoryReadRepeat("int", getProc(), address + addresses.pawnAttackable_offset) or 0;
	if bitAnd(tmp,0x8) then
		return true
	else
		return false
	end
end
	
--=== look for indicator that the chest has loot ===--
function clickchest(address)
	local chest = memoryReadRepeat("byte", getProc(), address + 0x2F0) or 0
	if chest ~= 0 then
		return true
	else
		return false
	end
end	

--=== Get into Survival Zone ===--
local zoneid = RoMScript("GetZoneID()")
if zoneid ~= 351 then -- not in Survival
	local Malatina = GetIdName(111813)
	-- Try to find Malatina and teleport in
	if player:target_NPC(Malatina) then
		if 50 > player.Level and (player.Level2 >= 50 or player.Level3 >= 50) then
			-- Wait for user to change class
			cprintf(cli.yellow,"If you want to earn Phirius Shells, change to your 50+ class before continuing.\n")
			player:sleep()
		end
		sendMacro("ChoiceOption(1);");
		yrest(2000)
		sendMacro("ChoiceOption(1);");
		if not waitForLoadingScreen(30) then
			print("Failed to teleport into Survival")
			checkRelog()
		end
	else
		print("You are too far from Malatina")
		checkRelog()
	end
end
	
--=== First mobs to kill ===--
function trashmelee()
	if player.Class1 == CLASS_MAGE then
		changeProfileSkill("MAGE_PURGATORY_FIRE" , "AutoUse", true)
		changeProfileSkill("MAGE_PURGATORY_FIRE" , "priority", 100)
	end
	for i = 1,listsize do
		local tile = tiles[orderlist[i]]
		teleport(GetAttackPosition(tile.X,tile.Z))
		yrest(500)
		local trash = player:findNearestNameOrId(101489)
		if trash then
			local distance = distance(player.X, player.Z, trash.X, trash.Z)
			if (attackdistance * 2) > distance then
				player:target(trash)
				player:fight()
				yrest(500)
				player:clearTarget();
			end
			if player.Battling then
				local _enemy = player:findEnemy(true,nil)
				if _enemy then
					player:target(_enemy.Address);
					player:fight()
				end
			end
		end
	end	
	spawnsmelee()
end

--=== Kill spawns melee ===--
function spawnsmelee()
	for i = 1,listsize do
		local tile = tiles[orderlist[i]]
		teleport(GetAttackPosition(tile.X,tile.Z))
		yrest(500)
		local spawn = player:findNearestNameOrId(guardianrockspirit)
		yrest(500)
		if spawn then
			local distance = distance(player.X, player.Z, spawn.X, spawn.Z)
			player:target(spawn) 
			player:fight()
		else
			printf("Something wrong, name incorrect.\n")
		end
		if player.Battling then
			local _enemy = player:findEnemy(true,nil)
			if _enemy then
				player:target(_enemy.Address);
				player:fight()
			end
		end		
	end	
	breaktiles()
end	

--=== Start of tiles function ===--
function breaktiles()	
	if player.Class1 == CLASS_MAGE then
		changeProfileSkill("MAGE_PURGATORY_FIRE" , "AutoUse", false)
	end
	--=== First run of tiles ===--
	orderlist = {1,4,7,10,13,16,19,22,25,28,31,34,2,5,8,11,14,17,20,23,26,29,32,35,3,6,9,12,15,18,21,24,27,30,33,36}
	for i = 1,36 do
		local tile = tiles[orderlist[i]]
		repeat
		local _enemy = player:findEnemy()
		local distance = distance(player.X, player.Z, _enemy.X, _enemy.Z)
		if _enemy and 100 > distance then
			player:target(_enemy.Address);
			player:fight()
		end			
		if not RoMScript("TimeKeeperFrame:IsVisible()") then
			checkRelog()
		end	
		teleport(tile.X,tile.Z,15)
		rest(100)
		player:target_Object(tile.Id, nil, false, true, clicktile);
		until clicktile(tile.Address) == false
	end
	
	--=== get any left over tiles as a double check ===--
	repeat
	local tile = player:findNearestNameOrId("Treasure Tile", nil, clicktile)
		if tile then
			if player.Battling then
				local _enemy = player:findEnemy(true,nil)
				if _enemy then
					player:target(_enemy.Address);
					player:fight()
				end
			end		
			teleport(tile.X,tile.Z,14)
			player:target_Object({111811,111812}, nil, false, true, clicktile);
		end
	until tile == nil
	chests()
end

--=== Open chests ===--
function chests()
	local chests = {}
	local objectList = CObjectList();
	objectList:update();
	local objSize = objectList:size()

	for i = 0,objSize do
		local obj = objectList:getObject(i);
		if obj.Name == "Brown wooden chest" then
			table.insert(chests, table.copy(obj))
		end
	end	

	for k,v in pairs(chests) do
		
		if not RoMScript("TimeKeeperFrame:IsVisible()") then
			checkRelog()
		end
		if clickchest(v.Address) == true then
			teleport(v.X+10,v.Z+10,15)
			repeat
				player:target_Object(v.Id, nil, nil, true);
			until clickchest(v.Address) ~= true
		end
	end
	checkRelog()
end
</onLoad>
	<!-- #  1 --><waypoint x="2519" z="2593" y="9">	
		speed(70)
		local joker = GetIdName(111814)	
		player:target_NPC(joker);
		sendMacro("ChoiceOption(2);");
	</waypoint>
	<!-- #  2 --><waypoint x="2546" z="2681" y="9" type="TRAVEL">	</waypoint>
	<!-- #  3 --><waypoint x="2586" z="2789" y="9" type="TRAVEL">	</waypoint>
	<!-- #  4 --><waypoint x="2606" z="2843" y="9" type="TRAVEL">
		createTileTable() -- do it here as you can't see the pawns until you start the event.
		local trash = player:findNearestNameOrId(101489)  -- check for trash
		local spawns = player:findNearestNameOrId(101652) -- check for spawns
		local tiles =  player:findNearestNameOrId("Treasure Tile", nil, clicktile) -- check if any tiles need opening
		
		if trash then -- add in options for aoe and ranged here
			trashmelee() -- clears trash within melee range
		end
		
		if spawns then
			spawnsmelee() -- kill spawns within melee range
		end
		
		if trash == nil and spawns == nil and tiles ~= nil then
			breaktiles() -- start breaking tiles
		end
		
		if tiles == nil then
			chests() -- open chests
		end
	</waypoint>

</waypoints>