<?xml version="1.0" encoding="utf-8"?><waypoints>
<onLoad>
	--= WeavingMachine  =--
	--=== version 2.1 ===--
	-- http://www.solarstrike.net/phpBB3/viewtopic.php?f=27&amp;t=3917&amp;start=100


	-- =================================================
	-- Change Log
	-- =================================================
	-- 1.0 	Original version
	-- 1.2 	Added in options and fixed facing
	-- 1.3 	Added in option for generating debugging output
	-- 1.4 	Added in endScore and enhancements from kkulesza
	-- 1.5 	Suggested fixes from Lisa,
	--		+ added clickDelay to allow adjustment of the time taken for clicks to occurr
	-- 1.6 	Added in 'cheat'
	-- 1.9  Full multilanguage support
	-- 2.1  Adjusted the clicking
	-- =================================================

	WEAVINGMACHINE_VERSION = "2.1";
	printf("WEAVING MACHINE Version: "..WEAVINGMACHINE_VERSION.."\n");


	--  ====================== OPTIONS ======================  --
	runsToMake = 0; 					-- 0 = until we run out of runes
	waitForOthers = true; 				-- will be nice and let other people complete the event by waiting for 15 second between runs
	endScore = 21;						-- 21=goddess package; 17=5 functional packages

	---===== CHEAT SECTION - use at your own risk - breaks ToS (not that botting doesn't ;) =====---

	local cheatSpell, useCheat

	useCheat = false -- set to true to use the buff "cheat", 2 points at a time instead of 1.

	if useCheat then
		if player.Class1 == CLASS_CHAMPION or player.Class2 == CLASS_CHAMPION then cheatSpell = GetIdName(498523) end -- Forge
		if player.Class1 == CLASS_WARDEN or player.Class2 == CLASS_WARDEN then cheatSpell = GetIdName(493642) end -- Briar Shield
		if player.Class1 == CLASS_KNIGHT or player.Class2 == CLASS_KNIGHT then cheatSpell = GetIdName(490152) end --Enhanced Armor
		if player.Class1 == CLASS_PRIEST or player.Class2 == CLASS_PRIEST then cheatSpell = GetIdName(491166) end --Magic Barrier
		if player.Class1 == CLASS_MAGE or player.Class2 == CLASS_MAGE then cheatSpell = GetIdName(490248) end --Fire Ward
		if player.Class1 == CLASS_DRUID or player.Class2 == CLASS_DRUID then cheatSpell = GetIdName(493531) end -- Savage Blessing
	end
	if cheatSpell == nil then useCheat = false end -- no skills to use

	---==========================================================================================---

	clickDelay = 500;					-- how long to wait for the box click to occur
	debugWM = false;					-- set to true to output debug messages

	local shuttleText = string.lower(RoMScript("TEXT(\"SC_2012LOOM_01\")"))
	local threadText = string.lower(RoMScript("TEXT(\"SC_2012LOOM_02\")"))
	local scissorsText = string.lower(RoMScript("TEXT(\"SC_2012LOOM_03\")"))
	local willing = RoMScript("TEXT(\"SC_423911_02\")")
	local transport = RoMScript("TEXT(\"SC_FLOWERFES_KORS_RS05\")")

	useCheat = useCheat and (string.len(cheatSpell)>0);

	local jamie_id=121044;

	local npc = player:findNearestNameOrId(jamie_id);
	player:moveTo(CWaypoint(npc.X,npc.Z,npc.Y),true);

	id_Shuttle = 121041;
	id_Thread = 121042;
	id_Scissors = 121043;
	id_WeavingBox = 121051;
	id_WeavingMachine = 121040;

	function waitToRunEvent()
		--check to see if someone else is already running the game
		local test = player:findNearestNameOrId(id_WeavingBox);
		if (test) then
			printf("Someone is already running this event..will wait\n");
		end;
		while (test) do
			yrest(500);
			test = player:findNearestNameOrId(id_WeavingBox);
		end;
	end;


	_boxes = {};
	_shuttle = nil;
	_thread = nil;
	_scissors = nil;
	_shuttleBox = nil;
	_threadBox = nil;
	_scissorsBox = nil;
	_redBox = nil;
	_yellowBox = nil;
	_whiteBox = nil;
	_machine = nil;

	function getSpecialBuffs(_pawn)
		local proc = getProc()
		local BuffSize = 0x54
		local buffStart = memoryReadRepeat("int", proc, _pawn.Address + addresses.pawnBuffsStart_offset);
		local buffEnd = memoryReadRepeat("int", proc, _pawn.Address + addresses.pawnBuffsEnd_offset);
		local Buffs = {};

		if buffStart == nil or buffEnd == nil or buffStart == 0 or buffEnd == 0 then return end
		if (buffEnd - buffStart)/ BuffSize > 50 then -- Something wrong, too many buffs
			return
		end

		for i = buffStart, buffEnd - 4, BuffSize do
			local tmp = {}
			--yrest(1)
			tmp.Id = memoryReadRepeat("int", proc, i + addresses.pawnBuffId_offset);
			table.insert(Buffs,tmp)
		end

		return Buffs;
	end



	buildBoxMap = function()
		_boxes = {};
		_shuttle = nil;
		_thread = nil;
		_scissors = nil;
		_shuttleBox = nil;
		_threadBox = nil;
		_scissorsBox = nil;
		_machine = nil;
		_redBox = nil;
		_yellowBox = nil;
		_whiteBox = nil;

		--get each box first
		local objectList = CObjectList();
		objectList:update();
		local objSize = objectList:size()

		for i = 0,objSize do
			local obj = objectList:getObject(i);
			if (obj.Id == id_Shuttle) then
				_shuttle = CPawn(obj.Address);
			elseif (obj.Id == id_Thread) then
				_thread = CPawn(obj.Address);
			elseif (obj.Id == id_Scissors) then
				_scissors = CPawn(obj.Address);
			elseif (obj.Id == id_WeavingBox) then
				table.insert(_boxes, CPawn(obj.Address));
			elseif (obj.Id == id_WeavingMachine) then
				_machine = CPawn(obj.Address);
			end
		end;

		local function outputPawn(_name, _pawn)
			if (_pawn) then
				printf(_name.." pawn found at ".._pawn.X..", ".._pawn.Z.."\n");
			else
				printf("Could not find ".._name.." pawn\n");
			end;
		end;

		outputPawn("Shuttle", _shuttle);
		outputPawn("Thread", _thread);
		outputPawn("Scissors", _scissors);

		local function findClosest(_obj)
			local result = _boxes[1];
			local dist = distance(_obj.X, _obj.Z, result.X, result.Z);
			for k,v in pairs(_boxes) do
				local d = distance(_obj.X, _obj.Z, v.X, v.Z);
				if (dist > d) then
					result = v;
					dist = d;
				end;
			end;

			return result;
		end;

		--find the box relating to each object
		_shuttleBox = findClosest(_shuttle);
		_threadBox = findClosest(_thread);
		_scissorsBox = findClosest(_scissors);

		outputPawn("ShuttleBox", _shuttleBox);
		outputPawn("ThreadBox", _threadBox);
		outputPawn("ScissorsBox", _scissorsBox);

		if ((_shuttleBox == nil) or (_threadBox == nil) or (_scissorsBox == nil)) then
			return false;
		else
			return true;
		end;
	end;

	executeEvent = function()
		printf("ExecuteEvent() started\n");

		local function getTarget(_isShuttle, _isThread, _isScissors)
			if (_isShuttle) then
				return _shuttleBox;
			elseif (_isThread) then
				return _threadBox;
			elseif (_isScissors) then
				return _scissorsBox;
			else
				error("Cannot get Target")
			end;
		end;

		BUFFS_RED = 622962;
		BUFFS_WHITE = 622963;
		BUFFS_YELLOW = 622964;

		local function getColorBox()
			if (debugWM) then printf("Checking machine for color buffs\n"); end;
			local buffs = getSpecialBuffs(_machine)
			if (buffs ~= nil) then
				if (debugWM) then printf("Found "..tostring(#buffs).." buffs\n"); end;
			end;

			for k,v in pairs(buffs) do
				if (debugWM) then printf("Testing buff: "..tostring(v.Id).."\n"); end;
				if (v.Id == BUFFS_RED) then
					return _shuttleBox;
				elseif (v.Id == BUFFS_WHITE) then
					return _threadBox;
				elseif (v.Id == BUFFS_YELLOW) then
					return _scissorsBox;
				end;
			end;
			return;
		end;

		local machineError = nil;
		local machineMessage = nil;
		local eventDone = false;

		repeat
			--get and errors and messages
			local message = nil;
			local time, moreToCome, msg, name;

			time, moreToCome, msg, name = EventMonitorCheck("MachineMessages");
			message = msg or "";
			while (moreToCome) do
				if (debugWM) then print("MachineMessages line 245 "..message) end
				time, moreToCome, msg, name = EventMonitorCheck("MachineMessages");
				message = message..(msg or "");
			end;
			if (debugWM) then print("MachineMessages what is actually checked "..message) end
			machineMessage = string.lower(message);


			if (string.len(machineMessage) > 0) then
				time, moreToCome, msg, name = EventMonitorCheck("MachineErrors");
				message = msg or "";

				while (moreToCome) do
					if (debugWM) then print("MachineErrors line 258 "..message) end
					time, moreToCome, msg, name = EventMonitorCheck("MachineErrors");
					message = message..(msg or "");
				end;
				if (debugWM) then print("machineError what is actually checked "..message) end
				machineError = (machineError or "").." "..string.lower(message);


				if (debugWM) then printf("machineError: "..tostring(machineError).."\n"); end;
				if (debugWM) then printf("machineMessage: "..tostring(machineMessage).."\n"); end;

				local hasBuff = player:hasBuff(623052);
				if (hasBuff) then
					local clothBuff = player:getBuff(623052);
					if (cbCount) then printf("clothBuff.Count = "..cbCount.."\n"); end;
					eventDone = (clothBuff.Level >= (endScore-1));
				else
					eventDone = true;
				end;

				if (not eventDone) then
					local isShuttle = string.find(machineMessage, shuttleText);
					local isThread = string.find(machineMessage, threadText);
					local isScissors = string.find(machineMessage, scissorsText);

					local target = nil;

					if (string.len(machineError) > 0) then
						--determine if this is a matrix/message error
						local isMessage = string.find(machineError, "message");
						local isMatrix = string.find(machineError, "matrix");

						if (isMessage and isMatrix) then
							--color AND message
							local matrixTarget = getColorBox();
							local messageTarget = getTarget(isShuttle, isThread, isScissors);
							if (debugWM) then printf("matrixTarget: "..tostring(matrixTarget.Address).."\n"); end;
							if (debugWM) then printf("messageTarget: "..tostring(messageTarget.Address).."\n"); end;

							for k,v in pairs(_boxes ) do
								if (debugWM) then printf("v: "..tostring(v.Address).."\n"); end;
								if ((v.Address ~= matrixTarget.Address) and (v.Address ~= messageTarget.Address)) then
									target = v;
								end;
							end;
						elseif (isMessage) then
							--color targetting
							target = getColorBox();
						elseif (isMatrix) then
							--normal targetting
							target = getTarget(isShuttle, isThread, isScissors);
						else
							target = getTarget(isShuttle, isThread, isScissors);
						end;
					else
						--normal targetting
						target = getTarget(isShuttle, isThread, isScissors);
					end;
					machineError = nil;
					machineMessage = nil;

					if (target) then
						if (debugWM) then printf("Moving to target\n"); end;
						player:moveInRange(CWaypoint(target.X, target.Z, player.Y), 20, true);
						if (debugWM) then printf("Targetting\n"); end;
						player:target(target.Address);
						yrest(100) Attack();
						yrest(100) Attack();
						if (debugWM) then printf("Clicking\n"); end;
						yrest(clickDelay);
						player:moveTo(CWaypoint(5506, -2198, 103), true);

						local angle = math.atan2(_machine.Z - player.Z, _machine.X - player.X);
						local yangle = math.atan2(_machine.Y - player.Y, ((_machine.X - player.X)^2 + (_machine.Z - player.Z)^2)^.5 );
						player:faceDirection(angle, yangle);

						if (useCheat) then
							yrest(50);
							sendMacro("CastSpellByName(\""..cheatSpell.."\")");
						end;
					end;
				else
					rest(7*1000); --wait to end the game
				end;
			else
				yrest(200);
			end;
		until (eventDone);
	end;

	local runeCount = nil;
	repeat
		waitToRunEvent();

		player:target_NPC(jamie_id);
		local options = RoMScript("GetNumSpeakOption()");
		if (options == 2) then
			printf("Using transport rune to reset\n")
			ChoiceOptionByName(transport);
			yrest(100);
			player:target_NPC(jamie_id);
		end;

		options = RoMScript("GetNumSpeakOption()");
		if (options == 3) then
			printf("Accepting challenge\n")
			ChoiceOptionByName(willing);
			yrest(200)
			RoMScript("ChoiceOption(1)")
			sendMacro("CloseAllWindows()");
			yrest(200);
		end;

		EventMonitorStart("MachineMessages", "SYSTEM_MESSAGE");
		EventMonitorStart("MachineErrors", "WARNING_MESSAGE");

		local waitTime = os.time()+60;
		repeat
		   player:target_Object(id_WeavingMachine,500);
		   yrest(50);
		   player:updateBuffs()
		until ((player:hasBuff(623052)) or (os.time() > waitTime))

		if ((player:hasBuff(623052)) and buildBoxMap()) then
			player:moveTo(CWaypoint(5483, -2216, 103), true);

			executeEvent();

			player:target_NPC(jamie_id);
			sendMacro("CloseAllWindows()");

			runsToMake = runsToMake - 1;
			runeCount = inventory:itemTotalCount(202903);
			if (runsToMake == 0) then
				printf("That was the last run\n");
			else
				local restTime = 2000;
				if (waitForOthers) then restTime = 15000; end;
				yrest(restTime);

				player:target_NPC(jamie_id);

				if runeCount then
					ChoiceOptionByName(transport);
				end
			end;
		else
			printf("Could not find the boxes, maybe someone else started the event? or you dont have enough space in your inventory, or it is bugged???\n");
			runsToMake = 0;
		end;
		EventMonitorStop("MachineMessages");
		EventMonitorStop("MachineErrors");
	until ((runsToMake == 0) or (runeCount == nil));

	error("finished");
</onLoad>
</waypoints>
