PDA

View Full Version : Question using a DB handler



Paul Pratt
February 26th, 2021, 08:24
I added a handler to my talent list in 40k to watch for a certain talent. If it is present, a value in a different part of the character sheet is set. It works to set the value, however, when I add or delete something in the list, using the buttons or right click, it throws an error that I am attempting to index a nil value.

It uses onChildUpdate pointing to a function. The main portion of the function is below. The error points to the second line when I add or delete from the list. What can I do/add/adjust to remove the error?


for k,v in pairs (nodeChar.getChildren()) do
if v.getChild("name").getValue() == ("True Grit") then
nTrueGritPC = 1;
end
end

Trenloe
February 26th, 2021, 10:59
What's the exact error?
What does nodeChar point to?
What is the code you've used to setup the handler?

Paul Pratt
February 26th, 2021, 15:32
The error is "Handler error:[string "campaign/scripts/talent_list.lua"]:22: attempt to index a nil value.

nodeChar points to the talent list charsheet.id-00004.talents, the talent list I am watching.

The handler is set up with this code. Currently I have the script called from the list. I had an earlier version called at the level of the talent tab. That threw the same error, so I moved the script file to the list itself.


function onInit()
local node = getDatabaseNode();
DB.addHandler(DB.getPath(node), "onChildUpdate", GritCheckPC);
end

function onClose()
local node = getDatabaseNode();
DB.removeHandler(DB.getPath(node), "onChildUpdate", GritCheckPC);
end


It works. The issue is when I add or delete from the list I am watching.

SilentRuin
February 26th, 2021, 15:48
The error is "Handler error:[string "campaign/scripts/talent_list.lua"]:22: attempt to index a nil value.

nodeChar points to the talent list charsheet.id-00004.talents, the talent list I am watching.

The handler is set up with this code. Currently I have the script called from the list. I had an earlier version called at the level of the talent tab. That threw the same error, so I moved the script file to the list itself.


function onInit()
local node = getDatabaseNode();
DB.addHandler(DB.getPath(node), "onChildUpdate", GritCheckPC);
end

function onClose()
local node = getDatabaseNode();
DB.removeHandler(DB.getPath(node), "onChildUpdate", GritCheckPC);
end


It works. The issue is when I add or delete from the list I am watching.

Not knowing exactly what you have elsewhere, The DB (https://fantasygroundsunity.atlassian.net/wiki/spaces/FGCP/pages/996644582/DB).addHandler function can trigger on different things. If you are using onChildUpdate your going to trigger on pretty much any changes to it including add and delete. I'd recommend testing - I've never had luck just "doing what I thought it did" in FGU. First you GUARD against the nil value and simply return or skip depending on situation when it is nil. As there is nothing you can do with that if its just "nature of the beast" type of garbage you can probably get.

Then test. If it all works as you want it to work. Your done.

Also, beware the client. Not all things are things you want executing in the client side so you would guard your handler from executing anywhere but on the host. Client won't have access to things host will.

Trenloe
February 26th, 2021, 15:54
Yeah, you need to identify which of v (it shouldn't be just v being nil, as the pairs shouldn't provide a nil value), v.getChild("name") or v.getChild("name").getValue() is actually nil and code for that.

A better API call to make in these cases is DB.getValue(v, "name", "") - which returns "" if that node doesn't exist. This is a much better way of handling these types of queries, and it's more efficient.

Paul Pratt
February 26th, 2021, 16:14
The onChildUpdate I knew was going to cause headaches. It also leads to extensive recursive calls when setting values if you aren't careful too. I was looking for a way to skip past a nil call. The v.getChild portion -- the nil -- I tested debugged, just couldn't figure that one out. That's why I finally came here after about two days of code iterations and testing.

I will change to a DB.getValue call, I had no idea it was a better more efficient method. There a few places in 40k and perhaps WHFRP2e that I use the same basic format for iterating of a list. I will look to change those as well.

Thanks for the assist, always something useful when I head over here for a chat.

Paul Pratt
February 26th, 2021, 16:22
So, I just changed v.getChild("name").getValue() to DB.getValue(v, "name", "") and it works 100%. No error when adding or deleting. Again, thanks.

Trenloe
February 26th, 2021, 16:31
So, I just changed v.getChild("name").getValue() to DB.getValue(v, "name", "") and it works 100%. No error when adding or deleting. Again, thanks.
Good stuff! :)