<?xml version="1.0" encoding="utf-8"?><waypoints type="TRAVEL" >
<!-- Rock5's Course of Terror waypoint file with teleport -->
<!--   version 1.82 . Thanks to lisa for original script  -->
<onload><![CDATA[
	--=== User Options ===--
	
	When_Finished         = "at"
		-- "end" to end script, "relog" to log next character, "charlist" to use the charlist and "waypointfilename" to load that waypointfile.
	ExitBeforeNextFile    = true	-- If you want it to exit game before loading next "waypointfilename".

		unregisterTimer("GMdetection");
		CharList={
			{account=2, chars= {2,3,4}},
			{account=3, chars= {1,3,4}},
			{account=4, chars= {1,2,3}},
			{account=5, chars= {2,3}},
		}	
	
	
	
	function getpoints()
		return {
			[1]={ X=4213 , Z=3707, Y=18.7, Links={[1]={Num=7},[2]={Num=8},[3]={Num=33},}},
			[2]={ X=3947 , Z=3707, Y=18.7, Links={[1]={Num=3},[2]={Num=28},[3]={Num=6},}},
			[3]={ X=4013.5 , Z=3707, Y=18.7, Links={[1]={Num=23},[2]={Num=2},[3]={Num=10},[4]={Num=36},}},
			[4]={ X=4079.2 , Z=3975.5, Y=18.7, Links={[1]={Num=25},}},
			[5]={ X=4146.5 , Z=3672.5, Y=18.7, Links={[1]={Num=9},[2]={Num=7},[3]={Num=8},}},
			[6]={ X=3947 , Z=3672.5, Y=18.7, Links={[1]={Num=10},[2]={Num=2},}},
			[7]={ X=4213 , Z=3672.5, Y=18.7, Links={[1]={Num=5},[2]={Num=1},}},
			[8]={ X=4146.5 , Z=3707, Y=18.7, Links={[1]={Num=1},[2]={Num=23},[3]={Num=5},[4]={Num=30},}},
			[9]={ X=4080 , Z=3672.5, Y=18.7, Links={[1]={Num=10},[2]={Num=5},[3]={Num=23},}},
			[10]={ X=4013.5 , Z=3672.5, Y=18.7, Links={[1]={Num=6},[2]={Num=9},[3]={Num=3},}},
			[11]={ X=4213 , Z=3914, Y=18.7, Links={[1]={Num=17},[2]={Num=26},[3]={Num=19},}},
			[12]={ X=4080 , Z=3845, Y=18.7, Links={[1]={Num=20},[2]={Num=13},[3]={Num=14},[4]={Num=39},}},
			[13]={ X=4013.5 , Z=3845, Y=18.7, Links={[1]={Num=12},[2]={Num=44},[3]={Num=45},[4]={Num=22},}},
			[14]={ X=4080 , Z=3879.5, Y=18.7, Links={[1]={Num=22},[2]={Num=12},[4]={Num=18},}},
			[15]={ X=4013.5 , Z=3914, Y=18.7, Links={[1]={Num=18},[2]={Num=31},[3]={Num=22},[4]={Num=27},}},
			[16]={ X=4146.5 , Z=3948.5, Y=18.7, Links={[1]={Num=25},[2]={Num=19},[3]={Num=26},}},
			[17]={ X=4213 , Z=3879.5, Y=18.7, Links={[1]={Num=21},[2]={Num=11},[3]={Num=24},}},
			[18]={ X=4080 , Z=3914, Y=18.7, Links={[1]={Num=26},[2]={Num=15},[3]={Num=25},[4]={Num=14},}},
			[19]={ X=4213 , Z=3948.5, Y=18.7, Links={[1]={Num=16},[2]={Num=11},}},
			[20]={ X=4146.5 , Z=3845, Y=18.7, Links={[1]={Num=24},[2]={Num=12},[3]={Num=40},[4]={Num=21},}},
			[21]={ X=4146.5 , Z=3879.5, Y=18.7, Links={[1]={Num=14},[2]={Num=17},[3]={Num=20},[4]={Num=26},}},
			[22]={ X=4013.5 , Z=3879.5, Y=18.7, Links={[1]={Num=43},[2]={Num=14},[3]={Num=13},[4]={Num=15},}},
			[23]={ X=4080 , Z=3707, Y=18.7, Links={[1]={Num=8},[2]={Num=3},[3]={Num=46},[4]={Num=9},}},
			[24]={ X=4213 , Z=3845, Y=18.7, Links={[1]={Num=37},[2]={Num=20},[3]={Num=17},}},
			[25]={ X=4080 , Z=3948.5, Y=18.7, Links={[1]={Num=27},[2]={Num=16},[3]={Num=4},[4]={Num=18},}},
			[26]={ X=4146.5 , Z=3914, Y=18.7, Links={[1]={Num=11},[2]={Num=18},[3]={Num=21},[4]={Num=16},}},
			[27]={ X=4013.5 , Z=3948.5, Y=18.7, Links={[1]={Num=35},[2]={Num=25},[3]={Num=15},}},
			[28]={ X=3947 , Z=3741.5, Y=18.7, Links={[1]={Num=2},[2]={Num=36},[3]={Num=38},}},
			[29]={ X=4146.5 , Z=3776, Y=18.7, Links={[1]={Num=41},[2]={Num=32},[3]={Num=30},[4]={Num=40},}},
			[30]={ X=4146.5 , Z=3741.5, Y=18.7, Links={[1]={Num=46},[2]={Num=33},[3]={Num=8},[4]={Num=29},}},
			[31]={ X=3947 , Z=3914, Y=18.7, Links={[1]={Num=15},[2]={Num=35},[3]={Num=43},}},
			[32]={ X=4080 , Z=3776, Y=18.7, Links={[1]={Num=29},[2]={Num=42},[3]={Num=39},[4]={Num=46},}},
			[33]={ X=4213 , Z=3741.5, Y=18.7, Links={[1]={Num=30},[2]={Num=41},[3]={Num=1},}},
			[34]={ X=3947 , Z=3810.5, Y=18.7, Links={[1]={Num=38},[2]={Num=45},[3]={Num=44},}},
			[35]={ X=3947 , Z=3948.5, Y=18.7, Links={[1]={Num=31},[2]={Num=27},}},
			[36]={ X=4013.5 , Z=3741.5, Y=18.7, Links={[1]={Num=28},[2]={Num=46},[3]={Num=3},[4]={Num=42},}},
			[37]={ X=4213 , Z=3810.5, Y=18.7, Links={[1]={Num=40},[2]={Num=24},[3]={Num=41},}},
			[38]={ X=3947 , Z=3776, Y=18.7, Links={[1]={Num=42},[2]={Num=34},[3]={Num=28},}},
			[39]={ X=4080 , Z=3810.5, Y=18.7, Links={[1]={Num=45},[2]={Num=40},[3]={Num=12},[4]={Num=32},}},
			[40]={ X=4146.5 , Z=3810.5, Y=18.7, Links={[1]={Num=39},[2]={Num=37},[3]={Num=29},[4]={Num=20},}},
			[41]={ X=4213 , Z=3776, Y=18.7, Links={[1]={Num=33},[2]={Num=29},[3]={Num=37},}},
			[42]={ X=4013.5 , Z=3776, Y=18.7, Links={[1]={Num=32},[2]={Num=38},[3]={Num=36},[4]={Num=45},}},
			[43]={ X=3947 , Z=3879.5, Y=18.7, Links={[1]={Num=44},[2]={Num=22},[3]={Num=31},}},
			[44]={ X=3947 , Z=3845, Y=18.7, Links={[1]={Num=13},[2]={Num=43},[3]={Num=34},}},
			[45]={ X=4013.5 , Z=3810.5, Y=18.7, Links={[1]={Num=34},[2]={Num=39},[3]={Num=42},[4]={Num=13},}},
			[46]={ X=4080 , Z=3741.5, Y=18.7, Links={[1]={Num=36},[2]={Num=30},[3]={Num=32},[4]={Num=23},}},	
		}
	end
	
	function cottravel(dest,_gate)
		player:update()
		local path = {}
		local points = getpoints() -- so we can edit table without affecting original

		--=== determine location ===--
		local closest = 1;
		for i,v in pairs(points) do
			local oldClosestWp = points[closest];
			if( distance(player.X, player.Z, oldClosestWp.X, oldClosestWp.Z) > distance(player.X, player.Z, v.X, v.Z) ) then
				closest = i;
			end
			travellocation = closest
		end	

		--=== determine destination ===--
		local closest = 1;
		for i,v in pairs(points) do
			local oldClosestWp = points[closest];
			if( distance(dest.X, dest.Z, oldClosestWp.X, oldClosestWp.Z) > distance(dest.X, dest.Z, v.X, v.Z)	) then
			closest = i;
			end
			traveldestination = closest
		end

		for pointnum,point in pairs(points) do
			for Num,link in pairs(point.Links) do
				if points[pointnum].Links[Num].dist == nil then
					points[pointnum].Links[Num].dist = distance(point.X, point.Z, points[Num].X, points[Num].Z)
				end
			end
		end

		local function findPath(_from, _val)

			-- initialize
			local dist = {} -- Current total distances to each point
			local previous = {} -- Current previous points that yield the shortest distance to those points
			local completed = {} -- points already checked and finished with
			local Q = {}-- queue of current points being worked on. Only the index numbers
			dist[_from] = 0
			Q[_from] = true

			local function getSmallestDist(_Q)
				-- Look for shortest path in Q
				local shortestdist = math.huge -- So we don't have to check for nil all the time
				local shortest
				for k,__ in pairs(_Q) do
					if shortestdist > dist[k] then
						shortestdist = dist[k]
						shortest = k
					end
				end

				return shortest
			end


			local destination_found = false
			while next(Q) ~= nil do -- not empty
				-- find point with shortest dist
				local currNum = getSmallestDist(Q)
				if currNum == nil then
					error("I think it finished without finding a path to the destination.")
				end
				if points[currNum]~= nil then -- This line is not needed. Added because of faulty database
					currPoint = table.copy(points[currNum])
					-- see if it's the destination
					if currNum == _val then
						destination_found = currNum
					end

					if destination_found then
						-- destination reached
						print("Destination found")
						break
					end

					-- bring in connected Links that aren't already completed
					for k,v in pairs(currPoint.Links) do
						if Q[v.Num] then -- Already in the Q. Update dist.
							local tmp = dist[currNum] + v.dist
							if  dist[v.Num] > tmp then
								dist[v.Num] = tmp
								previous[v.Num] = currNum
							end
						elseif not completed[v.Num] then -- add new point
							Q[v.Num] = true
							dist[v.Num] = dist[currNum] + v.dist
							previous[v.Num] = currNum
						end
					end
				end
				-- pop from the Q.
				completed[currNum] = true
				Q[currNum] = nil
			end

			if next(Q) == nil then
				print("Didn't find path to destination.")
				return false
			end

			if destination_found then -- return path
				-- 'currNum' is the destination
				table.insert(path,{X=points[destination_found].X,Z=points[destination_found].Z,Y=points[destination_found].Y})
				while previous[destination_found] do
					destination_found = previous[destination_found]
					--table.insert(path,destination_found)
					table.insert(path,{X=points[destination_found].X,Z=points[destination_found].Z,Y=points[destination_found].Y})
				end
			end
			if not _gate then
				table.remove(path)
			end
		end	
		findPath(traveldestination,travellocation)
		local count = #path
		for k,v in pairs(path) do
			player:moveTo(CWaypoint(v.X,v.Z,v.Y),true,false,20)
			--teleport(v.X,v.Z,v.Y + 5,true)
			checkaggro() -- check for open summon seals.
			print(count..": points left to go before destination.")
			count = (count - 1)
		end
		print("Arrived at destination.")
		return true
	end
	
	function gotogate()

		cottravel({X=4079,Z=3990,Y=28},true)
		--player:faceDirection(3.14/2) -- Face forward
		--keyboardPress( settings.hotkeys.MOVE_FORWARD.key );
		repeat
			player:update()
			dist = distance(player.X, player.Z, 4081, 3335)
			yrest(700)
		until 100 > dist
		print("passed dist check to start")
		yrest(500)
		player:update()
		if 18 > player.Y then
			print("\a")
			local y = player.Y
			for i = 1,20 do teleport(nil,nil,y+i) player:turnDirection(1) yrest(50) end
			keyboardPress( settings.hotkeys.MOVE_FORWARD.key ); yrest(500)
			player:update()
			if 18 > player.Y then
				print("\a\aplayer is stuck")
				player:sleep()
			end
		end

		printf("Distance checked and continuing.\n")
	end	
	
	function getallkeys()
		--=== changing teleport settings
		teleport_SetStepSize(50)
		teleport_SetStepPause(500)

		local lastSealAddress = 0
		repeat
			player:update()
			local keyseal = player:findNearestNameOrId(113112, lastSealAddress)
			if keyseal then
				cottravel(keyseal)
				-- click keyseal
				repeat
					checkaggro()
					player:target(keyseal)
					yrest(100)
					Attack()
					yrest(1500)
					player:update()
				until player:findNearestNameOrId(113106) -- until a key appears	
				-- Remember last keyseal
				lastSealAddress = keyseal.Address
				
				local keys = inventory:itemTotalCount(203027)
				repeat
					checkaggro()
					player:target_Object(113106,nil,nil,true) -- harvests key
				until inventory:itemTotalCount(203027) == keys + 1
			end
		until gotAllKeys()
	end

	function checkaggro()
		player:update()
		local seal, sealtable = player:findNearestNameOrId(102368)
		if seal then
			local oldsetting = settings.profile.options.MAX_TARGET_DIST
			settings.profile.options.MAX_TARGET_DIST = 1500 -- because of issue of distance to WP....
			yrest(2000) -- wait for seal to really appear
			print("found: "..#sealtable.." lets kill them")
			for i = 1, #sealtable do
				player:updateXYZ()
				player:target(sealtable[i]) -- kills the summoning portal and not the ghost clown.
				player:fight() -- might need to create fight function
				yrest(2000) -- give a couple of seconds for the clown to disappear.
				player:update()
			end
			print("they should be dead")
			settings.profile.options.MAX_TARGET_DIST = oldsetting
		end
	end

	function gotAllKeys()
		local room = currentRoom()
		local keys = inventory:itemTotalCount(203027)
		print("checking keys, we have: "..keys)
		local keyGoal = (room == 1 and 1) or (room == 2 and 3) or (room == 3 and 6) or (room == 4 and 10)
		return keys >= keyGoal
	end

	function currentRoom()
		return memoryReadRepeat("int",getProc(), player.Address + 0x1cc)
	end
	
	function checkRelog()
		-- Log result
		GuildDonate()		
		logloot()
		if When_Finished == "relog" then
			ChangeChar()
			yrest(3000)
			loadPaths("cot");
		elseif When_Finished == "charlist" then
			SetCharList(CharList)
			LoginNextChar()
			loadPaths("survivalr5");
		elseif When_Finished == "end" then
			error("Ending script",2)
		else
			-- Leave before loading next waypoint file.
			if ExitBeforeNextFile == true then
				local Malatina = 113120
				local IWantToLeave = RoMScript("TEXT(\"SC_111813_YU_42\")")
				local Confirm = RoMScript("TEXT(\"SC_OKAY\")")

				-- Exit COT if still in COT
				if getZoneId() == 353 and player:target_NPC(Malatina) then
					yrest(2000)
					ChoiceOptionByName(IWantToLeave)
					yrest(2000)
					ChoiceOptionByName(Confirm)
					waitForLoadingScreen()
					yrest(3000)
				end
			end

			loadPaths(When_Finished)
		end
	end


	numshells = inventory:getItemCount(240181)
	logentry = nil
	Malatina = GetIdName(111813)
	changeProfileOption("HARVEST_DISTANCE", 450);

	local zoneid = RoMScript("GetZoneID()")
	if zoneid ~= 353 then -- not in Course of Terror
		RoMScript("TimeKeeperFrame:Hide()") -- Just in case it's still open from another minigame (bug)
		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
		if inventory:itemTotalCount(240181) > 950 then
			-- Wait for user to use some shells.
			cprintf(cli.yellow,"Reaching the maximum number of Phirius Shells (1000). Please spend some before continuing.\n")
			player:sleep()
			numshells = inventory:getItemCount(240181)
		end
		local empties = inventory:itemTotalCount(0)
		if 10 > empties then
			-- Wait for user to make some space in inventory.
			cprintf(cli.yellow,"Not much space left in inventory. Are you sure you want to continue with only %d spaces left?\n",empties)
			player:sleep()
		end
		if 30 > inventory:itemTotalCount(203038) then
			print("Not enough Phirius Token Coins.")
			logentry = "Not enough Phirius Token Coins."
			checkRelog()
			return
		end

		-- Try to find Malatina and teleport in
		if player:target_NPC(Malatina) then
			yrest(1000)

			if 2 > RoMScript("GetNumSpeakOption()") then -- try again
				player:target_NPC(Malatina) yrest(1000)
			end

			sendMacro("ChoiceOption(2);");
			yrest(2000)

			if RoMScript("GetNumSpeakOption()") > 1 then -- enter game
				sendMacro("ChoiceOption(1);");
				if not waitForLoadingScreen(30) then
					print("Failed to teleport into Course of Terror")
					logentry = "Failed to teleport into Course of Terror."
					checkRelog()
				end
				yrest(1000)
				__WPL:setWaypointIndex(__WPL:getNearestWaypoint(player.X,player.Z))
			else
				print("This character already did Course of Terror.")
				logentry = "Already did Course of Terror."
				checkRelog()
			end
		else
			print("You are too far from Malatina")
			logentry = "Too far from Malatina."
			checkRelog()
		end
	end

]]></onload>

<!-- AT THE START POINT -->
	<!-- # 1 --><waypoint x="4081" z="3340" y="18" tag="START">
		if currentRoom() == 1 then -- Just arrived
			if not RoMScript("TimeKeeperFrame:IsVisible()") then
				player:target_NPC(Malatina);
				yrest(2000)
				sendMacro("ChoiceOption(2);");
				yrest(2000)
				sendMacro("ChoiceOption(1);");
				repeat yrest(1000) until RoMScript("TimeKeeperFrame:IsVisible()")
			end
		elseif currentRoom() > 4 then -- Finished. Open chests
			--=== Create table for chests ===--
			chests = {left = {}, right = {}}

			local objectList = CObjectList();
			objectList:update();
			local objSize = objectList:size()

			for i = 0,objSize do
				local obj = objectList:getObject(i);
				if obj.Id == 113114 or obj.Id == 113137 then
					if obj.X > 4081 then -- right side
						table.insert(chests.right, table.copy(obj))
					else -- left side
						table.insert(chests.left, table.copy(obj))
					end
				end
			end

			-- Sort chests
			table.sort(chests.left, function(a,b) return b.Z > a.Z end)
			table.sort(chests.right, function(a,b) return a.Z > b.Z end)

			-- Get left side
			for k,v in pairs(chests.left) do
				player:target(v.Address);
				Attack()
				yrest(2000)
				Attack()
				if k == 1 then yrest(2000) Attack() end
				repeat
					yrest(2000)
					player:update()
				until not player.Casting
				repeat yrest(500) player:update() until player.Stance== 0
			end

			-- Get right side
			for k,v in pairs(chests.right) do
				player:target(v.Address);
				Attack()
				yrest(2000)
				Attack()
				if k == 1 then yrest(2000) Attack() end
				repeat
					yrest(2000)
					player:update()
				until not player.Casting
				repeat yrest(500) player:update() until player.Stance== 0
			end

			player:moveTo(CWaypoint(4081,3335))

			local secondsleft = RoMScript("TimeKeeperFrame.startTime-GetTime()")
			local mm = string.format("%2s", math.floor(secondsleft/ 60))
			local ss = string.format("%02s", math.floor(math.fmod(secondsleft, 60)))
			printf("Succeeded with %s:%s remaining.\n",mm,ss)
			logentry = string.format("Succeeded with %s:%s remaining.",mm,ss)
			checkRelog()
		end
	</waypoint>
<!-- JUST BEFORE THE DOOR -->
	<!-- # 2 --><waypoint x="4081" z="3499" y="18" >	</waypoint>
<!-- JUST AFTER THE DOOR -->
	<!-- # 3 --><waypoint x="4081" z="3600" y="28" >
		logentry = "Ran out of time." -- default
		yrest(3000)
		--fly()
		getallkeys()
		gotogate()
		--flyoff()
		__WPL:setWaypointIndex(__WPL:findWaypointTag("START"));
	</waypoint>
</waypoints>
