PDA

View Full Version : Database Scripting Issues



GrimmSpector
February 26th, 2016, 06:13
Hello, more problems, in this case, trying to setup a couple fields to update when I change another field, getting a couple errors, first error occurs when I open the window, second one appears when I try to edit the "XP" field, which is a numberfield.

Error 1:

Script Error: [string "link"]:1: attempt to index global 'target' (a nil value)

Error 2:

Script Error: [string "charsheet_attribute:XP"]:1: attempt to index global 'target' (a nil value)

The code that manages everything is here:


<?xml version="1.0" encoding="iso-8859-1"?>

<root version="1.0">
<windowclass name="charsheet_attribute">
<sizelimits>
<maximum>
<height>23</height>
</maximum>
<minimum>
<height>23</height>
</minimum>
</sizelimits>
<sheetdata>
<numbercontrol name="order">
<bounds>0,0,0,0</bounds>
<invisible />
</numbercontrol>
<stringcontrol name="label">
<anchored position="insidetopleft" offset="0,6" width="75" height="15" />
<font>sheetlabel</font>
<static />
</stringcontrol>
<number_modifier name="score">
<anchored to="label" position="rightlow" offset="10,0" width="30" />
<font>sheetnumber</font>
<frame>
<name>fieldlight</name>
<offset>5,4,5,4</offset>
</frame>
<hideonvalue value="0" />
<displaysign />
<showemptywidget />
</number_modifier>
<number_modifier name="link">
<anchored to="score" position="right" offset="15,0" width="30" />
<font>sheetnumber</font>
<frame>
<name>fieldlight</name>
<offset>5,4,5,4</offset>
</frame>
<hideonvalue value="0" />
<displaysign />
<showemptywidget />
<script>
function onSourceUpdate()
local nodeWin = window.getDatabaseNode();
local nLink = DB.getValue(nodeWin, "attributes." .. target[1] .. ".link", -4);
setValue(nLink);
end

function onInit()
addSource("attributes." .. target[1] .. ".XP");
super.onInit();
end
</script>
</number_modifier>
<numberfield name="XP">
<anchored to="link" position="righthigh" offset="15,-1" width="30" />
<font>sheetnumber</font>
<frame>
<name>fielddark</name>
<offset>5,4,5,4</offset>
</frame>
<keyeditframe>
<name>fieldfocus</name>
<offset>5,4,5,4</offset>
</keyeditframe>
<script>
function onValueChanged()
local nScore = DB.getValue(window.getDatabaseNode(), "attributes." .. target[1] .. ".XP", 0)/100;
local nLink = 0;
if nScore &gt; 11 then
nLink = nScore % 3;
elseif nScore == 10 then
nLink = 2;
elseif nScore &gt; 6 then
nLink = 1;
elseif nScore &gt; 3 then
nLink = 0;
elseif nScore &gt; 1 then
nLink = -1;
elseif nScore == 1 then
nLink = -2;
else
nLink = -4;
end
end
</script>
</numberfield>
</sheetdata>
</windowclass>
</root>


It's implemented by this window:


<?xml version="1.0" encoding="iso-8859-1"?>

<!--
Please see the license.html file included with this distribution for
attribution and copyright information.
-->

<root>
<include source="charsheet_listclasses.xml" />
<windowclass name="charsheet_main">
<margins control="0,0,0,2" />
<sheetdata>
<frame_char name="attributesframe">
<bounds>15,0,280,225</bounds>
</frame_char>
<stringcontrol name="score_label">
<anchored to="attributesframe" position="insidetopleft" offset="98,8" width="35" />
<font>sheetlabelinline</font>
<static>Score</static>
<center />
</stringcontrol>
<stringcontrol name="link_label">
<anchored to="score_label" position="right" offset="10,0" width="35" />
<font>sheetlabelinline</font>
<static>Link</static>
<center />
</stringcontrol>
<stringcontrol name="xp_label">
<anchored to="link_label" position="right" offset="18,0" width="15" />
<font>sheetlabelinline</font>
<static>XP</static>
<center />
</stringcontrol>
<windowlist name="attributes">
<anchored>
<to>attributesframe</to>
<position>over</position>
<offset>-15,-20</offset>
</anchored>
<class>charsheet_attribute</class>
<datasource>.attributes</datasource>
<noscroll />
<script>
STR = nil;
BOD = nil;
RFL = nil;
DEX = nil;
INT = nil;
WIL = nil;
CHA = nil;
EDG = nil;

local order = 1;

function onInit()
STR = addEntry("STR","Strength");
BOD = addEntry("BOD", "Body");
RFL = addEntry("RFL", "Reflex");
DEX = addEntry("DEX", "Dexterity");
INT = addEntry("INT", "Intelligence");
WIL = addEntry("WIL", "Willpower");
CHA = addEntry("CHA", "Charisma");
EDG = addEntry("EDG", "Edge");
applySort();
end

function addEntry(name, label)
local node = getDatabaseNode().getChild(name);
local win = nil;
if not node then
node = getDatabaseNode().createChild(name);
end
for i,w in ipairs(getWindows()) do
if w.getDatabaseNode().getName()==name then
win = w;
end
end
if win then
win.label.setValue(label);
win.order.setValue(order);
order = order + 1;
end
return win;
end

function onSortCompare(w1, w2)
return (w1.order.getValue() &gt; w2.order.getValue());
end
</script>
<skipempty />
</windowlist>
</sheetdata>
</windowclass>

<windowclass name="char_main_category_header">
<margins control="0,0,0,5" />
<frame>rowshade</frame>
<sheetdata>
<genericcontrol name="leftanchor">
<anchored height="0" width="0">
<top offset="5" />
<left offset="10" />
</anchored>
</genericcontrol>

<genericcontrol name="rightanchor">
<anchored height="0" width="0">
<top offset="5" />
<right offset="-10" />
</anchored>
</genericcontrol>

<stringfield name="label">
<anchored>
<top offset="5" />
<left offset="30" />
<right offset="-30" />
</anchored>
<stateframe>
<keyedit name="fieldfocus" offset="7,5,7,5" />
<hover name="fieldfocus" offset="7,5,7,5" hidereadonly="true" />
<drophilight name="fieldfocus" offset="7,5,7,5" hidereadonly="true" />
</stateframe>
<font>reference-b-large</font>
<multilinespacing>20</multilinespacing>
<center />
</stringfield>
</sheetdata>
</windowclass>
</root>


Please excuse the variety of methods of layout, as I'm still working on efficiency and style. Thanks.

GrimmSpector
February 26th, 2016, 19:21
Seems like it's trying to use an undeclared variable, but other methods use this table, and I can't find anything that constructs it in the code, so I assumed it was a builtin lua item. "target"

Also looks like the database layout that is being generated is charsheet.attributes.<STAT>.XP, but it's trying to reference charsheet_attribute.XP from the error message, which is clearly wrong, I'm just unsure why, as I'm using the method I see in other bits of code to access a database node attached to the current window, and that node should just be charsheet, and the container should be attributes. Perhaps I'm misunderstanding the database methods in some way.

GrimmSpector
February 26th, 2016, 20:06
Well I'm having a lot of trouble with the database structure, despite reading through the reference doc, really hoping someone could help me figure this out. Here's a copy of the database, which may help.



<?xml version="1.0" encoding="iso-8859-1"?>
<root version="3.1" release="3|CoreRPG:3">
<calendar>
<public />
</calendar>
<charsheet>
<id-00001>
<abilitylist>
</abilitylist>
<attributes>
<BOD>
<XP type="number">0</XP>
<link type="number">0</link>
<linkmodifier type="number">0</linkmodifier>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</BOD>
<CHA>
<XP type="number">0</XP>
<link type="number">0</link>
<linkmodifier type="number">0</linkmodifier>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</CHA>
<DEX>
<XP type="number">0</XP>
<link type="number">0</link>
<linkmodifier type="number">0</linkmodifier>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</DEX>
<EDG>
<XP type="number">0</XP>
<link type="number">0</link>
<linkmodifier type="number">0</linkmodifier>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</EDG>
<INT>
<XP type="number">0</XP>
<link type="number">0</link>
<linkmodifier type="number">0</linkmodifier>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</INT>
<RFL>
<XP type="number">0</XP>
<link type="number">0</link>
<linkmodifier type="number">0</linkmodifier>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</RFL>
<STR>
<XP type="number">2</XP>
<link type="number">0</link>
<linkmodifier type="number">0</linkmodifier>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</STR>
<WIL>
<XP type="number">0</XP>
<link type="number">0</link>
<linkmodifier type="number">0</linkmodifier>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</WIL>
</attributes>
<coins>
<slot1>
<amount type="number">0</amount>
</slot1>
<slot2>
<amount type="number">0</amount>
</slot2>
<slot3>
<amount type="number">0</amount>
</slot3>
<slot4>
<amount type="number">0</amount>
</slot4>
<slot5>
<amount type="number">0</amount>
</slot5>
<slot6>
<amount type="number">0</amount>
</slot6>
</coins>
<encumbrance>
<load type="number">0</load>
</encumbrance>
<inventorylist>
</inventorylist>
<name type="string">Test</name>
<phenotype type="string">Human</phenotype>
<token type="token"></token>
</id-00001>
<id-00003>
<attributes>
<BOD>
<XP type="number">0</XP>
<link type="number">0</link>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</BOD>
<CHA>
<XP type="number">0</XP>
<link type="number">0</link>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</CHA>
<DEX>
<XP type="number">0</XP>
<link type="number">0</link>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</DEX>
<EDG>
<XP type="number">0</XP>
<link type="number">0</link>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</EDG>
<INT>
<XP type="number">0</XP>
<link type="number">0</link>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</INT>
<RFL>
<XP type="number">0</XP>
<link type="number">0</link>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</RFL>
<STR>
<XP type="number">0</XP>
<link type="number">0</link>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</STR>
<WIL>
<XP type="number">0</XP>
<link type="number">0</link>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</WIL>
</attributes>
<token type="token"></token>
</id-00003>
</charsheet>
<combattracker>
<public />
</combattracker>
<effects>
<public />
</effects>
<encounter>
</encounter>
<image>
</image>
<languages>
<public />
</languages>
<modifiers>
<public />
</modifiers>
<options>
<public />
</options>
<partysheet>
<public />
</partysheet>
</root>

GrimmSpector
February 26th, 2016, 20:20
Given the database setup, I would expect
getValue("attributes.BOD.XP") to return a number "0", but it returns nil, attempting to force the path to be relative ".attributes.BOD.XP", does the same, and so does attempting to examine the "phenotype" leaf, seems like I can't manually pull any data out of the nodes, and I'm really not sure what I'm doing wrong.

feldrol
February 26th, 2016, 20:38
I had the same issue 5 minutes ago and that posts explains how to solve it:
https://www.fantasygrounds.com/forums/showthread.php?26922-What-exactly-is-self-target

GrimmSpector
February 26th, 2016, 20:59
I had the same issue 5 minutes ago and that posts explains how to solve it:
https://www.fantasygrounds.com/forums/showthread.php?26922-What-exactly-is-self-target

That does help a bit, however my elements are being dynamically allocated, so the controls for "strength" for instance are a set in a window class with that name, so setting an absolute "target" in the xml doesn't seem like it will do what I want, so when I have one named "strength" it needs to be <target>strength</target>, but for another named "reflex" it needs to be "<target>reflex</target>".

I'll try a way of setting this through code, but given the way things have been going, I expect my attempt to fail.

GrimmSpector
February 26th, 2016, 21:08
Well my attempt worked, partly...

Still getting this error:
Script Error: [string "charsheet_attribute:XP"]:1: attempt to index field 'target' (a nil value)

When I attempt to edit the "link" field, however my default -4s are showing up. And the values in the Link field are never being saved, I imagine this is because I'm not calling the super.onUpdate() in the function I wrote?

Edit: Not a big deal, but it looks like I'm now getting a field under each in the database:


<BOD>
<XP type="number">0</XP>
<attributes>
<target>
<XP type="number">0</XP>
</target>
</attributes>
<link type="number">-4</link>
<linkmodifier type="number">0</linkmodifier>
<score type="number">0</score>
<scoremodifier type="number">0</scoremodifier>
</BOD>


Not sure why it's storing the target tag...not something I intended for. If someone could shed some light on the why, it could be helpful.

Here's the modified code of the class, only change is the addition of the target tag:



<?xml version="1.0" encoding="iso-8859-1"?>

<root version="1.0">
<windowclass name="charsheet_attribute">
<sizelimits>
<maximum>
<height>23</height>
</maximum>
<minimum>
<height>23</height>
</minimum>
</sizelimits>
<sheetdata>
<numbercontrol name="order">
<bounds>0,0,0,0</bounds>
<invisible />
</numbercontrol>
<stringcontrol name="label">
<anchored position="insidetopleft" offset="0,6" width="75" height="15" />
<font>sheetlabel</font>
<static />
</stringcontrol>
<number_modifier name="score">
<anchored to="label" position="rightlow" offset="10,0" width="30" />
<font>sheetnumber</font>
<frame>
<name>fieldlight</name>
<offset>5,4,5,4</offset>
</frame>
<hideonvalue value="0" />
<displaysign />
<showemptywidget />
</number_modifier>
<number_modifier name="link">
<anchored to="score" position="right" offset="15,0" width="30" />
<font>sheetnumber</font>
<frame>
<name>fieldlight</name>
<offset>5,4,5,4</offset>
</frame>
<hideonvalue value="0" />
<displaysign />
<showemptywidget />
<target mergerule="replace">target</target>
<script>
function onSourceUpdate()
local nodeWin = window.getDatabaseNode();
local nLink = DB.getValue(nodeWin, "attributes." .. target[1] .. ".link", -4);
setValue(nLink);
end

function onInit()
addSource("attributes." .. target[1] .. ".XP");
super.onInit();
end
</script>
</number_modifier>
<numberfield name="XP">
<anchored to="link" position="righthigh" offset="15,-1" width="30" />
<font>sheetnumber</font>
<frame>
<name>fielddark</name>
<offset>5,4,5,4</offset>
</frame>
<keyeditframe>
<name>fieldfocus</name>
<offset>5,4,5,4</offset>
</keyeditframe>
<script>
function onValueChanged()
local nScore = DB.getValue(window.getDatabaseNode(), "attributes." .. self.target[1] .. ".XP", 0)/100;
local nLink = 0;
if nScore &gt; 11 then
nLink = nScore % 3;
elseif nScore == 10 then
nLink = 2;
elseif nScore &gt; 6 then
nLink = 1;
elseif nScore &gt; 3 then
nLink = 0;
elseif nScore &gt; 1 then
nLink = -1;
elseif nScore == 1 then
nLink = -2;
else
nLink = -4;
end
end
</script>
</numberfield>
</sheetdata>
</windowclass>
</root>


And here's the modified version of the window itself:



<?xml version="1.0" encoding="iso-8859-1"?>

<!--
Please see the license.html file included with this distribution for
attribution and copyright information.
-->

<root>
<include source="charsheet_listclasses.xml" />
<windowclass name="charsheet_main">
<margins control="0,0,0,2" />
<sheetdata>
<frame_char name="attributesframe">
<bounds>15,0,250,225</bounds>
</frame_char>
<stringcontrol name="score_label">
<anchored to="attributesframe" position="insidetopleft" offset="98,8" width="35" />
<font>sheetlabelinline</font>
<static>Score</static>
<center />
</stringcontrol>
<stringcontrol name="link_label">
<anchored to="score_label" position="right" offset="10,0" width="35" />
<font>sheetlabelinline</font>
<static>Link</static>
<center />
</stringcontrol>
<stringcontrol name="xp_label">
<anchored to="link_label" position="right" offset="18,0" width="15" />
<font>sheetlabelinline</font>
<static>XP</static>
<center />
</stringcontrol>
<windowlist name="attributes">
<anchored>
<to>attributesframe</to>
<position>over</position>
<offset>-15,-20</offset>
</anchored>
<class>charsheet_attribute</class>
<datasource>.attributes</datasource>
<noscroll />
<script>
STR = nil;
BOD = nil;
RFL = nil;
DEX = nil;
INT = nil;
WIL = nil;
CHA = nil;
EDG = nil;

local order = 1;

function onInit()
STR = addEntry("STR","Strength");
BOD = addEntry("BOD", "Body");
RFL = addEntry("RFL", "Reflex");
DEX = addEntry("DEX", "Dexterity");
INT = addEntry("INT", "Intelligence");
WIL = addEntry("WIL", "Willpower");
CHA = addEntry("CHA", "Charisma");
EDG = addEntry("EDG", "Edge");
applySort();
end

function addEntry(name, label)
local node = getDatabaseNode().getChild(name);
local win = nil;
if not node then
node = getDatabaseNode().createChild(name);
end
for i,w in ipairs(getWindows()) do
if w.getDatabaseNode().getName()==name then
win = w;
end
end
if win then
win.label.setValue(label);
win.order.setValue(order);
win.label.setValue(name);
order = order + 1;
end
return win;
end

function onSortCompare(w1, w2)
return (w1.order.getValue() &gt; w2.order.getValue());
end
</script>
<skipempty />
</windowlist>
</sheetdata>
</windowclass>

<windowclass name="char_main_category_header">
<margins control="0,0,0,5" />
<frame>rowshade</frame>
<sheetdata>
<genericcontrol name="leftanchor">
<anchored height="0" width="0">
<top offset="5" />
<left offset="10" />
</anchored>
</genericcontrol>

<genericcontrol name="rightanchor">
<anchored height="0" width="0">
<top offset="5" />
<right offset="-10" />
</anchored>
</genericcontrol>

<stringfield name="label">
<anchored>
<top offset="5" />
<left offset="30" />
<right offset="-30" />
</anchored>
<stateframe>
<keyedit name="fieldfocus" offset="7,5,7,5" />
<hover name="fieldfocus" offset="7,5,7,5" hidereadonly="true" />
<drophilight name="fieldfocus" offset="7,5,7,5" hidereadonly="true" />
</stateframe>
<font>reference-b-large</font>
<multilinespacing>20</multilinespacing>
<center />
</stringfield>
</sheetdata>
</windowclass>
</root>


If I can figure out this last part, I can probably solve most of the problems I've had throughout this thread.

Trenloe
February 26th, 2016, 21:21
Given the database setup, I would expect
getValue("attributes.BOD.XP") to return a number "0", but it returns nil, attempting to force the path to be relative ".attributes.BOD.XP", does the same, and so does attempting to examine the "phenotype" leaf, seems like I can't manually pull any data out of the nodes, and I'm really not sure what I'm doing wrong.
getValue is executed against a databasenode (https://www.fantasygrounds.com/refdoc/databasenode.xcp), right? e.g. myDBNode.getValue()?

Or, are you using DB.getValue to go directly to a specific entry in the database (starting at the root of the database)?

Either way, you'll need to get a reference to the specific character in the database. In your db.xml in post #3 the full database path would be charsheet.id-00001.attributes.BOD.XP for the first character in the database.

So this would be DB.getValue("charsheet.id-00001.attributes.BOD.XP"); or get the databasenode of the character you're working against and use <databasenode>.getChild("attributes.BOD.XP").getValue(); where ]<databasenode> is the base databasenode the character sheet is anchored on, or got via the rActor record using ActorManager.getCreatureNode(rActor);

GrimmSpector
February 26th, 2016, 21:29
getValue is executed against a databasenode (https://www.fantasygrounds.com/refdoc/databasenode.xcp), right? e.g. myDBNode.getValue()?

Or, are you using DB.getValue to go directly to a specific entry in the database (starting at the root of the database)?

Either way, you'll need to get a reference to the specific character in the database. In your db.xml in post #3 the full database path would be charsheet.id-00001.attributes.BOD.XP for the first character in the database.

So this would be DB.getValue("charsheet.id-00001.attributes.BOD.XP"); or get the databasenode of the character you're working against and use <databasenode>.getChild("attributes.BOD.XP").getValue(); where ]<databasenode> is the base databasenode the character sheet is anchored on, or got via the rActor record using ActorManager.getCreatureNode(rActor);

Thanks Trenloe, ideally I want to do it relatively, from the sheet, because it should be accessing the character sheet that it's on. Can't I do that with ".attributes" .. ?? And if I have a target tag in the xml set to the value, shouldn't that make that target[1] value equivalent to the name, i.e. name="BOD", so then it would be ".attributes" .. ".BOD"?

Trenloe
February 26th, 2016, 21:39
Use <windowinstance>.getDatabaseNode: https://www.fantasygrounds.com/refdoc/windowinstance.xcp#getDatabaseNode to get the databasenode specific to the character (assuming your code is running in the base window instance of the character sheet. This will usually be window.getDatabaseNode()

Then use <databasenode>.getChild("attributes.BOD.XP").getValue(); or do it all in one window.getDatabaseNode().getChild("attributes.BOD.XP").getValue(); But, doing this all at once might result in errors if the database hierarchy can't be navigated correctly. So try:

local node = window.getDatabaseNode();
local xpNode = node.getChild("attributes.BOD.XP");

If xpNode then
XP = xpNode .getValue();
end

GrimmSpector
February 26th, 2016, 21:59
Ok, I'll try that method, though that will make it so I have to code each row by hand, instead of reusing the code as I have it setup. How can I make the middle element "BOD" into a dynamic pointer to the one being modified during the onValueChanged()?

Edit: Also seems when I try something like: local nodeWin = window.getDatabaseNode();
at the start of a script, to set it up as a global value for that script, it tells me:
Runtime Notice: Reloading ruleset
Script Error: [string "link"]:1: attempt to index global 'window' (a nil value)

Trenloe
February 26th, 2016, 22:16
Edit: Also seems when I try something like: local nodeWin = window.getDatabaseNode();
at the start of a script, to set it up as a global value for that script, it tells me:
Runtime Notice: Reloading ruleset
Script Error: [string "link"]:1: attempt to index global 'window' (a nil value)
The window doesn't exist during the onInit function, as it's being initialized at that point.


Ok, I'll try that method, though that will make it so I have to code each row by hand, instead of reusing the code as I have it setup. How can I make the middle element "BOD" into a dynamic pointer to the one being modified during the onValueChanged()?
Assuming the onValueChanged event is tied to a control: If the control is a stringfield or numberfield (i.e. anchored on a field in the database) then you can use <control>.getDatabaseNode to get the specific databasenode for the control: https://www.fantasygrounds.com/refdoc/databasecontrol.xcp#getDatabaseNode

Moon Wizard
February 26th, 2016, 22:23
The code in your OP for windowclass "charsheet_attribute" and control "link" doesn't make sense. The "number_modifier" template is designed to be a control which monitors other fields and displays the sum of those fields. The onSourceUpdate is completely redefinition in the script code for this control is completely overriding the built-in summing. In fact, I'm not even sure what "link" is supposed to provide.

Also, it looks like you borrowed code that assumes that a target XML tag is defined for that control, and you can't do that because of the way that you are dynamically creating those fields.

Let's step back a bit.

What are you expecting to see displayed for each attribute? Specifically describe what fields are displayed (label, attribute score, attribute modifier, ...?) Which fields are designed to be directly modified (i.e. attribute score), and which fields are derived (i.e. attribute modifier)? For any derived fields, what are the formulas used to calculate those derived fields?

Regards,
JPG

GrimmSpector
February 26th, 2016, 22:35
The code in your OP for windowclass "charsheet_attribute" and control "link" doesn't make sense. The "number_modifier" template is designed to be a control which monitors other fields and displays the sum of those fields. The onSourceUpdate is completely redefinition in the script code for this control is completely overriding the built-in summing. In fact, I'm not even sure what "link" is supposed to provide.

Also, it looks like you borrowed code that assumes that a target XML tag is defined for that control, and you can't do that because of the way that you are dynamically creating those fields.

Let's step back a bit.

What are you expecting to see displayed for each attribute? Specifically describe what fields are displayed (label, attribute score, attribute modifier, ...?) Which fields are designed to be directly modified (i.e. attribute score), and which fields are derived (i.e. attribute modifier)? For any derived fields, what are the formulas used to calculate those derived fields?

Regards,
JPG

Yea, I've started to realize that. So here's the goal, I'm setting it up to auto build me a list, that looks like this:

13169

So I set them up as a windowclass that sets it up with a defined label, and names the group and positions it underneath that name in the database, for instance "Strength" is the label in the code, and "STR" is the node under .attributes that will receive the data. under STR it has the Score, Link and XP value nodes.

In the code I can use the addEntry setup to put in as many attributes as I like, an they'll all generate and position themselves approriately.

Ideally I want to set up the code so that when I modify the XP field, it will recalculate the values for Score and Link, and update the fields and save the new values to the database. That's what I'm aiming for here.

Edit:

Here's the class code:


<?xml version="1.0" encoding="iso-8859-1"?>

<root version="1.0">
<windowclass name="charsheet_attribute">
<sizelimits>
<maximum>
<height>23</height>
</maximum>
<minimum>
<height>23</height>
</minimum>
</sizelimits>
<sheetdata>
<numbercontrol name="order">
<bounds>0,0,0,0</bounds>
<invisible />
</numbercontrol>
<stringcontrol name="label">
<anchored position="insidetopleft" offset="0,6" width="75" height="15" />
<font>sheetlabel</font>
<static />
</stringcontrol>
<number_modifier name="score">
<anchored to="label" position="rightlow" offset="10,0" width="30" />
<font>sheetnumber</font>
<frame>
<name>fieldlight</name>
<offset>5,4,5,4</offset>
</frame>
<hideonvalue value="0" />
<displaysign />
<showemptywidget />
</number_modifier>
<number_modifier name="link">
<anchored to="score" position="right" offset="15,0" width="30" />
<font>sheetnumber</font>
<frame>
<name>fieldlight</name>
<offset>5,4,5,4</offset>
</frame>
<hideonvalue value="0" />
<displaysign />
<showemptywidget />
<target>target</target>
<script>
function onSourceUpdate()
local nodeWin = window.getDatabaseNode();
local nLink = DB.getValue(nodeWin, "attributes." .. target[1] .. ".link", -4);
setValue(nLink);
end

function onInit()
local nodeWin = window.getDatabaseNode();
local nName = nodeWin.getName();
local nTarget = tostring(nodeWin.getParent(nName));
target = {[1] = nTarget};
addSource("attributes." .. target[1] .. ".XP");
super.onInit();
end
</script>
</number_modifier>
<numberfield name="XP">
<anchored to="link" position="righthigh" offset="15,-1" width="30" />
<font>sheetnumber</font>
<frame>
<name>fielddark</name>
<offset>5,4,5,4</offset>
</frame>
<keyeditframe>
<name>fieldfocus</name>
<offset>5,4,5,4</offset>
</keyeditframe>
<target>target</target>
<script>
function onInit()
local nodeWin = window.getDatabaseNode();
local nName = nodeWin.getName();
local nTarget = tostring(nodeWin.getParent(nName));
target = {[1] = nTarget};
end

function onValueChanged()
local nodeWin= window.getDatabaseNode();
local nScore = DB.getValue(nodeWin, "attributes." .. target[1] .. ".XP", 0)/100;
local nLink = 0;
if nScore &gt; 11 then
nLink = nScore % 3;
elseif nScore == 10 then
nLink = 2;
elseif nScore &gt; 6 then
nLink = 1;
elseif nScore &gt; 3 then
nLink = 0;
elseif nScore &gt; 1 then
nLink = -1;
elseif nScore == 1 then
nLink = -2;
else
nLink = -4;
end
end
</script>
</numberfield>
</sheetdata>
</windowclass>
</root>


I was making use of the modifier number class control in an attempt to shortcut some of the work, which was the wrong choice, I'll be changing it over to be number fields with the tag that adds the "+" to the frame, and mark them as being read only so players can't edit them manually.

Once I get the lua figured out I'll probably write up a custom class of numberfield with the script built in to compartmentalize and simplify my code.

The construction of the various fields occurs from the xml/script here:



<?xml version="1.0" encoding="iso-8859-1"?>

<!--
Please see the license.html file included with this distribution for
attribution and copyright information.
-->

<root>
<include source="charsheet_listclasses.xml" />
<windowclass name="charsheet_main">
<margins control="0,0,0,2" />
<sheetdata>
<frame_char name="attributesframe">
<bounds>15,0,250,225</bounds>
</frame_char>
<stringcontrol name="score_label">
<anchored to="attributesframe" position="insidetopleft" offset="98,8" width="35" />
<font>sheetlabelinline</font>
<static>Score</static>
<center />
</stringcontrol>
<stringcontrol name="link_label">
<anchored to="score_label" position="right" offset="10,0" width="35" />
<font>sheetlabelinline</font>
<static>Link</static>
<center />
</stringcontrol>
<stringcontrol name="xp_label">
<anchored to="link_label" position="right" offset="18,0" width="15" />
<font>sheetlabelinline</font>
<static>XP</static>
<center />
</stringcontrol>
<windowlist name="attributes">
<anchored>
<to>attributesframe</to>
<position>over</position>
<offset>-15,-20</offset>
</anchored>
<class>charsheet_attribute</class>
<datasource>.attributes</datasource>
<noscroll />
<script>
STR = nil;
BOD = nil;
RFL = nil;
DEX = nil;
INT = nil;
WIL = nil;
CHA = nil;
EDG = nil;

local order = 1;

function onInit()
STR = addEntry("STR","Strength");
BOD = addEntry("BOD", "Body");
RFL = addEntry("RFL", "Reflex");
DEX = addEntry("DEX", "Dexterity");
INT = addEntry("INT", "Intelligence");
WIL = addEntry("WIL", "Willpower");
CHA = addEntry("CHA", "Charisma");
EDG = addEntry("EDG", "Edge");
applySort();
end

function addEntry(name, label)
local node = getDatabaseNode().getChild(name);
local win = nil;
if not node then
node = getDatabaseNode().createChild(name);
end
for i,w in ipairs(getWindows()) do
if w.getDatabaseNode().getName()==name then
win = w;
end
end
if win then
win.label.setValue(label);
win.order.setValue(order);
order = order + 1;
target = {[1] = name}
end
return win;
end

function onSortCompare(w1, w2)
return (w1.order.getValue() &gt; w2.order.getValue());
end
</script>
<skipempty />
</windowlist>
</sheetdata>
</windowclass>

<windowclass name="char_main_category_header">
<margins control="0,0,0,5" />
<frame>rowshade</frame>
<sheetdata>
<genericcontrol name="leftanchor">
<anchored height="0" width="0">
<top offset="5" />
<left offset="10" />
</anchored>
</genericcontrol>

<genericcontrol name="rightanchor">
<anchored height="0" width="0">
<top offset="5" />
<right offset="-10" />
</anchored>
</genericcontrol>

<stringfield name="label">
<anchored>
<top offset="5" />
<left offset="30" />
<right offset="-30" />
</anchored>
<stateframe>
<keyedit name="fieldfocus" offset="7,5,7,5" />
<hover name="fieldfocus" offset="7,5,7,5" hidereadonly="true" />
<drophilight name="fieldfocus" offset="7,5,7,5" hidereadonly="true" />
</stateframe>
<font>reference-b-large</font>
<multilinespacing>20</multilinespacing>
<center />
</stringfield>
</sheetdata>
</windowclass>
</root>

Moon Wizard
February 26th, 2016, 22:47
I've been thinking about this a bit, and I think you are trying to abstract too much. (as I mentioned just now in another thread with questions you asked)


Try going back to defining all the attributes directly, without trying to auto-build a list in a listcontrol. This is part of the issue, you're trying to copy existing code and rewrite it from scratch at the same time. You can just use templates to abstract the attribute specific coding, and re-use code easier since it's more like other rulesets.
You'll notice that the 3.5E ruleset does this already using these templates ("number_charabilityscore", "string_charabilitylabel", "number_charabilitydamage", "number_charabilitybonus") in the "charsheet_main" windowclass. These aren't an exact match to what you need; but you can just change the names, adjust the templates, then place on the sheet (4 per attribute). Yours will be called something like ("number_charabilityscore", "string_charabilitylabel", "number_charabilitylink", "number_charabilityxp").
The "number_charabilityscore" template should inherit from the "basicnumber" template (CoreRPG) just like the 3.5E version does. (Don't use number_modifier here, since this is a directly editable field.)
You didn't provide any information on how Link is defined, so I don't know how to calculate this value.
I assume that "number_charabilityxp" template would be a "number_dropadd" template (CoreRPG), since I'm assuming that this is individual XP tracked per ability score, and that you would want dropped numbers to add, not replace.


Bottom line, try mimicking the 3.5E ruleset and change the minimum amount, instead of trying to write a solution from scratch. That comes later, as you gain more proficiency.

Regards,
JPG

GrimmSpector
February 26th, 2016, 23:59
Ok, that makes sense, ideally since I have all the position down quite nicely, I'd like to salvage what I can from the template I have, is there a way (ignoring most of the scripting), and using numberfield types (simplenumber or otherwise), to do what I'm aiming? I think you're right, I've probably abstracted too far, though I've noticed the habit in the ruleset seems to be a pretty high level of abstraction.

The main issue I'm having is addressing the control items within the windowclass to make them update, though in theory the database editing should be pretty easy at this point, I just have to get the name of the item holding the XP control somehow, which I thought I could do with the getName() function, as it should reside within the windowclass, and just append that to the database call for the other attribute I want to edit.

Is there perhaps a way to make the charsheet_notes window to update all of it's items from the database, without having to manually address the controls?

Moon Wizard
February 27th, 2016, 01:35
You still haven't mentioned how "link" value is calculated, or whether attribute score and XP fields should be straight data entry from user. How do those work in your system?

JPG

GrimmSpector
February 27th, 2016, 02:47
Ah sorry, sure that's easy it's here, I have it under the script for the "XP" control in the class setup. Basically you get the Score, which is determined by the XP, at a ratio of 100 XP per point of Score, and then the link value is a bit more complex, various ranges of attribute equate to various link bonuses as seen below.



function onValueChanged()
local nodeWin= window.getDatabaseNode();
local nScore = DB.getValue(nodeWin, "attributes." .. target[1] .. ".XP", 0)/100;
local nLink = 0;
if nScore &gt; 11 then
nLink = nScore % 3;
elseif nScore == 10 then
nLink = 2;
elseif nScore &gt; 6 then
nLink = 1;
elseif nScore &gt; 3 then
nLink = 0;
elseif nScore &gt; 1 then
nLink = -1;
elseif nScore == 1 then
nLink = -2;
else
nLink = -4;
end
end



So the short answer is that XP should be modifiable, and the other two fields should calculate based on it automatically.

In addition, I've noticed getNodeName() and feel like this should be the answer to some of my problems, but can't get it to work, can't seem to setup a piece of code that can call it properly, always tells me I'm attempting to call field getNodeName that's nil.

Long story short, if I can learn how to find the database path, modifying the score/link values should be trivial. Then of course I don't know how to make the fields update when the database changes.

I tried that target method, but it seems roundabout, and doesn't appear to work, though I was able to get rid of all the errors I'd been getting, it resulted in no changes being made to values somehow.

GrimmSpector
February 27th, 2016, 04:58
Wooo! Realized I can output to the console with the print function, and have been using it for debugging, I've got it setting my link value in the database properly, and found out that I don't need to tell the control to update, when the database changes, it updates on it's own!

Only issue I have now, is that I've set up Link and Score as "simplenumber" values, seems to have lost that lovely + sign on the frame, that the number modifiers gave, and I can't find what they do to the frame control to get that, I'll have to keep looking.

GrimmSpector
February 27th, 2016, 05:48
Nice, fixed that, found the bitmapwidget bit, which was easy enough to make use of.

Leads me to my next thing to attempt, want to make a control that looks like the portrait select box more or less, in my notes tab, that can display an image of the faction a player is part of when they select a faction.

Moon Wizard
February 27th, 2016, 06:17
In the vast majority of situations, you won't want the plus widget on any fields that you edit directly. This has been used in many other rulesets to denote a derived field that can be temporarily adjusted.

Basically, the number_modifier template creates a new field in the database with the same name as the control appended by "modifier", and creates a widget to show the temporary modifier in the upper right corner.

I'm assuming Score should be a directly editable field, just like primary ability scores in D&D.
I'm not familiar with Link, so it may be perfect for that field.

Regards,
JPG

GrimmSpector
February 27th, 2016, 07:04
In the vast majority of situations, you won't want the plus widget on any fields that you edit directly. This has been used in many other rulesets to denote a derived field that can be temporarily adjusted.

Basically, the number_modifier template creates a new field in the database with the same name as the control appended by "modifier", and creates a widget to show the temporary modifier in the upper right corner.

I'm assuming Score should be a directly editable field, just like primary ability scores in D&D.
I'm not familiar with Link, so it may be perfect for that field.

Regards,
JPG

Yes I know, so it's being used on the fields that I've setup as read only, that are derived from the other field which doesn't have the icon. Score and Link are both derived from XP. Scores are not directly editable. Everything in BT depends on the XP values. Everything is derived from them, and a few traits (which also get values from XP).

Moon Wizard
February 27th, 2016, 07:28
Cool. I was assuming XP was used to buff ability score, but the base score was set by the player. Thanks for clarifying, and that makes more sense now.

JPG

GrimmSpector
February 27th, 2016, 07:56
Thanks, I imagine if you haven't played with the system it wouldn't make much sense, it's not like other systems in almost any way honestly, since its by Catalyst it does share a bit with SR, but not enough to be much help.