PDA

View Full Version : 1st post with some questions...



Psysquig
June 12th, 2009, 20:48
Hey everyone. This software is absolutly great and im trying to modify it to suit my home system (with success so far) but now im trying to link up stats in the boxes...

Could some kind soul give me a guide to performing basic math functions with the variables in the xmls?

Example of what im trying to acheive...

I have an ability score (eg, weapon skill) and an ability bonus (eg, weapon skill bonus) that is derived from weaponskill / 10 and rounded to the lowest whole number... eg, weaponskill of 38 gives a weapon skill bonus of 3

I have my two variables - abilities.weaponskill.score & abilities.weaponskill.bonus but have no idea on how to use maths on the first and modify the second with the result.

Ive tried looking at the setvalue() bits but I just got very confused.

Once I get pointed in the right direction im sure ill be ok to work out the rest from there...

Thanks in advance, Really enjoying moding!!!

Psysquig.

Foen
June 13th, 2009, 09:05
Welcome to the forums, and I hope you find us helpful and friendy!

The lua code to divide by ten and round down is math.floor(x/10) and the code snippet is something like:


local score = <path>.score.getValue();
local bonus = math.floor(score/10);
<path>.bonus.setValue(bonus);

The <path> bit would need to change to reflect the context where the code is sited and the names of the controls used to hold the score and the bonus. You may also want to prevent manual editing of the bonus, and to recalculated the bonus whenever the underlying score changes (using the onValueChanged event, or something similar).

To be of much more help, you'd need to post some extracts from your windowclass definitions, but I hope this points you in the right direction.

Foen

Psysquig
June 13th, 2009, 09:51
Thanks Foen,

I think I need to have a more in depth read of the library stuff and really try to take it in. I never did like C type programming being a BASIC person all my life..
I can think programming but the whole function() thing where you pass back info is just strange to me...

Really gonna perservier though cus from what I can tell this software is pretty unique and it ROCKS!

Foen
June 13th, 2009, 09:58
No problem, hope you get really hooked!

Lua isn't that different to Basic, really (probably closer to VBScript though), and is certainly less terse than C. One thing to watch out for is the fact that functions can return more than one result - it certainly took me a bit by surprise when I first came across it.

Foen

Psysquig
June 13th, 2009, 13:58
I think im missing a really basic grasp of how this works...

Looking in the library at the setvalue function I'm not sure how it works.

\\\\\\\\\\\\\\\\\\

setValue

function setValue( value )

Sets the value of the number in the control.

Parameters
value (number)
The value to set the control to

\\\\\\\\\\\\\\\\\\

This is all well and good but how do you specify which control you want to alter?? eg if I want to set the value of variable X can I type something like.

setvalue (x,10) to set the value of X to the integer 10?

I cant really get to grips with the parsing of these type of command..

Do any BASIC commands work?
eg. Can I do something like ..

getvalue (X)
If X=10 setvalue (Y,5)
if X>10 setvalue (y,15)

If I can how do I go about formatting it? Do I need to make it a function or something?

Sorry if i'm appearing very very dumb,
Psysquig.

Bidmaron
June 13th, 2009, 14:12
You need to go to the library and read the ruleset documentation (https://www.fantasygrounds.com/modguide/) and the ruleset reference (https://www.fantasygrounds.com/refdoc/). I don't want to discourage you, but this is non-trivial to launch into. FG2 is powerful, but it can't read your mind. The best way to learn is to go to the FG wiki site here (https://oberoten.dyndns.org/fgwiki) and study how other people implemented their changes. If you have specific questions about doing things, post your code here and people will be glad to help. As for learning basic programming, study the Lua guides mentioned in the documentation above. I doubt whether anyone here is going to have the time to teach you basic programming.

Psysquig
June 13th, 2009, 14:23
Thanks Bidmaron,

Pointing me in that direction should be all I need.

Fingers Crossed..

Foen
June 13th, 2009, 14:24
The language uses a dot notation, like VB, applying the function to the control, so X.setValue(10) calls setValue on object X. It is important to remember that the ruleset environment is case-sensitive, so setvalue isn't the same as setValue and X isn't the same as x.

Hope that helps,

Foen

Foen
June 13th, 2009, 14:26
For your conditional statements, you can use:


if X==10 then
Y.setValue(5)
end

or

if X==10 then Y.setValue(5) end;


Foen

Psysquig
June 13th, 2009, 15:06
Foen!!!

Thats exactly what I needed explained.... Thank you.
Reading up on all the Lua commands now .. .. can they all be used within FG?

Psysquig.

Foen
June 13th, 2009, 15:24
Most of Lua 5.1 is in FG, but it is heavily 'sand boxed' to prevent rogue scripts causing harm to the user's computer, so most of the operating system access calls etc are disabled. The language itself is pretty much as the Lua 5.1 reference manual.

You might also want to take a peek at the tutorial I started here:

https://wiki.witheredlands.co.uk/anatomy.ashx

Unfortunately it doesn't look like I'm going to finish it, but there is enough there for you to get your teeth into.

Foen

Psysquig
June 13th, 2009, 19:32
Foen, Ur a godsend!! Read through (and tried to understand) your docs. Great reference..

Im just gettting stuck on this..

---------------------------

<abilityscore name="test" source="abilities.test.score">
<anchored>
<to>abilityframe</to>
<position>insidetopleft</position>
<offset>105,283</offset>
</anchored>
</abilityscore>

<abilityscore name="testBonus" source="abilities.test.bonus">
<anchored>
<to>test</to>
</anchored>
<readonly/>

<script>
function recalc()
local bon = ("abilities.test.score").getValue();
local mod = 0;
if bon >= 10 then mod = 1;
end
setvalue(mod);
end
</script>

<script>
function onInit()
recalc();
end
</script>

</abilityscore>

--------------------------

Ok all im trying to do (to learn) is to have 2 'scores'

test & testbonus

when they are drawn (this is in the main char sheet) I would like the test to be user input (which it is fine) and once the value of test equals or exceeds 10 I would like testbonus to show 1.

At the moment when I open the char sheet I get a script error -

Script Error : [string "charsheet_main:testBonus]:1: attempt to call field 'getvalue'(a nil value)

Am I missing something really silly??? Once I can work out how to have one 'box' interact with another il be on my way to sussing this out!!

Thanks in advance (and sorry if im being dense)

Psysquig.

Foen
June 13th, 2009, 20:05
It is great to see another addict in action ;o)

Objects in windowclass definitions are referenced by their names, but relative to the current context.

Your script is running in the context of testBonus, but the target control sits in a different context:


windowclass
- test
- (test script context)
- test.getValue()
- testBonus
- (testBonus script context)
- testBonus.setValue()
- testBonus.recalc()

For the testBonus.recalc function to refer to the getValue() method of test it needs to step up out of the testBonus context to the windowclass level and then back down to test.

For controls, this is done by chaining through the "window" object (testBonus.window refers to the windowclass containing testBonus).

The structure from the context of testBonus looks like this:


window
- window.test
- window.test.getValue()
- self
- setValue()
- recalc()

The script then becomes somethng like:


function recalc()
local bon = window.test.getValue();
local mod = 0;
if bon >= 10 then
mod = 1;
end
setValue(mod);
end

This is not meant to be confusing, so i hope it makes some sense!

Stuart

Psysquig
June 13th, 2009, 20:16
Right, gonna try to get my head round that.. I will not let this beat me!!!

Thanks fer the help Foen ill prolly be back soon!


Psysquig

Psysquig
June 13th, 2009, 20:36
Ok, I think I understood what you said, its all about the 'paths'

I have changed the script to this

<script>
function recalc()
local bon = charsheet_main.test.getValue();
local mod = 0;
if bon >= 10 then
mod = 1;
end
setvalue(mod);
end
</script>

Looking at the file -- charsheet_main is the topmost windowclass so therefore if I understood to access the value of ability score test I need to reference charsheet_main.test.getvalue() ???

However this script gives me the error that its attempting to index global 'charsheet_main'(a nil value)

Why is it accessing charsheet_main and not charsheet_main.test ??

Presumably this is how the 'variables' are stored, in these paths related to the windowclasses here created in.

Thanks fer your help!!!

Psysquig

Foen
June 13th, 2009, 21:23
Pretty close, but unlike file paths there isn't an absolute 'root' reference, everything has to be relative to the current position.

You could try using the following:


<script>
function recalc()
local bon = window.test.getValue();
local mod = 0;
if bon &gt;= 10 then
mod = 1;
end
setValue(mod);
end
</script>

The "window" keyword refers to the windowclass containing this control (where the script is executing), and "test" is a subcontrol of that windowclass.

I have also amended your setvalue to setValue, because the FG model is case sensitive.

Finally, if you take a look here (https://www.fantasygrounds.com/modguide/scripting.xcp) under Using Scripts, script embedded in XML files has to conform to XML syntax and the > sign needs to be replaced with &gt;.

Foen

Psysquig
June 13th, 2009, 21:57
Foen .. Ur Frakin AWESOME!

I now have 2 score boxes and as I increase on (by player input) the other shows the current bonus (calculated by dividing by ten and rounding down)

That way a score of 44 carries a bonus of 4.

Exactly what I wanted!!!

Sooooo now the question is, based on the standard D20 character sheet (which im mod'ing as a basis) If I have a stat (say weaponskill) on the main sheet windowclass.charsheet_main can I link to them from the abilities sheet (seperate xml file). Do I just add more to the 'path' ??

For example if I wanted a total value on the abiliies page of say a bladeskill score and the weaponskill score from teh main sheet how do I address the mainsheet?

I think this software is great but the support through the forums is fantastic!

Psysquig

Foen
June 13th, 2009, 22:55
My previous posts talked about linking controls based on their context, but that can only work if the controls are both being rendered on a common windowclass. If you want to link to a different window, you have to abandon control-based linking and use database linking.

Any control which has persistent data writes that data to the global database file (db.xml) which sits in the host (GM) computer. You can usually tell which controls they are beacuse they ave a type of "...field" instead of "...control" (so numberfield instead of numbercontrol, for example).

To update a database value using a database value from a control in another window, you need to keep track of where its database storage path is (which is different to its control path). Now is a good time to introduce the debug console...

If you type /console at the chat prompt, a text window pops up (the same one used for reporting errors) and you can write stuff to it from your Lua script using the print() function, so print("Hello World") pretty much does what you'd expect.

Before going too much further with your linked data, you should print out the database paths of the source and target controls, so you can get an idea of how it all fits together.

Here is some sample script:


function test()
local node = mycontrol.getDatabaseNode();
if node then
print("mycontrol has database path "..node.getNodeName());
else
print("mycontrol isn't bound to the database");
end
end

You will see that database paths are closely related to the windowclass layout, so that the parent of a database node for a control is usually the database node for the control's window.

In Lua, you can use node.getParent() to navigate up one level from a database node to its containing parent, in a similar way to mycontrol.window. Now here is where it gets neat: different tabs on a character sheet *share* the same database node as each other. So the Name control on the Main tab is a direct child of the character sheet top-level database node, and the Notes control of the Notes tab is also a direct child of the character sheet top-level database node:


char sheet database node
- name (string) database node, on the Main tab
- notes (string) database node, on the Notes tab

Accessing database nodes isn't quite so easy as accessing controls, you need to specify the child node using getChild(<name>) rather than using just a dot notation. So if win is your main tab, you'd access the name control in one of two ways:


Using the control hierarchy:
print(win.name.getValue());

Using the database hierarchy:
local winnode = win.getDatabaseNode();
local namenode = winnode.getChild("name");
print(namenode.getValue());

or

print(win.getDatabaseNode().getChild("name").getValue());

While it is a more cumbersome mechanism, it allows you to access data from all over the char sheet database, without the controls being present on the current window.

Just one final point: although your character sheet may have a field for "name", the underlying database node won't be created until you enter some data, and so getChild() will return a nil value. To avoid this problem, either test for nil values *every* time you access a child node, or else force it to be created using createChild() instead of getChild():


local winnode = win.getDatabaseNode();
local namenode = winnode.createChild("name","string");
print(namenode.getValue());

You will see that createChild takes a second parameter which is the name of the type of the node you want to be created. If the node doesn't already exist, it is created and given a default value (zero for "number", "" for "string") and if it already exists the existing node is returned without being over-ridden.

Foen

Psysquig
June 14th, 2009, 09:27
Cheers Foen,

For some reason I can't wright in the console windows (it opens fine but will not let me type!)

I understand the general gist of what you said..
So from the default Charseet_main (the D20 one) this line is using the database?

Is the source pointing at the node?

<abilityscore name="strength" source="abilities.strength.score">

Psysquig.

Foen
June 14th, 2009, 09:45
The console is read-only, you put print() commands in your Lua script to output to the console, mainly for debugging purposes. The console only shows stuff written to it after it is opened, so you should open the console first. The full console text is also available in the FGII applicatio data directory as console.txt.

The source attribute in an FG control points to the database node, relative to the containing window. If you put print(getDatabaseNode().getNodeName()) in the onInit function for the ability, and have the console open before you open the character sheet, you will see the whole database node path name.

Stuart

Lithl
June 14th, 2009, 10:34
The console only shows stuff written to it after it is opened, so you should open the console first.
Heh, I learned this quick. It'll open itself if you get an error, but not if you just try to print stuff, or only get warnings :)

In my testing campaign that I'm using for my Exalted ruleset, I've got two shortcuts in trays 1 and 2: /reload ruleset, and /console :D

Then if I'm trying to read the console but I'm not getting errors, I can hit F2 to open it, and when I change my XML or Lua, I can hist F1 to reload it.

Foen
June 14th, 2009, 10:49
I have /save, /reload and /console.