<waypoints type="TRAVEL" ><!-- Course of Terror v1.4.1 by Bot_romka. Thanks to lisa and Rock5 for original script -->

<onload>
	--=== User Options ===--

	When_Finished = "end"
		-- "end" to end script, "relog" to log next character, "waypointfilename" to load that waypointfile
		-- "Use_TP_Skill" for use teleport skill and after log next character.

	TP_Skill = 1
		-- Set to 1 for use skil "Recall", 2 for teleport to "Logar", 3 to "Reifort Camp", 4 to "Heffner Camp".
	
	TP_to_Phirius = false
		-- Set to false or true for use teleport skill if not enough Phirius Token Coins.
		
	Try_Clean_Bag = false
		-- Set to false or true for use clean Bag if not much space left in inventory.
	Receiver1 = "name"		-- Set name of items1 receiver for clean bag.
	Receiver2 = "name"		-- Set name of fusion stone with 1 or 2 stats receiver for clean bag.
	Receiver3 = "name"		-- Set name of items3 receiver from Andor Training for clean bag.

	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}},
		--		}

	Items1 = {201967, 203028, 203033, 203635, 205817, 205818, 205819, 205820, 205821}
	Items3 = {206590, 206591, 206592, 207326, 207330, 207930}

	--====================--

	changeProfileOption("HARVEST_DISTANCE", 450);
	settings.profile.options.WP_NO_STOP = false
	NumShells = inventory:getItemCount(240181)
	Logentry = "Ran out of time."					-- default
	if G_FirstTryClean == nil then G_FirstTryClean = true end
	--if player.Level > 55  then When_Finished = "end" end

	TP_Skill_nr = (TP_Skill == 1 and 540001) or (TP_Skill == 2 and 540190) or (TP_Skill == 3 and 540191) or (TP_Skill == 4 and 540193)

	function CheckRelog()
		-- Log result
		local filename = getExecutionPath() .. "/logs/cot.log";
		local file, err = io.open(filename, "a+");
		if file then
			file:write("Account: "..RoMScript("GetAccountName()").."\tName: " ..string.format("%-10s",player.Name ).." \tDate: "..os.date()..
			" \tShells gained/total: "..inventory:getItemCount(240181) - NumShells.."/" ..inventory:getItemCount(240181).." \t"..Logentry..
			" \tPhirius Coins: "..inventory:getItemCount(203038).." \tPurified Fusion Stone: "..inventory:getItemCount(202881)..
			" \tEmptie bag space: "..inventory:itemTotalCount(0).." \tCharges: "..RoMScript("GetMagicBoxEnergy()").." \n\n")
			file:close();
		end

		-- Log items with shell stats
		local Accwrite = true
		local filename = getExecutionPath() .. "/logs/shellitems.log";
		local file, err = io.open(filename, "a+");
		if file then
			inventory:update()
			for slot = 61, 240 do
				item = inventory.BagSlot[slot]
				if item.RequiredLvl >= 67 then
					if Accwrite then
						file:write("Account: "..RoMScript("GetAccountName()").." \tName: " ..string.format("%-10s",player.Name ).." \tDate: " .. os.date()..
						" \tShells: "..inventory:getItemCount(240181).." \tPC: "..inventory:getItemCount(203038).." \tPFS: "..inventory:getItemCount(202881))
						Accwrite = false
					end
					for k,v in pairs(item.Stats) do
						local itembagslot = slot - 60
						file:write("\n \tSlot = "..itembagslot.." \tName = "..item.Name.." \tStat = "..v.Name)
					end
				end
			end
			if Accwrite == false then
				file:write("\n\n")
			end
			file:close()
		end

		if When_Finished == "relog" then
			sendMacro("}LoginNextToon=true;a={")
			sendMacro("Logout();")
			waitForLoadingScreen()
			G_FirstTryClean = true
			loadPaths(__WPL.FileName)
		elseif When_Finished == "charlist" then
			SetCharList(CharList)
			LoginNextChar()
			G_FirstTryClean = true
			loadPaths(__WPL.FileName)
		elseif When_Finished == "end" then
			error("Ending script",2)
		elseif When_Finished == "Use_TP_Skill" then
			Cur_Zone = getZoneId()
			if Cur_Zone == 353 or Cur_Zone == 2 then		-- in Course of Terror or Varanas
				print("Use teleport skill.")
				sendMacro("CastSpellByName(TEXT('Sys"..TP_Skill_nr.."_name'));")
				waitForLoadingScreen(30)
			end
			sendMacro("}LoginNextToon=true;a={")
			sendMacro("Logout();")
			waitForLoadingScreen()
			G_FirstTryClean = true
			loadPaths(__WPL.FileName)
		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 RemoveObjeckt()
		local objectList = CObjectList();
		objectList:update();
		local objSize = objectList:size()
		for i = 0,objSize do
			local obj = objectList:getObject(i);
			if obj.Id == 113108 or obj.Id == 113109 or obj.Id == 113110 or obj.Id == 113111 or obj.Id == 113113 then
				if obj.X > 3800 then
					memoryWriteFloatPtr(getProc(), obj.Address + 4, 0xB0, 3800)
				end
			end
		end
	end;

	function GetAllKeys()
		local lastSealAddress = 0
		repeat
			player:update()
			RemoveObjeckt()
			local seal = player:findNearestNameOrId(113112, lastSealAddress)
			if seal and seal.Address ~= lastSealAddress then

				-- click seal
				repeat
					player:target(seal.Address)
					yrest(100)
					Attack()
					yrest(1000)
					player:update()
				until player:findNearestNameOrId(113106)	-- until a key appears

				-- Remember last seal
				lastSealAddress = seal.Address
				local seal = nil

				-- Collect key
				local keys = inventory:itemTotalCount(203027)

				repeat
					player:target_Object(113106,nil,nil,true)	-- harvests key
				until inventory:itemTotalCount(203027) == keys + 1
				yrest(1500)

			end
		until GotAllKeys()
	end;

	function GotoGate()
		repeat
			cprintf(cli.white, "Go to gate.\n")
			player:moveTo(CWaypoint(4080,3960))
			player:turnDirection(3.14/2)					-- Face forward
			keyboardPress( settings.hotkeys.MOVE_FORWARD.key );
			yrest(700)
			player:update()
			retry_count = 0
			dist = distance(player.X, player.Z, 4080, 3335)
			while( dist > 100 and retry_count&lt;7 ) do
				keyboardPress( settings.hotkeys.MOVE_FORWARD.key );
				yrest(700)
				player:update()
				retry_count = retry_count + 1;
				dist = distance(player.X, player.Z, 4080, 3335)
			end
		until 100 > dist
		printf("Distance checked and continuing.\n")
	end;

	function GotAllKeys()
		local room = CurrentRoom()
		local keys = inventory:itemTotalCount(203027)
		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 SpeedUp(_speed)
		local playerAddress = memoryReadIntPtr(getProc(), addresses.staticbase_char, addresses.charPtr_offset);
		if playerAddress ~= 0 and _speed ~= nil then
			memoryWriteFloat(getProc(), playerAddress + 0x40, _speed);
			printf("Speedhack ACTIVATED!\n");
			local Speed = memoryReadFloat(getProc(), playerAddress + 0x40);
			print("Player speed:", Speed);
		end
	end;

	if getZoneId() ~= 353 then								-- not in Course of Terror
		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,"\a\a\a Reaching the maximum number of Phirius Shells (1000). Please spend some before continuing.\n")
			if When_Finished == "relog" then
				Logentry = "Reaching the maximum number of Phirius Shells (1000)."
				CheckRelog()
				return
			else
				player:sleep()
				NumShells = inventory:getItemCount(240181)
			end
		end
		if 30 > inventory:itemTotalCount(203038) then
			print("Not enough Phirius Token Coins.")
			if TP_to_Phirius and getZoneId() == 2 then		-- in Varanas
				print("\a Use teleport skill.")
				sendMacro("CastSpellByName(TEXT('Sys"..TP_Skill_nr.."_name'));");
				waitForLoadingScreen(30);
			end
			Logentry = "Not enough Phirius Token Coins."
			CheckRelog()
			return
		end
		if 10 > inventory:itemTotalCount(0) then
			if getZoneId() == 2 and G_FirstTryClean and Try_Clean_Bag then		-- in Varanas
				__WPL:setWaypointIndex(__WPL:findWaypointTag("CleanBag"))
				G_FirstTryClean = false
				return
			elseif When_Finished == "relog" then
				Logentry = "Not much space left in inventory."
				CheckRelog()
				return
			else
				-- Wait for user to make some space in inventory.
				cprintf(cli.yellow,"\a\a\a Not much space left in inventory. Are you sure you want to continue with only %d spaces left?\n", inventory:itemTotalCount(0))
				player:sleep()
			end
		end
		if RoMScript("TimeKeeperFrame:IsVisible()") then
			RoMScript("TimeKeeperFrame:Hide()")
		end

		-- Try to find Malatina and teleport in
		if player:target_NPC(111813) then		-- Malatina
			yrest(1000)

			if 2 > RoMScript("GetNumSpeakOption()") then	-- try again
				player:target_NPC(111813)		-- Malatina
				yrest(1000)
			end

			sendMacro("ChoiceOption(2);");
			yrest(1000)

			if RoMScript("GetNumSpeakOption()") > 1 then	-- enter mini 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)
				SpeedUp(59)
				__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="4080" z="3340" y="18" tag="START">
		cprintf(cli.white, "Current Room: %s\n", CurrentRoom())
		if CurrentRoom() == 1 then				-- Just arrived
			if not RoMScript("TimeKeeperFrame:IsVisible()") then
				player:target_NPC(113120);		-- Malatina
				yrest(1000)
				sendMacro("ChoiceOption(2);");
				yrest(1000)
				sendMacro("ChoiceOption(1);");
				player:target_NPC(113120);		-- Malatina
				yrest(1000)
				sendMacro("ChoiceOption(2);");
				yrest(1000)
				sendMacro("ChoiceOption(1);");
				repeat yrest(1000) until RoMScript("TimeKeeperFrame:IsVisible()")
			end
		elseif CurrentRoom() > 4 then			-- Finished. Open chests
			cprintf(cli.white, "Open chests.\n")
			--[[
			--=== Open chests ===--
			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
					player:target(obj.Address);
					Attack()
					yrest(2000)
					Attack()
					yrest(2000)
					repeat
						yrest(2000)
						player:update()
					until not player.Casting
				end
			end;
			]]--

			--=== Create table for chests ===--
			chests = {}; tempchests = {};

			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 > 4080 then		-- right side
						table.insert(chests, table.copy(obj))
					else						-- left side
						table.insert(tempchests, table.copy(obj))
					end
				end
			end;

			-- Sort chests
			table.sort(chests, function(a,b) return a.Z > b.Z end)
			table.sort(tempchests, function(a,b) return b.Z > a.Z end)
			for i=1, #tempchests do table.insert(chests, table.copy(tempchests[i])) end

			-- Open chests
			for k,v in pairs(chests) do
				player:target(v.Address);
				Attack()
				yrest(2000)
				Attack()
				yrest(2000)
				repeat
					yrest(2000)
					player:update()
				until not player.Casting
			end;

			inventory:update();
			while inventory:itemTotalCount(203487) > 0 do
				inventory:useItem(203487);
				yrest(1000)
				inventory:update();
			end

			local secondsleft = RoMScript("TimeKeeperFrame.startTime-GetTime()")
			local mm = string.format("%2s", math.floor(secondsleft/ 60))
			local ss = string.format("%02s", math.floor(math.mod(secondsleft, 60)))
			printf("Succeeded with %s:%s remaining.\n",mm,ss)
			Logentry = string.format("Succeeded with %s:%s remaining.",mm,ss)

			if 30 > inventory:itemTotalCount(203038) then
				print("Not enough Phirius Token Coins for next run.")
				if TP_to_Phirius then
					print("Use teleport skill.")
					sendMacro("CastSpellByName(TEXT('Sys"..TP_Skill_nr.."_name'));");
					waitForLoadingScreen(30);
				end
				Logentry = string.format("Succeeded with %s:%s remaining. Not enough Phirius Token Coins for next run.",mm,ss)
			end

			CheckRelog()
		end
	</waypoint>
<!-- JUST BEFORE THE DOOR -->
	<!-- # 2 --><waypoint x="4080" z="3499" y="18" >	</waypoint>
<!-- JUST AFTER THE DOOR -->
	<!-- # 3 --><waypoint x="4080" z="3600" y="28" >
		yrest(3000)
		GetAllKeys()
		GotoGate()
		__WPL:setWaypointIndex(__WPL:findWaypointTag("START"));
	</waypoint>

<!-- CLEAN BAG -->
	<waypoint x="4820" z="-1894" y="109" tag="CleanBag">	</waypoint>
	<waypoint x="4709" z="-1951" y="109">	</waypoint>
	<waypoint x="4634" z="-2031" y="104">	</waypoint>
	<waypoint x="4589" z="-2104" y="103">	</waypoint>
	<waypoint x="4566" z="-2178" y="103">	</waypoint>
	<waypoint x="4566" z="-2178" y="103">
		player:target_Object(110538,1500);
		RoMScript("ChoiceOption(1);"); yrest(1000);
		UMM_SendByNameOrId(Receiver1, Items1);
		-- Send Fusion Stone
		inventory:update()
		for __, item in pairs(inventory.BagSlot) do
			if ( item.SlotNumber > 60 and item.Id == 203001 and 3 > #item.Stats ) then
				UMM_SendInventoryItem(Receiver2, item)
			end
		end
		UMM_SendByNameOrId(Receiver3, Items3);
	</waypoint>
	<waypoint x="4600" z="-2127" y="103">	</waypoint>
	<waypoint x="4659" z="-2029" y="109">	</waypoint>
	<waypoint x="4730" z="-1953" y="113">	</waypoint>
	<waypoint x="4808" z="-1900" y="109">	</waypoint>
	<waypoint x="4869" z="-1902" y="109">
		loadPaths(__WPL.FileName);
	</waypoint>
</waypoints>
