PDA

View Full Version : Accessing the database from hotkeys



Hamish
September 8th, 2007, 19:34
Gents,

I'm working on a ruleset modification that lets you add references to the database in hotkeys. Mostly intended for things like skill rolls, so you don't have to redefine every hotkey when you level and you add ranks.
My question is how I can reference the character sheet from a hotkey. I don't think:

window.getDatabaseNode()
is going to do the trick, since I don't have a window to start with.
Any ideas?

Hamish

Toadwart
September 8th, 2007, 23:41
Gents,

I'm working on a ruleset modification that lets you add references to the database in hotkeys. Mostly intended for things like skill rolls, so you don't have to redefine every hotkey when you level and you add ranks.
My question is how I can reference the character sheet from a hotkey. I don't think:

window.getDatabaseNode()
is going to do the trick, since I don't have a window to start with.
Any ideas?

Hamish

Not sure, maybe DB.findNode?
https://www.fantasygrounds.com/refdoc/DB.xcp

Hamish
September 9th, 2007, 10:20
Hmmm, looks good. But it doesn't specify what you should use as argument. Also findNode is not used in the d20 ruleset at all.... so no help there.

Foen
September 10th, 2007, 06:15
I agree, the reference documentation (here (https://www.fantasygrounds.com/refdoc/DB.xcp)) only says you pass it a nodeid - not fully sure what one of those is. Joshuha or Griogre might know?

Stuart

joshuha
September 10th, 2007, 14:32
nodeid is just the name of the node. I usually use it like so:



function test()
print(DB.findNode("charsheet").getChild("id-00001").getChild("name").getValue());
end


Obviously id-00001 needs to be changed to the ID node that matches the character but that should not be hard if you are doing this from the client side.

Foen
September 10th, 2007, 17:46
Thanks Joshuha.

Testing your code, it seems you can also use a fully-qualified node name (path) such as:



print(DB.findNode("charsheet.id-00001.name").getValue());


Cheers

Stuart

Hamish
September 11th, 2007, 09:34
Okay, that helps a lot. All I need now is a way to find out which charactersheet ID I should reference when I want to access the current player's character sheet. I don't have much time right now, I'll experiment later!


Ahh, post #100 from me! :)

Hamish
September 14th, 2007, 13:38
Okay... a little progress!

User.getCurrentIdentity() will get me the ID of the character I need to access in the DB. Now I run into the fact that skills are also identified by an ID number, and not by name. Anyone have any idea how to acces a skill in the DB by name?

joshuha
September 14th, 2007, 13:51
I just loop through them and check the name value against your search criteria.

Use the skills dbnode and call getChildren to get a container of all the children you can loop through.

Hamish
September 14th, 2007, 20:25
Thanks Joshuha, I had thought about that myself. Problem is, I would like to use the same system to reference all possible database nodes. But I'm afraid this means either using skilllist.id-00001.total for skill modifiers, or scripting different way to access them.
Hmmmm, I'll need to think about that one.

Hamish
September 15th, 2007, 18:53
I'm having a bit of trouble with getChildren (not IRL BTW, I have 2 :) ) on the skilllist database node. I get the message that I'm trying to index a nil value. From the description of getChildren I see that it will return the name property of all child nodes, but in the DB the name of a skill is actually in a tag called 'label'. Am I correct in assuming that getChildren is not going to work on the skilllist database node?

joshuha
September 15th, 2007, 23:52
This should work as long as the skills node is there and you are somewhere on the PC sheet. You'll need to modify it if you are working from the outside which you are through DB.findNode().



function checkSkill()
skills = {};
if window.getDatabaseNode().getChild("skills") == nil then return false; end
skills = window.getDatabaseNode().getChild("skills").getChildren();
for i,j in pairs(skills) do
if string.upper(j.getChild("name").getValue()) == "CONCENTRATION" then
return j;
end
end
return false;
end

Hamish
September 16th, 2007, 20:06
Right, I've learned some more about Lua and FG scripting. Plus it turns out I was trying to modify the wrong file. :mad: Now, instead of editing chat_entry.lua I'm looking at chatmanager.lua, and specifically the processDie function.
I'm having trouble understanding the next line:


for s, m, d in string.gmatch(diestring, "([%+%-]?)(%d*)(%w*)") do

I know it's use is to split up the first part of the /die command using Lua string patterns, but can't figure out how it does it.

s indicates a bonus or penalty (+ or -)
m indicates the amount of the bonus or penalty
d is the type of die, I think

But how 1d20+4 is translated to s=+; m=4 and d=20 is beyond me.

Hamish
September 17th, 2007, 10:30
Joshuha, I can't seem to find the "skills" node you are using in your script in the database. I think we may be working on 2 different parts of the database. I'm still testing my script, so I will keep you posted.

Hamish
September 17th, 2007, 14:11
I think I fixed it!

Add this to chatmanager.lua:
For me, the first line to be added is at line 206



local modifier = 0;

sTemp = diestring;
sTemp = string.gsub(sTemp, "%[(.+)%]", getSkillID);
sTemp = string.gsub(sTemp, "{(.+)}", getFromDB);
diestring = sTemp;

for s, m, d in string.gmatch(diestring, "([%+%-]?)(%d*)(%w*)") do


and a little further down (for me the first new line is at line 254)



control.throwDice("dice", dice, modifier, descriptionstring);
end
end
end

-- Database retrieval
function getSkillID(sName)
sNode = "charsheet." .. User.getCurrentIdentity() .. ".skilllist";
tSkills = DB.findNode(sNode).getChildren();
for sID, oSkill in pairs(tSkills) do
if string.upper(oSkill.getChild("label").getValue()) == string.gsub(string.upper(sName), "_", " ") then
return sID;
end
end
return false;
end

function getFromDB(sNode)
sFinalNode = "charsheet." .. User.getCurrentIdentity() .. "." .. sNode;
return DB.findNode(sFinalNode).getValue();
end

-- Initialization
function onInit()
registerSlashHandler("/whisper", processWhisper);


Usage:
To make a Strength check, type: /die 1d20+{abilities.strength.bonus} Strength
To make a Will save, type: /die 1d20+{saves.will.total} Will save
To make a Climb check, type: /die 1d20+{skilllist.[Climb].total} Climb
To make a Move Silently check, type: /die 1d20+{skilllist.[Move_Silently].total} Move Silently

I hope someone else can use this, I certainly will in my ruleset.

Tokuriku
September 18th, 2007, 13:47
You can bet I'll use it more then my share :D

Hamish
November 14th, 2007, 19:58
I found an error in my code, it was not handling skills with sublabels correctly. Just thought I'd post the new code here for anyone who's using it. It's just the getSkillID function that has changed.


function getSkillID(sName)
if string.match(sName, "([%a_]+)_%(([%a_]+)%)") == nil then
label = string.gsub(string.lower(sName), "_", " ");
sublabel = "";
else
label, sublabel = string.match(sName, "([%a_]+)_%(([%a_]+)%)");
label = string.gsub(string.lower(label), "_", " ");
sublabel = string.gsub(string.lower(sublabel), "_", " ");
end
sNode = "charsheet." .. User.getCurrentIdentity() .. ".skilllist";
tSkills = DB.findNode(sNode).getChildren();
for sID, oSkill in pairs(tSkills) do
if string.lower(oSkill.getChild("label").getValue()) == label then
if sublabel == "" or string.lower(oSkill.getChild("sublabel").getValue()) == sublabel then
return sID;
end
end
end
return false;
end