------------------------------------------------------------ -- Excelsior beekeeper - apply potions daily ------------------------------------------------------------ function yellowredline (lx,ly) -- find the color of the line next to the disease and skull -- icons to determine how many potions are needed local colorvariable = UO.GetPix(lx,ly) --grab color of the chosen line if colorvariable == 0xe7e7 then --if line is yellow -- print ("yellow("..string.format("%08x",colorvariable)..") line @ "..lx.." "..ly) return 1 end if colorvariable == 0x18e7 then --if line is red -- print ("red("..string.format("%08x",colorvariable)..") line @ "..lx.." "..ly) return 2 end if (colorvariable == 0x423839) or (colorvariable == 0x392829) then return 0 -- no line, don't need to add potions end error ("yellowredline unexpected color=".. string.format("%08x",colorvariable).." @ "..lx.." "..ly) end function zerooneortwo (nX,nY) -- determine whether the number whose top left is at -- nX,nY is a zero, a one, a two or something else. -- Abort the program if something else: the gump must -- show that 0, 1 or 2 potions have been applied. local color = UO.GetPix(nX+3,nY+5) if 0xefefd6 == color then --print ("one("..string.format("%08x",color)..") line @ " -- ..(nX+3).." "..(nY+5)) return 1 end color = UO.GetPix(nX+1,nY+8) if 0xefefd6 == color then --print ("zero("..string.format("%08x",color)..") line @ " -- ..(nX+1).." "..(nY+8)) return 0 end if 0xefefd6 == UO.GetPix(nX+5,nY+7) then return 2 end print ("could not determine number at x="..nX.." y="..nY) error("zeroneortwo abort"); end function closehive (nX,nY) -- close the hive gump at nX, nY with a right-click -- wait (100) -- wait a moment first local mName, mX, mY, mSX, mSY, mKind, mId, mType, mHP = UO.GetCont (0) local startcolor = UO.GetPix(mX+85, mY+48) -- print ("closehive "..string.format("%08x",startcolor)) UO.Click(nX+65, nY+80, false, true, false, false) UO.Click(nX+65, nY+80, false, false, true, false) --close the current beehive gump --now wait until the system closes it to move on local timeout = 5000 local color while timeout > 0 do mName, mX, mY, mSX, mSY, mKind, mId, mType, mHP = UO.GetCont (0) color = UO.GetPix(mX+85, mY+48) if color == startcolor then -- print ("closehive "..string.format("%08x",color)) wait (50) timeout = timeout - 50 else wait(380) -- don't spam the server break end end -- print ("hive closed "..string.format("%08x",color)) if timeout <= 0 then print ("Error: hive did not close. color="..string.format("%08x",color)) error ("closehive") end end function healthcheck (nX,nY) -- Is the behive thriving or not? local colorvariable = UO.GetPix(nX+147,nY+156) --grab color of the text if colorvariable == 0x00e718 then --if "Healthy" print "healthy" return 1 end colorvariable = UO.GetPix(nX+120,nY+153) --grab color of the text if colorvariable == 0xe78c00 then --if "Thriving" -- also seen 0xe78e00; why? -- print "thriving" return 0 end if colorvariable == 0x080000 then -- unhealthy return 2 -- if it wasn't Healthy or Thriving, pour two heal end print ("health color = "..string.format("%08x",colorvariable)) error ("determine colors for this case") return 2 end function oldhealthcheck (nX,nY) -- Is the behive thriving or not? colorvariable = UO.GetPix(nX+147,nY+156) --grab color of the text if colorvariable == 59160 then --if "Healthy" return 1 end colorvariable = UO.GetPix(nX+120,nY+153) --grab color of the text if colorvariable ~= 15174656 then -- check if it was "Thriving" return 2 -- if it wasn't Healthy or Thriving, pour two heal end return 0 end function ClickRedDots (tX, tY) -- open the hive gump with all the red dots and click on each one movecursor = false -- client may try to drag the object if this is not true wait(50) -- open potion gump and scan for red dots UO.Click(tX, tY, true, true, false, movecursor) UO.Click(tX, tY, true, false, true, movecursor) --wait for gump to open wait (100) timeout=5000 while timeout > 0 do sName, dX, dY, nSX, nSY, nKind, nId, nType, nHP = UO.GetCont (0) temp = UO.GetPix(dX+81, dY+161) -- print ("temp="..temp.." timeout="..timeout.."\n") if temp ~= 3763092 then wait (50) timeout = timeout - 50 else break -- gump opened end end if timeout <= 0 then print ("Error: red dots gump did not open.") error ("clickreddots") end wait (50) -- give the server a moment -- initialize variables scannumber = 6 --scan for max of 6 dots in a beehive x = dX+12 --this is the leftmost point of the gump that can contain a dot y = dY --this is the topmost point of the gump that can contain a dot while scannumber >= 0 do print ("ClickRedDots scan="..scannumber) while y < (dY+145) do --nY+144 is the bottommost point of the gump that can contain a dot a = UO.GetPix(x,y) if a == 526443 then --check pixel for the red dot UO.Click(x, y, true, true, false, movecursor) UO.Click(x, y, true, true, false, movecursor) UO.Click(x, y, true, false, true, movecursor) -- click red dot scannumber = scannumber - 1 -- decrement scannumber y = y - 10 -- move y back up a few lines so it doesn't miss any of the dots that are on top of each other wait (100) --give time for gump to disapear -- FIXME wait by color for the gump to disappear timeout=5000 while timeout > 0 do rName, rX, rY, rSX, rSY, rKind, rId, rType, rHP = UO.GetCont (0) temp = UO.GetPix(rX+81, rY+161) if temp ~= 3763092 then if temp == 3221801 then --check if base hive gump reopened and exit if it did return end wait (50) timeout = timeout - 50 else break -- gump reopened end end if timeout <= 0 then print ("Error: red dots did not reopen.") error ("clickreddots2") end end x = x + 1 if x == dX+161 then --nX+160 is the rightmost point of the gump that can contain a dot x = dX + 12 y = y + 1 end -- print ("loop x="..x.." y="..y.."\n"); end y = dY print ("missed a dot, trying again") UO.Click(1, 1, true, false, true, movecursor) -- make it here only when something (e.g. the mouse) obscures the dots -- so, move the mouse away and start over end -- should not make it here. Should exit via 3221801 above error ("ClickRedDots abnormal termination") end function SimpleClick (tX, tY) -- click a button and expect the colony gump to return movecursor = false wait(50) -- open potion gump and scan for red dots UO.Click(tX, tY, true, true, false, movecursor) UO.Click(tX, tY, true, false, true, movecursor) --wait for gump to disappear wait (100) -- wait for gump to return timeout=5000 while timeout > 0 do sName, dX, dY, nSX, nSY, nKind, nId, nType, nHP = UO.GetCont (0) temp = UO.GetPix(dX+81, dY+161) -- print ("temp="..temp.." timeout="..timeout.."\n") if temp == 0x312929 then -- colony gump reappeared -- also seen 0x312829 return end wait (50) timeout = timeout - 50 end error ("SimpleClick Error: colony gump did not reappear: color=" ..string.format("%08x",temp)..".") end function rgb (color) -- separate the red, green and blue values from UO.GetPix local rcolor = {} rcolor["blue"] = math.floor(color / 0x10000) local sub = rcolor["blue"] * 0x10000 rcolor["green"] = math.floor((color - sub) / 0x100) sub = sub + rcolor["green"] * 0x100 rcolor["red"] = color - sub return rcolor end spotsizeexamined = {} -- used by spotcheck function xystring (x,y) -- used by spotcheck return tostring(y)..","..tostring(x) end function spotcheck (fuzzy,x,y,hexs) -- starting at position x,y determine whether it's part of a -- dark spot. If it is, return the size and center of the dark spot. local nope = {} -- return this if x,y is not part of a dark spot nope["count"] = 0 nope["xx"] = 0 nope["yy"] = 0 if ((x<0) or (y<0)) then return nope end if (fuzzy[y] == nil) then return nope end if (fuzzy[y][x] == nil) then return nope end local xys = xystring (x,y) -- print ("xys="..xys) if (spotsizeexamined[xys] ~= nil) then -- print ("already examined: y="..y.." x="..x) return nope end -- valid x,y coordinate not yet examined local gsdiv = math.floor(fuzzy[y][x]/16) -- print ("try x="..x.." y="..y.." gsdiv="..gsdiv) local gschar = string.sub(hexs,gsdiv+1,gsdiv+1) spotsizeexamined[xys] = 1 if ("." ~= gschar) then -- this x,y coordinate is not part of a dark spot -- print ("nope: y="..y.." x="..x) return nope end -- this x,y coordinate IS part of a dark spot. -- Include it and check the adjacent x,y coordinates too -- print ("walk: y="..y.." x="..x.." gschar="..gschar) local up = spotcheck (fuzzy,x,y-1,hexs) local down = spotcheck (fuzzy,x,y+1,hexs) local left = spotcheck (fuzzy,x-1,y,hexs) local right = spotcheck (fuzzy,x+1,y,hexs) local yup = {} yup["xx"] = x + up.xx + down.xx + left.xx + right.xx yup["yy"] = y + up.yy + down.yy + left.yy + right.yy yup["count"] = 1 + up.count + down.count + left.count + right.count -- print ("walked: y="..y.." x="..x.." count="..yup["count"]) return yup end function fuzzyprint (image,maxx,maxy,hex,cx,cy) -- print the program's view of the hive image and its -- dark spots. Put a Z where it plans to click. local y=0 local x=0 local gstring = "" local zreplace = "" while y < maxy do -- print ("test: "..gs.." -> "..gsdiv.." -> "..string.sub(hextochar,gsdiv+1,gsdiv+1)..":end") local gsdiv = math.floor(image[y][x]/16) local gschar = string.sub(hex,gsdiv+1,gsdiv+1) if (y==cy) and (x==cx) then zreplace = gschar gschar ="Z" end gstring = gstring..gschar x = x + 1 if x == maxx then --nX+160 is the rightmost point of the gump that can contain a dot print (gstring) gstring = "" x = 0 y = y + 1 end end print ("zreplace="..zreplace) end function HivePicture (tX, tY) -- handle the "dark spots" version of the beehive potion gump -- open the dark spots gump, locate all the dark spots, -- pick the largest one and click in its center -- The rough theory of operation for the HivePicture function is this: -- 1. Capture the image of the hive. -- 2. Shrink the image of the hive. Shrinking blurs the pixels together into an image -- containing solid bright and solid dark regions. -- 3. Collapse the dynamic range of the shrunk image (i.e. turn the contrast way up) -- so that pixels are either dark or light but nothing in between. -- 4. Find a dark pixel in the shrunk version. Walk around the dark pixel counting the -- total nearby dark pixels and stopping when the light pixels are hit. -- 5. Average the x and y coordinates of each dark pixel to find the center of the dark area. -- 6. Repeat until the entire image is scanned and the largest region of dark pixels identified. -- 7. Click the center of the largest region of dark pixels. local movecursor = false wait(50) -- open potion gump and scan for red dots UO.Click(tX, tY, true, true, false, movecursor) UO.Click(tX, tY, true, false, true, movecursor) --wait for gump to open wait (100) local timeout=5000 local pixel while timeout > 0 do sName, dX, dY, nSX, nSY, nKind, nId, nType, nHP = UO.GetCont (0) pixel = UO.GetPix(dX+81, dY+161) -- print ("temp="..temp.." timeout="..timeout.."\n") if pixel ~= 0x396B94 then wait (50) timeout = timeout - 50 else break -- gump opened end end if timeout <= 0 then error ("Error: HivePicture dots gump did not open color="..string.format("%08x",pixel)..".") end --local hextochar = "0123456789abcdef" --local hextochar = " .,:*########" --0123456789abcdef local hextochar = " ...#########" spotsizeexamined = {} -- fresh gump so spotcheck hasn't examined any of it yet wait (50) -- give the server a moment -- initialize variables local image = {} local fuzzyimage = {} local y = 0 local maxy = 148 -- 145 local maxx = 152 -- 161 - 12 while y < maxy do image[y] = {} fuzzyimage[y] = {} y = y + 1 end y = 0 local x = 0 -- x = dX+12 --this is the leftmost point of the gump that can contain a dot -- y = dY --this is the topmost point of the gump that can contain a dot -- fetch the beehive potions gump image from the screen while y < maxy do --nY+144 is the bottommost point of the gump that can contain a dot image[y][x] = UO.GetPix(dX+12+x,dY+y) x = x + 1 if x == maxx then --nX+160 is the rightmost point of the gump that can contain a dot x = 0 y = y + 1 end end -- shrink the image, blurring the bright and dark areas together -- in to solid masses y=0 x=0 local scale = 6 while y < math.floor(maxy/scale) do local yy=0 local xx=0 local red=0 local green=0 local blue=0 while (yy0) then s["x"] = math.floor(s.xx/s.count) s["y"] = math.floor(s.yy/s.count) if (click.count148) or (clickcolor.green>132) or ((clickcolor.red>96) and (clickcolor.red/clickcolor.blue>1.25)) or ((clickcolor.green>96) and (clickcolor.green/clickcolor.blue>1.25)) then -- bright. Maybe a bright spot in the middle of the dark? Try a little lower. fuzzyprint (fuzzyimage,math.floor(maxx/scale),math.floor(maxy/scale),hextochar,click.x,click.y) y=y+6 clickcolor = rgb(UO.GetPix(x,y)) print (" clickcolor retry="..clickcolor.red..","..clickcolor.green..","..clickcolor.blue) if (clickcolor.red>148) or (clickcolor.green>132) or ((clickcolor.red>96) and (clickcolor.red/clickcolor.blue>1.25)) or ((clickcolor.green>96) and (clickcolor.green/clickcolor.blue>1.25)) then -- dangerous, abort UO.Click(x, y, true, false, false, true) -- move cursor to the spot I'd click error (" HivePicture Error: click spot is too bright.") end end if (click.count>48) then fuzzyprint (fuzzyimage,math.floor(maxx/scale),math.floor(maxy/scale),hextochar,click.x,click.y) -- merged spots don't work right UO.Click(x, y, true, false, false, true) -- move cursor to the spot I'd click error (" HivePicture Error: merged spots do not work right.") end --UO.Click(x, y, true, false, false, true) -- move cursor to the spot I'd click --wait (500) -- see before click --error ("HivePicture checkpoint") -- click around the center of the dark area UO.Click(x, y, true, true, false, movecursor) UO.Click(x, y, true, true, false, movecursor) UO.Click(x, y, true, false, true, movecursor) -- click red dot wait (100) --give time for gump to disapear -- wait for the hive status gump to reappear timeout=5000 while timeout > 0 do rName, rX, rY, rSX, rSY, rKind, rId, rType, rHP = UO.GetCont (0) temp = UO.GetPix(rX+81, rY+161) if temp ~= 3763092 then if temp == 3221801 then --check if base hive gump reopened and exit if it did wait (100) return end wait (50) timeout = timeout - 50 else print " dark spots gump reopened unexpectedly" break -- gump reopened, that shouldn't have happened end end if timeout <= 0 then error (" HivePicture Error: hive gump did not reopen.") end end -- riskily small dark spot, report and abort fuzzyprint (fuzzyimage,math.floor(maxx/scale),math.floor(maxy/scale),hextochar,click.x,click.y) error (" HivePicture abnormal termination") end function TendBeehive (id,hive) -- open hive UO.LObjectID = id UO.LTargetKind = 0 UO.Macro(17,0) -- wait for hive to open local timeout = 5000 -- 5 seconds local pixel local sName, nX, nY, nSX, nSY, nKind, nId, nType, nHP while timeout > 0 do sName, nX, nY, nSX, nSY, nKind, nId, nType, nHP = UO.GetCont (0) pixel = UO.GetPix(nX+85, nY+48) if pixel ~= 0x393131 then wait (50) timeout = timeout - 50 else break -- hive gump opened end end if timeout <= 0 then print ("Error: hive "..hive.." did not open. Color="..string.format("%08x",pixel)) error ("tendbeehive") end wait (100) -- hive is open local agilityapplied = zerooneortwo (nX+190,nY+51); local poisonapplied = zerooneortwo (nX+190,nY+75); local cureapplied = zerooneortwo (nX+190,nY+100); local healapplied = zerooneortwo (nX+190,nY+125); local strengthapplied = zerooneortwo (nX+190,nY+150); local agilityneeded = 2 agilityneeded = agilityneeded - agilityapplied local poisonneeded = yellowredline (nX+84,nY+80) -- check the disease line poisonneeded = poisonneeded - poisonapplied local cureneeded = yellowredline (nX+84,nY+105) -- check the skull line cureneeded = cureneeded - cureapplied local healneeded = healthcheck(nX,nY) - healapplied -- check thriving/healthy/sickly local strengthneeded = 0 strengthneeded = strengthneeded - strengthapplied print ("Hive: "..hive .." Agility: "..agilityapplied.."+"..agilityneeded .." Poison: "..poisonapplied.."+"..poisonneeded .." Cure: "..cureapplied.."+"..cureneeded .." Heal: "..healapplied.."+"..healneeded .." Strength: "..strengthapplied.."+"..strengthneeded) for j = 1,poisonneeded do SimpleClick (nX+208, nY+81) end for j = 1,cureneeded do -- ClickRedDots (nX+208, nY+106) HivePicture (nX+208, nY+106) end for j = 1,healneeded do SimpleClick (nX+208, nY+131) end for j = 1,strengthneeded do SimpleClick (nX+208, nY+156) end for j = 1,agilityneeded do HivePicture (nX+208, nY+54) end -- for xx = 190,198 do -- for yy = 149,162 do -- colorvariable = UO.GetPix(nX+xx,nY+yy) -- print (yy.." "..xx.." "..colorvariable.."\n") -- end -- end closehive (nX,nY) end function itemtable () -- create a table of all the items visible to the UO client local byid = {} local itemcount = UO.ScanItems(true) local i, key, value for i=0,(itemcount-1) do local nID,nType,nKind,nContID,nX,nY,nZ,nStack,nRep,nCol = UO.GetItem(i) if (nID > 0) then local id = "i"..nID byid[id] = {} byid[id]["id"] = nID byid[id]["type"] = nType byid[id]["kind"] = nKind byid[id]["contid"] = nContID byid[id]["x"] = nX byid[id]["y"] = nY byid[id]["z"] = nZ byid[id]["stack"] = nStack byid[id]["reputation"] = rep byid[id]["color"] = nCol -- don't bother keeping the index; it'll change next time we scan end end local containers = {} for key,value in pairs(byid) do local container = {} local cid = "i"..value["contid"] if (containers[cid]) then container = containers[cid] end container[#container+1] = key; containers[cid] = container; end return byid, containers end -- main loop. find beehives within distance 2 of the player and tend each one local items, containers = itemtable() local i = 1 for id,item in pairs(items) do if (item.type == 2330) then if (math.abs(UO.CharPosX - item.x)<=2) and (math.abs(UO.CharPosY - item.y)<=2) then TendBeehive (item.id,i) i = i + 1 wait(100) end end end print "Done beekeeping!" dofile("beedrainhoney.lua")