The Wiki for Tale 8 is in read-only mode and is available for archival and reference purposes only. Please visit the current Tale 11 Wiki in the meantime.

If you have any issues with this Wiki, please post in #wiki-editing on Discord or contact Brad in-game.

User:Augir/Foliage

From A Wiki in the Desert
< User:Augir
Revision as of 02:08, 12 July 2018 by Augir (talk | contribs)
Jump to navigation Jump to search

http://www.atitd.org/wiki/tale3/Guides/Foliage

-- crematory.lua v1.2 by Tallow -- -- Runs one or more crematories. Automatically discovers button -- configuration on its own and loads/unloads materials. --

dofile("common.inc");

askText = singleLine([[

 Crematory v1.2 (by Tallow) --
 Automatically runs one or more crematories.

]]);

wmText = "Tap Ctrl on Crematories to open and pin.\nTap Alt to open, pin and stash.";

OPP = 0; SAME_UP = 1; SAME_DOWN = 2;

tolerance = 6500; tickTime = 500; maxWait = 1000; longWait = 500; shortWait = 30;

colOffsets = {

 {15, 22}, --{35-40-3, 204-182}
 {51, 22}, --{71-40-3, 204-182}
 {87, 22}, --{107-40-3, 204-182}
 {123, 22},--{143-40-3, 204-182}
 {159, 22},--{179-40-3, 204-182}
 {195, 22},--{215-40-3, 204-182}
 {231, 22} --{251-40-3, 204-182}

};

colWidth = 36-35+6; colHeight = 323-204; colMiddle = 57;

buttonOffsets = {

 {32, 151}, --{49-40, 333-182}
 {72, 151}, --{89-40, 333-182}
 {112, 151},--{129-40, 333-182}
 {152, 151},--{169-40, 333-182}
 {192, 151} --{209-40, 333-182}

};

buttonWidth = 78-49; buttonHeight = 354-333; buttonClick = 10;

limestoneOffset = 0; leeksOffset = 16; flaxOffset = 32; papyrusOffset = 48; woodOffset = 64;

load_flax = true; load_papyrus = true; load_leeks = true; load_limestone = true;

currentPass = 1; passCount = 5;

windows = nil;


-- doit


function doit()

 askForWindow(askText);
 windowManager("Crematory Setup", wmText);
 unpinOnExit(runCrematories);

end



function runCrematories()

 promptLoad();
 askForFocus();
 for i=1,passCount do
   currentPass = i;
   local iter = 0;
   srReadScreen();
   while closeEmptyAndErrorWindows() ~= 0 and iter < 10 do
     lsSleep(100);
     checkBreak();
     srReadScreen();
     iter = iter + 1;
   end
   takeAll();
   loadAll();
   start();
   local is_done = false;
   while not is_done do
     tick();
     is_done = checkDone();
   end
   sleepWithStatus(longWait*5, updateMessage("Waiting to take"));
 end
 takeAll();
 lsPlaySound("Complete.wav");

end


-- addWindow


function addWindow(vPos)

 local newWindow = {
   origin = {vPos[0], vPos[1]},
   ups = {nil, nil, nil, nil, nil},
   downs = {nil, nil, nil, nil, nil},
   dirs = {OPP, OPP, OPP, OPP, OPP},
   double = {false, false, false, false, false, false, false},
   probe = 0,
   lastPos = nil;
   lastDiff = nil;
   buttonState = {true, true, true, true, true},
   sameCount = 0,
   done = false
 };
 local vFire = srFindImageInRange("crem-fire.png", newWindow.origin[1] - 31,
                                  newWindow.origin[2] - 175, 238, 175,
                                  tolerance);
 if vFire then
   newWindow.fire = {vFire[0], vFire[1]};
 else
   error "No fire button. Do you have Advanced Chemistry?"
 end
 windows[#windows + 1] = newWindow;

end


-- resetWindow


function resetWindow(current)

 local vLime = srFindImageInRange("crem-lime.png", current.origin[1] - 20,
                                  current.origin[2] - 20, 100, 100,
                                  tolerance);
 if (not vLime) then
    error "Could not find origin again.";
 end
 if ((vLime[0] ~= current.origin[1]) or
     (vLime[1] ~= current.origin[2])) then
    current.origin[1] = vLime[0];
    current.origin[2] = vLime[1];
 end
 local vFire = srFindImageInRange("crem-fire.png", current.origin[1] - 31,
                                  current.origin[2] - 175, 238, 175,
                                  tolerance);
 if vFire then
   current.fire = {vFire[0], vFire[1]};
 end
 if current.probe < 6 then
   current.probe = 0;
   current.ups = {nil, nil, nil, nil, nil};
   current.downs = {nil, nil, nil, nil, nil};
   current.dirs = {OPP, OPP, OPP, OPP, OPP};
   current.double = {false, false, false, false, false, false, false};
 end
 current.lastPos = nil;
 current.lastDiff = nil;
 current.buttonState = {true, true, true, true, true};
 current.sameCount = 0;
 current.done = false;

end


-- start


function start()

 sleepWithStatus(longWait, updateMessage("Waiting to begin"));
 srReadScreen();
 if windows then
   for i=1,#windows do
     resetWindow(windows[i]);
   end
 else
   windows = {};
   local posList = findAllImages("crem-lime.png");
   if #posList == 0 then
     error "No crematories found";
   end
   for i=1,#posList do
     addWindow(posList[i]);
   end
 end
 for i=1,#windows do
   if windows[i].fire then
     safeClick(windows[i].fire[1] + 5, windows[i].fire[2] + 5);
     lsSleep(shortWait);
   end
 end
 sleepWithStatus(longWait, updateMessage("Finding my Chi"));
 srReadScreen();
   for i=1,#windows do
        windows[i].origin[2] = windows[i].origin[2] - 7;
   end
 for i=1,#windows do
   windows[i].lastPos = findPoints(windows[i]);
   if not windows[i].lastPos then
     windows[i].done = true;
   end
 end

end


-- tick


function tick()

 sleepWithStatus(tickTime, updateMessage("Tending Crematory"));
 srReadScreen();
 for i=1,#windows do
   tickWindow(windows[i]);
 end
 checkBreak();

end


-- tickWindow


function tickWindow(current)

 if not current.done then
   local points = findPoints(current);
   if points then
     probeNext(current, points);
     if current.probe > 5 then
       toggleButtons(current, points, current.buttonState);
     end
   else
     current.done = true;
   end
 end

end


-- checkDone


function checkDone()

  local allFound = true;
  cremWins = findAllText("This is a Crematory", nil, REGION);
  for i = 1, #cremWins do
     safeClick(cremWins[i].x + 5, cremWins[i].y + 5);
  end
  for i = 1, #cremWins do
     if not findText("Fire the Crematory", cremWins[i]) then
        allFound = false;
     end
  end
  return allFound;

end


-- findPoints


function findPoints(current)

 local result = {};
 for i=1,7 do
   local offset = {current.origin[1] + colOffsets[i][1],
                   current.origin[2] + colOffsets[i][2]};
   local point = srFindImageInRange("crem-point.png", offset[1],
                                    offset[2] - 5,
                                    colWidth, colHeight + 10, tolerance);
   if point then
     result[i] = point[1] - colOffsets[i][2] - current.origin[2] - colMiddle;
   else
     result = nil;
     break;
   end
 end
 return result;

end


-- findDiffs


function findDiffs(current, points)

 local result = {};
 local all_zero = true;
 for i=1,7 do
   result[i] = points[i] - current.lastPos[i];
   if result[i] ~= 0 then
     all_zero = false;
   end
 end
 if all_zero then
   result = nil;
 end
 return result;

end


-- probeNext


function probeNext(current, points)

 local diffs = findDiffs(current, points);
 checkSame(current, diffs);
 if diffs and current.probe < 6 then
   if current.probe > 0 then
     for i=1,7 do
       if current.lastDiffs[i] < 0 and diffs[i] > 0 then
         if current.ups[current.probe] then
           current.downs[current.probe] = i;
           current.dirs[current.probe] = SAME_UP;
         else
           current.ups[current.probe] = i;
         end
       elseif current.lastDiffs[i] > 0 and diffs[i] < 0 then
         if current.downs[current.probe] then
           current.ups[current.probe] = i;
           current.dirs[current.probe] = SAME_DOWN;
         else
           current.downs[current.probe] = i;
         end
       end
     end
     if current.ups[current.probe] and current.downs[current.probe] then
       current.double[current.ups[current.probe]] = true;
       current.double[current.downs[current.probe]] = true;
     end
   end
   current.lastPos = points;
   current.lastDiffs = diffs;
   current.probe = current.probe + 1;
   if current.probe <= 5 then
     local newProbe = not current.buttonState[current.probe];
     local clickX = current.origin[1] + buttonOffsets[current.probe][1] +
   buttonClick;
     local clickY = current.origin[2] + buttonOffsets[current.probe][2] +
   buttonClick;
     current.buttonState[current.probe] = newProbe;
     safeClick(clickX, clickY);
   end
 end

end


-- checkSame


function checkSame(current, diffs)

 if diffs then
   local all_same = true;
   for i=1,#diffs do
     if diffs[i] ~= 0 then
       all_same = false;
     end
   end
   if all_same then
     current.sameCount = current.sameCount + 1;
   else
     current.sameCount = 0;
   end
   if current.sameCount > 10 then
     current.done = true;
   end
 end

end


-- toggleButtons


function toggleButtons(current, points, buttonState)

 local balance = getBalance(points, current.double);
 for i=1,5 do
   local up = getPointValue(points, current.double, current.ups[i],
                            balance);
   local down = getPointValue(points, current.double, current.downs[i],
                              balance);
   local goalState = ((up >= 0 and down <= 0) or
                      (up >= 0 and down >= 0 and up > down) or
                      (up <= 0 and down <= 0 and up > down));
   if current.dirs[i] == SAME_UP then
     goalState = ((up >= 0 and down >= 0) or
                  (up >= 0 and down <= 0 and up >= -down) or
                  (up <= 0 and down >= 0 and -up <= down));
   elseif current.dirs[i] == SAME_DOWN then
     goalState = ((up <= 0 and down <= 0) or
                  (up >= 0 and down <= 0 and up <= -down) or
                  (up <= 0 and down >= 0 and -up >= down));
   end
   local goalStateStr = "false";
   if goalState then
     goalStateStr = "true";
   end
   local buttonStr = "false";
   if buttonState[i] then
     buttonStr = "true";
   end
   if (goalState and not buttonState[i]) or
      (not goalState and buttonState[i]) then
     safeClick(current.origin[1] + buttonOffsets[i][1] + buttonClick,
       current.origin[2] + buttonOffsets[i][2] + buttonClick);
     buttonState[i] = goalState;
   end
 end

end


-- getBalance


function getBalance(points, double)

 local above = 0;
 local below = 0;
 for i=1,#points do
   if points[i] > 0 and double[i] then
     below = below + 1;
   elseif points[i] < 0 and double[i] then
     above = above + 1;
   end
 end
 local result = 0;
 if above >= 3 then
   result = -5;
 elseif below >= 3 then
   result = 5;
 end
 return result;

end


-- getPointValue


function getPointValue(points, double, index, balance)

 local result = 0;
 if index then
   result = points[index];
   if not double[index] then
     result = result + balance;
   end
 end
 return result;

end


-- takeAll


function takeAll()

 srReadScreen();
 local wins = findAllText("This is a Crematory", nil, REGION);
 for i, win in ipairs(wins) do
   local t = findText("Take...", win);
   if t then
     clickText(findText("Take...", win));
     t = waitForText("Everything");
     clickText(t);
     waitForNoText("Everything");
     safeClick(wins[i].x + 25, wins[i].y + 5);
   end
 end

end


-- promptLoad


function promptLoad()

 scale = 1.0;
 local z = 0;
 local is_done = nil;
 while not is_done do
   checkBreak("disallow pause");
   lsPrint(10, 10, z, scale, scale, 0xFFFFFFff, "Configure");
   local y = 60;
   lsPrint(5, y, z, scale, scale, 0xffffffff, "Passes:");
   is_done, passCount = lsEditBox("passes", 110, y, z, 50, 30, scale, scale,
                                  0x000000ff, 5);
   if not tonumber(passCount) then
     is_done = false;
     lsPrint(10, y+18, z+10, 0.7, 0.7, 0xFF2020ff, "MUST BE A NUMBER");
     passCount = 1;
   end
   y = y + 48;
   load_flax = lsCheckBox(15, y, z+10, 0xffffffff, "Dried Flax",
                          load_flax);
   y = y + 32;
   load_papyrus = lsCheckBox(15, y, z+10, 0xffffffff, "Dried Papyrus",
                             load_papyrus);
   y = y + 32;
   load_leeks = lsCheckBox(15, y, z+10, 0xffffffff, "Leeks",
                           load_leeks);
   y = y + 32;
   load_limestone = lsCheckBox(15, y, z+10, 0xffffffff, "Limestone",
                               load_limestone);
   y = y + 32;
   lsPrintWrapped(10, y, z+10, lsScreenX - 20, 0.7, 0.7, 0xd0d0d0ff,
                  "Make sure each crematory is pinned and empty.");
   if lsButtonText(10, lsScreenY - 30, z, 100, 0xFFFFFFff, "Begin") then
       is_done = 1;
   end
   if lsButtonText(lsScreenX - 110, lsScreenY - 30, z, 100, 0xFFFFFFff,
                   "End script") then
     error "Clicked End Script button";
   end
   lsDoFrame();
   lsSleep(shortWait);
 end

end


-- loadAll


function loadAll()

  cremWins = findAllText("This is a Crematory", nil, REGION);
  lsPrintln("loading");
  loads = {};
  if load_flax then
     table.insert(loads, "Flax");
  end
  if load_papyrus then
     table.insert(loads, "Papyrus");
  end
  if load_limestone then
     table.insert(loads, "Limestone");
  end
  if load_leeks then
     table.insert(loads, "Leeks");
  end
  table.insert(loads, "Wood");
  for i=1, #cremWins do
     cremWin = cremWins[i]
     for i, v in ipairs(loads) do
        clickText(findText("Load the Crematory...", cremWin));
        local t = waitForText("Wood", nil, nil, nil, REGION);
        t = waitForText(v, nil, nil, t);
        clickText(t);
        t = waitForText("Load how much", nil, nil, nil, REGION);
        safeClick(t.x + t.width/2, t.bottom - 50);
        waitForNoText("Load how much");
     end
  end

end


-- updateMessage


function updateMessage(message)

 local result = "Pass " .. currentPass .. " / " .. passCount .. "\n";
 result = result .. message .. "\n\n";
 if message == "Tending Crematory" then
   for i=1,#windows do
     local status = "Buttons: ";
     for j=1,5 do
   if windows[i].dirs[j] == OPP then
     status = status .. getDir("+", windows[i].ups[j]) ..
       getDir("-", windows[i].downs[j]);
   elseif windows[i].dirs[j] == SAME_UP then
     status = status .. getDir("+", windows[i].ups[j]) ..
       getDir("+", windows[i].downs[j]);
   else
     status = status .. getDir("-", windows[i].ups[j]) ..
       getDir("-", windows[i].downs[j]);
   end
   if j ~= 5 then
     status = status .. ", ";
   else
     status = status .. "\n";
   end
     end
     result = result .. "\n" .. status;
   end
 end
 return result;

end

function getDir(sign, number)

 local result = "";
 if number then
   result = sign .. number
 end
 return result;

end