PDA

View Full Version : Pathfinder Kingdom Builder extension WIP questions



ronalmb
November 29th, 2016, 19:15
Hello,

I am fumbling along on my Pathfinder Kingdom Builder extension. It's slow but progressing.

My buttons now work (Thanks Trenloe, Damned) and I have figured out enough about how to add frames, controls, and labels to a windowclass to have a working sheet (it ain't pretty yet, but it has the data I need).

16694

When pressing the Kingdoms Button, the record list window for Kingdoms pops up, but I do not yet understand how to make it so i can access the "create item" radial to create records (See attached Image). I have tried looking at Spells, NPCs, and the like.. and I'm missing something (as usual).

16695

As I am still not grasping datasources, Im unable to get my kingdom sheet to "remember" its data. It will probably all fall into place at some point, but if someone can point me in the right direction and offer some guiding advice, I'd be very appreciative. I am not looking for someone to do the work for me!

As I continue to develope this extension, I will update this post with more questions and report on my progress.

Finally, how do i embed images directly into my post instead of having them appear as attachments?

Thank you for any assistance offered.

Moon Wizard
November 29th, 2016, 23:38
Kingdom List Create Item
If you're using the LibraryData package in CoreRPG to add the Kingdom button and list, make sure that there is no .sEditMode="none" variable in the "kingdom" record type table. This would make the list read-only.

If you're creating your own list window, then you'll need to make sure windowlist is not set to readonly and that the allowcreate flag is part of the windowlist XML definition.

Data sources
Every window you see on the screen requires 2 pieces of information: a data source and a window class. The data source tells FG what path to use to get and to save data in the database. If the data source is an empty string, then the window is considered "source-less", and is not linked to the database at all. The window class tells FG which window class definition to use to display the data.

The data source is just a series of tag names separated by periods, and the database is sort of like a tree of these nodes that branch from the top. I would guess that your default path for your kingdom record types might be "kingdom". So, an example of a record automatically created by the built-in window list control pointing at the "kingdom" path might look like "kingdom.id-00002". (This is an example of a path that would be used to open a window to a particular instance of a kingdom record.)

Linking to Data
In your scenario, you will either need to let the window list create the record (preferred); or you will need to find the kingdom data list path, create a child node, and open a window using the new child node and the kingdom detail window class (if you need to open outside the list environment).

Cheers,
JPG

ronalmb
November 30th, 2016, 04:00
My data_library_KM.lua I think draws on the 3.5 ruleset and used aRecords. When I press my kingdom button, it calls up the default records list window, I think as I have not created my own window list.

My aRecords for the Kingdom looks like this so sEditMode is a whoopsie. Deleting this line fixed things for me! Thank you.



aRecords = {
["kingdom"] = {
sEditMode = "none",
aDataMap = { "reference.kingdoms" },
aDisplayIcon = { "button_kingdoms", "button_kingdoms_down" },
sRecordDisplayClass = "referencekingdoms",
}
}


My windows class for the kingdom sheet is called "kingdomSheet".

Once I changed the sRecordDisplayClass to "kingdomSheet" (The error message i was getting led me to believe sRecordDisplayClass was looking for a window class... it worked! I now have the ability to make and save kingdom data. Which is simply awesome.

Thank you so very much for the lesson.. it made things very clear :)

16702

Is my aDataMap correct tho? The desire was for kingdom to be my default path.

Moon Wizard
November 30th, 2016, 04:29
You'll want your aRecords to look like this. Note: I removed the sEditMode, and added a base data path that matches the others (and allows for a read-only "reference" material path). Also, you might think about changing the sRecordsDisplayClass to something simpler, like "kingdom". (and the matching windowclass definition too)



aRecords = {
["kingdom"] = {
aDataMap = { "kingdom", "reference.kingdoms" },
aDisplayIcon = { "button_kingdoms", "button_kingdoms_down" },
sRecordDisplayClass = "referencekingdoms",
}
}


Cheers,
JPG

ronalmb
November 30th, 2016, 15:02
Kingdom Builder Extension: Part II

So I now have a functional, if ugly, tracker for kingdoms. I can add and delete kingdoms from the list and it remembers the information between uses of Fantasy Grounds. A great start!

For my next goal, I want to be able to track what settlements exist within a kingdom. A settlement is a set of attributes, a list of links to specific buildings present, a list of links to specific NPCs present and assorted other data. For the purpose of the kingdom sheet's settlement tab, all I need is to track a list of links (of class 'settlement') and display some data useful to the kingdom (such as each settlement's size, population, and modifiers to the kingdom's attributes).

The settlement tab consists of two frames... the top one will display the total sum of all settlement modifiers added together. These are what makes up the kingdom's "Attributes" (plus leadership and event modifiers.. but that's further down the road). The bottom one is my list. Looking through the resources available to me, it looks like I'll want to use the inventory list from the character sheet as inspiration.

16705

Side Note: Why does it instead create a link to an image instead of displaying an image when i add an image to my forum post?.

So, I know that I'll now need to use .lua scripting and that it will require more than just copy pasting from inventory and messing with numbers. But certain core things I think I grasp. I'll need to have events for when a link is dropped (update the kingdom's stats), when a link is removed (update the kingdom's stats).

Another question: I have a separate button and list for settlements. Settlements created can change as time progresses (buildings added, population changes, etc). If a settlement's attribute changes, is it possible to automate tracking down the kingdom it belongs to and updating its stats on the kingdom sheet to?

Moon Wizard
November 30th, 2016, 18:30
The question of settlements is very similar to inventory in characters, and you can probably use that as a starting point. Also, the encumbrance calculation will give you a good idea on how to add up all the settlement attributes for the kingdom.

I wouldn't add Settlements as a separate top-tier record type, just leave it as a list in the kingdom details and add there. You can always use edit/add/delete buttons to manage the settlement "inventory" of a kingdom, just like the inventory on a PC.

Regards,
JPG

ronalmb
December 1st, 2016, 12:59
Thanks as always. I feel like a broken record, but I do appreciate the direct assistance and helpful tidbits. If I ever forget my thanks, know I still mean it!

I want/desire to be able to track considerable amount of information about settlements as the game progresses... important NPCs present, what buildings have been built in the settlement, the settlement's own ratings, etc. If I go the route you suggested, can the settlement item (leading to its own sheet) also be tabbed and support multiple tab pages of information and links?

Added:

So, i have started working on the settlement inventory list and am having difficulty.
I have created a button_iedit named "settlementList_iedit" as follows:



<button_iedit name="settlementList_iedit">
<anchored to="settlementList" position="aboveright" offset="5,10" />
<target>settlementList</target>
</button_iedit>


It works fine. Button appears, i have it in right spot, etc. If I press on it, I get the following script error:



Script Error: [string "settlementList_iedit"]:1: attempt to call field 'update' (a nil value)


I'm not sure what to do here but I'm guessing its because I have no clue what I'm doing and it's looking for something I haven't taken into account.

It targets settlementList which I am imagining is a database node which I have failed to create, maybe? I didn't think it was targetting the same settlementList in the windowClass, but maybe it is.

So, the entry for that settlementList is exactly the same as <list_charinv> "inventorylist" from the CoreRPG inventory record. I have made my own template however, named <list_sInv> and used that instead. That looks like:



<template name="list_sInv">
<windowlist> <!--NEED TO MAKE A WINDOW CLASS for king_sItem-->
<datasource>.settlementlist</datasource>
<class>king_sItem</class>
<allowdelete />
<script file="/Scripts/king_sInvList.lua" />
</windowlist>
</template>


Despite the comment I left there, I did go ahead and then make a king_sItem class, which looks like this:


<windowclass name="king_sItem">
<margins control="0,0,0,2" />
<script>
function onInit()
onIDChanged();
getDatabaseNode().onDelete = onDelete;
end

function onIDChanged()
local bID = ItemManager.getIDState(getDatabaseNode(), true);
name.setVisible(bID);
nonid_name.setVisible(not bID);
end

function onDelete(node)
ItemManager.onSettlementRemoveEvent(node);
end
</script>
<sheetdata>
<hn name="isidentified">
<script>
function onValueChanged()
window.onIDChanged();
end
</script>
</hn>

<genericcontrol name="rightanchor">
<anchored width="0" height="0">
<top />
<right />
</anchored>
<invisible />
</genericcontrol>
<button_idelete name="idelete">
<anchored width="20" height="20">
<top offset="2" />
<right parent="rightanchor" anchor="left" relation="relative" offset="-5" />
</anchored>
</button_idelete>
<linkcontrol_id name="shortcut">
<anchored width="20" height="20">
<top offset="2" />
<right parent="rightanchor" anchor="left" relation="relative" offset="-2" />
</anchored>
<class>item</class>
<readonly />
</linkcontrol_id>

<string_charinvname name="name">
<anchored position="insidetopleft" offset="35,2" height="20">
<right parent="rightanchor" anchor="left" relation="current" offset="-5" />
</anchored>
<tabtarget next="nonid_name" prev="count" />
</string_charinvname>
<string_charinvname name="nonid_name">
<anchored position="insidetopleft" offset="35,2" height="20">
<right parent="rightanchor" anchor="left" relation="current" offset="-5" />
</anchored>
<empty textres="library_recordtype_empty_nonid_item" />
<invisible />
<tabtarget next="location" prev="name" />
</string_charinvname>
</sheetdata>
</windowclass>

king_sItem is mostly cut and paste directly from windowclass char_invitem, removing things like count, carried, weight that have to do with equipment inventory and nothing to do with settlements.
Hopefully this hasn't gone too far off reservation yet and muddled my Script Error question: I just want to provide as much data as I can.
Again, thanks to everyone who is offering help!

ADDED, PART II

I do have a king_sInvList.lua as well, it is copy/pasted directly from char_invlist.lua at the moment.

Swipht
December 1st, 2016, 19:53
I need this! Thank you for using your time to enrich the community.

ronalmb
December 1st, 2016, 20:20
If i get it figured out, I'll absolutely share it.
But it's a big IF.

I'm an artist. A gamemaster. A creative storyteller. But not really a programmer (even tho I try). I understand just enough of this to get me into trouble I can't get myself out of. :) But I'll do my best to stick with it. I've already gotten further than I thought I would!

Moon Wizard
December 1st, 2016, 23:39
When in doubt, try running a search for the template name you are using ("button_iedit") over the CoreRPG ruleset using a multi-file search tool (I use Notepad++).

You'll find that it runs a script function when pressed that calls an "update" button on the target control. The idea is that the list should implement an "update" function that will show/hide the delete buttons for each individual child window based on the value of the edit button.

Something like this inside your "/Scripts/king_sInvList.lua":


function update()
local bEditMode = (window[getName() .. "_iedit"].getValue() == 1);

for _,w in pairs(getWindows()) do
w.idelete.setVisibility(bEditMode);
end
end


Cheers,
JPG

ronalmb
December 2nd, 2016, 01:38
Hi, thanks again.
Yeah, I had done that. I copied from item's version of it in CoreRPG (I use Notepad++ to, love it) the following:



function update()
local bEditMode = (window.inventorylist_iedit.getValue() == 1);
window.idelete_header.setVisible(bEditMode);
for _,w in ipairs(getWindows()) do
w.idelete.setVisibility(bEditMode);
end
end


and was getting the error. I will try your version and see how it goes.

Follow-Up
That had no impact on the error. I am missing something else.. something probably pretty easy. I may need to scrap the settlement parts that i have (not the kingdom) and try to do it again.

In the CONSOLE, I see a ruleset warning of it having an issue loading script king-sInvList.lua -- Im willing to bet that it not loading is what is causing my update script error. king-sInvList.Lua is a direct copy/paste of char_invlist.lua ... would that cause some kind of conflict since a lot of that stuff already exists in char_invlist.lua?

Follow-Up's Follow-Up

Nope.. not a conflict from that.. it's something else. I took everything out of the king_sInvList.lua and it still could not load the script. Perplexing.

I'm pretty certain it's <script file="/Scripts/king_sInvList.lua" /> that is causing me the trouble. If i comment that out, the error goes away. So the way i am trying to point to the folder is wrong.

My folder structure is:
Kingmaker
XML (Where the file with that script call is)
Scripts (Where I want to point to)

So I need to go up one folder before then going into Scripts folder. I tried both "." and ".." before the /

i also tried getting rid of the / (knew that wouldnt work)...

Follow-up to my.. erm.. Follow-Up's Follow-Up

This is now solved... my script references needed to be just like they are in my xKingdomFiles.xml. That is, they need to be "Kingmaker/Scripts/king_sInvLis.lua" ... I blame DOS for my wanting to try and use . and .. ! :D

ronalmb
December 2nd, 2016, 03:07
Kingmaker Kingdom Builder extension, Part III

So I have progress. It isn't pretty, but there will be plenty of time for that later. The settlement tab now lets me add entries, and at least displays attribute boxes for a settlement's modifiers. It's cramped, and there isn't enough room for Population or settlement size (town, village, etc).. but there will be time for that later to.

16719

Next perplexing me is the "delete record" button on the settlement inventory list. When clicked, it pops an error "Attempt to call field "onSettlementRemoveEvent" (a nil value). I probably need to get in there and just change a reference to an Item to a settlement, like i did with the add button.. but it's late and will wait until tomorrow. --Note, it DOES delete the settlement.. but i do need to figure out what is calling that script error and fix it.

In addition to fixing the delete issue, next will be looking at how the Weight controls in Inventory accumulate for encumbrance and then copy that so i can get my kingdom modifiers totaled.

Fun stuff!

ronalmb
December 2nd, 2016, 22:21
Kingdom Building Extension: Good Progress Today

I made progress I'm happy with on my project today. I dug into the db.xml to inspect how my extension was saving stuff. It wasn't doing that very well. But I was able to use that to correct those issues before they got out of hand. I've temporarily commented out everything on the sheet accept for the attributes. I then figured out what to do make the kingdom attributes read-only. They'll be displaying the total values of all modifiers for a kingdom for settlements, buildings, npcs, events, and who knows what else.

On the Settlements tab, i figured out how to properly add and remove new settlements and have squashed all errors. Each settlement added displays its attribute modifiers (also read-only). I want a better display for each entry, so I will probably take a look at the combat tracker, as it is capable of displaying a lot of handy info.

When you click on the link for a new settlement, it pops up with the settlement window. The settlement window will have tabs for buildings you add, npcs that are present, as well as a tab for notes. I want to include a link there that leads to an appropriate image map as well, down the road. For now, I'm just happy that this all works without confusing data.

16724

Next up will be to work a bit on the buildings tab, so that i can add buildings. In the Pathfinder Kingdom Building rules, buildings are the primary way for a kingdom to improve its attributes. The buildings list works just like the settlement "inventory" list on the kingdom tab, so I don't forsee any problems there. Once that is done, i will need to look at the weight tracking on the character sheet inventory to learn how to accumulate data. That will be a major step!

Bidmaron
December 3rd, 2016, 04:31
Great job on this, ronalmb. Watching in rapt attention. We may want to have the settlement generate a location record eventually too.

ronalmb
December 3rd, 2016, 11:39
I had asked here: "Does Fantasy Grounds have anything like an Options style button collection? I.e. Having four buttons of which when you select one, it untoggles the others?" and I have found my answer. The answer to this is yes, and bottom of 3.5E NPC tab holds its secrets.

In Pathfinder, a settlement's alignment affects its attributes (for example, a Lawful Good settlement gains +1 Law and +1 Society). While its easy enough to just type an alignment in and then have GMs manually adjust a settlement as appropriate, i was thinking that if they could select the settlement's alignment from the available choices, the extension could make that change for them.

The settlement form is coming along. It's up to four tabs now (Main, Buildings, NPCs, and Notes) and a 5th for Locations is a likely candidate for being added. Only Main has content. You can track size, qualities, disadvantages, population, danger rating, base value, purchase value, spellcasting level, and even track the minor, medium, and major magic items in the settlement.

On the danger rating, a happy accident was adding a table link to accompany it. Each settlement you create has a random encounter table that accompanies it that you can fill out. If you are like me, you will probably have a lot of tables. This makes it a little easier to track - no need to hunt it down with the bazillions of others you'll have! Ideally, you will be able to click on the Danger button, it will roll on the table, adding the danger modifier to the roll. I don't know if that's possible, but it would be handy.

16733

For magic items, I am thinking of doing something similar -- a table for each category that you can add magic items to and then use to determine what's currently at the settlement. Is the settlement filled with highly skilled dwarven artisans but light on wizards? The table could reflect this with more chances for weapons or armor than ioun stones and librams, for example. It'd be really nice if you could click a button and it would automatically populate a list-window with magic items from the table... but I am getting WAY ahead of myself here.

The settlements sheet as it currently stands. It will be changing when i add the control tab, which will contain choices you can select for the settlement, including government type and alignment. These will impact the settlement's attributes, which will then impact the kingdom's.

16734

ronalmb
December 3rd, 2016, 13:49
Is buttongroup_radio only horizontal? Is there support for vertical radio columns?

ronalmb
December 3rd, 2016, 22:40
What I mean by only horizontal is currently if i use a radio_record, it will look like this:

16748

It goes horizontally across. But I'd like to have one that displays vertically up and down instead. Is this possible?

damned
December 3rd, 2016, 23:29
Post the xml for that record please?

ronalmb
December 3rd, 2016, 23:50
Here is the xml for radio_record_alignment:


<template name="radio_record_alignment">
<buttongroup_radio>
<anchored to="fControlAlignment" height="20">
<top offset="20" />
<left anchor="center" offset="-180" />
</anchored>
<parameters>
<optionwidth>40</optionwidth>
<labelsres>LGa|LNa|LEa|NGa|Na|NEa|CGa|CNa|CEa</labelsres>
<values>LG|LN|LE|NG|N|NE|CG|CN|CE</values>
</parameters>
<gmeditonly/>
<script>
function onValueChanged()
window.changeAlignment();
end;
</script>
</buttongroup_radio>
</template>


Additional Question
Is there a way to check to see if a Node exists? Im sure it's something simple like "if !BlahBlah" but I have no idea what the correct method is for .lua

damned
December 4th, 2016, 00:04
Im thinking there is not a simple way to change this - you probably need a copy of this script common/scripts/buttongroup_radio.lua and need to see if you can rework it for vertical instead and create a new buttongroup_radio_vert template.

ronalmb
December 4th, 2016, 00:14
I was afraid of that. I'll put it on my todo list.

I've a bigger issue and I'm not sure I know how to describe it but i'll try:

1. I have a button on kingdom sheet creates a new settlement.
2. I need to populate the new settlement node with information when it is first created.
3. I tried using onInit(), but that was clearly wrong as it overwrites existing settlements with "new settlement information".
4. I thought maybe I could use onInit() to check to see if the data already exists and if it does, do nothing. But I don't know how to do that.

Am I making any sense? It's preventing me from progressing.

damned
December 4th, 2016, 00:22
You can set Default values for fields on creation... could that work for you? As a super basic example look at the Attributes in any version of D&D and they have a default value of 10.

ronalmb
December 4th, 2016, 00:24
Will this work with string_labeled as well? I have defaults for my numerical values... but couldn't find an example for string_labeled. That's the control that I'm choking on at the moment.

I'll give it a try.

Update: That would be a yes. <default> works in string_labeled to. Thanks!

damned
December 4th, 2016, 00:38
Will this work with string_labeled as well? I have defaults for my numerical values... but couldn't find an example for string_labeled. That's the control that I'm choking on at the moment.

I'll give it a try.

Update: That would be a yes. <default> works in string_labeled to. Thanks!

I do a fair bit of this in MoreCore.

ronalmb
December 4th, 2016, 00:44
I will make a point of checking it out. Thank you :) I'm pretty happy with my progression in learning so far. I've spent like a bazillion hours the last couple of days banging my head on this stuff, trying different things. I'm slow at it.. but persistent. Thankfully I have a lot of free time now.

damned
December 4th, 2016, 01:45
From where Im sitting you are making great progress and in good time too. You are learning this stuff much faster than I did.
Maybe a StringCycler might be a good option instead of Radio Buttons.

Nickademus
December 4th, 2016, 02:18
Im thinking there is not a simple way to change this - you probably need a copy of this script common/scripts/buttongroup_radio.lua and need to see if you can rework it for vertical instead and create a new buttongroup_radio_vert template.


I've a bigger issue and I'm not sure I know how to describe it but i'll try:

Not able to test this at the moment, but in common/scripts/buttongroup_radio.lua, on line 159, if you change
boxwidgets[k].setPosition("topleft", ((k-1)*option_width)+10, h/2); ... to ...
boxwidgets[k].setPosition("bottomleft", w/2, (k-1)+10);... it might be vertical.

ronalmb
December 4th, 2016, 10:40
Nickademus, Thank you. Unfortunately, that did not seem to display anything. I also made sure to change the code to display the label a few lines above that one was similarily altered (with an additional +10 to the 'y'). I ran a Debug.console in there to ensure it was being called. It just refused to cooperate for me. Not sure why.

ronalmb
December 4th, 2016, 14:29
Day 5: So Very Confused Now

Day 5.. Getting Desperate. The Food is gone. The expedition has hit upon hard times. Several porters have vanished and my guide has gotten fatter. I'm not...

Oh, ahem. Not on safari. I'm programming. Still desperate tho.

I thought I understood enough about data, nodes, and calls.. but I'm frankly very confused on something probably scope-related (?). I'll try to explain and hopefully someone will understand.

So, I create a new kingdom. I add a settlement. Currently, the information just seems to exist on the forms until a set amount of time has passed and the campaign is saved. I can confirm this by creating the settlement and then looking at the campaign database before it has done a save.

16757

I have default information when a settlement is created and the settlement's attributes are determined by modifiers based on size, government, and alignment. But these totals are not being calculated properly because until the campaign auto-saves, the data does not exist and DB.getValues can't seem to find the information it seeks.

Example using picture attached above.
A new settlement defaults to LG. It should have Law+1 and Society+1, but when the settlement is created, those attributes are zero. If i go to the Control tab, toggle the Alignment from LG to LN, and then toggle it back to LG, it now displays Law and Society properly.

I tried creating a function that gets called from onInit() when the new Settlement window pops up that does this, but well.. since it's onInit, it overwrites actual data.. so that's not an option.

I tried setting <default> values on my various buttons and labels and it displays the information correctly, but this info is not added to the database until the campaign saves (either from auto or from exiting out of the campaign and reloading it). It only exists in memory until then.

At any rate, I'm thoroughly unsure as to where to go from here. I suppose i could leave the form completely blank until the user goes to the control tab and adjusts the settings.. but even then, if they happened to want the default LG (since it appears first in the alignment radio), they'll have to select a different alignment and then go back to LG) before it calculates it.

Does any of this make sense? It doesn't to me and I wrote it. Thanks for any help!

Moon Wizard
December 4th, 2016, 18:10
FG auto-saves the database files every 5 minutes, but you can force a manual save using the /save chat command.

If you create a new settlement, but do not immediately open the settlement detail window, then default values are not going to work for you. Because, these values do not get created until the detail window is opened, or until you explicitly create in the mini version in the kingdom window, or you explicitly create in Lua. Also, the onInit function gets called every time, and the controls are initialized before the onInit function; so you can't use that spot to set default values.

In this case, I would override the Create Item and add buttons to have your own addEntry function in the settlement list. This isn't a built-in function, but something commonly used by templates in CoreRPG. Once you have that function, you can perform some writes of default values using DB.setValue after the record is created.

Regards,
JPG

Nickademus
December 4th, 2016, 18:39
Nickademus, Thank you. Unfortunately, that did not seem to display anything. I also made sure to change the code to display the label a few lines above that one was similarily altered (with an additional +10 to the 'y'). I ran a Debug.console in there to ensure it was being called. It just refused to cooperate for me. Not sure why.

I'm having this problem too. Something to do with the anchor; some controls just fail to be displayed. I haven't figured out why yet.

ronalmb
December 4th, 2016, 19:23
Day 5: Have managed to escape the crazy guide. He was eating my porters! I'm still lost in uncharted territory but things are looking better. Now if I could only do something about that nagging spider bite...."

I have had some success. I made a work around for my data problem. I don't know if it's the right way or the most efficient way to do it, but it works. Until something else breaks it, of course.

What I did was create a NewSettlement.lua that is called when the settlement sheet is first open. In the onInit() I created a test variable to check to see if its a brand new settlement or if the user is opening an already existing settlement. It looks like this:

NewSettlement.lua



local isNEW = DB.getValue(self.getDatabaseNode(), "exists", "");

if isNEW == "" then
--Brand new entry lets set some defaults!
nMe = self.getDatabaseNode();
--######################
--## Initializations ##
--######################
DB.setValue(nMe,"size.attr_mod","number",-4);
DB.setValue(nMe,"size.quality_mod","number",1);
DB.setValue(nMe,"size.danger_mod","number",-10);
DB.setValue(nMe,"size.baseValue_mod","number",50);
DB.setValue(nMe,"size.purchaseLimit_mod","number",500);
DB.setValue(nMe,"spellcasting.base","number",1);
DB.setValue(nMe,"attributes.corruption.alignment","number",0);
DB.setValue(nMe,"attributes.crime.alignment","number",0);
DB.setValue(nMe,"attributes.productivity.alignment","number",0);
DB.setValue(nMe,"attributes.lore.alignment","number",0);
DB.setValue(nMe,"attributes.law.alignment","number",1);
DB.setValue(nMe,"attributes.society.alignment","number",1);
TotalAttributes();
DB.setValue(self.getDatabaseNode(),"exists","string","Exists");
end


Provided that isNew is empty (which it will be if its a brand new entry), it inserts those values into the settlement's db entry so that when i total them up (with TotalAttributes), it has information to work with. I confess I don't know what will happen if FG does a campaign save during this activity.. it might throw things askew. Best i can do is keep an eye out for unforseen complications.

With this done, I can finish up the control tab. This is where GMs will change the settlement's basic structure (government, size, alignment) and it will modify your settlement's attributes according to Pathfinder's GameMastery Guide, pg. 206). When the control tab is done, it's off to either the building or npc tab!

ronalmb
December 5th, 2016, 00:04
I started on the Qualities list. I realized quickly there was too many settlement qualities in Pathfinder for a check system. Instead, it will function like feats to a character. But I plan on having a settlement's "Feat Sheets" have numeric boxes that you can enter modifiers into and they will apply those modifiers to the settlement. This has the added bonus of allowing custom qualities.

16772

Disadvantages will function the same.

Once this is done, I will be moving on to the Buildings tab.

ronalmb
December 5th, 2016, 18:11
Im not clear on what Handlers are, and the significance of addHandler. I have a feeling their important. Is someone willing to take a little time and hit me over the head with the Club of Knowledge on these?

Thank you.

Trenloe
December 5th, 2016, 20:57
Im not clear on what Handlers are, and the significance of addHandler.
See "Handler functions" at the bottom of this page: https://www.fantasygrounds.com/modguide/scripting.xcp And here for the DB API definition of addHandler: https://www.fantasygrounds.com/refdoc/DB.xcp#addHandler which lists the events that can be captured. For example, onUpdate: https://www.fantasygrounds.com/refdoc/databasenode.xcp#onUpdate

Basically, they allow you to run some code when a specific event happens against a specific database field. Do a "find in files" in the 3.5e ruleset for addHandler and you'll see lots of examples. For example: DB.addHandler(DB.getPath(node, "*.ac"), "onUpdate", onArmorChanged); which will run the onArmorChanged event when the ac field value changes (is updated). It is very handy for kicking off calculations/verification - like calculating the AC that worn armour provides (in the case of this example).

ronalmb
December 5th, 2016, 22:31
I thought that would be how it is supposed to work. But the testing I tried did not seem to do anything.. so I must be attempting to implement it wrong.

Example:
I have windowclass "qualitySheet". It is the window that displays so that the user can enter in a settlement quality. Think of it as a 3.5 Feat, but for settlements. The qualitySheet looks like this:

16778

When info is changed on the sheet, i need it to modify the settlement's attributes. My plan was to call a script "quality_controls.lua" from the qualitySheet windowclass. I know that script is being used, because the onInit() does fire off a Debug.console message.

BUT, I added the following to onInit():


DB.addHandler(DB.getPath(node, ".modifiers.corruption"), "onUpdate", onCorruptionChanged);

I figure that is supposed to set up an event for when the corruption data for the sheet is changed.

I have a function onCorruptionChanged():


function onCorruptionChanged()

Debug.console ("You changed corruption. You fool!");

end



My assumption was that this would mean that when i change the data in the Corruption modifier box on the qualitySheet, that it would then call onCorruptionChanged, which would then put a debug message in the console. But.. it doesn't do a thing.

And for completion, the sheetdata for the windowclass pertaining to that numberbox:



<number_kingabilityscore name="corruption" source="modifiers.corruption">
<anchored to="frame_modifiers" position="insidetopleft" offset="22,23" width="20" />
<description textres="corruption" />
<default>0</default>
</number_kingabilityscore>


I have the datasource set correctly. If AddHandler works the way i think its supposed to.. why does changing the data in the box not work?

One perplexing fight after another. It is exhausting!

Trenloe
December 5th, 2016, 22:41
I have the datasource set correctly.
Are you sure... ;)

Looks like the reference to the database field in the addHandler call isn't correct. This would be the most common cause of the onUpdate event not firing.

Looking at the documentation for DB.getPath: https://www.fantasygrounds.com/refdoc/DB.xcp#getPath It says that the second parameter is "One or more strings to be appended to database path returned." and looking at examples in the 3.5E ruleset, I never see the DB refrerence starting with a period (.) - they always start with the direct reference to be added to the node. So, what I'm guessing is happening here, your node reference will be <node>..modifiers.corruption (note the two periods). Try your code with DB.addHandler(DB.getPath(node, "modifiers.corruption"), "onUpdate", onCorruptionChanged); - no period before modifiers.corruption.

ronalmb
December 5th, 2016, 22:56
The ONLY thing I'm sure about is that I'm a clueless noob doing the best I can. I had just finished trying the DB.addHandler with a * in front of the ., since I see some examples of that in char_invlist.lua. That didn't seem to do it tho.

I have now tried it with your suggestion, but that doesn't seem to be doing anything either.

...BUT, your suggestion, combined with replacing node with getDatabaseNode() does work! Seems my node, which is copied from char_invlist.lua is pretty worthless if i don't actually assign it a value *embarassed*.

Trenloe
December 5th, 2016, 23:03
Seems my node, which is copied from char_invlist.lua is pretty worthless if i don't actually assign it a value *embarassed*.
LOL! :D

Glad you got it working. I frequently get database references messed up, so I usually expand the whole path out into a local variable before using it - which allows me to output to the console to check I've got it right.

For example, DB.addHandler(DB.getPath(node, "modifiers.corruption"), "onUpdate", onCorruptionChanged); could be expanded to:


local dbNodeString = DB.getPath(node, ".modifiers.corruption");
Debug.console("Adding onUpdate handler for " .. dbNodeString);
DB.addHandler(dbNodeString, "onUpdate", onCorruptionChanged);

ronalmb
December 5th, 2016, 23:23
Yeah, my go to for something like that is "nMe"



nMe = self.getDatabaseNode();


.. n for node and Me for self.getDatabasenode(). BUT, i suspect I should start learning to use getPath regularly so I always know where I'm at.

It's challenging to learn this stuff, but I'm enjoying it. I think plotting the pixel by pixel location of objects on my sheets is a whole lot more tedious and horrible!

Trenloe
December 5th, 2016, 23:29
You can use the <databasenode>.getNodeName() function to return the whole node string: https://www.fantasygrounds.com/refdoc/databasenode.xcp#getNodeName

e.g. nMe = self.getDatabaseNode().getNodeName();

Then you can write nMe directly to the console, as it's a string. Without getNodeName it's a LUA reference to the databasenode, which you can't send to the console.

ronalmb
December 5th, 2016, 23:40
That would explain why I can use nME the way i do to get and set values but why Debug.console never worked with it. I shoulda known that :)

Thanks for the heads up

ronalmb
December 6th, 2016, 02:13
Ok, now I need to look through a list of objects and total up the value of data within it.

For example, a settlement's qualities is stored in qualityList. Each quality entry is arranged as follows:



<id-00001>
<description type="formattedtext">
<p>The settlement is filled with nosy people that won't let a rogue go unnoticed.</p>
</description>
<exists type="string">Exists</exists>
<modifiers>
<baselimit type="number">0</baselimit>
<corruption type="number">0</corruption>
<crime type="number">-1</crime>
<law type="number">0</law>
<lore type="number">0</lore>
<productivity type="number">-1</productivity>
<purchaseLimit type="number">0</purchaseLimit>
<society type="number">0</society>
<spellcasting type="number">0</spellcasting>
</modifiers>
<name type="string">Busybodies</name>
</id-00001>


So I need to go through all the qualities a settlement may have, and then total them all up and add them to the appropriate settlement modifier attribute.

I know I'll be using:


for _,vNode in pairs(DB.getChildren(NODE, "qualityList")) do
nCorruption = nCorruption + DB.getValue(vNode, SOMETHINGHERE, 0);
nCrime = nCrime + DB.getValue(vNode, SOMETHINGELSEHERE, 0);
.... each attribute I want to accumulate;
end


Once I have totaled all quality modifiers of each attribute, I then need to assign it to the settlement that owns the qualityList. I guess I would want to use getParent to ID the correct settlement and once i've ID'd that, assign the values.

I'm familiar with for loops from Visual Basic and C+, but this loop is kinda alien looking. I understand (I think) what it is doing but not really how. I am also not yet totally positive what the SOMETHINGHERE paths are, yet but I'm pretty sure its "modifiers.ABILITY" where ABILITY is corruption, crime, law, etc.

Am I on the right path?

Trenloe
December 6th, 2016, 02:27
Am I on the right path?
Without knowing your actual database structure, it sounds like you are on the right path.

Bidmaron
December 6th, 2016, 03:51
I don't think you have it right. The for will loop through for each child of your quality list (is the xml in your post the contents of the quality list?). You need to post a complete picture of your data structure, but I am not sure why you unnecessarily next your fields inside the <modifiers> tag? Perhaps it is driven by your UI code? Without presenting both your data structure and your UI, it is hard for us to counsel you on how you should be doing this. One thing I know is that your code won't work no matter what you put in the 'something's because you don't want to loop through the quality list and then explicitly process each node in that list inside the loop.

Trenloe
December 6th, 2016, 04:11
I think this is fine. As the qualities for a settlement are each stored in an entry in the "Qualities" windowlist (see post #33) called "qualityList" (according to post #43), then each quality is a child record within the "qualityList" windowlist. Stepping through each child record within a windowlist (accessed using for _,vNode in pairs(DB.getChildren(NODE, "qualityList")) do) to access data from across the whole list is a fairly standard operation within FG. See the CoreRPG updateEncumbrance function in campaign\scripts\manager_char.lua - this is triggered whenever any value in the inventory changes that effects encumbrance (weight of an item, quantity of an item, "carried" flag) and the code steps through each inventory record (using for _,vNode in pairs(DB.getChildren(nodeChar, "inventorylist")) do - look familiar?), accesses the weight and quantity of each record and adds this to a running total. This is exactly what ronalmb is doing in his code above - I'm guessing he got the example from somewhere similar to the CoreRPG Inventory encumbrance calculations.

@ronalmb - keep going mate, it looks like you're on the right path. :)

Moon Wizard
December 6th, 2016, 18:18
The getPath function was added to be able to combine multiple path bits into a single path, which is especially helpful if the initial node is from a module and as "@modulename" appended on the end.

Regards,
JPG

ronalmb
December 7th, 2016, 18:09
After a day away so I could run my D&D game, I'm back at this and already I've two questions. I'll keep each in it's own post to try and stay organized.

1. My buttongroup_radio is calling twice (or at least that's what console tells me).

radio_record_size


<template name="radio_record_size">
<buttongroup_radio>
<anchored to="fControlSize" height="20">
<top offset="20" />
<left anchor="center" offset="-232" />
</anchored>
<parameters>
<optionwidth>58</optionwidth>
<labelsres>Tho|Ham|Vil|STwn|LTwn|SCty|LCty|Met</labelsres>
<values>Tho|Ham|Vil|STwn|LTwn|SCty|LCty|Met</values>
</parameters>
<gmeditonly/>
<script>
function onValueChanged()
window.changeSize();
end;
</script>
</buttongroup_radio>
</template>


The windowclass that the radio is placed in uses settlement.lua like so:



<windowclass name="settlement_controls">
<!--This tab is designed for the GM to control settings he will infrequently change
without worrying about accidently changing something elsewhere and not knowing where he dun goofed.-->

<script file = "Kingmaker/scripts/settlement.lua" />

<sheetdata>
<frame_char ....blahblah blah



A handler has been created and called from a function called settlementHandlers() which is called from onInit: DB.addHandler(DB.getPath(nMe, "size.name"), "onUpdate", onSizeChanged);

onSizeChanged looks like this:


function onSizeChanged()

Debug.console("Size was changed");
local nMe = self.getDatabaseNode();
Debug.console(DB.getValue(nMe, "size.name", "Didn't find name!"));

onCorruptionChanged();
onCrimeChanged();
onLawChanged();
onLoreChanged();
onProductivityChanged();
onSocietyChanged();

end


Finally, the changesize function from settlement.lua that is called whenever the radio button is clicked:



function changeSize()

local sSize = DB.getValue(self.getDatabaseNode(), "radioSize", "string");
local nMe = self.getDatabaseNode();
local sString = "default";

Debug.console("Settlement's size was changed to " .. sSize);

if sSize == "Tho" then
sString = "Thorp";
DB.setValue(nMe,"size.attribute_modifier","number",-4);
DB.setValue(nMe,"size.number_of_qualities","number",1);
elseif sSize == "Ham" then
sString = "Hamlet";
DB.setValue(nMe,"size.attribute_modifier","number",-2);
DB.setValue(nMe,"size.number_of_qualities","number",1);
elseif sSize == "Vil" then
sString = "Village";
DB.setValue(nMe,"size.attribute_modifier","number",-1);
DB.setValue(nMe,"size.number_of_qualities","number",2);
elseif sSize == "STwn" then
sString = "Small Town";
DB.setValue(nMe,"size.attribute_modifier","number",0);
DB.setValue(nMe,"size.number_of_qualities","number",2);
elseif sSize == "LTwn" then
sString = "Large Town";
DB.setValue(nMe,"size.attribute_modifier","number",0);
DB.setValue(nMe,"size.number_of_qualities","number",3);
elseif sSize == "SCty" then
sString = "Small City";
DB.setValue(nMe,"size.attribute_modifier","number",1);
DB.setValue(nMe,"size.number_of_qualities","number",4);
elseif sSize == "LCty" then
sString = "Large City";
DB.setValue(nMe,"size.attribute_modifier","number",2);
DB.setValue(nMe,"size.number_of_qualities","number",5);
else
sString = "Metropolis";
DB.setValue(nMe,"size.attribute_modifier","number",4);
DB.setValue(nMe,"size.number_of_qualities","number",6);
end

DB.setValue(nMe, "size.name", "string", sString);

end


When it runs my console looks like this when i change the radio button:

16818

onCorruptionChanged currently has a debug.console that tells me the name of a parent node (firing twice). Each of the other onBLAHBLAHChanged functions do math to tally an attribute total and then tell me that it was changed.

The highlighted yellow is the duplicated call. I've tried to follow all the steps in the flow and I don't see why it would call twice. How'd I goof?

ronalmb
December 7th, 2016, 18:39
So this question is shorter.. but the answer is possibly more complicated.

I have Kingdom X. It's a collection of data. One of Kingdom X's data items is settlementList, which is a collection of settlements. Each settlement has its own data. When data in one settlement changes (for instance, Corruption), the change needs to trigger the Kingdom to recalculate it's totals (to reflect the change in Corruption).

Example data structure (edited for brevity)


<kingdom>
<id-00001>
<attributes>
<corruption>
<alignment type="number">0</alignment>
<government type="number">0</government>
<qualities type="number">0</qualities>
<settlements type="number">0</settlements>
<total type="number">0</total>
</corruption>
</attributes>
<name type="string">Brevoy</name>
<settlementlist>
<id-00002>
<alignment type="string">CN</alignment>
<attributes>
<corruption>
<alignment type="number">0</alignment>
<government type="number">0</government>
<qualities type="number">0</qualities>
<total type="number">1</total>
</corruption>
</attributes>
</id-00002>
</settlementlist>
</id-00001>
</kingdom>


I am not quite sure how/best way to set up a handler to track a change two nodes down in data that may or may not exist yet (if a settlement hasn't been created yet, for example) and then make sure that the handler is triggered properly.

Does this make sense?

Because pictures always help me:

16819

I know I need to be using an item's weight from a character's inventory tab from the character sheet in 3.5/Core as an example.. but it seems like it is going to be more complicated than that since my settlements have their own handlers tracking data that changes, and its when that information changes that i need to then change the info further up the data tree..

Am I overthinking this?

I know i've asked something related to this before, just seven or so posts ago, and you've told me I'm on the right path.. but i've thought myself into circles and need some more clairty.

Trenloe
December 7th, 2016, 20:19
1. My buttongroup_radio is calling twice (or at least that's what console tells me).
Not sure, from the code you've shown.

I'd add some debug just before the DB.addHandler(DB.getPath(nMe, "size.name"), "onUpdate", onSizeChanged); code, to see if that is being called twice, which would create two handlers.

Trenloe
December 7th, 2016, 20:25
I have Kingdom X. It's a collection of data. One of Kingdom X's data items is settlementList, which is a collection of settlements. Each settlement has its own data. When data in one settlement changes (for instance, Corruption), the change needs to trigger the Kingdom to recalculate it's totals (to reflect the change in Corruption).

...

I am not quite sure how/best way to set up a handler to track a change two nodes down in data that may or may not exist yet (if a settlement hasn't been created yet, for example) and then make sure that the handler is triggered properly.
Don't setup a high level handler that triggers onUpdate - as you say, the record might not exist.

Write a top level function that can be called from the settlement record. Kind-of similar to your window.changeSize() in post #48. Pass the database node where the change was made so you can write code to get the data that has changed - if you need to do that, you might just be able to get away with a "window.recalculateTotal()" command that goes through all of the records and recalculates the total.

ronalmb
December 7th, 2016, 20:31
Hmmm. Yep, my Handlers are indeed being called twice.

It is calling from the settlement window during onInit() .. it is then being called again when i click the tab for the settlement's controls which is also using the same .lua.. so the onInit is effectively called twice. Both call the same .lua. Hrm.

So, I have a settlement sheet. It's script is settlements.lua, which contains the handlers, which are added in a function called from onInit.

If the settlement sheet has tabs and subwindows.. and those tabs/subwindows are their own window class... will it automatically use scripts from the settlement window class its located on? I suspect not. If not, can the subwindows use the same .lua as the base sheet their placed on?

Bidmaron
December 8th, 2016, 01:35
ronalmb, I found this that may help with your problem. It is in table_main.lua in the campaign\scripts folder. It is a way to avoid double calling in similar circumstances.

First, it relies upon this local variable declaration:

local bInitPhase = true;

In places you need to guard against execution when not initialized (as in this example inside the routine UpdateColumns):

function updateColumns()
--Does nothing if the window hasn't completed initialization
--Sets column width of each row
--Sets up the left margin of each column in a row and its cell width
--Modified to handle variable width columns
if bInitPhase then
return;
end

updateColumns();
....


Then, this code handles clearing the variable so the guarded code can execute:

function onSubwindowInstantiated()
bInitPhase = false;
updateColumns();
end

ronalmb
December 8th, 2016, 14:00
@Bidmaron, thank you. That is going to be helpful with my initializations.

More question time!

So I have this code:



function total_qualities()

--1. get the current node. This is the quality that is being worked on.
local thisItem = self.getDatabaseNode();
--2. From there, get the parent of this node. This should be "qualityList"
local thisParent = thisItem.getParent();
--3. For testing purposes, count the number of children in the qualityList.
local totalChildren = thisParent.getChildCount();
--3. Now that we have the quality list, we need to sort through it.
for _,v in pairs (DB.getChildren(thisParent)) do
Debug.console("My name is " .. DB.getValue(v, "name", ""));
end

Debug.console("There are " .. totalChildren .. " qualities in this list.");

end


I am getting the following when executed: Script Error: [string "Kingmaker/scripts/quality_controls.lua"]: 49: getChildren: Missing parameter 2

I see that the for loop for sorting through inventory has two parameters.. but i also see the for loops in manager_chat.lua only taking one parameter. The reference page for getChildren does not list what parameters it needs. How do I know how many parameters and of what kind I need?

In this case, I want to cycle through <qualityList> and do stuff. This time i'm just getting .name for testing purposes.. but i want to use it to total up all of ".modifiers.corruption"

What is the proper phrasing for this?

Thanks as always for any insight.

Trenloe
December 8th, 2016, 14:21
The reference page for getChildren does not list what parameters it needs. How do I know how many parameters and of what kind I need?
OK, here we need to be clear on the difference between <databasenode>.getChildren and DB.getChildren.

With <databasenode>.getChildren you already have the database node element, so you don't need to specify where in the database you want to get the children, you already know because the database node points to it. https://www.fantasygrounds.com/refdoc/databasenode.xcp

DB.getChildren is different: https://www.fantasygrounds.com/refdoc/DB.xcp#getChildren DB is a global package for doing operations against the database, when you call DB package functions FG doesn't know what part of the database you're operating against. So, you need to provide it with where to get the children. The definition is" function getChildren( [source], sourcepath ) The square brackets around [source] mean that it is an optional argument, which is defined as Optional source node to which path is relative. So, if you provide an argument which is a databasenode you also need to provide the sourcepath, even if that is just "". If you do a find in files in CoreRPG you will see plenty of examples of this in operation.

So, you can use either DB.getChildren(thisParent, "") or thisParent.getChildren() to get the children of the thisParent database node.

damned
December 8th, 2016, 14:25
How do you remember all this stuff!!!!!??

Trenloe
December 8th, 2016, 14:29
ronalmb, I found this that may help with your problem. It is in table_main.lua in the campaign\scripts folder. It is a way to avoid double calling in similar circumstances.

First, it relies upon this local variable declaration:

local bInitPhase = true;

In places you need to guard against execution when not initialized (as in this example inside the routine UpdateColumns):

function updateColumns()
--Does nothing if the window hasn't completed initialization
--Sets column width of each row
--Sets up the left margin of each column in a row and its cell width
--Modified to handle variable width columns
if bInitPhase then
return;
end

updateColumns();
....


Then, this code handles clearing the variable so the guarded code can execute:

function onSubwindowInstantiated()
bInitPhase = false;
updateColumns();
end
This is useful for race conditions, when we have two (or more) different processes accessing the same data.

However, in this case, we don't have a race condition - we have the exact same onUpdate event handler registered twice, which is why the event handler gets called twice. We should fix the base issue, and only have one event handler registered.

@ronalmb can you post the code you're working against for the whole window definition? From your comments in post #52, I'm not exactly clear on how the base window and subwindows have been setup, along with the <script> elements for each.

ronalmb
December 8th, 2016, 14:29
I'm going to have to mirror damned's amazement here. That's pretty impressive. Thanks!

@Trenloe: I've managed to sort out the double handler issue. Or, rather ... it seems to be fixed. I'm clueless enough NOT to make any assumptions on this. I had both subwindow main's window class and the subwindow control's window class calling the same exact .lua script. So.. when I toggled first _main and then went to the _control tab, i'm assuming it was running those onInits twice. I have cleaned up that code, called what i need from scripts unique to each window class and then let the handlers that are tracking the data just do their job.

I'd be happy to wrap all this stuff im doing up into a zip and share.. but i'd be terribly embarassed to show how bad I am at this.

But then again.. i've put a serious effort in for a week and a half(?) now.. so I am clearly learning stuff.

Follow-Up
thisParent.getChildren() solved it. Thank you very much. I think that is hopefully the biggest hurdle I have to cross on this. If i can get qualities to total for a settlement, i can do the same exact approach to totalling settlements for kingdoms.

Trenloe
December 8th, 2016, 14:31
How do you remember all this stuff!!!!!??
LOL! I don't remember it all. Basically, I look in the API guide and do lots of searches in the rulesets.

ronalmb
December 8th, 2016, 14:51
I'm going to have to mirror damned's amazement here. That's pretty impressive. Thanks!

@Trenloe: I've managed to sort out the double handler issue. Or, rather ... it seems to be fixed. I'm clueless enough NOT to make any assumptions on this. I had both subwindow main's window class and the subwindow control's window class calling the same exact .lua script. So.. when I toggled first _main and then went to the _control tab, i'm assuming it was running those onInits twice. I have cleaned up that code, called what i need from scripts unique to each window class and then let the handlers that are tracking the data just do their job.

I'd be happy to wrap all this stuff im doing up into a zip and share.. but i'd be terribly embarassed to show how bad I am at this.

But then again.. i've put a serious effort in for a week and a half(?) now.. so I am clearly learning stuff.

Follow-Up
thisParent.getChildren() solved it. Thank you very much. I think that is hopefully the biggest hurdle I have to cross on this. If i can get qualities to total for a settlement, i can do the same exact approach to totalling settlements for kingdoms.

Ok, not quite yet figured this out.

For-in loop


for _,v in pairs (thisParent.getChildren()) do
Debug.console("Settlement " .. DB.getValue(self.getDatabaseNode(),"name", "string", "UGH"));
end


Instead of giving me the .name field of each quality in the list (there are three).. it gave me the first one three times.

The Data:


<qualityList>
<id-00001>
<description type="formattedtext">
<p>Restov is a bunch of fishmongers. They love to monger fish. It's disgusting.</p>
</description>
<exists type="string">Exists</exists>
<modifiers>
<baselimit type="number">0</baselimit>
<corruption type="number">3</corruption>
<crime type="number">0</crime>
<law type="number">0</law>
<lore type="number">0</lore>
<productivity type="number">0</productivity>
<purchaseLimit type="number">0</purchaseLimit>
<society type="number">0</society>
<spellcasting type="number">0</spellcasting>
</modifiers>
<name type="string">Fishmongers</name>
</id-00001>
<id-00002>
<description type="formattedtext">
<p>Everyone in Restov is a bootlicker. They have very dirty mouths.</p>
</description>
<exists type="string">Exists</exists>
<modifiers>
<baselimit type="number">0</baselimit>
<corruption type="number">2</corruption>
<crime type="number">0</crime>
<law type="number">0</law>
<lore type="number">0</lore>
<productivity type="number">0</productivity>
<purchaseLimit type="number">0</purchaseLimit>
<society type="number">0</society>
<spellcasting type="number">0</spellcasting>
</modifiers>
<name type="string">Bootlickers</name>
</id-00002>
<id-00004>
<description type="formattedtext">
<p>Restov is hopelessly corrupt. Its a shame.</p>
</description>
<exists type="string">Exists</exists>
<modifiers>
<baselimit type="number">0</baselimit>
<corruption type="number">4</corruption>
<crime type="number">0</crime>
<law type="number">0</law>
<lore type="number">0</lore>
<productivity type="number">0</productivity>
<purchaseLimit type="number">0</purchaseLimit>
<society type="number">0</society>
<spellcasting type="number">0</spellcasting>
</modifiers>
<name type="string">Hopelessly Corrupt</name>
</id-00004>
</qualityList>


The console result:


Runtime Notice: s'Settlement Bootlickers'
Runtime Notice: s'Settlement Bootlickers'
Runtime Notice: s'Settlement Bootlickers'


The answer is probably sitting right in front of my face at this moment!

Trenloe
December 8th, 2016, 14:59
thisParent.getChildren() returns the result of getChildren in a LUA table, the first piece of data being a numberical index (1, 2, 3...) and the second being the database node. This format is known as key, value so you will sometimes see the individual pieces of data referred to as "k" and "v", for Key and Value, respectively. In this case (getChildren) the key would be 1 for the first row, 2 for the second, etc. and the value for each row would be the database node for the child record.

for _,v in pairs (<LUA table>) do steps through the LUA table and provides the database node for this row of the table in v (the Value).

So.... to get the value from each child record you need to work against the database node "v": DB.getValue(v,"name", "string", "UGH") Not self.getDatabaseNode() because that is always the same. "self" refers to the control the code is running in and so is the same within the whole scope of the LUA script. See the "Self and Super Variables" section here: https://www.fantasygrounds.com/modguide/templates.xcp and "Script block scope" here: https://www.fantasygrounds.com/modguide/scripting.xcp

ronalmb
December 8th, 2016, 15:06
This one WAS staring me in the face. I came back to type "Nevermind, I don't use 'blah blah blah', I use 'v' " but you have already answered and can say "yeah, suuuuure you figured it out on your own, uh huh." :D

Thank you! Seriously, you've been a font of education. While i stumbled on v being used instead of the self. stuff, I had no idea what the reasons were behind it (and the k & v) stuff.. so very informative. Scope has proven to be a challenge for me. The only time i've been MORE confused is when i tried to first wrap my head around Object Oriented Programming years ago! I jest. Kind of.

Trenloe
December 8th, 2016, 15:13
No problem at all. And please do share your end result - no one will look under the hood, as long as it (kinda) works it'll be fine. :)

Oh, and I was slightly wrong about the LUA table returned by getChildren. I should have read the documentation, which says: "The child nodes are returned as databasenode objects in a table with keys corresponding to the names of the child nodes." So, the keys of the LUA table aren't 1, 2, 3... in this case. For a lot of tables they are, but it all depends on the function that creates them. So, this is actually a quite handy LUA table, as each row will be key = database name of the child node (string format), value = databasenode element of the child node. So, you can use the key for node string manipulation, or the value for direct databasenode element access (such as .getValue, etc.).

ronalmb
December 8th, 2016, 15:27
When this project is finished (as will be all of the ones I'd like to do), I will share them.
I look forward to when i have to update all of this to work with FG 3. :D

Bidmaron
December 8th, 2016, 17:21
Where you have this:


Debug.console("Settlement " .. DB.getValue(self.getDatabaseNode(),"name", "string", "UGH"));

You need this:

Debug.console("Settlement " .. DB.getValue(V.getDatabaseNode(),"name", "string", "UGH"));

I am away from computer so I think the getdatabasenode is right but you need "v" in there for sure

I suck trying to do this on iPhone and took forever

ronalmb
December 8th, 2016, 20:00
Ok, I am now successfully tracking the bonuses and penalties that individual qualities (which i may rename traits but then I won't be 100% pathfinder accurate). I can add a new quality and when i set what attributes that quality affects it properly adds or subtracts from the settlement's overall score.

HOWEVER, if i use the delete button to remove the quality from the list, it is failing to update.

I figure i need to set a handler for "onDelete", but it feels like there is something else needed.

I.E.
Settlement has 3 traits.
Trait 1 adds +2 to corruption.
Trait 2 adds +1 to corruption.
Trait 3 adds +5 to corruption.

As a trait is added, it properly totals everything up. In this case, the total settlement's trait modifiers to corruption are +8.

BUT, if i hit the delete toggle (copy and pasted pretty much from inventory CORE RPG), the object disappears properly but the total modifiers do NOT immediately adjust.

IF I add another trait to the list, it does total the traits properly, so i know the item is getting removed (and can confirm by looking at the db.xml. It's just "that moment" in time after the list item is deleted that I'm not properly catching.

Hopefully this makes sense!

Trenloe
December 8th, 2016, 20:08
Have a look at the CoreRPG campaign\scripts\char_invlist.lua file. In the onInit() function there is a handler set for onChildDeleted. https://www.fantasygrounds.com/refdoc/databasenode.xcp#onChildDeleted

ronalmb
December 8th, 2016, 20:30
That is what I have been using for reference. Your answer tells me that I am on the right track but am implementing it wrong, or in the wrong place.

Let's see. I have a settlement.lua that handles everything for a settlement and a record_quality.lua that handles everything for each quality on the quality list. I had those handlers in the .lua for the qualities.. which actually doesn't make any sense.. since the qualities have no children, a handler detecting child deleted would fail. I'll give it a go in the .lua one level higher up. That sounds like I should have done that from the start.

ronalmb
December 9th, 2016, 13:00
Ok, so by default when I click the Kingdoms button on the sidebar, i get the nice collection list popup that lets me create new kingdoms. When I add a new kingdom there, it kindly opens up the new kingdom's sheet for me.

On the kingdom sheet, i have a settlement tab. On the settlement tab, i can add/delete settlements (like character inventory does with items). What I would like is that when i add a settlement, it automatically opens up the new settlement window. But, I used character inventory as my reference and it doesn't do that, so mine doesn't.

I've not found the proper xml or lua to do this. I know it can be done, because Story, Quest, NPC, Item, and even my Kingdom button on the sidebar does it.

Where do I look to pull this off with an iedit_add button?

ronalmb
December 9th, 2016, 13:48
Button_iedit. Used to add and remove from the inventory list. I assume it is used for other things as well.

So I have the target set to settlementList. As it should, it adds an entry to my settlement list whenever it is clicked. When that link is clicked, it opens up the settlement window at which point my onInit populates the data if it's never been opened before.

Until i open that link and it is populated with data, the basic information displayed in the settlement list remains devoid of data (because it hasnt been created until the link is clicked and onInit populates it). I suspect this is not the way to do this, but its working.

What I would like to know is, if when the iadd button is clicked, the initial information (i.e. name = "New Settlement", size.name = "Thorp" etc) can be created and not wait until i open the sheet. Technically, i suppose that if the add button auto-opens the window this issue is moot which is question #1.

Pointless Babble Update: Ok, so in the script for my settlementList, I can add handlers that detect when a child is added and when a child is deleted. They work. I would like to initialize the data for a new child at this point. The issue with this is how do i get the child that is being added?

I see that getChild requires a name. I could write a loop to go through all the children and get the name of the last child in the list, assuming that the last child in the list is always the last child added. Since it sorts alphanumerically however, I suspect that the last child in the list ISN'T the most recently added child. I need to pass the child added to the function I want, but don't know how or if that is handled in a DB.addHandler. I see that onChildAdded() function is described in the wiki as having a source, and a child but don't understand if/how I can include that in my addhandler line. Gah! I confuse myself so easily.

Let's try again:

I have a handler DB.addHandler(DB.getPath(node), "onChildAdded", doSomething));

when I get to doSomething, i need to have passed it the child. How do i get that child to pass it?

Trenloe
December 9th, 2016, 16:04
when I get to doSomething, i need to have passed it the child. How do i get that child to pass it?
It comes as an argument to the onChildAdded event: https://www.fantasygrounds.com/refdoc/databasenode.xcp#onChildAdded Do a search for "function onChildAdded" in CoreRPG, there's one example.

Trenloe
December 9th, 2016, 16:07
Where do I look to pull this off with an iedit_add button?
See CoreRPG campaign\scripts\campaign_button_new.lua This is the code that gets called to create (and open) a new campaign data window (story, NPC, etc.). Interface.openWindow is used: https://www.fantasygrounds.com/refdoc/Interface.xcp#openWindow

ronalmb
December 9th, 2016, 16:21
It comes as an argument to the onChildAdded event: https://www.fantasygrounds.com/refdoc/databasenode.xcp#onChildAdded Do a search for "function onChildAdded" in CoreRPG, there's one example.

This is where my noobness and inexperience really shines. The source I was looking at was from onChildAdded in masterindex_window.lua. But I'm not grasping what its supposed to be telling me. I'm guessing this is because my basic assumption of how to use onChildAdded in a handler doesn't work the way I think it does. OR it tells me something else, and I'm just not understanding what.

Are you saying that when i have the event triggered and it goes to doSomething, all i needed to do was have it receive the node? I.e.:



function doSomething (node)

DoSomethingHere

end



Follow-up: No, not quite that. If I do that, and then in the function do Debug.console(node.getName()) it returns settlementList to the console.. the name of the containing node but not the child. Yurg! I need to be smart enough to grasp this stuff.

ronalmb
December 9th, 2016, 16:38
See CoreRPG campaign\scripts\campaign_button_new.lua This is the code that gets called to create (and open) a new campaign data window (story, NPC, etc.). Interface.openWindow is used: https://www.fantasygrounds.com/refdoc/Interface.xcp#openWindow

Two prompt answers in a row and I understand neither of em today, lol. Clearly time to get out of the deep end and get back in the kiddie pool. :) Time to reread all of the wiki and documentation and see if anything new clicks. This teaches me not to bite off more than I can chew in a project.

Trenloe
December 9th, 2016, 16:46
Follow-up: No, not quite that. If I do that, and then in the function do Debug.console(node.getName()) it returns settlementList to the console.. the name of the containing node but not the child. Yurg! I need to be smart enough to grasp this stuff.
Check the documentation for onChildAdded: https://www.fantasygrounds.com/refdoc/databasenode.xcp#onChildAdded It can return a source and a child node. If you have one parameter ("node" in your example) you'll just get the first parameter - "source" which is what you're seeing.

ronalmb
December 9th, 2016, 16:50
Check the documentation for onChildAdded: https://www.fantasygrounds.com/refdoc/databasenode.xcp#onChildAdded It can return a source and a child node. If you have one parameter ("node" in your example) you'll just get the first parameter - "source" which is what you're seeing.


That... actually made sense. Which is great.. and bad. Bad because now i feel silly. :)

Moon Wizard
December 9th, 2016, 18:12
Look at the "button_iadd_masterindex" template. It basically pops open the window (Interface.openWindow) after creating the list child. If you do use this script, make sure the control is only visible to the GM, or you could have players adding records (which will create weird ownership patterns and potential errors, since they won't own the kingdom record).

If you have an onChildAdded handler registered in the settlement list code (similar to onChildDeleted), you will receive the parent node as the first parameter and the child node as the second parameter. Use the child node reference to set the "initial" values for the settlement.

NOTE: I started answering on the last page, so some of this may be redundant.

Regards,
JPG

ronalmb
December 11th, 2016, 12:09
I took some time to clean up my existing code and restructuring my extension folder. I've gotten the handle on going through a list of objects and totalling an attribute so I'm thrilled about that. Now I am back with another question!

So, I have a settlement. The settlement has a list of Qualities (think feats). Each Quality has values you can assign corresponding to settlement attributes. When I change an attribute, it successfully goes through the list of qualities and totals up the modifiers to each attribute. So for instance, a settlement may have "attributes.corruption.total" which is the sum of modifiers from size, qualities, government, and alignment. These values are totaled from the settlement's lua function "totalAttributes".

Now, when a quality is updated, it correctly adds the quality modifier to the appropriate attribute of its settlement parent. However, doing so does not trigger "totalAttributes" from the parent settlement's lua. I tried different Handlers in the settlement's lua to trigger this but those end up getting fired whenever ANY data in the quality changes including every keypress of whatever you choose to name the quality.

My question tho, is this: Is it possible to call the parent settlement's totalAttributes function from the child quality? If so, how is this done?

If it is not possible (I suspect it is), what's the best way to have a change "go up the tree" to affect data at higher tiered levels?

Followup: I am able to total things by recreating the same totalAttributes function from the settlement's lua in the quality.lua but i am hoping there's an easier way to do this.

Followup to Followup: After rereading the section on script packages in Scripting (https://www.fantasygrounds.com/modguide/scripting.xcp), I believe what i need to do is create a script package called "kingdom manager" and include various functions to total things up there. Then call that when i need to update a settlement or a kingdom.
Is that the correct answer to my earlier uninformed question?

Bidmaron
December 11th, 2016, 14:03
To answer this, we'd need to see your UI structure and your data structure. However, there are two ways to get to parent routines in general. Through the interface, if you are working from a subwindow, you can get to the parent windowlist through the windowlist variable. (warning: I am not an expert on this, so I am sure MW or Trenloe will come along and fix this where I have it wrong)


if windowlist.totalattributes then
windowlist.totalattributes(parameters?)
end

If you are in a subwindow, you can get to the parent as follows:


if parentcontrol.totalattributes then
parentcontrol.totalattributes(parameters?)
end

If you are in a control within a subwindow, it would be like this:


if window.parentcontrol.totalattributes then
window.parentcontrol.totalattributes(parameters?)
end

All of the examples of these types of usage I could find in the code base have '.window' between parentcontrol and the routine name, and I'm not sure why you would necessarily need that if your total attributes were in the <script> attribute....

From a data node, you can invoke the parent update handler like this I think:


ourNode.getParent().onUpdate()

So, if the parent node has the totalattributes defined as the update handler, this should invoke that routine.

ronalmb
December 11th, 2016, 15:29
Bidmaron, thank you for your reply! I appreciate your looking into this.

Since posting, I've begun working my totalling functions into a script package called "KingdomManager" that is included in my launch xml like so:


<script name="KingdomManager" file="Kingmaker/scripts/manager_kingdom.lua" />

Since doing that, i can just place my often used total functions there and call them as needed from anywhere by passing it the settlement or kingdom as required, such as:




KingdomManager.totalCorruption(settlement);



In this example, the KingdomManager takes the settlement, looks at all the stuff that affects Corruption, and totals it. I have had a lot of success this morning since then, although I have to go through all the scripts and change how im doing things to account for this.

I'm sure this is pretty basic stuff for everyone. But for me, it feels like a huge epiphany and a major step forward on figuring this out on my own.

Trenloe
December 11th, 2016, 16:26
Sounds like you're on the right track. Having a global package for frequently used calculations is a good way to go. It keeps most of your code in one place, and allows easier debugging and changes to that code.

Passing the settlement databasenode allows you to operate directly against the database record you desire, which works well. Just be aware that this package has a single script scope, so any "global" variables you might use within the KingdomManager package are stored within that script scope for all calls, from all different settlements that might access it.

Bidmaron
December 11th, 2016, 16:50
Trenloe, I was hoping someone might confirm that my post was logically and syntactically correct. Did you see any errors with that? I am still learning all of this also, and I'd like to make sure that what I stated was correct.

Trenloe
December 11th, 2016, 17:53
Trenloe, I was hoping someone might confirm that my post was logically and syntactically correct. Did you see any errors with that?
As far as pseduo code goes it's fine (with the proviso mentioned below). But, without that actual GUI to reference, the code can't be verified.

Also, checking for the presence of each control/entity, e.g. if windowlist.totalattributes then ... will prevent possible errors (I'm assuming that's why you use it), but it doesn't actually help identify issues if something changes in the code or there's an issue and windowlist.totalattributes no longer exists or isn't available. It could actually cause confusion as you'd expect code to run, but it doesn't - without any errors being raised; or people will be using the ruleset thinking everything is great but there could be stuff broken underneath (maybe by an extension, or some such). Checking for the presence of entities is generally only used if there is a chance that they don't exist (e.g. an empty list) and/or if you want to execute different code if that is the case. Checking for the presence of every possible entity is overkill and not displaying an error (usually allowing FG to generate a standard error) can cause more issues than avoiding an error. This approach (not checking for the existence of entities unless you want to execute different code or there's a standard possibility the entity might not exist) is standard practice in the FG ruleset code.

Any Fantasy Grounds code you write is not 100% under your control. i.e. a GM can load up a bunch of other extensions that modify/impact your code. Therefore, it's a good idea to let FG generate errors if there is an error/issue, so that users know there is an issue and can track down the problem. Yes, you could write your own error handler if <entity exists> then <access entity> else <generate message> end but this would be 5 lines of code to 1 (just accessing the entity) and wouldn't even raise a full FG error message (only FG can do this). So, best to leave FG to the error handling for cases like this.

ronalmb
December 11th, 2016, 22:58
Today I rebuilt how i was doing things from the ground up, moving redundant tracking to a script package. This has made totalling things from the kingdom level all the way down much easier.

It now lets me add settlements and modify their stats and those totals get passed up to the kingdom level (where they total and serve as bonuses for the Kingdom building rules). This was absolutely a monster for me to figure out, but it's been a great learning experience.

I've included screenshots of what i have so far as well as where I intend to go with this project.

16870

16871

16872

16873

I've done a lot today. Time to conquer Stellaris some.

Trenloe
December 11th, 2016, 23:04
Looking very nice indeed. Great work! :)

Bidmaron
December 11th, 2016, 23:22
Good point, Trenloe. It was just a pattern I saw used and duplicated in my pseudo code, but you are right that it is probably better to generate the error than to trap it and do nothing about it.

ronalmb
December 12th, 2016, 11:36
When a player adds a quality (feat) to a settlement, a window pops up for them to edit. The NAME category for the quality is added to a string so it can display the names of all qualities the settlement possesses on the main tab. For instance, if a settlement has qualities named "Academic", "Artifact Gatherer" and "Cultured" it would display on the main page's qualities line as "Academic, Artifact Gatherer and Cultured".

Right now, if i set an event handler for the quality window to detect an update to the quality.name line (so that it can update the combined names of all qualities), it will run the update with every single keypress which seems like it might be the wrong way to do that.

Is there a way to trap this event to fire ONLY after the player is done entering input and has moved to a different box, tab, etc?

I suppose I could have a function at the quality.lua level (instead of in the kingdom manager) that is fired that ONLY updates the Qualities combined label. That way when it gets called it is separate from the rest of the functions that add and calculate all the way up the node tree.

damned
December 12th, 2016, 12:45
There is an onLoseFocus function... have you tried that?

ronalmb
December 12th, 2016, 14:21
OooOoo. nope! That sounds like exactly what I need. I've made it so the functions for combining the various settlement quality-names don't call or mess with settle and kingdom totalling functions (which they shouldn't).. but this will hopefully make it so that my function for doing this only gets called once upon completion instead of with every key press!

Thanks.

ronalmb
December 12th, 2016, 14:30
A settlement, depending on its size, will have minor, medium, and major magic items available in it. For instance, a Village will have 2d4 minor items and 1d4 medium items. Various buildings and qualities can increase the die-type or add additional dice to these rolls. My eventual goal for this is to possibly have buttons you click that rolls these totals for the DM (and later down the line MAYBE even roll the items). Is there a "dice" data type? I know you can drop dice onto some combat tabs in 3.5 and it remembers them.. so there must be something.

Trenloe
December 12th, 2016, 16:18
Right now, if i set an event handler for the quality window to detect an update to the quality.name line (so that it can update the combined names of all qualities), it will run the update with every single keypress which seems like it might be the wrong way to do that.

Is there a way to trap this event to fire ONLY after the player is done entering input and has moved to a different box, tab, etc?
Use <delaykeyupdate /> in the control’s XML definition to update the underlying database only when the control loses focus.

https://www.fantasygrounds.com/refdoc/stringcontrol.xcp

Trenloe
December 12th, 2016, 16:28
A settlement, depending on its size, will have minor, medium, and major magic items available in it. For instance, a Village will have 2d4 minor items and 1d4 medium items. Various buildings and qualities can increase the die-type or add additional dice to these rolls. My eventual goal for this is to possibly have buttons you click that rolls these totals for the DM (and later down the line MAYBE even roll the items). Is there a "dice" data type? I know you can drop dice onto some combat tabs in 3.5 and it remembers them.. so there must be something.
Have a look at <windowclass name="char_weapon_editor_main"> in the campaign\record_char_actions.xml in the 3.5E ruleset. You can see some dice drop code in the <script> section and then in the <windowclass name="char_weapon_damage_entry"> there is the <basicdice name="dice"> control. This is a template (in CoreRPG) for a diefield control: https://www.fantasygrounds.com/refdoc/diefield.xcp A dice is a specific type within FG - a LUA table (array) that has various fields, usually "type" and "result". Info in the "dice" line of the "Message Data Structure" here: https://www.fantasygrounds.com/refdoc/Comm.xcp

ronalmb
December 14th, 2016, 03:27
Thank you for your replies. Both were helpful. I'm trying to figure out how calls to roll dice work. I'm looking at the various template_char buttons that you double click to roll a die but I'm not having much luck grasping all the different things in play.

If I want to get started on a button that when i click, it rolls a d20 and adds the source value attached to the butotn... where is the easiest place to start? I thought it would be the initiative roll.. but it calls to the ActionsManger (which i get manages all actions including dice rolling) which wants three parameters. I'm not sure I'm looking in the right place for a good example.

Trenloe
December 14th, 2016, 05:20
All rolls are actions - hence why you're seeing actions manager. Look at the header of manager_actions.lua - it gives a brief rundown of the dice roll mechanic. The big thing to keep in mind is that dice rolling is asynchronous - FG doesn't roll the dice and sit there in the code waiting for the result. The result of a dice roll is processed through a handler.

I discuss it here (for rolling a save in a new ruleset): https://www.fantasygrounds.com/forums/showthread.php?34976-AD-amp-D-Ruleset&p=301866&viewfull=1#post301866 Reading around this might help.

Basically, you'll need to either just do a "dice" action (action type = "dice", a default framework for just rolling dice) or define a custom action type if you want to do more - like specific processing of the dice result (e.g. comparing with a target number).

Some info here: https://www.fantasygrounds.com/forums/showthread.php?22530-Adding-in-new-dice-mechanics-to-the-CoreRPG-foundation&p=191573&viewfull=1#post191573

ronalmb
December 14th, 2016, 11:27
Well. Who had thought that I'd be stumbling over rolling dice. I've looked through those actions. Most I guess I grasp. I think. It's possibly the most difficult thing I'm going to learn yet with Fantasy Grounds extension making!

So I want to link a Kingdom Ability score (in this case "economy") to a die roll. Starting with initiative I was able to get that to roll.. but of course, ActionInit although the simplest for me to grasp isn't what I need. An Economy check is just another type of Ability check, I think, , so I decide to take a look at ActionAbility. I need to roll a D20 and add my economy.total value to that to get a result. I do want to be able to drag that result onto the kingdom's controlDC to see "success" or "fail" but .. little bites.

ActionAbility has a pesky third parameter, sent as self.target[1], that I don't understand however. I've tried assigning different values to <target> in the sheetdata xml entry for the economy button, but I am obviously not getting what <target> does or well, targets.

I usually end up with:


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


I know that it's telling me to look at line 1 because thats what it does when it parses a Script block and I know that it is reporting a nil value because <target> doesn't exist in a way it understands.

I guess my question is, What in the happy nine halls of holiday cheer is <target> supposed to be? :)

Follow-up: Ok, so i tried to run the script again, making sure i had <target>controldc</target> in my ..control(?) and this time it ran with no error. Since the time before I got the error, I must have had it in the wrong spot or .. ya know, who knows what I did. It's early.

So <target>controldc</target> causes it to tell me in the chat box that the check is an [ability] controldc check and gives me the results. I'm going to go out on a limb and take a guess that if i drag that result onto the kingdom's controldc box, it might tell me something.

No, it doesn't. But then again, i don't have controldc set up to do anything other then source it to the kingdom's controldc value.

Since i have a known target number, MAYBE i can learn something from ActionSkill or ActionAttack since i think both of those can be compared against another number.

Follow-up to Follow-up: Ok, looking at the Action Ability check a little more and watching how it works for a character, <target> isn't quite what I think it is. For a Character's strength check, it report's in chat as a Strength check.. so target clearly seems to be a descriptor for what kind of check is being made.

I changed my economy score to 5 and did a reroll. It doesn't add anything to the die roll.. so the source the control is linked to doesn't seem to impact that. Looking around, I see <modifierfield>, <modifiersize>,and a few others. So new questions:

<modifierfield> seems to be telling where to look for temporary modifiers to add?
<source><name>initiative.misc</name><op>+</op></source> seems to say 'add initiative.misc'?

It's clear that <ability><source> is adding the Dexterity modifier to the die roll. I'm not sure yet how that works, but i understand it.

I do not understand what <modifiersize>mini</modifiersize> means.

Trenloe
December 14th, 2016, 14:27
OK, I think one of the main issues is that you're expecting a lot of stuff to just happen. You're writing a custom action handler, for quite a specific action. So you're going to have to do some coding to process that action correctly.

<target> is a tag in the control XML, which is accessed in LUA by self.target[1]. See "Accessing XML parameters from script" here: https://www.fantasygrounds.com/modguide/scripting.xcp It is a way of re-using a control template with different parameters. In the 3.5e ruleset, an example is number_charabilitybonus in template_char.xml. This is the ability bonus field on the character sheet, that when it is "actioned" (double-clicking) it will perform a roll in the Ability action manager with ActionAbility.performRoll(draginfo, rActor, self.target[1]);

Looking at performRoll in manager_action_ability.lua we see: function performRoll(draginfo, rActor, sAbilityStat, nTargetDC, bSecretRoll) So, the sAbilityStat argument matches with the self.target[1] parameter from the template. There's a couple of arguments (nTargetDC and bSecretRoll) that aren't passed in this case.

Following the whole ActionAbility.performRoll function:

function performRoll(draginfo, rActor, sAbilityStat, nTargetDC, bSecretRoll)
local rRoll = getRoll(rActor, sAbilityStat, nTargetDC, bSecretRoll);

ActionsManager.performAction(draginfo, rActor, rRoll);
end

The next step is getRoll which basically puts all of the roll data together in the rRoll record:

function getRoll(rActor, sAbilityStat, nTargetDC, bSecretRoll)
local rRoll = {};
rRoll.sType = "ability";
rRoll.aDice = { "d20" };
rRoll.nMod = ActorManager2.getAbilityBonus(rActor, sAbilityStat);

rRoll.sDesc = "[ABILITY]";
rRoll.sDesc = rRoll.sDesc .. " " .. StringManager.capitalize(sAbilityStat);
rRoll.sDesc = rRoll.sDesc .. " check";

rRoll.bSecret = bSecretRoll;

rRoll.nTarget = nTargetDC;

return rRoll;
end
This is where the type is set = "ability" in this case, what dice to roll, what modifier to use (calls a helper function to get the ability bonus based off sAbilityStat which come from our XML <target> parameter). Then sets up the roll description - this is key (see below). A couple of other parameters are added and then control passes back to performRoll and ActionsManager.performAction(draginfo, rActor, rRoll); is called to initiate the full action sequence.

Looking in the header of manager_actions.lua we get some info on the action flow:

-- ACTION FLOW
--
-- 1. INITIATE ACTION (DRAG OR DOUBLE-CLICK)
-- 2. DETERMINE TARGETS (DROP OR TARGETING SUBSYSTEM)
-- 3. APPLY MODIFIERS
-- 4. PERFORM ROLLS (IF ANY)
-- 5. RESOLVE ACTION

-- ROLL
-- .sType
-- .sDesc
-- .aDice
-- .nMod
-- (Any other fields added as string -> string map, if possible)

Step 1 has just been initiated with ActionsManager.performAction.

Step 2 will be done automatically to see if there are any targets for the roll - this is targeting in the combat tracker and has nothing to do with the <target> parameter in the XML. In this case, there won't be any targets, or if there are (the roller has something targeted in the combat tracker), it won't be used.

Step 3 is where we apply modifiers - this is done with the action modifier Handler. So we go back to manager_action_ability.lua and we see that the onInit() function has a mod handler registered with ActionsManager.registerModHandler("ability", modRoll); So, the modRoll function is our modifier handler. Note: there is also another handler registered here - the ResultHandler of onRoll (more on that later - this is step 5 in our action flow.

Back to the modifier handler - this is where FG sees if there are any additional modifiers to apply to the roll. We've already added the base ability modifier to the roll in step 1 (stored in rRoll.nMod). The modRoll function is more to handle effects that could modify this type of roll. In this case there are a few: ABIL effects, Conditions, STAT effects, negative levels, etc..

Note that the way modRoll gets which ability to use is somewhat strange. It parses it out of the roll description using local sAbility = string.match(rRoll.sDesc, "%[ABILITY%] (%w+) check"); It isn't passed as a parameter in rRoll. This is pretty standard practice in FG rulesets - it allows data to be passed asynchronously and also allows the roll to keep it's data well after the roll has finished (so that the result can be drag/dropped from the chat window, for example). The data is usually identified by a keyword in square brackets [] - you've probably seen this a few times in FG roll results in the chat window.

This data passing in the description is setup in the getRoll function, in this case:

rRoll.sDesc = "[ABILITY]";
rRoll.sDesc = rRoll.sDesc .. " " .. StringManager.capitalize(sAbilityStat);
rRoll.sDesc = rRoll.sDesc .. " check";

Confused yet? Still with me? I hope so, because we're nearly there...

Step 4 After the modRoll handler has calculated the final modifications to the roll, the actions manager performs the actual roll. It throws rRoll.aDice (set in the getRoll function) and once the 3D dice land the final final step occurs...

Step 5 The dice land and FG raises a result event and the result handler registered in the manager_action_ability.lua onInit function is executed. This was registered with ActionsManager.registerResultHandler("ability", onRoll); so the onRoll function executes.

This is a fairly straightforward script - it basically gets the result of the roll and works out what the final description displayed in the chat window should be. At this point (the beginning of the onRoll function) no data has been outputted to the chat window, the dice have just landed...


function onRoll(rSource, rTarget, rRoll)
local rMessage = ActionsManager.createActionMessage(rSource, rRoll);

if rRoll.nTarget then
local nTotal = ActionsManager.total(rRoll);
local nTargetDC = tonumber(rRoll.nTarget) or 0;

rMessage.text = rMessage.text .. " (vs. DC " .. nTargetDC .. ")";
if nTotal >= nTargetDC then
rMessage.text = rMessage.text .. " [SUCCESS]";
else
rMessage.text = rMessage.text .. " [FAILURE]";
end
end

Comm.deliverChatMessage(rMessage);
end

A base rMessage record is created - this is what will get sent to the chat window and the message data structure is detailed here: https://www.fantasygrounds.com/refdoc/Comm.xcp

Then the message description has additional data added to it (the description from step 1 comes through and is used as the basis of the description here). So, in this case, we already have a description of "[ABILITY] XXXX check", say "[ABILITY] strength check" for example.

Then, if we have a target DC (stored in rRoll.nTarget) we check that against the result of the roll nTotal (returned from ActionsManager.total(rRoll)) and add " (vs. DC XX" (where XX is the target DC) and add [SUCCESS] or [FAILURE] to the description. Then the message is sent to the chat window. This includes the dice roll result, which is stored in rMessage.dice in the message data structure.

That's it! :)

This might seem very complex, but all you have to do is take manager_action_ability.lua as a template:
- use it to create the manager for a new action
- modify getRoll to setup the roll - set the type, the dice, add the base modifier to rRoll.nMod and include any data to be passed in square brackets - this might be your best way of passing the target number needed.
- use a modifier handler if needed - to handle effects, etc.. I don't know if you'll need this for the kingdom rolls.
- Modify the result handler onRoll to output the appropriate message to the chat window.

ronalmb
December 14th, 2016, 16:35
Hey, it's not my fault that Fantasy Grounds seems to be robust enough that a chimpanzee (in this case, me) can sit down at a keyboard, bang a few keys, see actual results and then expect the magic to just keep working ;) !

Seriously, thank you for the time you took to type all this out. I will need to re-read it several times (plus reread the links you've shared) and repeatedly do trial and error until i have have an epiphany and finally understand it like I did with the using high-level scripts. This is very complex and challenging! Thank you!

One thing I'm sure about. Just rolling a d20 and adding two has never sounded so complicated. :D

Moon Wizard
December 14th, 2016, 16:52
There are easier ways to do it by far in the FG API if you were just focusing on this one roll. However, then, you don't have all of the standard targeting, modifier system, and more incorporated. If you were going to do it directly, you could call Comm.throwDice and then override chatwindow.onDiceLanded to capture your example. Also, you would have to be careful to not break all the other rolling code.

In this case, I would just use the 3.5E file for script/manager_action_ability.lua as a starting point, and I would even take out the modRoll references to make it even simpler. I think this is the gist of what Trenloe was suggesting.

Regards,
JPG

Trenloe
December 14th, 2016, 17:00
In this case, I would just use the 3.5E file for script/manager_action_ability.lua as a starting point, and I would even take out the modRoll references to make it even simpler. I think this is the gist of what Trenloe was suggesting.
Yup.

Trenloe
December 14th, 2016, 19:09
I've taken the time to expand on the post about actions above in a new thread here: https://www.fantasygrounds.com/forums/showthread.php?35531-Fantasy-Grounds-v3-X-CoreRPG-based-Actions-(dice-rolling)

This attempts to describe the whole process. Post #4 includes a base custom action manager (the minimum needed), with an extension for a custom "MyTestAction" action that you can play with and see the results directly in your chosen CoreRPG based ruleset.

ronalmb
December 14th, 2016, 22:22
@Trenloe, I've been following that topic since earlier today when it first appeared, and throughout it's editing process (I first noticed it when #3, #4, and #5 were mere placeholders!). It is really helpful! I am sorry it required several hours of your time on my account -- but I am sure that it's going to help a lot more than just me. Again, thank you!

Trenloe
December 14th, 2016, 22:56
I am sorry it required several hours of your time on my account -- but I am sure that it's going to help a lot more than just me. Again, thank you!
No worries. It's something I've had to do a number of times over the last couple of years, and it's probably going to be used more with damned's excellent MoreCore ruleset now supporting custom dice actions, so I thought it was high time that I documented the process fully. It will save me time in the long run. :)

ronalmb
December 16th, 2016, 23:47
Captain's Log, Stardate... Spock.. how the heck do you track stardates?... Stardate.. whatever. We continue to explore the LUA cluster. Although we've made a great deal of progress, I've been informed that the security teams are on strike. They demand that starfleet change their uniform colors to gold....

Ahem. I ran my pathfinder game on tuesday and have been fighting a cold the last couple of days.. but I'm still banging away at the keyboard like a chimpanzee. Actually, I suspect the chimp might be a little further ahead of me, but oh well!

The kingdom builder extension is coming along nicely. Qualities now add to the settlement properly and then track properly up to the kingdom level. Settlements now properly update based on population size, changing the marketplace statistics for Base Value of gp, Purchase Limit, Spellcasting, and magic items (minor, medium, and major). Qualities alter these values as well. A fun but useless addition is that the main page of the settlement will display the titles of all the qualities the settlement possesses. It inserts commas and even makes sure to put "and" before the last item in the list. IF a settlement has more than 3 qualities, it makes sure to put the additional ones on the second line. I plan on extending this to a third line, for more than 6 qualities.. but this works nicely for now (see image).

Note: In case you noticed an excessive amount of usage of the word "properly", this is deliberate. The last iteration failed to add anything properly.

16947

16948

The settlement note's page is done. It's pretty much just like the notes section on the player character sheet. Nothing to take screenshots of.

I've started on the Settlement NPC tab. There's a lot I want to do with this tab, but I'll keep it pretty basic at start. An ambitious plan would have a portrait box that you can place an NPC portrait in (dimensions like a baldur's gate portrait). It'd be awesome if you could somehow right click the portrait and share the image with players.. but that might be beyond my skillset. I also want to include a speech bubble button here so you can toggle to that npc's speech. Included on the npc sheet will be a place to track notes for him as well as his opinions of pcs. Optionally, you can have especially talented npcs (i.e. high level) modify a settlement's attributes. This is not pathfinder official, so just leave these at 0 if you don't want the npcs influencing a settlement's attributes.

Once the NPC tab is finished, it's on to buildings.

Appearance wise, it's not pretty. But cleaning it up and making it look spiffy is low on my priority list at the moment.

Bidmaron
December 17th, 2016, 00:11
ronalmb, I would request you tie this into Dulux's outstanding DOE series and avoid duplicating his work. Have your settlements link to his locations extension, or at least give us the option to use that and avoid redundancies of data. I whole-heartedly endorse your effort to get the kingdom stuff working, but I believe we should avoid building in clashes with other outstanding extensions.

ronalmb
December 17th, 2016, 00:26
@Bidmaron: Thank you for the suggestion.
However, if you read from the beginning of this topic, you will see that initially, I was working from DOE as a basis, but as a very new coder, it was beyond my ability.

But more importantly, while the DOE series is freaking awesome, it does not fill my needs for pathfinder. It does not, for instance, contain the settlement attribute system nor does it provide what I require for kingdom management as per the Ultimate Campaign sourcebook and the Kingmaker Adventure Path. If you and others feel that my work intrudes on his, I shall stop posting updates and work on this solely for my own.

It was not my intention to step on toes.

Bidmaron
December 17th, 2016, 00:58
ronalmb, I agree you need what you are doing, and so do all we pathfinder fans. I am saying please don't duplicate NPC functionality and simply link to NPC records and link to locations from your settlement records for the data in Dulux's extensions. When you start talking about adding portraits to NPCs, I think you are getting into duplicative territory. Right now, you cannot do what you want outside reference library materials anyway (although I suppose you could use a giant token as a portrait). All I am asking you to consider is please don't duplicate functionality and data required elsewhere because in many cases, you are going to want to be able to use the NPCs in an encounter or the combat tracker, for example.

Perhaps when I get done with the table extension work I am doing, I might be able to help you by working on Dulux's extension to link back to your extension where it makes sense.

ronalmb
December 18th, 2016, 12:28
@Bidmaron: Currently this is what my NPC records do (please forgive the ugliness of the sheets, i've done nothing to make them look nice yet).

Main Page: Standard NPC information block to provide the DM with quick access to important stuff, should it be necessary, plus a box section where they can set how the NPC affects the settlement/kingdom. The modifiers block is crucial for rulers, councilors, generals, High Priests, etc in the Kingdom Building rules. The link box in the upper right hand corner just creates the standard NPC record that can be drug from here to anyplace that accepts an NPC. The attributes on this page link to the npc entry as well.. and can roll attribute checks.. but I'm not stuck on using this. It's mostly a placeholder until i can figure out how to stick a nice portrait in there.

16968

Description Page: A place for the DM to record information on the NPC. I like the detail that Realm Works from Lone Wolf provides. I own the product but frankly, its difficult to try to run that and Fantasy Grounds.. and i believe I can use Fantasy Grounds to do the same exact thing but prettier and access to dice and tabletop. I know i could use the last page of the NOTES page for the standard npc record to do all this stuff.. but I like to keep track of a lot of information for important npcs.. and that single page gets long and cluttered.

16969

History Page: Another text box, to keep track of the npc's ongoing history as it relates to the party. It's handy to have when I need to remember that Vloras the Green insulted Blacksmith Tomas's wife on the last visit six months ago. The relationships box will be a list you add to with no links. Each line of the list will be a player name, plus the npc's current relationship with them, as per Ultimate Campaign rules on relationships.

16970

Motives, Friends & Allies: More fluff text, just organized. I am sure i could have really pruned the Realm Works fields for all sorts of stuff but I tried to stick to the ones i used most. There's only so much space and so many tabs (but someday I'd love to figure out a tab system that uses BOTH sides of a character sheet!)

16971

Notes: And finally just an additional page for anything else that I may have missed.

Its not the intent of the npc entry to duplicate any current functionality anywhere if i can help it. I like DOE and that has been my inspiration for making this extension. I'd love to be as skilled as Dulux at this! Buildings will work almost the same. They need to exist within the Kingdom Building extension context as they provide modifiers to settlements and kingdoms. For ease of use, I would have wanted a buy and sell inventory list for shop-type buildings but 1)It is beyond my skillset at this time and 2)DOE already does it. Buildings should have their own npc tab for the npcs there.. but trying to handle all the information is already getting challenging for me!

And speaking of information and data... it occurs to me that it can get incredibly complex trying to remember it all. I am curious as to how others handle keeping track of all the various data nodes they have and remembering where they are, what they are. What are some tools or tips you have that makes your life easier?

damned
December 18th, 2016, 12:55
ronalmb having followed the thread but not tried the extension I have a couple of questions/suggestions...

Is this a new NPC record sheet? You might be better off (I dont know how far down this particular lane you are) adding these tabs to the existing NPC records and then you get ALL the data in teh one location. Then configure your Kingdom windows to accept links to the standard NPCs.

ronalmb
December 18th, 2016, 13:06
@damned: A very good idea. I was leery of touching any of the core stuff. Mostly because I have no clue how to add on without overwriting (is this what the merge thing is?) and because i have no idea how to handle linking from one thing to another. Doesn't matter how far down the lane i may or may not be.. I suspect redoing things is part and parcel of making extensions (and programming in general).

The npc link box is just duplicating the happy accident i had with the random table link box on the settlement tab. Both just open up an appropriate record, but they are not attached at all to the records and npc collections as they should be. I know i can drag a copy from my links to the tables or npcs recordlists and they will duplicate there (but not vice versa).

I'm doing pretty well for an artist with minimal programming experience - I am sure that when anyone looks under the hood of this thing there will be all sorts of things I could have done better! Yes, the responsible thing would be to learn all this stuff first and start with small extensions and then tackle larger things as i get better -- but I DM the pathfinder Kingmaker adventure on tuesdays and the party is just starting to found their settlement. There's a lot to track. Fool me would probably be done by now if i had just madepages that tracked input without trying to auto-calculate!

Bidmaron
December 18th, 2016, 13:21
....Currently this is what my NPC records do (please forgive the ugliness of the sheets, i've done nothing to make them look nice yet)....

Ronalmb, you've done a great job on this, and I don't know why you would want to change your sheets (other than below). I am with damned though that it would be better to modify Dulux's work to add yours than create parallel material.



Main Page: .... The link box in the upper right hand corner just creates the standard NPC record that can be drug from here to anyplace that accepts an NPC. The attributes on this page link to the npc entry as well.. and can roll attribute checks.. but I'm not stuck on using this. It's mostly a placeholder until i can figure out how to stick a nice portrait in there....


This is great that you have linked (meaning you extract and place the data on the other record I think?) to the NPC record (I suppose it will be smart enough to create that shell record should one not exist?) for the attributes. As for the link, you state you intend to remove it, but this will be a great way to link to the built-in functionality. Why would you remove that?
As for the portrait, as I've mentioned before, until Unity (or some other profound modification to the existing underlying engine), your only option will be to link to an image or to use a token. There are no imbedded graphics other than these unless it is a reference manual (I have looked hard to find otherwise, and I don't think I've missed anything in this regard).



....
History Page: ...The relationships box will be a list you add to with no links. Each line of the list will be a player name, plus the npc's current relationship with them, as per Ultimate Campaign rules on relationships.
....

You should always link to other records, like here and in the friends and allies section. Why wouldn't you want to do that?

Again, I am tracking your work with great interest, but as much as I love what you are trying to do, I am too wed to the current DOE extensions and the built-in NPC functionality to want a parallel architecture that does not tie into the built-in and established extension functionality.

damned
December 18th, 2016, 13:42
@damned: A very good idea. I was leery of touching any of the core stuff. Mostly because I have no clue how to add on without overwriting (is this what the merge thing is?) and because i have no idea how to handle linking from one thing to another. Doesn't matter how far down the lane i may or may not be.. I suspect redoing things is part and parcel of making extensions (and programming in general).

You only learn this stuff I think by doing. Big project, little project you still make plenty of decisions that you might do differently later on.

Have a look at the 3.5e ruleset, \campaign\record_npc.xml
Copy the whole thing into your extension and work out how to add a single tab.
Comment your changes start and finish locations as this file may change a little over time in the 3.5e ruleset but probably not by much and not often.
See how long it takes to work out and add one tab and I think you might find that direction a good way to go... or not... :)

ronalmb
December 18th, 2016, 14:04
My biggest concern with overriding(?) an existing thing is the potential harm i could do to someone's campaign data files if i screw something up. Right now, it seems like any potential bugs I have in my data-structure will be limited to the <kingdom></kingdom> entries since i don't go outside of it at all. In which case a worse case scenario is to just turn off the extension, open the .db, and delete <kingdom>. I may be wrong, but I have a feeling that if i tamper with <npc> and screw up handling the data, I could do damage to people's campaigns. I'd hate to be "that" guy. Once I have a solid understanding of everything and feel more confident, I could see where that is the ideal and right way to go. Off course, this is moot if I don't share the extension - but I'm hoping others will be interested in it.

If I did go that route, I would need to be able to access that npc to see how he affects the settlement/kingdom. In the kingdom-building rules, you can appoint a character to a position such as ruler, councilor, etc. Based upon position and character attributes, they can modify a kingdom's attribute scores. I have extended that concept in my campaign to the idea that very skilled characters can improve or worsen the settlement's attributes as well.

I would need to be able to assign settlement/attribute modifiers to an npc. Then, when i drag the npc on to a link in the settlement, it would need to access that npc's modifiers to know how much and of what to add. When the npc is removed, it needs to remove those modifiers. Currently this is done on on the settlement level, through it's npc list. You are right that having it all condensed to one location (the npc record) is better but that brings up the following questions:

1) If i drag an npc link to, say, a building. What is the best way to go from settlement->building->linked npc to get it's modifiers to economy, stability, etc so that i may feed it to the functions that update a kingdom's attributes? I guess that it is still a list of npcs.. and i would still just go through all the children looking for that info.

2) If i alter a modifier on an npc in the npc record list, how do i trace upward to make sure that the settlement he 'belongs' to is also updated? Of course, it might be as simple as getParent(), to.

3) If i add tabs on to the 3.5 record_npc through my extension what would happen to it or other people's campaigns if they are using other extensions that modify the npc record?

Bidmaron
December 19th, 2016, 00:02
My biggest concern with overriding(?) an existing thing is the potential harm i could do to someone's campaign data files if i screw something up. Right now, it seems like any potential bugs I have in my data-structure will be limited to the <kingdom></kingdom> entries since i don't go outside of it at all. In which case a worse case scenario is to just turn off the extension, open the .db, and delete <kingdom>. I may be wrong, but I have a feeling that if i tamper with <npc> and screw up handling the data, I could do damage to people's campaigns. I'd hate to be "that" guy. Once I have a solid understanding of everything and feel more confident, I could see where that is the ideal and right way to go. Off course, this is moot if I don't share the extension - but I'm hoping others will be interested in it.

Well, for this, if you add a tab to the NPC record and put the data in a subwindow, it should not contaminate the parent data. During the test phase, and upon first install, encourage people to back up their data base.


If I did go that route, I would need to be able to access that npc to see how he affects the settlement/kingdom. In the kingdom-building rules, you can appoint a character to a position such as ruler, councilor, etc. Based upon position and character attributes, they can modify a kingdom's attribute scores. I have extended that concept in my campaign to the idea that very skilled characters can improve or worsen the settlement's attributes as well.

I would need to be able to assign settlement/attribute modifiers to an npc. Then, when i drag the npc on to a link in the settlement, it would need to access that npc's modifiers to know how much and of what to add. When the npc is removed, it needs to remove those modifiers. Currently this is done on on the settlement level, through it's npc list. You are right that having it all condensed to one location (the npc record) is better but that brings up the following questions:

1) If i drag an npc link to, say, a building. What is the best way to go from settlement->building->linked npc to get it's modifiers to economy, stability, etc so that i may feed it to the functions that update a kingdom's attributes? I guess that it is still a list of npcs.. and i would still just go through all the children looking for that info.

To see how to get to record data through a link, take a look at the code in manager_table.lua (I am sure there are lots of other places). The getResults function sets up an action table for the onTableRoll routine to use. Within onTableRoll you can see examples of how to get to the data underlying a link.


2) If i alter a modifier on an npc in the npc record list, how do i trace upward to make sure that the settlement he 'belongs' to is also updated? Of course, it might be as simple as getParent(), to.

Well, what I'd recommend you do is add a reverse link back to any settlement the NPC is in. You would traverse the link in the same manner as in #1.


3) If i add tabs on to the 3.5 record_npc through my extension what would happen to it or other people's campaigns if they are using other extensions that modify the npc record?

That part gets hard. If they have used good coding, unless you happen to use the same node names or window names, you should be ok. Unless you want to scour the extensions listed in the PFRPG ruleset and its parents, you would just have to let users test it.

damned
December 19th, 2016, 00:33
As you would be adding extra tabs and extra fields you should not contaminate existing data. Unloading the extension would hide any data your system added.
If someone elses extension also changed the tabs in the NPC record then one or the other extensions wont load properly - I dont use Pathfinder and am unaware of any extensions that currently modify the NPC tabs.

The more complex programming questions... I dont have suggestions/answers for - Bidmaron or Trenloe can offer better advice.

ronalmb
December 19th, 2016, 14:03
@Bidmaron: Thank you for your continued assistance. I feel silly for asking: What do you mean by reverse link? Yeah, I'm that clueless.

Buildings and a future library

Here is a brief image from a couple of buildings from Ultimate Campaign, Pathfinder to illustrate what I am doing with buildings and to serve as reference for the question(s) that follow.

16979

Every building is a template of information and this information is fortunately pretty consistent throughout all of them. Down the road, I picture a library of buildings (like feats, spells, skills, etc) that can be dragged from the library and onto a settlement where they automatically apply the modifiers. You'd be able to further edit the building by giving it a name, etc.

This involves drag and drop - which is something I have yet played with. Where do I look in the xml/lua for good examples of how to drag and drop a link from one location to another? I figured record_story from CoreRPG was a good start but there was nothing there. Is this built into the code for links instead?

Bidmaron
December 19th, 2016, 23:06
ronalmb, it is honestly amazing that you have come as far as you have in as short a time as you have. So please don't belittle yourself.

Let me preface this by saying I am not an expert either, and I regularly get a calibration from MW or Trenloe on stuff I post.

Sorry on the reverse link. What I am really saying is that in the npc record, you would need to record a link to the settlement record. The settlement, in its list of npcs, would have links to all the npcs. This is what I meant by a reverse link. You couldn't use 'GetParent' because the parent of any npc record would be the list of npcs, not the settlement. You can decide whether you want to expose the reverse link (back to the settlement) in the npc UI or not (I'd argue that you probably should.). The other thing you would need to decide is whether you want to confine an npc to one settlement or not. Obviously (unless you want to support an NPC who can have physical presence in multiple locations simultaneously), the NPC only has one location (unless you are interested in supporting multi-plane existence, where some or all have simultaneous presences in more than one quasi-physical location), but you might want to retain a list of locations where they could appear, with only one 'active' location at a time. So, a reverse link is either a window reference DB node (which contains the window class name and the data node name) or you can simply store the absolute node name as a string value. A window reference DB node looks like this:


<link type="windowreference">
<class>npc</class>
<recordname>reference.npcdata.aasimar1stlevelwarrior@Complete SRD Monsters</recordname>
</link>

This example is a reference to the npc window and the aasimar npc.

So, unless you want to give the user the option to navigate to the settlement from the npc, I'd recommend saving database space and just storing the database node name as a string.

By the way, I believe I own everything pathfinder except the T-shirts from Paizo.(yes, I own the convention buttons)

As for drag and drop, the system FG uses is really flexible and ingenious. In the immortal words of Moon Wizard:

When a user clicks on a windowcontrol object and begins dragging, an onDragStart event is fired for the windowcontrol. One of the parameters passed into the event function is a dragdata object. If your windowcontrol script is handling the event, then it would update the dragdata object with the drag "type", strings, numbers, shortcuts, dice, etc.; then, return true to tell FG that the script is handling the drag event and not to perform the default processing for the control (i.e. drag text if stringcontrol, drag number if numbercontrol, etc.).

When the user releases a dragdata object onto another windowcontrol, that windowcontrol receives an onDrop event with the dragdata object passed as a parameter. Then, the windowcontrol can inspect the dragdata object to determine whether it is a drag type that it wants to capture, inspect any elements, and return true or false to tell FG whether it is handling the drop event.

There are several examples of drag and drop handling in the built-in rulesets (3.5E / 4E). Just look for "function onDragStart" and "function onDrop".

Regards,
JPG
If you search for these functions in NotePad++ file search, you will be overwhelmed in the number of hits. It is actually not that hard to get working if you can find a similar drag and drop example and steal it.

ronalmb
December 23rd, 2016, 16:22
Update: I am still plugging away at this, despite the last four days of silence. I'm currently working on a simple system for adding events at the kingdom and settlement levels. This is another form of "inventory" with modifiers that affect the kingdom or settlement, depending upon the level at which the event occurs. When a kingdom has an ongoing event, you will want to make sure you add information to the calendar to help remind you to remove the event when it expires. I'm sure there's probably some sort of automation that can be done there between the extension and the calendar.. but bridge and crossing, and all that.

In the meantime, I hope everyone has a wonderful Christmas holiday, if you celebrate. If not, I still wish you ongoing warm, good cheer, and prosperity!

ronalmb
December 29th, 2016, 12:42
Progress Report
The holidays have slowed me up some. Mostly because I got Stellaris and Civ Vi -- both colossal time devourers. I'll need to be careful of them. I used my kingdom builder for my first game session on Tuesday, which coincided with the party founding their kingdom and putting down the first settlement. The tracker was handy for recording the effects of their decision on what alignment to run the settlement under. The NPC tabs were handy for the short term, but they aren't a good way of recording the modifiers provided by PC rulers. I dropped the NPC tab off the Kingdom-level sheet and have replaced that with a Ruler tab that lets me enter who is filling what post, and their modifiers to Economy, Stability, and Loyalty (Rulers do not effect the other settlement related attributes).

17111

I plan on including a link box to each name entry that you can drag a PC or an NPC to and you can open that to access the actual character. I haven't gotten to learning how to make empty link boxes and working out how to accept only a PC or NPC record, but I've already received some pointers on that in this topic so its only a matter of getting to it and getting it done. In the campaign rules for running a kingdom, a ruler applies one of two modifiers to one or more of the three kingdom attributes. Ideally, I should just include a system on the Ruler tab where you check boxes to identify which character attribute to use and what kingdom attribute to affect and let the system take care of the math. For now, the DM has to input the correct numbers into the correct boxes. It'll do.

The settlement added its first building during the game, a general store.

17112

As with the ruler tab at the kingdom level, it'd be nice to link an NPC sheet here. I also wonder if i should have put the npc tab I have at the settlement level on each building instead. It seems to make sense. It's better organized.

Adding a Kingdom Building assistant tab to the NPC records
I've received the excellent suggestion of adding a tab to the NPC records where i can apply settlement modifiers and more ways to organize campaign data about non-monster NPCs and I started giving that a go. So I decided to add a Campaign tab to the NPC sheet. It would include all the settlement modifiers that the npc affects, plus a more organized way for me to record personality, appearance, history, and attitudes towards various PCs over the course of the campaign's history.

The first thing I realized is that the NPC record tabs do not behave like the tabs on the player character sheet. There is more complicated stuff going on. I realize this is necessary because it is important to differentiate between Creatures, Traps, and Vehicles but its an additional complication that I really don't want to tangle with - even if its the best and right way to do it. I'll have to explore my options and weigh whether the time investment on sorting it out is worth the extra and correct functionality. I suspect it is.. but it will also take me off my timetable.

So for the short term, I'm still using the additional NPC tabs on the settlement sheets until I work out a plan to do this the right way.

Bidmaron
December 29th, 2016, 13:05
Progress Report
....
As with the ruler tab at the kingdom level, it'd be nice to link an NPC sheet here. I also wonder if i should have put the npc tab I have at the settlement level on each building instead. It seems to make sense. It's better organized.
...

I think this is too restrictive. You will eventually want to get to the settlement's list of NPCs (say you have a settlement random encounter table, and one of the entries is 'Settlement NPC' - then you would want to see all the settlement NPCs in one place so as to pick or roll which one you want to be in the encounter. So, by all means put the NPC in the building they are most likely to be found in, but also put them in the settlement NPC list. At least that's what I recommend.

ronalmb
December 29th, 2016, 16:11
I think this is too restrictive. You will eventually want to get to the settlement's list of NPCs (say you have a settlement random encounter table, and one of the entries is 'Settlement NPC' - then you would want to see all the settlement NPCs in one place so as to pick or roll which one you want to be in the encounter. So, by all means put the NPC in the building they are most likely to be found in, but also put them in the settlement NPC list. At least that's what I recommend.

I agree with you. I really need to make time to sit down and grasp links. I'm sure they aren't as hard as some of the things I have already done.

By the rules, I think, the only way an NPC character affects a settlement or a kingdom is by being a position of rulership and adding to economy, loyalty, and stability. There is no reason I need to include settlement modifiers on NPCs other than I like the option to be able to do so included if I choose to have a character "that vital" to a settlement.

Trenloe
December 29th, 2016, 17:08
I really need to make time to sit down and grasp links.
Yeah, they're pretty straightforward. Some pointers here: https://www.fantasygrounds.com/forums/showthread.php?35736-Drag-and-Drop-List-of-Links&p=309707&viewfull=1#post309707 and in that thread in general.

Bidmaron
December 29th, 2016, 17:37
I think you should absolutely support NPCs that have the potential to affect settlement modifiers. After all, the list of 'leaders' in the Ultimate Campaign volume cannot account for all the vagaries that might exist in your world.

Links are really not that hard. If you search for 'onDrop' across the files of a ruleset, you will find lots of examples of supporting links, including checking the type of the underlying record to ensure the link fits the context or to tweak the context to match the link.

ronalmb
January 1st, 2017, 11:50
Hello, playing around with links still. Have some questions for a specific scenario that I am looking for assistance with.

17161

Above is the kingdom rulership tab. The idea here is that there will be an entry for each position within a ruler. Ideally, each post should have an empty link box that would take a player or an npc link. Clicking on the empty link should not create anything. Only clicking an existing link should, and it should open up the actual record, not a copy.

The first obstacle I've hit is that players don't have link boxes (that i can tell) so linking a charsheet is out. Not really a big deal, as there isn't many players and you can just look them up other ways.

Mostly, i'm having difficulty working this out in my head how to get it to work with NPCs. I've looked at the list example from record_char_abilities and template_char in 3.5, thinking I should be able to make it work for me and it should be simpler because on this page I'm not dealing with creating dynamic lists. Each link is an empty, static box that I just drag to. Turns out for me that not using a list here complicates my ability to understand the process.

I'm drawing a blank on finding an existing example of what I want to do here and am looking for suggestions.

Bidmaron
January 1st, 2017, 14:59
OK, let's deal with one issue at a time. You can synthesize drag and drop of a character using the character's token (this appears to be the way FG officially handles character drag). You really should not just have a static box, by the way. The best technique would be to have the drop destination be a 'windowreferencefield'. You would have to put the following code into the 'onDrop' handler through a <script> tag or in a script file:


function onDrop(x, y, draginfo)
if draginfo.isType("shortcut") then
draginfo.setSlot(1);
local winClass,winDataPath= draginfo.getShortcutData();
if winClass=="charsheet" then
setValue(winClass,winDataPath);
else --in here later, we will check for an NPC and handle that case as well
ChatManager.SystemMessage(Interface.getString("Shortcut_Not_Supported"));
return;
endif
else
ChatManager.SystemMessage(Interface.getString("Shortcut_Not_Supported"));
return;
endif
end

This works because the system currently uses the character's token as the drag field to represent the character. Why they didn't include a character link is very puzzling and should be fixed.

Caveat: I have not tested this code.

I am sure one of the experts will be along in a few and point out something wrong above, but I think it will work.

Bidmaron
January 1st, 2017, 15:03
By the way, you also need to provide a corollary onDragStart so people can drag the character to other meaningful places. See the onDragStart in the file template_char.xml in the token_char template for how to do this.

Bidmaron
January 1st, 2017, 16:40
I would store the parameters in the character's record rather just in the kingdom/settlement. That way, if the character moves to another realm, his data goes with him instead of vanishing. To do this, you can place the following code in the onInit code for each of the ruler and leader windows:


DB.addHandler(DB.getPath(getDatabaseNode(), "economy"), "onUpdate", onEconomyUpdate);
DB.addHandler(DB.getPath(getDatabaseNode(), "loyalty"), "onUpdate", onLoyaltyUpdate);
DB.addHandler(DB.getPath(getDatabaseNode(), "stability"), "onUpdate", onStabilityUpdate);

And their corollaries in your record's onClose:


DB.removeHandler(DB.getPath(getDatabaseNode(), "economy"), "onUpdate", onEconomyUpdate);
DB.removeHandler(DB.getPath(getDatabaseNode(), "loyalty"), "onUpdate", onLoyaltyUpdate);
DB.removeHandler(DB.getPath(getDatabaseNode(), "stability"), "onUpdate", onStabilityUpdate);

Then you will need each of the handlers, one of which is below (this assumes each of your leaders is in a window of its own and that the name of the windowreferencefield is leaderLink):


function onEconomyUpdate()
local _,adjustData=window.leaderlink.getShortcutData();
local kingdomAttrAdjustNode=adjustData.createChild("economy","number");
kingdomAttrAdjustNode.setValue(getValue());
end

If you ever decide to add those adjustments into the character sheet, you would need to update the data stored in the character's current kingdom/settlement record. Note these routines will work whether it is a character or NPC, as they are agnostic as to the window class of the enclosing data entity.

ronalmb
January 3rd, 2017, 11:46
OK, let's deal with one issue at a time. You can synthesize drag and drop of a character using the character's token (this appears to be the way FG officially handles character drag). You really should not just have a static box, by the way. The best technique would be to have the drop destination be a 'windowreferencefield'. You would have to put the following code into the 'onDrop' handler through a <script> tag or in a script file:

<snip>

This works because the system currently uses the character's token as the drag field to represent the character. Why they didn't include a character link is very puzzling and should be fixed.

Caveat: I have not tested this code.

I am sure one of the experts will be along in a few and point out something wrong above, but I think it will work.

Bidmaron, thank you for your continued assistance. I will digest this information and put it to use, after i locate and learn what a 'windowreferencefield' is! I don't have much time until later this week - it's been a busy holiday stretch.

Bidmaron
January 3rd, 2017, 12:25
If you go to pathfinder wiki, there is a link to developer guides, which has a link to ruleset references. I am sure you have already used this though by now. Anyway windowreferencefield is there.

Bidmaron
January 14th, 2017, 18:38
Step 5 The dice land and FG raises a result event and the result handler registered in the manager_action_ability.lua onInit function is executed. This was registered with ActionsManager.registerResultHandler("ability", onRoll); so the onRoll function executes.


It seems like it does no good to register a handler unless the handler type is defined in the ruleset, right? Because the following code in the manager_actions.lua file will not execute the handler even it is registered unless the manager_gamesystem.lua file has defined the action:


function onDiceLanded(draginfo)
local sDragType = draginfo.getType();
if GameSystem.actions[sDragType] then
local rSource, rRolls, aTargets = decodeActionFromDrag(draginfo, true);

for _,vRoll in ipairs(rRolls) do
if #(vRoll.aDice) > 0 then
handleResolution(vRoll, rSource, aTargets);
end
end

return true;
end
end

So, it would seem like the steps necessary to handle an entirely new action would be to have the following in your onInit:


If not GameSystem.action["newaction"] then
Gamesystem.action["newaction"]={sIcon="someicon", sTargeting="target kind",bUseModStack="boolean"};
end
ActionsManager.registerHandler("newaction",myCallBack);

where SIcon, sTargeting are optional and must be respectively the valid name of an icon resource and a valid targeting type for the ruleset, and where bUseModStack should be true or false depending upon whether you wanted the modifier stack to be used or not.

Can one of the luminaries of FG make sure I have this important concept right or am I just missing something?

Moon Wizard
January 15th, 2017, 04:13
Yes, you need to set up in GameSystem.actions with the appropriate flags. (Default should probably be { bUseModStack = true }) And, then you need to set up handlers using ActionsManager (registerResultsHandler, registerModHandler, registerPostRollHandler, registerTargetingHandler), where the default is just registerResultsHandler unless you need extra handling for effect modifiers, post roll cleanup or targeting differences.

Regards,
JPG

Bidmaron
January 15th, 2017, 05:06
Thanks, MW. Just out of curiosity, why doesn't registerResultsHandler put the action into the GameSystem?

One other question: what happens if you call the Action Manager performAction with a dice array that has a non-standard die for the ruleset? Code calling it seems very careful to filter out non-standards before calling ActionManager. This seems wise, as ActionManager doesn't seem to do anything but pass the dice to Comm.throwDice. There is nothing I can find documented as to what Comm will do if it gets a non-standard die.

Trenloe
January 15th, 2017, 06:04
It seems like it does no good to register a handler unless the handler type is defined in the ruleset, right?
The "action" needs to be defined. See the "note" at the bottom of post #1 here: https://www.fantasygrounds.com/forums/showthread.php?35531-Fantasy-Grounds-v3-X-CoreRPG-based-Actions-(dice-rolling)

Bidmaron
January 15th, 2017, 06:17
I was doing it anyway 'cuz I figured it couldn't hurt. Do you know what happens if you do performAction with an aDice that contains non-standard die for the ruleset? Comm.throwDice doesn't really mention what will happen in API docs.

Trenloe
January 15th, 2017, 06:26
Do you know what happens if you do performAction with an aDice that contains non-standard die for the ruleset?
I don't know, try it.

Bidmaron
January 15th, 2017, 06:44
I'll let you know....

Moon Wizard
January 16th, 2017, 03:47
I just added the automatic registration into GameSystem.actions for the add registration handler functions in ActionsManager for v3.2.2 beta.

Regards,
JPG

Bidmaron
January 16th, 2017, 03:53
Wow. Thanks MW.

damned
April 3rd, 2017, 03:35
Hey ronalmb - how are you going with this?

BakaMatt
June 25th, 2017, 16:56
Is this extension still in development? The in progress looks amazing and I would love to get my hands on it!

flipwalker42
December 29th, 2017, 01:31
I too would like to know if this is still in progress? About to start a Kingmaker game and would love to have integrations for the Kingdom stuff.

Philip

Bidmaron
December 29th, 2017, 03:49
I am not yet working on kingdom maker because I needed better tables first. I am getting pretty close to releasing version 0.1 of a Generators extension. This fixes the asynchronous roll problem Myrdin reported, adds the ability to have pre-processor and post-processor stuff (common things you might want to do before and/or after the roll on the table), and essentially provides all of the functionality of story templates right within the table itself. I have also inserted an experimental a/an feature that lets the table provide either a or an depending upon the antecedent (is that the right word?). That is, you can roll something like this: The backpack includes [a] [color] sphere. If color came up brown, this would produce "The backpack includes a brown sphere," while if color came up orange, it would produce "The backpack includes an orange sphere.".

Additionally, you can provide punctuation (or almost any other character) to separate series, so that something like "The backpack has [d3xa,] [junk items]" would generate either:

The backpack has a knife
The backpack has a knife and a fork
The backpack has a knife, a fork, and an arquebus

assuming that the table junk items generated those three items (and others).

The experimental a/an does not deal with all the English edge cases properly yet (like the silent 'h').

You can also do rudimentary singular/plurals, so something like "The backpack has [d12] [junk items]" would generate either "The backpack has one fork," The backpack has two forks," ... "The backpack has ten forks," "The backpack has 11 forks," or "The backpack has 12 forks." Unfortunately, with my primitive version it will also generate "The backpack has two knifes", but it will handle most 'es' plurals okay. I will make this algorithm more sophisticated downstream, but it handles a lot of singular/plurals correctly now.

Also, you can now export and import individual tables, which will facilitate the rapid sharing of tables without having to produce a module. You can drag existing tables onto the generators list to convert a table to a generator.

I am not in the business of predicting when I will get it done because my work schedule is crazy, but I have the synchronous roll problem figured out, but I am still testing a lot of the other features.

I also fixed the issue someone mentioned the other day (https://www.fantasygrounds.com/forums/showthread.php?41535-Suggestion-re-Tables) so now when you create a new generator, if you drag dice onto the custom dice field, it will auto populate an empty table (it won't monkey with a table that already has entries) to create one entry for each possible roll.

Furthermore, it will properly figure out that a table with items labeled 2, 3, 4 ... 8 should be 2d4 and not d7+1 like the current table implementation will do.