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
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