Lua Question

Language: JP EN DE FR
New Items
2023-11-19
users online
Forum » Windower » Support » Lua question
Lua question
 Fenrir.Brimstonefox
Offline
Server: Fenrir
Game: FFXI
user: Brimstone
Posts: 183
By Fenrir.Brimstonefox 2016-09-16 22:28:57
Link | Quote | Reply
 
How do I do math on table values?

foo["bar"] = 1
foo["bar"] = foo["bar"] + 1

gives errors.

I've tried mixing with tostring() and tonumber() and doing raw integer vs. string integer (ie "1" vs 1) math.

I'm either getting errors in lib/functions line 215 about unpack or unable to perform arithmatic on global variable (a nil or string value and in an else condition from == nil) so I'm thoroughly confused at this point.
 Ragnarok.Flippant
Offline
Server: Ragnarok
Game: FFXI
user: Enceladus
Posts: 658
By Ragnarok.Flippant 2016-09-16 23:27:06
Link | Quote | Reply
 
There must be context missing here, because there's nothing wrong with what you wrote. I can't understand what you're saying the errors are reporting (it seems like you're reporting four separate errors? but not in full?).

Can you give me more information? Just enough to replicate the issue (or issues) is fine.

Otherwise, only suggestion I can make is that you should be sure that this variable exists within the scope at the time you're trying to use it. Also remember you can always print a variable to check its value.
 Fenrir.Brimstonefox
Offline
Server: Fenrir
Game: FFXI
user: Brimstone
Posts: 183
By Fenrir.Brimstonefox 2016-09-17 09:15:03
Link | Quote | Reply
 
Ok full context I'm working on an addon I'm calling closetCleaner the goal being to cross check all data in my mog house against all gear in my gearswap and report the number of times gear is used. (with the idea being getting rid of all the 0s and potentially some of the 1s)

So I have a function that exports all the gear my mog house to a file.

Now I was trying to export everything in the sets table to a separate file. (Ideally I'll beable to look up everything by id and compare that under the covers, I was having some issues there, so for now I'm just trying to get some ascii lists to compare, potentially I'd like to give recommendations for what can be done with the gear in the report too (ie toss, send to mule, put on storage slip #, store at npc etc... although I may never be this ambitious) I'll also need to figure out how to load all the gearswap lua at once and combine the sets tables without overwriting since assume sets.engaged from one would clobber the same table from another).

Anyways this function is supposed to just list (and count) each piece of gear in sets. I can list them all, list them uniquely but When I try to count as I throw them into the write sets table it barfs.
Code
write_sets = T{}
function list_sets ( t, f )  
    local print_r_cache={}
    local function sub_print_r(t,indent)
        if (print_r_cache[tostring(t)]) then
            -- f:write(indent.."*"..tostring(t))
        else
            print_r_cache[tostring(t)]=true
            if (type(t)=="table") then
                for pos,val in pairs(t) do
                    if (type(val)=="table") then
                        -- f:write(indent.."["..pos.."] => "..tostring(t).." {")
                        sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))
                        -- f:write(indent..string.rep(" ",string.len(pos)+6).."}")
                    elseif (type(val)=="string") then
						if pos == "name" or pos == "main" or pos == "sub" or pos == "ranged" or pos == "ammo" or pos == "head" or pos == "neck" or pos == "left_ear" or pos == "right_ear" or pos == "body" or pos == "hands" or pos == "left_ring" or pos == "right_ring" or pos == "back" or pos == "waist" or pos == "legs" or pos == "feet" then
							if write_sets[val] == nil then
								-- count = table_count(t, val)
								write_sets[val] = 1
								-- write_sets[val] = 2
								-- f:write('"'..val..'" #'..count..'\n')
							else	
								gcs = tostring(write_sets[val])
								gcn = tonumber(write_sets[val])
								gca = write_sets[val] + 1
								f:write('else"'..val..'" #'..gca..'\n')
								write_sets[val] = gcs
							end
							-- f:write('"'..val..'" #'..write_sets[val]..'\n')
						end
                    else
                        -- f:write(indent.."["..pos.."] => "..tostring(val)..'\n')
                    end
                end
            else
                -- f:write(indent..tostring(t))
            end
        end
    end
    if (type(t)=="table") then
        -- f:write(tostring(t).." {")
        sub_print_r(t,"  ")
        -- f:write("}")
    else
        sub_print_r(t,"  ")
    end
	for k,v in pairs(write_sets) do
		f:write('"'..k..'" #'..v..'\n')
	end
    f:write()
end


This line is the problem: gca = write_sets[val] + 1
The error I get is closetCleaner: lua runtime error: libs/functions.lua:215: bad argument #1 to 'unpack' (table expected, got number)

The other errors I mentioned above are variables depending if I use tostring() or tonumber() or try to do math on strings instead of numbers etc...I can't figure out how to make it work, just a different kind of error message depending on syntax. I can send you the whole code if you want to try it yourself (or even work on the addon) Was hoping it was something dumb But I'm flummoxed (additionally I don't think its a scoping issue since I can put different numbers in there and print them in the else conditional, I just can't change them)
 Ragnarok.Flippant
Offline
Server: Ragnarok
Game: FFXI
user: Enceladus
Posts: 658
By Ragnarok.Flippant 2016-09-17 11:45:45
Link | Quote | Reply
 
I just tossed my THF sets in and had no trouble running the function through using write_sets[val] + 1.

I may need to see the whole thing x: I'm not sure what could be throwing that error, especially considering your conditions, and trying to manually reproduce it doesn't work. Other suggestions:
Try working with a small example table. Does it work? Is it a single element that you can narrow it down to? Is it -all- elements?
If it's all elements, are you manipulating this table in other areas?
 Fenrir.Brimstonefox
Offline
Server: Fenrir
Game: FFXI
user: Brimstone
Posts: 183
By Fenrir.Brimstonefox 2016-09-17 15:25:03
Link | Quote | Reply
 
https://github.com/Fox214/closetCleaner

I had initially copied the gearswap folder to closetCleaner and renamed the gearswap.lua to closet cleaner, then started messing with it. I noticed it was actually loading gearswap when I called it, but I was just trying to reuse the functions. Before I put it on github I tried to clean up some stuff (ie delete the content files from gearswap the mote stuff and <job>.lua stuff, data and examples directories) after doing that the error went away, but it doesn't work at all (since no Table "sets" exists now).

So I guess the answer is it was due to some other file beign loaded (which I needed without realizing I needed it, even though I don't want it functionally loaded, just the table space). I just manually put a small section of sets from one of my files and the function above works like I expected it to.

I'll have to figure out how to load the table info from gear swap now....
 Fenrir.Brimstonefox
Offline
Server: Fenrir
Game: FFXI
user: Brimstone
Posts: 183
By Fenrir.Brimstonefox 2016-09-18 07:41:02
Link | Quote | Reply
 
Next question:
Code
fpath = windower.addon_path:gsub('\\','/')
	fpath = fpath:gsub('//','/')
	gspath = fpath:gsub('closetcleaner\/','')..'gearswap/data/'
	print(gspath)
	if windower.file_exists(gspath..player.name..'_BLM.lua') then
		dofile "gspath..player.name..'_BLM.lua'"
		supersets.BLM = sets
	else
		print(gspath..player.name..'_BLM.lua does not exist')
		print('checking '..gspath..'BLM.lua')
		if windower.file_exists(gspath..'BLM.lua') then
			print('found it!')
			dofile "gspath..'BLM.lua'"
			supersets.BLM = sets
		end
	end


my path looks good, and prints the 'found it!' but the dofile isn't working any ideas?
 Ragnarok.Flippant
Offline
Server: Ragnarok
Game: FFXI
user: Enceladus
Posts: 658
By Ragnarok.Flippant 2016-09-18 14:39:31
Link | Quote | Reply
 
You'd need to call get_sets() to actually instantiate the sets, so I'd check first if that's the reason it doesn't seem to be working.

You shouldn't really need many GS functions, as all the information you require is in the user files (including augments, etc.). So it would be better to start from a fresh file, if that isn't what you've started to do already.

The only function that I can think of that you would require is set_combine(), and perhaps any of the other user functions (although they wouldn't actually need to do anything). You would also need to create all the base tables found in GS; sets is the obvious one, but there's also the chance of users trying to reference a child of buffactive, player, etc. on load, which would cause an indexing error when you call get_sets().
 Leviathan.Vow
Offline
Server: Leviathan
Game: FFXI
user: woVow
Posts: 125
By Leviathan.Vow 2016-09-19 14:14:24
Link | Quote | Reply
 
Code
dofile "gspath..'BLM.lua'"


You can't concatenate within quotes. If you're trying to avoid using parentheses, you cannot in this situation.
 Fenrir.Brimstonefox
Offline
Server: Fenrir
Game: FFXI
user: Brimstone
Posts: 183
By Fenrir.Brimstonefox 2016-09-29 12:54:12
Link | Quote | Reply
 
Well I fixed the dofile issue (parens worked, the example on stackoverflow or wherever had quotes and I didn't realize I could just switch to parens)

I have includes in my files for the Mote-lib stuff and organizer lib stuff so when I load it that is erroring out now when I run those lines (if I comment them out it works ok) I've tried copying the files to the local directory and its still not working, so it seems to me its either a path issue or I'm missing something from gearswap to get the includes to work. Any ideas? (apologies I can't paste the exact error, I can try to do so in a couple days traveling and such now)
 Leviathan.Vow
Offline
Server: Leviathan
Game: FFXI
user: woVow
Posts: 125
By Leviathan.Vow 2016-09-30 22:38:20
Link | Quote | Reply
 
There is no include function in Lua. You'll need to spoof it, which is probably as simple as
Code
local include = require
unless you set an include path, in which case you'll need to account for it as well.
 Fenrir.Brimstonefox
Offline
Server: Fenrir
Game: FFXI
user: Brimstone
Posts: 183
By Fenrir.Brimstonefox 2016-10-25 22:30:00
Link | Quote | Reply
 
Ok I have it mostly working: https://github.com/Fox214/closetCleaner

However, I was trying to create 1 table to loop through which would be a superset of all the sets tables.

but clearly its just taking last in wins, I've tried playing with the syntax but nothing seems to work any ideas?
Code
	for i,v in ipairs(ccjobs) do
		lname = dpath..player.name..'_'..v..'.lua'
		sname = dpath..v..'.lua'
		if windower.file_exists(lname) then
			dofile(lname)
			init_gear_sets()
			table.insert(supersets[v], sets)
			-- add_to_supersets(v, sets)
		else
			if windower.file_exists(sname) then
				dofile(sname)
				init_gear_sets()
				table.insert(supersets[v], sets)
				-- add_to_supersets(v, sets)
			end
		end
	end
 Fenrir.Brimstonefox
Offline
Server: Fenrir
Game: FFXI
user: Brimstone
Posts: 183
By Fenrir.Brimstonefox 2016-10-28 21:50:40
Link | Quote | Reply
 
I'll answer my own question.

lua stores its variables as references, so when so inside my loop i'm creating supersets[BRD] = sets and supersets[BLM] = sets

but each time i 'dofile' sets is changing and all the jobs are pointing to the same sets (which keeps changing)

But if I do a deepcopy that seems to do the trick.
http://lua-users.org/wiki/CopyTable

I'll try and have this fixed up tomorrow.
VIP
Offline
Posts: 111
By Iryoku 2016-10-29 10:03:03
Link | Quote | Reply
 
Fenrir.Brimstonefox said: »
lua stores its variables as references...

This is not entirely true, but if it helps you think about what's going on, it's close enough.

Under the hood, every time you call a function lua allocates a chunk of memory called a "stack frame". Each stack frame has up to 256 slots called "registers". There is usually one register for each local variable. Registers are all the same size. Numbers, booleans, and a special type that's only usable from the C API called "light userdata" can all fit inside of a register and are stored there directly. Strings, tables, coroutines, functions and userdata (another type intended for use from the C API) are all too big to fit into registers, and so references to these types are stored.

Strings, and functions are immutable in Lua, so the fact that references are used for them isn't ever observable anyway. I won't go into coroutines here, because that's a fairly advanced topic, and we don't really use userdata anywhere in Windower 4.

So tables are the only type you're likely to use right now that get passed around as references and where you can actually tell that it's happening. But there's one other wrinkle: upvalues. This is another somewhat advanced topic, so don't worry too much if you don't understand this. Whenever you create a closure in Lua, the function stores some information about the closed over variable that says "variable x is actually a reference to register y, in the stack frame z levels below this one."

So there you go. More than you probably needed to know, but it never hurts to understand what's happening inside the interpreter.
[+]
Log in to post.