<commit_before>-- mining_ore.lua v2.2.9.2 -- by Cegaiel
-- Credits to Tallow for his Simon macro, which was used as a template to build on.
-- 
-- Brute force method, you manually click/set every stones' location and it will work every possible 3 node/stone combinations.
--
-- New in v2.2.0 - Now allows you to optionally try 4 stone combos after doing the regular 3 stone combos.
-- 4 stone combos don't produce ore very often, but when it does, its usually 100+
-- Choosing 4 stone combos will double the time per round, as the nodes worked quantity will double
-- ie Iron is 35 works for the normal 3 stone method.  But choosing 4 stone will cause it to be 70 (35 for 3 stone combos + 35 for 4 stone combos).
--
-- New in v2.2.3 Dual Monitor mode. This will use the srClickMouseNoMove method. Instead of moving mouse, hovering each node and sending a 'A' or 'S' key...
-- Instead it will right click each mouse (without moving mouse and click on the menus. This allows you to do something on 2nd monitor without having mouse move.
-- You will also be given a 3 second countdown (after selecting nodes) to get your mouse over to the 2nd monitor.
-- It will then move mouse once to upper left corner then start popping up menus.
-- BEWARE: You must uncheck Options, Interface Options: Right-Click opens a menu as pinned. Or else you will have tons of left-over pinned menus, that you need to close out!
--
-- v 2.2.9 + New check box "Broken Stone Check" . When you tap shift over each node, it now records pixel color, in addition to the x,y position.
-- The tolerance is defined in rgbTol and hueTol. It might occassionaly give a false positive.  I've found if you zoom in a bit more, it usually fixes that.
-- The purpose of this is to skip all future nodes from attempting to be worked. Speeds up by not trying to work future stones that don't exist.

-- For a more detailed Change Log and history, see https://github.com/DashingStrike/Automato-ATITD/commits/master/scripts/mining_ore.lua


dofile("common.inc");
dofile("settings.inc");

info = "Ore Mining v2.2.9.2 by Cegaiel --\nMacro brute force tries every possible 3 stone combination (and optionally 4 stone, too). Time consuming but it works!\n\nMAIN chat tab MUST be showing and wide enough so that each line doesn't wrap.\n\nChat MUST be minimized but Visible (Options, Chat-Related, \'Minimized chat channels are still visible\'). Press Shift over ATITD window.\n\nOptional: Pin the mine's Take... Ore... menu (\"All Ore\" will appear in pinned window) and it will refresh every round.\n\nWARNING: If you use the Dual Monitor option, uncheck in Interface Options: Right-Click opens a menu as pinned.";


-- Start don't alter these ...
oreGathered = 0;
oreGatheredTotal = 0;
oreGatheredLast = 0;
miningTime = 0;
autoWorkMine = true; -- written to Settings.mining_ore.lua.txt
timesworked = 0;
miningTimeTotal = 0;
dropdown_key_values = {"Shift Key", "Ctrl Key", "Alt Key", "Mouse Wheel Click"};
dropdown_ore_values = {"Aluminum (9)", "Antimony (14)", "Copper (8)", "Gold (12)", "Iron (7)", "Lead (9)", "Lithium (10)", "Magnesium (9)", "Platinum (12)", "Silver (10)", "Strontium (10)", "Tin (9)", "Titanium (12)","Tungsten (12)", "Zinc (10)"};
cancelButton = 0;
lastLineFound = "";
lastLineFound2 = "";
-- End Don't alter these ...


--Customizable
extraStones = false; -- written to Settings.mining_ore.lua.txt
noMouseMove = false; -- written to Settings.mining_ore.lua.txt
muteSoundEffects = false; -- written to Settings.mining_ore.lua.txt
minPopSleepDelay = 150;  -- The minimum delay time used during findClosePopUp() function
clickDelay = 100; -- written to Settings.mining_ore.lua.txt
defaultOrder = true;  -- written to Settings.mining_ore.lua.txt -- Determines to run 4 stone combo first, then 3 (true); or vice versa (false). Only applies when "Work 4 stone combo" is checked.
 -- Useful for debugging. If true, will write log file to mining_ore.txt - This also plays a sound anytime it is skipping a broken Node (assuming it's not a false positive).
-- While writeLogFile true, you should pay attention to see if you got a "You got some coal" message (node broke). Once at least one node is broke, you might hear this sound in future.
-- If you're hearing sounds, but "You got some coal" messages DON'T appear, then this is a false positive. Suggestes maybe rbgTol or hueTol needs adjust. Maybe zoom size... ?
writeLogFile = false;

brokenStoneCheck = false;
--These tolerance values might need tweaked
rgbTol = 150; --50
hueTol = 75; --10

-- We normally look for an OK popup box to move on. We also compare last chat Line to current chat Line.
-- If we gathered the EXACT same amount of Ore from previous round, then this confuses macro and needs timeOut to move on.
-- Silver is a good example of repetive quantities, 1, 2 silver is common, back to back. Later in script, Silver will use 4000ms timeout instead of usual 6000ms timeout.
chatReadTimeOut = 6000; -- Maximum Time (ms) before moving on.
--End Customizable


function doit()
    askForWindow(info);
    promptDelays();
    getMineLoc();
    getPoints();
    clickSequence();
end


function doit2()
    promptDelays();
    getMineLoc();
    getPoints();
    clickSequence();
end


function getMineLoc()
    mineList = {};
    local was_shifted = lsShiftHeld();
    if (dropdown_cur_value_key == 1) then
        was_shifted = lsShiftHeld();
        key = "tap Shift";
    elseif (dropdown_cur_value_key == 2) then
        was_shifted = lsControlHeld();
        key = "tap Ctrl";
    elseif (dropdown_cur_value_key == 3) then
        was_shifted = lsAltHeld();
        key = "tap Alt";
    elseif (dropdown_cur_value_key == 4) then
        was_shifted = lsMouseIsDown(2); --Button 3, which is middle mouse or mouse wheel
        key = "click MWheel ";
    end

    local is_done = false;
    mx = 0;
    my = 0;
    z = 0;
    while not is_done do
        mx, my = srMousePos();
        local is_shifted = lsShiftHeld();

        if (dropdown_cur_value_key == 1) then
            is_shifted = lsShiftHeld();
        elseif (dropdown_cur_value_key == 2) then
            is_shifted = lsControlHeld();
        elseif (dropdown_cur_value_key == 3) then
            is_shifted = lsAltHeld();
        elseif (dropdown_cur_value_key == 4) then
            is_shifted = lsMouseIsDown(2); --Button 3, which is middle mouse or mouse wheel
        end

        if is_shifted and not was_shifted then
            mineList[#mineList + 1] = {mx, my};
        end
        was_shifted = is_shifted;
        checkBreak();
        lsPrint(10, 10, z, 1.0, 1.0, 0xc0c0ffff,
            "Set Mine Location");
        local y = 60;
        lsPrint(10, y, z, 0.7, 0.7, 0xf0f0f0ff, "Lock ATITD screen (Alt+L) - OPTIONAL!");
        y = y + 20;
        lsPrint(10, y, z, 0.7, 0.7, 0xf0f0f0ff, "Suggest F5 view, zoomed about 75% out.");
        y = y + 60;
        lsPrint(10, y, z, 0.7, 0.7, 0xc0c0ffff, "Hover and " .. key .. " over the MINE !");
        y = y + 70;
        lsPrint(10, y, 0, 0.6, 0.6, 0xffffffff, "TIP (Optional):");
        y = y + 20;
        lsPrint(10, y, 0, 0.6, 0.6, 0xffffffff, "For Maximum Performance (least lag) Uncheck:");
        y = y + 16;
        lsPrint(10, y, 0, 0.6, 0.6, 0xffffffff, "Options, Interface, Other: 'Use Flyaway Messages'");
        local start = math.max(1, #mineList - 20);
        local index = 0;
        for i=start,#mineList do
            mineX = mineList[i][1];
            mineY = mineList[i][2];
        end

        if #mineList >= 1 then
            is_done = 1;
        end

        if ButtonText(205, lsScreenY - 30, z, 110, 0xFFFFFFff,
            "End script") then
            error "Clicked End Script button";
        end
        lsDoFrame();
        lsSleep(10);
    end
end


function fetchTotalCombos3()
    stoneCombo3 = 0;
    TotalCombos = 0;
    for i=1,#clickList do
        for j=i+1,#clickList do
            for k=j+1,#clickList do
                TotalCombos = TotalCombos + 1;
                stoneCombo3 = stoneCombo3 + 1;
            end
        end
    end
end

function fetchTotalCombos4()
    stoneCombo4 = 0;
--    TotalCombos = 0;
    for i=1,#clickList do
        for j=i+1,#clickList do
            for k=j+1,#clickList do
            	   for l=k+1,#clickList do
                    TotalCombos = TotalCombos + 1;
                    stoneCombo4 = stoneCombo4 + 1;
                end
            end
        end
    end
end


function getPoints()
    clickList = {};
    clickListColor = {};
    if (dropdown_ore_cur_value == 1) then
        ore = "Aluminum";
        stonecount = 9;
    elseif (dropdown_ore_cur_value == 2) then
        ore = "Antimony";
        stonecount = 14;
    elseif (dropdown_ore_cur_value == 3) then
        ore = "Copper";
        stonecount = 8;
    elseif (dropdown_ore_cur_value == 4) then
        ore = "Gold";
        stonecount = 12;
    elseif (dropdown_ore_cur_value == 5) then
        ore = "Iron";
        stonecount = 7;
    elseif (dropdown_ore_cur_value == 6) then
        ore = "Lead";
        stonecount = 9;
    elseif (dropdown_ore_cur_value == 7) then
        ore = "Lithium";
        stonecount = 10;
    elseif (dropdown_ore_cur_value == 8) then
        ore = "Magnesium";
        stonecount = 9;
    elseif (dropdown_ore_cur_value == 9) then
        ore = "Platinum";
        stonecount = 12;
    elseif (dropdown_ore_cur_value == 10) then
        ore = "Silver";
        stonecount = 10;
    elseif (dropdown_ore_cur_value == 11) then
        ore = "Strontium";
        stonecount = 10;
    elseif (dropdown_ore_cur_value == 12) then
        ore = "Tin";
        stonecount = 9;
    elseif (dropdown_ore_cur_value == 13) then
        ore = "Titanium";
        stonecount = 12;
    elseif (dropdown_ore_cur_value == 14) then
        ore = "Tungsten";
        stonecount = 12;
    elseif (dropdown_ore_cur_value == 15) then
        ore = "Zinc";
        stonecount = 10;
    end

    local nodeleft = stonecount;
    local was_shifted = lsShiftHeld();
    if (dropdown_cur_value_key == 1) then
        was_shifted = lsShiftHeld();
    elseif (dropdown_cur_value_key == 2) then
        was_shifted = lsControlHeld();
    elseif (dropdown_cur_value_key == 3) then
        was_shifted = lsAltHeld();
    elseif (dropdown_cur_value_key == 4) then
        was_shifted = lsMouseIsDown(2); --Button 3, which is middle mouse or mouse wheel
    end

    local is_done = false;
    local nx = 0;
    local ny = 0;
    local z = 0;
    while not is_done do
        nx, ny = srMousePos();
        pixels = srReadPixel(nx, ny);
        local is_shifted = lsShiftHeld();
        if (dropdown_cur_value_key == 1) then
            is_shifted = lsShiftHeld();
        elseif (dropdown_cur_value_key == 2) then
            is_shifted = lsControlHeld();
        elseif (dropdown_cur_value_key == 3) then
            is_shifted = lsAltHeld();
        elseif (dropdown_cur_value_key == 4) then
            is_shifted = lsMouseIsDown(2);
        end

        if is_shifted and not was_shifted then
            clickList[#clickList + 1] = {nx, ny};
            clickListColor[#clickListColor + 1] = {pixels};
            nodeleft = nodeleft - 1;
        end
        was_shifted = is_shifted;
        checkBreak();
        lsPrint(10, 10, z, 1.0, 1.0, 0xc0c0ffff,
            "Set Node Locations (" .. #clickList .. "/" .. stonecount .. ")");
        local y = 60;
        lsSetCamera(0,0,lsScreenX*1.4,lsScreenY*1.4);
        autoWorkMine = readSetting("autoWorkMine",autoWorkMine);
        autoWorkMine = lsCheckBox(15, y, z, 0xffffffff, " Auto 'Work Mine'", autoWorkMine);
        writeSetting("autoWorkMine",autoWorkMine);
        y = y + 25
        noMouseMove = readSetting("noMouseMove",noMouseMove);
        noMouseMove = lsCheckBox(15, y, z, 0xffffffff, " Dual Monitor (NoMouseMove) Mode", noMouseMove);
        writeSetting("noMouseMove",noMouseMove);
        y = y + 25
        if brokenStoneCheck then
          brokenStoneCheckColor = 0xffc0c0ff;
        else
          brokenStoneCheckColor = 0xffffffff;
        end
        brokenStoneCheck = readSetting("brokenStoneCheck",brokenStoneCheck);
        brokenStoneCheck = lsCheckBox(15, y, z, brokenStoneCheckColor, " Beta: Broken Stone Check", brokenStoneCheck);
        writeSetting("brokenStoneCheck",brokenStoneCheck);
        y = y + 25
        extraStones = readSetting("extraStones",extraStones);
        extraStones = lsCheckBox(15, y, z, 0xffffffff, " Work 4 stone combinations", extraStones);
        writeSetting("extraStones",extraStones);
        if defaultOrder then
          defaultOrderText = " Order: Do 4 stone combo first, then 3";
          defaultOrderTextColor = 0xffffffff;
        else
          defaultOrderText = " Order: Do 3 stone combo first, then 4";
          defaultOrderTextColor = 0xffff80ff;
        end
        y = y + 25
        if extraStones then
          defaultOrder = readSetting("defaultOrder",defaultOrder);
          defaultOrder = lsCheckBox(15, y, z, defaultOrderTextColor, defaultOrderText, defaultOrder);
          writeSetting("defaultOrder",defaultOrder);
        end
        lsSetCamera(0,0,lsScreenX*1.0,lsScreenY*1.0);
        y = y - 22
        lsPrint(10, y, z, 0.7, 0.7, 0xc0c0ffff, "Hover and " .. key .. " over each node.");
        y = y + 20;
        lsPrint(10, y, z, 0.7, 0.7, 0xff8080ff, "Make sure chat is MINIMIZED!");
        y = y + 25;
        lsPrint(10, y, z, 0.7, 0.7, 0xB0B0B0ff, "Mine Type: " .. ore .. " / Worked: " .. timesworked .. " times");
        y = y + 20;
        if miningTime ~= 0 then
          miningTimeGUI = DecimalsToMinutes(miningTime/1000);
        else
          miningTimeGUI = "N/A";
        end

        if miningTimeTotal ~= 0 then
          avgMiningTimeGUI = DecimalsToMinutes(miningTimeTotal/timesworked/1000);
        else
          avgMiningTimeGUI =  "N/A";
        end

        lsPrint(10, y, z, 0.7, 0.7, 0xf0f0f0ff, "Last: " .. miningTimeGUI .. "   /   Average: " .. avgMiningTimeGUI);
        y = y + 20;
        lsPrint(10, y, z, 0.7, 0.7, 0x80ff80ff, "Total Ore Found: " .. comma_value(math.floor(oreGatheredTotal)));
        lsPrint(175, y, z, 0.7, 0.7, 0x40ffffff, " Last: " .. comma_value(math.floor(oreGatheredLast)));
        y = y + 20;
        lsPrint(10, y, z, 0.65, 0.65, 0xB0B0B0ff, "Select " .. nodeleft .. " more nodes to automatically start!");
        y = y + 20;
        local start = math.max(1, #clickList - 20);
        local index = 0;
        for i=start,#clickList do
            local xOff = (index % 4) * 75;
            local yOff = (index - index%4)/2 * 7;
            local xOff2 = (#clickList % 4) * 75;
            local yOff2 = (#clickList - #clickList%4)/2 * 7;
            lsPrint(11 + xOff, y + yOff, z, 0.5, 0.5, 0xffffffff, i .. ":");
            lsPrint(11 + xOff, y + yOff, z, 0.5, 0.5, clickListColor[i][1], "     (" .. clickList[i][1] .. ", " .. clickList[i][2] .. ")");
            index = index + 1;
            if #clickList < stonecount then
              lsPrint(11 + xOff2, y+yOff2, z, 0.5, 0.5, 0xffffffff, #clickList+1 .. ":");
              lsPrint(11 + xOff2, y+yOff2, z, 0.5, 0.5, pixels, "      " .. nx .. ", " .. ny);
            end
        end

        if #clickList == 0 then
          lsPrint(11, y, z, 0.5, 0.5, 0xffffffff, "1:");
          lsPrint(11, y, z, 0.5, 0.5, pixels, "      " .. nx .. ", " .. ny);
        end

        if #clickList >= stonecount then
            is_done = 1;
        end

        if #clickList == 0 then
            if ButtonText(10, lsScreenY - 30, z, 110, 0xffff80ff, "Work Mine") then
                workMine();
            end
        end

        if ButtonText(120, lsScreenY -30, z, 80, 0xffffffff, "Config") then
            cancelButton = 1;
            doit2();
        end

        if #clickList > 0 then
            if ButtonText(10, lsScreenY - 30, z, 100, 0xff8080ff, "Reset") then
                reset();
            end
        end

        if ButtonText(205, lsScreenY - 30, z, 110, 0xFFFFFFff,
            "End script") then
            error "Clicked End Script button";
        end
        lsDoFrame();
        lsSleep(10);
    end
end


function clickSequence()
    fetchTotalCombos3();
  if extraStones then
    fetchTotalCombos4();
  end
    chatRead();	
    if noMouseMove then
      sleepWithStatus(3000, "Starting... Now is your chance to move your mouse to second monitor!", nil, 0.7, 0.7);
    else
      sleepWithStatus(150, "Starting... Don\'t move mouse!");
    end
    oreGatheredLast = 0;
    oreGathered = 0;
    worked = 0;
    startMiningTime = lsGetTimer();

  if extraStones and defaultOrder then
    fourStoneCombo();
    threeStoneCombo();
  elseif extraStones and not defaultOrder then
    threeStoneCombo();
    fourStoneCombo();
  else
    threeStoneCombo();
  end

    miningTime = lsGetTimer() - startMiningTime;
    miningTimeTotal =  miningTimeTotal + miningTime;
    timesworked = timesworked + 1;

    lsSleep(1000); -- Delay not required, just gives a slight chance to see the last node worked on GUI, from updateGUI(), before it disappears off screen


    if not muteSoundEffects then

        lsPlaySound("beepping.wav");
    end

    if autoWorkMine then
        workMine();
    end
    TakeOreWindowRefresh();
    reset();
end


function workMine()
    if noMouseMove then
      srClickMouseNoMove(mineX, mineY);
      lsSleep(clickDelay);
      clickAllText("Work this Mine", 20, 2, 1); -- offsetX, offsetY, rightClick (1 = true)
    else
      srSetMousePos(mineX, mineY);
      lsSleep(clickDelay);
      --Send 'W' key over Mine to Work it (Get new nodes)
      srKeyEvent('W');
    end

if writeLogFile then
  WriteLog("\nWorking Mine...");
end
    sleepWithStatus(1000, "Working mine (Fetching new nodes)");
    findClosePopUpOld();
end


function checkCloseWindows()
    -- Rare situations a click can cause a window to appear for a node, blocking the view to other nodes.
    -- This is a safeguard to keep random windows that could appear, from remaining on screen and blocking the view of other nodes from being selected.
    srReadScreen();
    lsSleep(10);
    local closeWindows = findAllImages("thisis.png");

    if #closeWindows > 0 then
        for i=#closeWindows, 1, -1 do
            -- 2 right clicks in a row to close window (1st click pins it, 2nd unpins it
            srClickMouseNoMove(closeWindows[i][0]+5, closeWindows[i][1]+10, true);
            lsSleep(100);
            srClickMouseNoMove(closeWindows[i][0]+5, closeWindows[i][1]+10, true);
        end
        lsSleep(50);
    end
end


function reset()
    getPoints();
    clickSequence();
end


function checkAbort()
    if lsShiftHeld() then
        sleepWithStatus(750, "Aborting ...");
        reset();
    end
end


function findClosePopUp()
    chatRead();
    lastLineFound = lastLineParse;
    lastLineFound2 = lastLineParse2;
    startTime = lsGetTimer();

    while 1 do
        checkBreak();
        chatRead();
        OK = srFindImage("OK.png");

        if clickDelay < minPopSleepDelay then
            popSleepDelay = minPopSleepDelay;
        else
            popSleepDelay = clickDelay
        end

        if OK then
            srClickMouseNoMove(OK[0]+2,OK[1]+2, true);
            lsSleep(popSleepDelay);
            break;
        end

	  if ore == "Silver" then
	    chatReadTimeOut = 4000; -- else we use default 6000
	  end

       --If we gathered new ore, add to tally, we're not going to get a popup.
	  if (lastLineFound2 ~= lastLineParse2) or (lastLineFound ~= lastLineParse) or skipRead or ( (lsGetTimer() - startTime) > chatReadTimeOut )  then

		if oreFound and ( (lsGetTimer() - startTime) <= chatReadTimeOut ) then -- if it timed out, don't add ore to total, because we're not sure if we got any or not
              oreGatheredTotal = oreGatheredTotal + oreGathered;
              oreGatheredLast = oreGatheredLast + oreGathered;
		end

            lsSleep(popSleepDelay);
            break;
        end
    lsSleep(50);
    end
end

<commit_msg>Update mining_ore.lua<commit_after>-- mining_ore.lua v2.2.9.2 -- by Cegaiel
-- Credits to Tallow for his Simon macro, which was used as a template to build on.
-- 
-- Brute force method, you manually click/set every stones' location and it will work every possible 3 node/stone combinations.
--
-- New in v2.2.0 - Now allows you to optionally try 4 stone combos after doing the regular 3 stone combos.
-- 4 stone combos don't produce ore very often, but when it does, its usually 100+
-- Choosing 4 stone combos will double the time per round, as the nodes worked quantity will double
-- ie Iron is 35 works for the normal 3 stone method.  But choosing 4 stone will cause it to be 70 (35 for 3 stone combos + 35 for 4 stone combos).
--
-- New in v2.2.3 Dual Monitor mode. This will use the srClickMouseNoMove method. Instead of moving mouse, hovering each node and sending a 'A' or 'S' key...
-- Instead it will right click each mouse (without moving mouse and click on the menus. This allows you to do something on 2nd monitor without having mouse move.
-- You will also be given a 3 second countdown (after selecting nodes) to get your mouse over to the 2nd monitor.
-- It will then move mouse once to upper left corner then start popping up menus.
-- BEWARE: You must uncheck Options, Interface Options: Right-Click opens a menu as pinned. Or else you will have tons of left-over pinned menus, that you need to close out!
--
-- v 2.2.9 + New check box "Broken Stone Check" . When you tap shift over each node, it now records pixel color, in addition to the x,y position.
-- The tolerance is defined in rgbTol and hueTol. It might occassionaly give a false positive.  I've found if you zoom in a bit more, it usually fixes that.
-- The purpose of this is to skip all future nodes from attempting to be worked. Speeds up by not trying to work future stones that don't exist.

-- For a more detailed Change Log and history, see https://github.com/DashingStrike/Automato-ATITD/commits/master/scripts/mining_ore.lua


dofile("common.inc");
dofile("settings.inc");

info = "Ore Mining v2.2.9.2 by Cegaiel --\nMacro brute force tries every possible 3 stone combination (and optionally 4 stone, too). Time consuming but it works!\n\nMAIN chat tab MUST be showing and wide enough so that each line doesn't wrap.\n\nChat MUST be minimized but Visible (Options, Chat-Related, \'Minimized chat channels are still visible\'). Press Shift over ATITD window.\n\nOptional: Pin the mine's Take... Ore... menu (\"All Ore\" will appear in pinned window) and it will refresh every round.\n\nWARNING: If you use the Dual Monitor option, uncheck in Interface Options: Right-Click opens a menu as pinned.";


-- Start don't alter these ...
oreGathered = 0;
oreGatheredTotal = 0;
oreGatheredLast = 0;
miningTime = 0;
autoWorkMine = true; -- written to Settings.mining_ore.lua.txt
timesworked = 0;
miningTimeTotal = 0;
dropdown_key_values = {"Shift Key", "Ctrl Key", "Alt Key", "Mouse Wheel Click"};
dropdown_ore_values = {"Aluminum (9)", "Antimony (14)", "Copper (8)", "Gold (12)", "Iron (7)", "Lead (9)", "Lithium (10)", "Magnesium (9)", "Nickel (13)", "Platinum (12)", "Silver (10)", "Strontium (10)", "Tin (9)", "Titanium (12)","Tungsten (12)", "Zinc (10)"};
cancelButton = 0;
lastLineFound = "";
lastLineFound2 = "";
-- End Don't alter these ...


--Customizable
extraStones = false; -- written to Settings.mining_ore.lua.txt
noMouseMove = false; -- written to Settings.mining_ore.lua.txt
muteSoundEffects = false; -- written to Settings.mining_ore.lua.txt
minPopSleepDelay = 150;  -- The minimum delay time used during findClosePopUp() function
clickDelay = 100; -- written to Settings.mining_ore.lua.txt
defaultOrder = true;  -- written to Settings.mining_ore.lua.txt -- Determines to run 4 stone combo first, then 3 (true); or vice versa (false). Only applies when "Work 4 stone combo" is checked.
 -- Useful for debugging. If true, will write log file to mining_ore.txt - This also plays a sound anytime it is skipping a broken Node (assuming it's not a false positive).
-- While writeLogFile true, you should pay attention to see if you got a "You got some coal" message (node broke). Once at least one node is broke, you might hear this sound in future.
-- If you're hearing sounds, but "You got some coal" messages DON'T appear, then this is a false positive. Suggestes maybe rbgTol or hueTol needs adjust. Maybe zoom size... ?
writeLogFile = false;

brokenStoneCheck = false;
--These tolerance values might need tweaked
rgbTol = 150; --50
hueTol = 75; --10

-- We normally look for an OK popup box to move on. We also compare last chat Line to current chat Line.
-- If we gathered the EXACT same amount of Ore from previous round, then this confuses macro and needs timeOut to move on.
-- Silver is a good example of repetive quantities, 1, 2 silver is common, back to back. Later in script, Silver will use 4000ms timeout instead of usual 6000ms timeout.

chatReadTimeOut = 3000; -- Maximum Time (ms) before moving on.
chatReadTimeOutSilver = 4000; -- Since silver frequently gets 1, 2 silver back to back, then lower time out to 4000 instead of 6000 so prevent longer hang times (when last chat line is same as previous line).

--End Customizable


function doit()
    askForWindow(info);
    promptDelays();
    getMineLoc();
    getPoints();
    clickSequence();
end


function doit2()
    promptDelays();
    getMineLoc();
    getPoints();
    clickSequence();
end


function getMineLoc()
    mineList = {};
    local was_shifted = lsShiftHeld();
    if (dropdown_cur_value_key == 1) then
        was_shifted = lsShiftHeld();
        key = "tap Shift";
    elseif (dropdown_cur_value_key == 2) then
        was_shifted = lsControlHeld();
        key = "tap Ctrl";
    elseif (dropdown_cur_value_key == 3) then
        was_shifted = lsAltHeld();
        key = "tap Alt";
    elseif (dropdown_cur_value_key == 4) then
        was_shifted = lsMouseIsDown(2); --Button 3, which is middle mouse or mouse wheel
        key = "click MWheel ";
    end

    local is_done = false;
    mx = 0;
    my = 0;
    z = 0;
    while not is_done do
        mx, my = srMousePos();
        local is_shifted = lsShiftHeld();

        if (dropdown_cur_value_key == 1) then
            is_shifted = lsShiftHeld();
        elseif (dropdown_cur_value_key == 2) then
            is_shifted = lsControlHeld();
        elseif (dropdown_cur_value_key == 3) then
            is_shifted = lsAltHeld();
        elseif (dropdown_cur_value_key == 4) then
            is_shifted = lsMouseIsDown(2); --Button 3, which is middle mouse or mouse wheel
        end

        if is_shifted and not was_shifted then
            mineList[#mineList + 1] = {mx, my};
        end
        was_shifted = is_shifted;
        checkBreak();
        lsPrint(10, 10, z, 1.0, 1.0, 0xc0c0ffff,
            "Set Mine Location");
        local y = 60;
        lsPrint(10, y, z, 0.7, 0.7, 0xf0f0f0ff, "Lock ATITD screen (Alt+L) - OPTIONAL!");
        y = y + 20;
        lsPrint(10, y, z, 0.7, 0.7, 0xf0f0f0ff, "Suggest F5 view, zoomed about 75% out.");
        y = y + 60;
        lsPrint(10, y, z, 0.7, 0.7, 0xc0c0ffff, "Hover and " .. key .. " over the MINE !");
        y = y + 70;
        lsPrint(10, y, 0, 0.6, 0.6, 0xffffffff, "TIP (Optional):");
        y = y + 20;
        lsPrint(10, y, 0, 0.6, 0.6, 0xffffffff, "For Maximum Performance (least lag) Uncheck:");
        y = y + 16;
        lsPrint(10, y, 0, 0.6, 0.6, 0xffffffff, "Options, Interface, Other: 'Use Flyaway Messages'");
        local start = math.max(1, #mineList - 20);
        local index = 0;
        for i=start,#mineList do
            mineX = mineList[i][1];
            mineY = mineList[i][2];
        end

        if #mineList >= 1 then
            is_done = 1;
        end

        if ButtonText(205, lsScreenY - 30, z, 110, 0xFFFFFFff,
            "End script") then
            error "Clicked End Script button";
        end
        lsDoFrame();
        lsSleep(10);
    end
end


function fetchTotalCombos3()
    stoneCombo3 = 0;
    TotalCombos = 0;
    for i=1,#clickList do
        for j=i+1,#clickList do
            for k=j+1,#clickList do
                TotalCombos = TotalCombos + 1;
                stoneCombo3 = stoneCombo3 + 1;
            end
        end
    end
end

function fetchTotalCombos4()
    stoneCombo4 = 0;
--    TotalCombos = 0;
    for i=1,#clickList do
        for j=i+1,#clickList do
            for k=j+1,#clickList do
            	   for l=k+1,#clickList do
                    TotalCombos = TotalCombos + 1;
                    stoneCombo4 = stoneCombo4 + 1;
                end
            end
        end
    end
end


function getPoints()
    clickList = {};
    clickListColor = {};
    if (dropdown_ore_cur_value == 1) then
        ore = "Aluminum";
        stonecount = 9;
    elseif (dropdown_ore_cur_value == 2) then
        ore = "Antimony";
        stonecount = 14;
    elseif (dropdown_ore_cur_value == 3) then
        ore = "Copper";
        stonecount = 8;
    elseif (dropdown_ore_cur_value == 4) then
        ore = "Gold";
        stonecount = 12;
    elseif (dropdown_ore_cur_value == 5) then
        ore = "Iron";
        stonecount = 7;
    elseif (dropdown_ore_cur_value == 6) then
        ore = "Lead";
        stonecount = 9;
    elseif (dropdown_ore_cur_value == 7) then
        ore = "Lithium";
        stonecount = 10;
    elseif (dropdown_ore_cur_value == 8) then
        ore = "Magnesium";
        stonecount = 9;
    elseif (dropdown_ore_cur_value == 9) then
        ore = "Nickel";
        stonecount = 13;
    elseif (dropdown_ore_cur_value == 10) then
        ore = "Platinum";
        stonecount = 12;
    elseif (dropdown_ore_cur_value == 11) then
        ore = "Silver";
        stonecount = 10;
    elseif (dropdown_ore_cur_value == 12) then
        ore = "Strontium";
        stonecount = 10;
    elseif (dropdown_ore_cur_value == 13) then
        ore = "Tin";
        stonecount = 9;
    elseif (dropdown_ore_cur_value == 14) then
        ore = "Titanium";
        stonecount = 12;
    elseif (dropdown_ore_cur_value == 15) then
        ore = "Tungsten";
        stonecount = 12;
    elseif (dropdown_ore_cur_value == 16) then
        ore = "Zinc";
        stonecount = 10;
    end

    local nodeleft = stonecount;
    local was_shifted = lsShiftHeld();
    if (dropdown_cur_value_key == 1) then
        was_shifted = lsShiftHeld();
    elseif (dropdown_cur_value_key == 2) then
        was_shifted = lsControlHeld();
    elseif (dropdown_cur_value_key == 3) then
        was_shifted = lsAltHeld();
    elseif (dropdown_cur_value_key == 4) then
        was_shifted = lsMouseIsDown(2); --Button 3, which is middle mouse or mouse wheel
    end

    local is_done = false;
    local nx = 0;
    local ny = 0;
    local z = 0;
    while not is_done do
        nx, ny = srMousePos();
        pixels = srReadPixel(nx, ny);
        local is_shifted = lsShiftHeld();
        if (dropdown_cur_value_key == 1) then
            is_shifted = lsShiftHeld();
        elseif (dropdown_cur_value_key == 2) then
            is_shifted = lsControlHeld();
        elseif (dropdown_cur_value_key == 3) then
            is_shifted = lsAltHeld();
        elseif (dropdown_cur_value_key == 4) then
            is_shifted = lsMouseIsDown(2);
        end

        if is_shifted and not was_shifted then
            clickList[#clickList + 1] = {nx, ny};
            clickListColor[#clickListColor + 1] = {pixels};
            nodeleft = nodeleft - 1;
        end
        was_shifted = is_shifted;
        checkBreak();
        lsPrint(10, 10, z, 1.0, 1.0, 0xc0c0ffff,
            "Set Node Locations (" .. #clickList .. "/" .. stonecount .. ")");
        local y = 60;
        lsSetCamera(0,0,lsScreenX*1.4,lsScreenY*1.4);
        autoWorkMine = readSetting("autoWorkMine",autoWorkMine);
        autoWorkMine = lsCheckBox(15, y, z, 0xffffffff, " Auto 'Work Mine'", autoWorkMine);
        writeSetting("autoWorkMine",autoWorkMine);
        y = y + 25
        noMouseMove = readSetting("noMouseMove",noMouseMove);
        noMouseMove = lsCheckBox(15, y, z, 0xffffffff, " Dual Monitor (NoMouseMove) Mode", noMouseMove);
        writeSetting("noMouseMove",noMouseMove);
        y = y + 25
        if brokenStoneCheck then
          brokenStoneCheckColor = 0xffc0c0ff;
        else
          brokenStoneCheckColor = 0xffffffff;
        end
        brokenStoneCheck = readSetting("brokenStoneCheck",brokenStoneCheck);
        brokenStoneCheck = lsCheckBox(15, y, z, brokenStoneCheckColor, " Beta: Broken Stone Check", brokenStoneCheck);
        writeSetting("brokenStoneCheck",brokenStoneCheck);
        y = y + 25
        extraStones = readSetting("extraStones",extraStones);
        extraStones = lsCheckBox(15, y, z, 0xffffffff, " Work 4 stone combinations", extraStones);
        writeSetting("extraStones",extraStones);
        if defaultOrder then
          defaultOrderText = " Order: Do 4 stone combo first, then 3";
          defaultOrderTextColor = 0xffffffff;
        else
          defaultOrderText = " Order: Do 3 stone combo first, then 4";
          defaultOrderTextColor = 0xffff80ff;
        end
        y = y + 25
        if extraStones then
          defaultOrder = readSetting("defaultOrder",defaultOrder);
          defaultOrder = lsCheckBox(15, y, z, defaultOrderTextColor, defaultOrderText, defaultOrder);
          writeSetting("defaultOrder",defaultOrder);
        end
        lsSetCamera(0,0,lsScreenX*1.0,lsScreenY*1.0);
        y = y - 22
        lsPrint(10, y, z, 0.7, 0.7, 0xc0c0ffff, "Hover and " .. key .. " over each node.");
        y = y + 20;
        lsPrint(10, y, z, 0.7, 0.7, 0xff8080ff, "Make sure chat is MINIMIZED!");
        y = y + 25;
        lsPrint(10, y, z, 0.7, 0.7, 0xB0B0B0ff, "Mine Type: " .. ore .. " / Worked: " .. timesworked .. " times");
        y = y + 20;
        if miningTime ~= 0 then
          miningTimeGUI = DecimalsToMinutes(miningTime/1000);
        else
          miningTimeGUI = "N/A";
        end

        if miningTimeTotal ~= 0 then
          avgMiningTimeGUI = DecimalsToMinutes(miningTimeTotal/timesworked/1000);
        else
          avgMiningTimeGUI =  "N/A";
        end

        lsPrint(10, y, z, 0.7, 0.7, 0xf0f0f0ff, "Last: " .. miningTimeGUI .. "   /   Average: " .. avgMiningTimeGUI);
        y = y + 20;
        lsPrint(10, y, z, 0.7, 0.7, 0x80ff80ff, "Total Ore Found: " .. comma_value(math.floor(oreGatheredTotal)));
        lsPrint(175, y, z, 0.7, 0.7, 0x40ffffff, " Last: " .. comma_value(math.floor(oreGatheredLast)));
        y = y + 20;
        lsPrint(10, y, z, 0.65, 0.65, 0xB0B0B0ff, "Select " .. nodeleft .. " more nodes to automatically start!");
        y = y + 20;
        local start = math.max(1, #clickList - 20);
        local index = 0;
        for i=start,#clickList do
            local xOff = (index % 4) * 75;
            local yOff = (index - index%4)/2 * 7;
            local xOff2 = (#clickList % 4) * 75;
            local yOff2 = (#clickList - #clickList%4)/2 * 7;
            lsPrint(11 + xOff, y + yOff, z, 0.5, 0.5, 0xffffffff, i .. ":");
            lsPrint(11 + xOff, y + yOff, z, 0.5, 0.5, clickListColor[i][1], "     (" .. clickList[i][1] .. ", " .. clickList[i][2] .. ")");
            index = index + 1;
            if #clickList < stonecount then
              lsPrint(11 + xOff2, y+yOff2, z, 0.5, 0.5, 0xffffffff, #clickList+1 .. ":");
              lsPrint(11 + xOff2, y+yOff2, z, 0.5, 0.5, pixels, "      " .. nx .. ", " .. ny);
            end
        end

        if #clickList == 0 then
          lsPrint(11, y, z, 0.5, 0.5, 0xffffffff, "1:");
          lsPrint(11, y, z, 0.5, 0.5, pixels, "      " .. nx .. ", " .. ny);
        end

        if #clickList >= stonecount then
            is_done = 1;
        end

        if #clickList == 0 then
            if ButtonText(10, lsScreenY - 30, z, 110, 0xffff80ff, "Work Mine") then
                workMine();
            end
        end

        if ButtonText(120, lsScreenY -30, z, 80, 0xffffffff, "Config") then
            cancelButton = 1;
            doit2();
        end

        if #clickList > 0 then
            if ButtonText(10, lsScreenY - 30, z, 100, 0xff8080ff, "Reset") then
                reset();
            end
        end

        if ButtonText(205, lsScreenY - 30, z, 110, 0xFFFFFFff,
            "End script") then
            error "Clicked End Script button";
        end
        lsDoFrame();
        lsSleep(10);
    end
end


function clickSequence()
    fetchTotalCombos3();
  if extraStones then
    fetchTotalCombos4();
  end
    chatRead();	
    if noMouseMove then
      sleepWithStatus(3000, "Starting... Now is your chance to move your mouse to second monitor!", nil, 0.7, 0.7);
    else
      sleepWithStatus(150, "Starting... Don\'t move mouse!");
    end
    oreGatheredLast = 0;
    oreGathered = 0;
    worked = 0;
    startMiningTime = lsGetTimer();

  if extraStones and defaultOrder then
    fourStoneCombo();
    threeStoneCombo();
  elseif extraStones and not defaultOrder then
    threeStoneCombo();
    fourStoneCombo();
  else
    threeStoneCombo();
  end

    miningTime = lsGetTimer() - startMiningTime;
    miningTimeTotal =  miningTimeTotal + miningTime;
    timesworked = timesworked + 1;

    lsSleep(1000); -- Delay not required, just gives a slight chance to see the last node worked on GUI, from updateGUI(), before it disappears off screen


    if not muteSoundEffects then

        lsPlaySound("beepping.wav");
    end

    if autoWorkMine then
        workMine();
    end
    TakeOreWindowRefresh();
    reset();
end


function workMine()
    if noMouseMove then
      srClickMouseNoMove(mineX, mineY);
      lsSleep(clickDelay);
      clickAllText("Work this Mine", 20, 2, 1); -- offsetX, offsetY, rightClick (1 = true)
    else
      srSetMousePos(mineX, mineY);
      lsSleep(clickDelay);
      --Send 'W' key over Mine to Work it (Get new nodes)
      srKeyEvent('W');
    end

if writeLogFile then
  WriteLog("\nWorking Mine...");
end
    sleepWithStatus(1000, "Working mine (Fetching new nodes)");
    findClosePopUpOld();
end


function checkCloseWindows()
    -- Rare situations a click can cause a window to appear for a node, blocking the view to other nodes.
    -- This is a safeguard to keep random windows that could appear, from remaining on screen and blocking the view of other nodes from being selected.
    srReadScreen();
    lsSleep(10);
    local closeWindows = findAllImages("thisis.png");

    if #closeWindows > 0 then
        for i=#closeWindows, 1, -1 do
            -- 2 right clicks in a row to close window (1st click pins it, 2nd unpins it
            srClickMouseNoMove(closeWindows[i][0]+5, closeWindows[i][1]+10, true);
            lsSleep(100);
            srClickMouseNoMove(closeWindows[i][0]+5, closeWindows[i][1]+10, true);
        end
        lsSleep(50);
    end
end


function reset()
    getPoints();
    clickSequence();
end


function checkAbort()
    if lsShiftHeld() then
        sleepWithStatus(750, "Aborting ...");
        reset();
    end
end


function findClosePopUp()
    chatRead();
    lastLineFound = lastLineParse;
    lastLineFound2 = lastLineParse2;
    startTime = lsGetTimer();

    while 1 do
        checkBreak();
        chatRead();
        OK = srFindImage("OK.png");

        if clickDelay < minPopSleepDelay then
            popSleepDelay = minPopSleepDelay;
        else
            popSleepDelay = clickDelay
        end

        if OK then
            srClickMouseNoMove(OK[0]+2,OK[1]+2, true);
            lsSleep(popSleepDelay);
            break;
        end

	  if ore == "Silver" then
	    chatReadTimeOut = chatReadTimeOutSilver; -- Since Silver gets 1,2 ore commonly back to back, then wait less time to timeout.
	  end

       --If we gathered new ore, add to tally, we're not going to get a popup.
	  if (lastLineFound2 ~= lastLineParse2) or (lastLineFound ~= lastLineParse) or skipRead or ( (lsGetTimer() - startTime) > chatReadTimeOut )  then

		if oreFound and ( (lsGetTimer() - startTime) <= chatReadTimeOut ) then -- if it timed out, don't add ore to total, because we're not sure if we got any or not
              oreGatheredTotal = oreGatheredTotal + oreGathered;
              oreGatheredLast = oreGatheredLast + oreGathered;
		end

            lsSleep(popSleepDelay);
            break;
        end
    lsSleep(50);
    end
end


{'fraction_non_alphanumeric': 0.10687513916033745, 'fraction_numerical': 0.03255733405902872, 'mean_word_length': 2.408550467998988, 'pattern_counts': {'":': 4, '<': 9, '<?xml version=': 0, '>': 13, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 4, 'substrings_counts': 24, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4001171', 'n_tokens_mistral': 13899, 'n_tokens_neox': 12447, 'n_words': 4240}