This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
kain184's profile picture

getting error in code but cant find a way to fix it.

Started by kain184, 09 January 2015 - 08:47 PM
kain184 #1
Posted 09 January 2015 - 09:47 PM
hello all. been working on an auto brewing system. i have the basic system working but am having trouble with the more advanced touch screen components. i am using the button api from direwolf20. to give credit where credit is due and the progress bar api from http://hawkee.com/snippet/10100/.
now i will upload the code and give you the issue



----modified version of progress bar api from hawkee.com/snippet/10100 just made it work over network-----------------------------------------
batch=1
status= loading
local monitor
local hasMonitor = false
local ProgressBar = {}
local FillColor = colors.orange
local EmptyColor = colors.blue
local TextColor = colors.white
function SetPeripheral(Pname)

	monitor = peripheral.wrap(Pname)
	hasMonitor = true
end
function SetTable(name, maxVal, curVal, xmin, xmax, y)
  ProgressBar[name] = {}
  ProgressBar[name]["Max"] = maxVal
  ProgressBar[name]["Current"] = curVal
  ProgressBar[name]["XMin"] = xmin
  ProgressBar[name]["XMax"] = xmax
  ProgressBar[name]["YVal"] = y
end
function ClearTable()
  if (hasMonitor) then
	ProgressBar = {}
  end
end
function SetFillColor(color)
  if (colors.combine(color,color)) then
	FillColor = color
  end
end
function SetEmptyColor(color)
  if (colors.combine(color,color)) then
	EmptyColor = color
  end
end
function SetTextColor(color)
  if (colors.combine(color,color)) then
	TextColor = color
  end
end
function SetMaxValue(name, intVal)
  if (ProgressBar[name]) then
	ProgressBar[name]["Max"] = intVal
  end
end
function SetCurValue(name, intVal)
  if (ProgressBar[name]) then
	ProgressBar[name]["Current"] = intVal
  end
end
function DrawToPeripheral(status)
  if (hasMonitor) then
	for name, data in pairs(ProgressBar) do
	  DrawBar(name, data)
  
	end
  end
  monitor=peripheral.wrap("monitor_1")
  monitor.setCursorPos(1,18)
  monitor.write("status:" ..status )
  

end
function DrawBar(name, arr)
  local y = arr["YVal"]
  local fill = math.floor((arr["XMax"] - arr["XMin"]) * (arr["Current"] / arr["Max"]))
  monitor.setBackgroundColor(FillColor)
  monitor.setTextColor(TextColor)
  for x = arr["XMin"], arr["XMax"] do
	local num = math.floor(x - arr["XMin"])
	monitor.setCursorPos(x,y)
	if (num > fill) then
	  monitor.setBackgroundColor(EmptyColor)
	end
	if (num == 0) then
	  monitor.write("[")
	end
	if (x == arr["XMax"]) then
	  monitor.write("]")
	else
	  monitor.write(" ")
	end
  end
  monitor.setBackgroundColor(colors.black)
end

------------------------------------------

-------------------------
function bucket()
print(r)
redstone.setAnalogOutput("right",15)
sleep(1)
redstone.setAnalogOutput("right",0)
end
-------------------------
function pickPotion(side,potion)
SetCurValue("Test",2)
DrawToPeripheral("choosing potions")
redstone.setAnalogOutput(side,potion)
sleep(1)
redstone.setAnalogOutput(side,0)
end
-------------------------
function items()
redstone.setAnalogOutput("right",5)

sleep(1)
redstone.setAnalogOutput("right",0)
SetCurValue("Test",3)
DrawToPeripheral("dispensing items")
end
-------------------------
function bottle()
redstone.setAnalogOutput("right",1)
sleep(1)
redstone.setAnalogOutput("right",0)
end
-------------------------------------
function extras()
redstone.setAnalogOutput("right",2)
sleep(1)
redstone.setAnalogOutput("right",0)
SetCurValue("Test",7)
DrawToPeripheral("removing excess bottles")
end
-------------------------------------


-------------------------------------
function Brew(side,potion)
r=redstone.getInput("left")
redstone.setOutput("right",false)
redstone.setOutput("left",false)
redstone.setOutput("top",false)
redstone.setOutput("bottom",false)
bucket()
  SetCurValue("Test",1)
  DrawToPeripheral("dispensing water")
  if r==false then
   while r==false do
   r=redstone.getInput("left")
   print("system not ready waiting")
   sleep(1)
   end
   pickPotion(side,potion)
  else
   pickPotion(side,potion)
  end
sleep(3)
  if r==false then
   while r==false do
   r=redstone.getInput("left")
   print("system not ready waiting")
   sleep(1)
   end
   items()
  else
   items()
  end
sleep(1)
  if r==false then
   while r==false do
   r=redstone.getInput("left")
   print("system not ready waiting")
   sleep(1)
   end
   x=3
   while x >= 1 do
   if x==3 then
   SetCurValue("Test",4)
  
   elseif x==2 then
   SetCurValue("Test",5)
  
   elseif x==1 then
   SetCurValue("Test",6)
  
   else
   end
   bottle()
   sleep(2)
   x=x-1
   DrawToPeripheral()
   end
  else
   x=3
   while x >= 1 do
   if x==3 then
   SetCurValue("Test",4)
  
   elseif x==2 then
   SetCurValue("Test",5)
  
   elseif x==1 then
   SetCurValue("Test",6)
  
   else
   end
   bottle()
   sleep(2)
   DrawToPeripheral("dispensing bottle "..x)
   x=x-1
  
   end
  end
  sleep(1)
	 print("removing extra bottles")
  if r==false then
   while r==false do
   r=redstone.getInput("left")
   print("system not ready waiting")
   sleep(1)
   end
   extras()
  else
   sleep(1)
   extras()
  end
print("extras removed")
monitor.clear()
DrawToPeripheral("processing complete")
sleep(3)
monitor.clear()
SetCurValue("Test",0)
DrawToPeripheral("")
end
-----------------------------------------
os.loadAPI("button")
SetPeripheral("monitor_1")
monitor.clear()
ClearTable()
SetTable("Test", 7, 1, 1,20,19)
--------------------------------------
function fillTable()
button.setTable("page1", page1, 1,7,1,3)
button.setTable("page2", page2, 33,39,1,3)
	button.setTable("batch", batch, 22,28,1,3)
button.setTable("vines", vines, 1,7,5,7)
button.screen()
end
function fillTable2()


	button.setTable("page1", page1, 1,7,1,3)
	button.setTable("page2", page2, 33,39,1,3)
	button.setTable("batch", batch, 22,28,1,3)
	button.screen()
end
function batch()
button.ClearTable()
monitor.clear()
button.setTable("page1", page1, 1,7,1,3)
button.setTable("page2", page2, 33,39,1,3)
button.setTable("t1",batch1,9,11,1,3)
button.setTable("t2",batch2,13,15,1,3)
button.setTable("t3",batch3,17,19,1,3)
button.setTable("t4",batch4,21,23,1,3)
button.setTable("t5",batch5,25,27,1,3)
	 button.screen()
end
------------------------------------
function page1()
button.ClearTable()
monitor.clear()
fillTable()
button.flash("page1")
end
function page2()
button.ClearTable()
monitor.clear()
fillTable2()
button.flash("page2")
end
function batch1()
name = t1
for name,data in pairs(button) do
	  button.toggleButton(t1)
	  local on = data["active"]
	  if on == true then
	  batch=1
   else
   batch=1
   end
  
   end
end
function batch2()
name = t2
for name,data in pairs(button) do
	  button.toggleButton(t2)
	  local on = data["active"]
	  if on == true then
	  batch=2
   else batch=1
   end
  
  end
name = t1
for name,data in pairs(button) do
	  local on = data["active"]
	  if on == true then
   button.toggleButton(t1)
   end
  
  end
end
--------------------------------
function getClick()
   event,side,x,y = os.pullEvent("monitor_touch")
   button.checkxy(x,y)
end
---------------------------------------------------
function batchs(side,potion,batch)
print("batch processing enabled")
batch=batch+1
while batch >=2 do
batch=batch-1
Brew(side,potion)
if  batch > 1 then print("batch processing enabled")
else print("batch processing disabled")
end
sleep(2)
end
end

------------------------------------------------------
button.heading("witchery auto brewing")
fillTable()
while true do
   getClick()
end




note this is not complete yet as i have alot to add. for each of the witchery potions. kind of looking to find if i can put that data in a table and pull it some how. so any advice and ways to make the code more simple is appreciated as well. but the problem i am having is in

function batch1()
name = t1
for name,data in pairs(button) do
	  button.toggleButton(t1)
	  local on = data["active"]
	  if on == true then
	  batch=1
   else
   batch=1
   end

   end
end
function batch2()
name = t2
for name,data in pairs(button) do
	  button.toggleButton(t2)
	  local on = data["active"]
	  if on == true then
	  batch=2
   else batch=1
   end

  end
when i run this part it calls an error in the button api and i cannot find out why. is there anything i can do to fix this. if anyone who knows a lot is out there i would appreciate the help
KingofGamesYami #2
Posted 09 January 2015 - 11:20 PM

for name,data in pairs(button) do
   button.toggleButton(t2) --#here you index the table
   local on = data["active"] --#here you index the function above.
   if on == true then
      batch=2
   else
      batch=1
   end
end

This is totally incorrect. You iterate through the "button" table, calling a function inside the table and indexing that table. I'm not sure what you meant to do, but that isn't going to work.

Edit: fixed code spacing
Edited on 09 January 2015 - 10:22 PM
kain184 #3
Posted 09 January 2015 - 11:29 PM
what it is doing is checking in the button to see if it is active then setting a veriable but on every activation of this button it needs to toggle the active status of the button using button.toggle so that the system that brews the potions will know how many to brew using the batch selector



btw that is just a small blerb of what the code is to see it all you need to look at the full code and the button code from direwolf20. the table is created up further in this section

function batch()
button.ClearTable()
monitor.clear()
button.setTable("page1", page1, 1,7,1,3)
button.setTable("page2", page2, 33,39,1,3)
button.setTable("t1",batch1,9,11,1,3)
button.setTable("t2",batch2,13,15,1,3)
button.setTable("t3",batch3,17,19,1,3)
button.setTable("t4",batch4,21,23,1,3)
button.setTable("t5",batch5,25,27,1,3)
		 button.screen()
end
and by default it is inactive. in the creation code in the button api.
function setTable(name, func, xmin, xmax, ymin, ymax)
button[name] = {}
button[name]["func"] = func
button[name]["active"] = false
button[name]["xmin"] = xmin
button[name]["ymin"] = ymin
button[name]["xmax"] = xmax
button[name]["ymax"] = ymax
end


using the toggle switches it from inactive to active like so in the button api.

function toggleButton(name)
   button[name]["active"] = not button[name]["active"]
   screen()
end
Edited on 09 January 2015 - 10:57 PM
KingofGamesYami #4
Posted 09 January 2015 - 11:59 PM
I don't think you understand.

Your loop will work until…

name = toggleButton
data = function() … end

When this happens,

local on = data["active"]

Will be:

local on = function() … end["active"]

..which gives you "attempt to index function"

If this isn't the error you are getting, please post the error and where it occurs. Even if an API is erroring, I can backtrace from that line, to the function, to the lines in your program that call that function.
kain184 #5
Posted 10 January 2015 - 01:02 AM
but where is it pulling this function your talking about from. from what a gather data is a designator for a table to get the infro from the active category. like here

function screen()
   local currColor
   for name,data in pairs(button) do
	  local on = data["active"]
	  if on == true then currColor = colors.lime else currColor = colors.red end
	  fill(name, currColor, data)
   end
end
this is the code inside the button api. does a similar function to what i am trying to do which is check for in the table of name. which should be the button. if the data active says active. if that is true than it changes colors. so i modified it to change a veriable from one number to another so what has changed between the two versions of this code that is throwing the error as it works in this version and not in my edited version
KingofGamesYami #6
Posted 10 January 2015 - 01:10 AM
You are iterating through the table button. You are calling the function toggleButton, in the table button. When you put button.toggleButton, that is referring to an item in the table button. When you use for name, data in pairs( button) do, this iterates through the table button. Inevitably, data will equal button.toggleButton and name will be "toggleButton".
kain184 #7
Posted 10 January 2015 - 01:15 AM
i see what your trying to say but thats not what it should be doing. toggle button should only change "active" to active or to not active in table button.(button name) for mine it is t1 it should then in FOR look to see what "active says and change the veriable to reflect that. what code would you write to do that. if what i have will not work
Bomb Bloke #8
Posted 10 January 2015 - 04:31 AM
There are two button tables you need to be thinking about here.

First off, there's one in Direwolf's button API. This table is local to that API, and therefore only accessible by that API - your script can't touch it (see this tutorial about "scope"). The API uses it to store information about all the buttons, including their associated functions.

When your script loads the API, os.loadAPI() creates a global table called "button" and loads everything Direwolf wanted you to be able to access into there - as with most APIs, this is limited to functions (basically, anything that wasn't declared as local to the API). This "button" table, which your script can access, is completely different to the "button" table that's referred to by the API itself.

This means that if you want to keep track of which buttons the API is handling, and what their specs are (including the function attached to each one), you've got to do it yourself.

The API is rigged to only run a button's associated function when button.checkxy() is called with the co-ordinates of that button. To change that behaviour, you'd need to change the code of the API.

One way would be to modify its "flash" function like so:

function flash(name)
   toggleButton(name)
   screen()
   button[name]["func"]()
   sleep(0.15)
   toggleButton(name)
   screen()
end

Calling button.flash("somebutton") would therefore also be a way to make that button's function run.
kain184 #9
Posted 10 January 2015 - 06:09 AM
now that is an explanation that said a lot. thank you i did not know that the api once loaded would not load that data into the script i was using. so i have to find some way to send data back from the api in order for it to tell me what i want to know. that actually helps a lot. thank you. if you have any suggestions on how to do that other than integrating the entire script it would love to know.
kain184 #10
Posted 10 January 2015 - 06:26 AM
i do have one question for you tho so does the set table not pass that information into the api and store it there or does it only store it in the active script
i want to know becouse i think i have a solution but not sure if it will work if i add a function in the api

function checkActive(name)
for name,data in pairs(button) do
	
	  local on = data["active"]
	  if on == true then
	  return true
   else
   return false
   end
  
  end
end
and have it return to

function batch1()
if button.checkActive(t1) == false then
button.toggleButton(t1)
batch=1
if button.checkActive(t2) == true then
button.toggleButton(t2)
end
if button.checkActive(t3) == true then
button.toggleButton(t3)
end
if button.checkActive(t4) == true then
button.toggleButton(t4)
end
if button.checkActive(t5) == true then
button.toggleButton(t5)
end
else
batch=1
button.flash(t1)
end
it works like this but i am now having a problem in the new section i wrote it is not turning off the other buttons through toggle. like i ask when i ask it to. but the brewing system is now working.
Edited on 10 January 2015 - 06:36 AM
Bomb Bloke #11
Posted 10 January 2015 - 06:53 AM
It'd fail, because instead of checking the button you passed to your checkActive() function, you're checking the first button the pairs function picks out of the button list, then returning (preventing further checks). You only need to iterate through the button list if you don't know the name of the button you're interested in - you can refer to it directly if you do know.

Thus you're wanting something like:

function checkActive(name)
  return button[name]["active"]
end

By the way, this sort of thing:

if button.checkActive(t2) == true then

… is also a bit pointless, as the if…then statement is already checking to see if a given condition is true. Checking to see if "button.checkActive(t2) == true" is true is an unneeded extra step - you can just do:

if button.checkActive(t2) then

If you want to check if a given value is false, it's generally neater to use "not":

if not button.checkActive(t1) then
kain184 #12
Posted 10 January 2015 - 02:33 PM
didn't know that about the if statement ether that's really cool however this

function checkActive(name)
  return button[name]["active"]
end
error out with attempt to index a nil value


edit: got it needed to make the name as a string because of the change. works like a charm now.
Edited on 10 January 2015 - 01:50 PM
kain184 #13
Posted 10 January 2015 - 04:48 PM
the code works completely now i'm going to clean it up a bit and ill put it in the programs. no further help required at this time