View Full Version : Hoping to avoid lots of duplication
GMBazUK
June 29th, 2011, 13:53
Im not sure this is entirely possible...
I'm in the process of ressurrecting my Harnmaster ruleset, and I'm currently working to improve the armour section.
What I'm trying to do is create a standard set of headings and associated numberfields, that I can reuse over and over for different armour location entries.
I want to create a windowlist for each body location (skull, forearm, thigh etc) which calls on a standard windowclass that contains the definitions for the headings and numberfields.
The individual windowlists will then store the data (datasource) for their respective locations.
I have anchored the windowlist to body locations (stringfield) heading (skull, eye, forearm, thigh etc)
Unfortunately I cannot get it to work.
Here's my code
(located in Charsheet_combat):
<stringcontrol name="skulllabel">
<anchored>
<to>armlabel</to>
<position>belowleft</position>
<offset>0,5</offset>
<size>
<width>50</width>
<height>45</height>
</size>
</anchored>
<font>sheetlabelsmall</font>
<static>Skull</static>
</stringcontrol>
<windowlist name="skullprot">
<anchored>
<to>skulllabel</to>
<position>right</position>
</anchored>
<class>charsheet_armourwindow</class>
<datasource>.armourskull</datasource>
<allowdelete />
</windowlist>
<stringcontrol name="eyeslabel">
<anchored>
<to>skulllabel</to>
<position>belowleft</position>
<offset>0,30</offset>
<size>
<width>50</width>
<height>20</height>
</size>
</anchored>
<font>sheetlabelsmall</font>
<static>Eyes</static>
</stringcontrol>
<windowlist name="eyesprot">
<anchored>
<to>eyeslabel</to>
<position>righthigh</position>
</anchored>
<class>charsheet_armourwindow</class>
<datasource>.armoureyes</datasource>
<allowcreate />
<allowdelete />
<skipempty/>
</windowlist>
(Located in Charsheet_listclasses). Please note, I have used templates to avoid duplicate formatting:
<windowclass name="charsheet_armourwindow">
<sizelimits>
<maximum>
<height>45</height>
</maximum>
<minimum>
<height>45</height>
</minimum>
</sizelimits>
<sheetdata>
<armourvalue name="blade">
<anchored>
<position>insidetopleft</position>
<offset>5,5</offset>
</anchored>
</armourvalue>
<armourvalue name="edge">
<anchored>
<to>blade</to>
</anchored>
</armourvalue>
<armourvalue name="point">
<anchored>
<to>edge</to>
</anchored>
</armourvalue>
<armourvalue name="fire">
<anchored>
<to>point</to>
</anchored>
</armourvalue>
<armourvalue name="squeeze">
<anchored>
<to>fire</to>
</anchored>
</armourvalue>
<armourvalue name="talon">
<anchored>
<to>squeeze</to>
</anchored>
</armourvalue>
<armourhead name="b">
<anchored>
<to>blade</to>
</anchored>
<static>B</static>
</armourhead>
<armourhead name="e">
<anchored>
<to>edge</to>
</anchored>
<static>E</static>
</armourhead>
<armourhead name="p">
<anchored>
<to>point</to>
</anchored>
<static>P</static>
</armourhead>
<armourhead name="f">
<anchored>
<to>fire</to>
</anchored>
<static>F</static>
</armourhead>
<armourhead name="s">
<anchored>
<to>squeeze</to>
</anchored>
<static>S</static>
</armourhead>
<armourhead name="t">
<anchored>
<to>talon</to>
</anchored>
<static>T</static>
</armourhead>
</sheetdata>
</windowclass>
Thank you in advance
Baz.
Zeus
June 29th, 2011, 16:43
When you say it doesn't work, could you be a bit more descriptive with what you do see or better yet, attach a screenshot. That would help us to helping you discover the root problem.
Having said that, one quick thing I did spot that maybe causing a problem is that you are not setting the size of the windowlist controls.
e.g. the windowlist skullprot is anchored to the right of the stringcontrol skulllabel but you don't specify a size.
I suspect FGII will render the windowlists invisible as FGII won't understand the bounds the control needs to fit to.
Moon Wizard
June 29th, 2011, 16:48
Also, try opening the console and watching for warnings about layout. Type /console in the chat entry box before you open the character sheet.
Cheers,
JPG
GMBazUK
June 29th, 2011, 19:02
Thank you for your prompt responses guys.
What I'm seeing in the Combat sheet is:
Skull
Eye
What I had hoped to see was:
........B E P F S T
Skull 0 0 0 0 0 0
......B E P F S T
Eye 0 0 0 0 0 0
(please ignore the dots, tab doesn't work; the zeros would be underlined due to the frame type)
I added a <width> to the windowlist definition, but still nothing.
I've checked my console and I have no reported errors.:confused:
Do I need to add something like <skipempty/> or some script to give the zeros a value onInit()?
Baz.
Zeus
June 29th, 2011, 21:12
OK, try something like this:
<windowlist name="skullprot">
<anchored>
<to>skulllabel</to>
<position>right</position>
<offset>10,0</offset>
<size>
<width>65</width> -- sets the width of the windowlist cntrl
<height>15</height> -- sets the height of the windowlist cntrl
</size>
</anchored>
<class>charsheet_armourwindow</class>
<datasource>.armourskull</datasource>
<allowdelete />
<columns> -- specifies column based list output
<width>10</width> -- specifies width of each column
<fillwidth /> -- entries are created left to right and then down
</columns>
</windowlist>
You will need to also create the label controls for the windowlist entry fields e.g. B E P F S T
GMBazUK
June 30th, 2011, 09:19
Thanks Doc for taking the time to write some additional code.
I tried it, but to no avail. In fact Fantasy Grounds crashed. I'm guessing but it was probably due to the Test version I'm running, and an incompatibility with the tags(?)
Just to clarify one thing, I am correct in thinking that the windowlist should be visible by default, and it's OK to position it to the right of the Skulllabel rather than over it?
I'm going to play around with it a bit more. I was able to get it partially working (for skullprot, but not eyeprot at the same time) when I included <allowdelete> <allowcreate>, but I was rather hoping to have it automatically appear.
Thanks again ,
Baz.
OK, partial success. I can get the windowlist to appear on the charactersheet, but only with <allowcreate>, and the use of the radial menu. Is there a way to have it appear automatically?
Baz.
Zeus
June 30th, 2011, 16:49
Thanks Doc for taking the time to write some additional code.
I tried it, but to no avail. In fact Fantasy Grounds crashed. I'm guessing but it was probably due to the Test version I'm running, and an incompatibility with the tags(?)
Hmm, the code I provided should not have caused a crash. Not sure what's happened there. All the additional tags I provided do, is define that size of the windowlist control as well as set the list output to column based.
Having said that, I now realise (from re-reviewing your code) you don't want the column based output as you only seem to have one entry per list and the entry has six values. You can therefore remove the <column> tag and its children.
e.g.
<windowlist name="skullprot">
<anchored>
<to>skulllabel</to>
<position>right</position>
<offset>10,0</offset>
<size>
<width>65</width> -- sets the width of the windowlist cntrl
<height>15</height> -- sets the height of the windowlist cntrl
</size>
</anchored>
<class>charsheet_armourwindow</class>
<datasource>.armourskull</datasource>
</windowlist>
Just to clarify one thing, I am correct in thinking that the windowlist should be visible by default, and it's OK to position it to the right of the Skulllabel rather than over it?
As your windowlist control is frameless, unless you create an entry, it will appear invisible. And yes, its OK to position it to the right, I would avoid positioning it over any other control as this will render the control underneath inaccessible and hidden.
I'm going to play around with it a bit more. I was able to get it partially working (for skullprot, but not eyeprot at the same time) when I included <allowdelete> <allowcreate>, but I was rather hoping to have it automatically appear.
To ensure a minimum of one entry exists when the window is opened. Add the following LUA script to the windowlist. To do this either add a <script> block to the windowlist windowclass definitions or create a LUA script file in the scripts folder of the ruleset and reference it from each windowlist windowclass definition using the notation <script file="scripts/nameofyourscriptfile.lua" />
function onInit()
if not getNextWindow(nil) then -- check to see if the list is empty, if yes
createWindow(self); -- create one entry
end
end
OK, partial success. I can get the windowlist to appear on the charactersheet, but only with <allowcreate>, and the use of the radial menu. Is there a way to have it appear automatically?
Baz.
Yes, see onInit() code example above. Depending upon the functionality you want, I would add the code above to create the default entry in the windowlist and remove the <allowcreate />, <allowdelete> tags unless you want players to be able to delete, add entries themselves. If the ruleset your using requires the one default entry its probably a good idea not to give the players create/delete functionality.
GMBazUK
June 30th, 2011, 18:37
Thanks again Doc for taking the time to compose a comprehensive reply.
I like the sound of the referenced LUA script, as I've got a bit of a penchant for templates at the moment.
I've always been impressed by how complex the structure of the ruleset files appeared (as a non-programmer) but now I'm beginning to understand them, I can see the inherent benefits of templates and referencing.
As your windowlist control is frameless, unless you create an entry, it will appear invisible.
If I were to add a <frame> definition to my windowlist, could I avoid the LUA script? I'm not sure what frame type I would use?
Baz
Zeus
June 30th, 2011, 20:34
Thanks again Doc for taking the time to compose a comprehensive reply.
I like the sound of the referenced LUA script, as I've got a bit of a penchant for templates at the moment.
I've always been impressed by how complex the structure of the ruleset files appeared (as a non-programmer) but now I'm beginning to understand them, I can see the inherent benefits of templates and referencing.
If I were to add a <frame> definition to my windowlist, could I avoid the LUA script? I'm not sure what frame type I would use?
Baz
No, but a frame (like a simple border around the edge of the control) would allow you to know the control is there and created. This is useful for controls that start life empty or where no value is displayed e.g. a numbercontrol with the <hideonvalue> tag set to 0.
Take a look in the 4E ruleset in the file graphics_frames.xml and look for the sheetgroup frame definition and associated graphic for an example of a soft shadowed border.
However if you don't want a frame, you obviously don't have to have one. Using the LUA script to create a default entry will still enable players to know the fields are there.
GMBazUK
July 1st, 2011, 07:48
Interesting.
I will check out the 4E ruleset later today.
Thanks again Doc
Baz.
GMBazUK
July 2nd, 2011, 10:38
OK, I'm beaten again.
First off, I'm using the windowlist function (and its associated windowclass definitions as I have alot of different body locations, so I want to use the same windowclass definitions over and over again, but called from different windowlists (Skull, arm, leg... etc)
With reference to my two windowlists, Skullentry and Skulltot the following database has been generated:
<charsheet>
<id-00006>
<armeyestot>
</armeyestot>
<armskullentry idcounter="3">
<id-00001>
<blade type="number">2</blade>
<edge type="number">0</edge>
<fire type="number">0</fire>
<point type="number">0</point>
<quality type="number">0</quality>
<size type="number">0</size>
<squeeze type="number">0</squeeze>
<talon type="number">0</talon>
<weight type="number">0</weight>
</id-00001>
<id-00002>
<blade type="number">2</blade>
<edge type="number">0</edge>
<fire type="number">0</fire>
<point type="number">0</point>
<quality type="number">0</quality>
<size type="number">0</size>
<squeeze type="number">0</squeeze>
<talon type="number">0</talon>
<weight type="number">0</weight>
</id-00002>
</armskullentry>
<armskulltot idcounter="2">
<id-00001>
<bladetot type="number">0</bladetot>
<edgetot type="number">0</edgetot>
<firetot type="number">0</firetot>
<pointtot type="number">0</pointtot>
<squeezetot type="number">0</squeezetot>
<talontot type="number">0</talontot>
</id-00001>
</armskulltot>
Whilst skullentry may have numerous ids due to numerous entries, skulltot will always, only have one id, as it will hold the total values for each of the skullentry tags (blade, edge, etc)
So the script I'm trying to use is:
<windowlist name="skullentry">
<bounds>200,45,285,40</bounds>
<class>charsheet_armourentry</class>
<datasource>.armskullentry</datasource>
<script>
function updatearmskulltot()
local bladeamnt;
local bladeentries = 0;
for i, w in ipairs(getWindows())do
bladeamnt = w.blade.getValue();
bladeentries = bladeentries + bladeamnt
end
if window.bladetot then
window.bladetot.setValue(bladeentries)
Debug.chat(bladetotal)
end
end
function onInit()
updatearmskulltot();
end
</script>-->
I think I know why its not working, because the armsskulltot (being a windowlist) has an id-00001, even though it will always only have one id. I'm afraid I dont know how to access the bladetot value for id-00001; my database navigation know how, runs out at this point.
I have a nasty feeling (for me at least) I might have to iterate through the armsskulltot windows (for i, w in ipairs(getWindow(armskulltot))), but I'm hoping with there being only one id I might be able to use getChild or something similar.
Baz.
Sorcerer
July 2nd, 2011, 11:26
if you are sure you will never have more than this one entry in the list, then you can treat the id-00001 tag as a child name since it will be fixed.
so for example it would be possible to use getChild("armskulltot.id-00001.bladetot").getValue()
GMBazUK
July 2nd, 2011, 14:07
Thank you once again, Sorcerer for helping me out.
If I could ask for a little clarification?
So would I set up a local variable to store the value of bladetot (lets call it bladetotal), and then change it to the sum total of all the blade entry values (bladeentries), with...
bladetotal.setValue = bladeentries;
Heres a modified script I tried:
<script>
function updatearmskulltot()
local bladeamnt;
local bladeentries = 0;
local bladetotal = window.getDatabaseNode().getChild("armskulltot.id-00001.bladetot").getValue();
for i, w in ipairs(getWindows())do
bladeamnt = w.blade.getValue();
bladeentries = bladeentries + bladeamnt
bladetotal.setValue = bladeentries;
end
end
function onInit()
local bladetotalnode = window.getDatabaseNode().getChild("armskulltot.id-00001.bladetot");
if bladetotalnode then
bladetotalnode.onUpdate = recalc
updatearmskulltot();
end
end
</script>
Heres the console error:
Script Error: [string "charsheet_combat:armskullentry"]:1: attempting to set a nil value as a handler function
Baz.
Sorcerer
July 2nd, 2011, 14:35
There are several problems here.
The first is the error message.
you have set up a handle function
bladetotalnode.onUpdate = recalc
basically when the bladetotal node updates, FG should recalc.
what the message is telling you is that recalc does not exist, or is not defined within this script block.
presumably this should read.
bladetotalnode.onUpdate = updatearmskulltot
second thing is bladetotal.setValue, you are missing the brackets.
bladetotal.setValue().
However the problem here is bladetotal has already been set with a getValue() at the end so if you wrote that in full it would be
window.getDatabaseNode().getChild("armskulltot.id-00001.bladetot").getValue().setValue();
which is not valid. Since you don't appear to need to getValue() I would knock that off the end to leave it as
local bladetotal = window.getDatabaseNode().getChild("armskulltot.id-00001.bladetot")
anyway try that and see how it goes
GMBazUK
July 3rd, 2011, 13:18
Firstly an update as to Doctor Zeus's advice; I added the script file you wrote for me, to my scripts folder (empty_windowlist.lua) and referenced it with the <script file="scripts/empty_windowlist.lua" /> in my windowlist.
At first I got an error... Invalid datasource parameter to createWindow. After some thought (more luck than judgement) I decided to change the "self" reference to "super" and bingo! It now works like a charm. Obviously I have a much better idea as to the structure of my ruleset than you so thank you Doc, another great piece of code for future use.
With regard to my current issue;
Thanks Sorcerer for the feedback. I modified my script as follow:
<windowlist name="armskullentry">
<bounds>200,45,285,40</bounds>
<class>charsheet_armourentry</class>
<datasource>.armskullentry</datasource>
<script>
function updatearmskulltot()
local bladeamnt;
local bladeentries = 0;
local bladetotal = window.getDatabaseNode().getChild("armskulltot.id-00001.bladetot");
for i, w in ipairs(getWindows())do
bladeamnt = w.blade.getValue();
bladeentries = bladeentries + bladeamnt
bladetotal.setValue() = bladeentries;
end
end
function onInit()
local bladetotalnode = window.getDatabaseNode().getChild("armskulltot.id-00001.bladetot");
if bladetotalnode then
bladetotalnode.onUpdate = updatearmskulltot;
end
end
</script>
...and the following error popped up:
Runtime Notice: Reloading ruleset
Script Error: [string "charsheet_combat:armskullentry"]:1: unexpected symbol near '='
Script Error: [string "armskullentry"]:1: unexpected symbol near '='
...so I modified it to:
<windowlist name="armskullentry">
<bounds>200,45,285,40</bounds>
<class>charsheet_armourentry</class>
<datasource>.armskullentry</datasource>
<script>
function updatearmskulltot()
local bladeamnt;
local bladeentries = 0;
local bladetotal = window.getDatabaseNode().getChild("armskulltot.id-00001.bladetot");
for i, w in ipairs(getWindows())do
bladeamnt = w.blade.getValue();
bladeentries = bladeentries + bladeamnt
bladetotal.setValue(bladeentries);
end
end
function onInit()
local bladetotalnode = window.getDatabaseNode().getChild("armskulltot.id-00001.bladetot");
if bladetotalnode then
bladetotalnode.onUpdate = updatearmskulltot;
end
end
</script>
...but alas the values are still not totalling. No console errors though, so not all bad.
Baz.
Moon Wizard
July 10th, 2011, 09:27
You should try using the Debug extension, and insert Debug.chat statements into your code to see which code is running and what values are getting calculated. This will allow you to narrow in on the specific piece of code that is not working as you expect.
Remember, you will have to install the Debug extension, and enable it for your test campaign. Otherwise, you will get LUA errors when the Debug.chat functions are called.
Example:
function updatearmskulltot()
Debug.chat("UPDATE AS TOTAL");
local bladeamnt;
local bladeentries = 0;
local bladetotal = window.getDatabaseNode().getChild("armskulltot.id-00001.bladetot");
Debug.chat("UPDATE AS TOTAL 2", bladetotal);
for i, w in ipairs(getWindows())do
bladeamnt = w.blade.getValue();
bladeentries = bladeentries + bladeamnt;
bladetotal.setValue() = bladeentries;
Debug.chat("UPDATE AS TOTAL LOOP", bladeamnt, bladeentries, bladetotal.getValue());
end
end
function onInit()
Debug.chat("BLADE TOTAL INIT");
local bladetotalnode = window.getDatabaseNode().getChild("armskulltot.id-00001.bladetot");
Debug.chat("BLADE TOTAL INIT 2", bladetotalnode);
if bladetotalnode then
bladetotalnode.onUpdate = updatearmskulltot;
end
end
Regards,
JPG
GMBazUK
July 10th, 2011, 11:30
Thanks Moon Wizard for the advice.
Since your earlier post (on Debug), I have been using Print and Debug, to evaluate whether parts of the code are actually working. I know that the data retrieved (ipairs) is working, but when I tried to check whether window.getDatabaseNode().getChild("armskulltot.id-00001.bladetot"); was the correct location, I got nothing.
I'm still figuring out how and where to implement Debug and Print so this post, will shed new light.
Thanks again.
Baz.
Powered by vBulletin® Version 4.2.1 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.