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.
Difference between revisions of "User:Augir/Marble Quarry Map"
Line 67: | Line 67: | ||
* GyW - WT | * GyW - WT | ||
* BrM - MG | * BrM - MG | ||
+ | |||
+ | -- 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 |
Revision as of 16:58, 20 July 2018
This map uses the CondMap template, if this map imports data from other maps please edit those. Please see Maps for further details and links to all raw data pages
- WhD - done
- GyW - WT
- BrM - MG
-- 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