1. #1

    Ruleset layering summary?

    Hey all,
    I've been reading about the new merge functionality in 3.0 and wanted to run a few questions by you, and maybe hopefully round up some of the information I've read in various different posts into one place as well as get some clarification on how this feature works so those learning about 3.0 can have a starting point. I can update this post to reflect the info that is provided, if you all agree that that is helpful. Or, if this is all found somewhere else and I've merely overlooked it, please point me in the right dir!

    I am a newbie to fiddling around under FG's hood, so some of what follows may elicit facepalms from the more experienced among you. I ask for your patient forebearance! :P

    The release notes say:
    Developer - Ruleset Layering

    • Ruleset layering support added via use of importruleset tag within base.xml file. Higher layers override lower layer objects (font, framedef, windowclass, template, etc.). Lower layers will be checked for files referenced in higher layer, but not included in higher layer.
    • Attribute merging supported in templates.
    • New merge attribute supported by controls and templates. Applied at referencing layer, and overrides mergerule attribute used at referenced layer.
    • Valid control/template merge attribute values are: merge/join (default), add, resetandadd, replace, and delete
    • Valid panel/windowclass merge attribute values are: replace (default), join, and delete
    • Valid die/customdie merge attribute values are: replace (default) and delete
    • When merging windowclass objects, nested scripts are supported. (i.e. accessible via super variable, similar to controls)
    • When merging windowclass sheetdata, the name attribute will be used instead of the tag name for matching.
    • When merging windowclass sheetdata, insertbefore attribute added to define alternate control order other than appending newly merged controls to end of control order.
    So, if I create a new ruleset and put <importruleset source="CoreRPG" /> into my base.xml, then I'll get what's in the CoreRPG for any and everything that I don't explicitly override with new code, much like if I were writing an extension. Right?

    To override a particular item, we use <merge = " " /> tags in our new code to specify how the new objects are to interact with the old code, right?

    So, does this mean we can make overrides at an object level? We can leave everything in a given file just the same as in Core, but override a single class definition? That means we don't have to replace an entire file just to make one change in it. Am I still following correctly?

    Example 1: Suppose you want to make changes to a windowclass charsheet_main in the CoreRPG ruleset. In CoreRPG, that's located at \campaign\record_char_main.xml. So, for your changes:
    1. Where will you put them? Do you create a file called record_char_main.xml, and put it in the campaign folder, so that it's in the same place as the class you are modifying?
    2. In your newly created .xml file, will you put ONLY the xml header, root tags, and your new version of the windowclass, including merge tags?
    3. What if your change was something very small, like adding a <nodrag /> to the existing class and not replacing it entirely?
    4. Are there times when merging and/or replacing are going to happen implicitly, and no merge tag is needed? What if I just include a totally new version of a given file, with no mention of merge in it. Does FG sub the whole file for the original? Are merge tags only needed when you want to replace something smaller than an entire file?

    Example 2: Let's say you want to modify not a class, but a .png or a .lua? Let's take for example the background on the desktop. To keep it simple and focused on what's new in 3.0, let's say you're not moving decal or frame coordinates or anything, and just say you slapped a new icon exactly within the area of the original decal.
    • So, you would put your new desktop.png in your own ruleset folder, creating the location \graphics\frames\ and putting it there. Right?
    • Since the file name is the same as it was in CoreRPG, are you immediately all set, or do you need to go in somewhere to specify that the desktop.png file in the new ruleset takes precedence?
    • Or to come from another angle, say you want to make some changes in manager_char.lua. Do you just drop in your new .lua file? This file is specified in Core's base.xml in line 96. Would you need to put something in your own base.xml to let FG know to expect a new version of this script? If so, what would that look like?

    Merge types:
    The release notes mention several types of merges. Not all of them are valid for every kind of object, as described.
    • Merge/add: This is the default, the notes say. Does this mean that to specify this type, we can just say <merge /> without including = " "?
    • <merge = "add">: I'm going to guess and say that this tells FG that you're adding a new object or whatever to the existing code. Es verdad?
    • <merge = "resetandadd">: Can anyone offer a quick definition for this one?
    • <merge = "replace">: I would imagine this means you are just straight replacing the given entity as described in the original ruleset with a new definition?
    • <merge = "delete">: This means you want the entity stricken from the rolls and not used in the ruleset?

    Any other basic info that should be mentioned about this functionality?

  2. #2
    The ruleset layering functionality has not been documented yet other than the release notes. I plan to do a writeup once it is ready, but I can definitely answer questions as we go as well.

    I'm going to answer as best I can at this hour. Feel free to ask for clarifications.

    • The importruleset tag loads all files in the target ruleset into the current campaign session.
    • All named top-level objects and XML tags can be overwritten by a higher layer. (font, framedef, desktopframe, categoryselectionssettings, die, customdie, diebox, pollbox, windowclass, panel, hotkeybar, tooltip, portraitset, icon, characterdbroot, tokenroot, imageupdatefolder, template, script, distance)
    • Some named top-level objects (panel, die, pollboxwindowclass, templates) support additional editing options (replace, join/merge, delete). The default for all top-level objects is "replace".
    • When using control templates, the default behavior is to "merge".
    • "replace" will fully replace the named object or control.
    • "merge" or "join" will merge the underlying XML into a unified single record. Values specified in the top-level object override values in the bottom-level object. Any child nodes also merge unless otherwise specified on the child nodes.
    • "delete" will delete the named object or control.
    • Additional merge options can be specified at the XML tag level (add, resetandadd). When "add" is specified, the specified tag will be appended to the bottom-level record, regardless of whether a tag with the same name already exists. If "resetandadd" is specified, it will behave the same as "add", except that any tags with the same name will be cleared first.
    • When replacing/merging/deleting a top-level object from a files, only the object you are changing needs to be named. No other objects in the original file need to be referenced.
    • When using the "merge" attribute for windowclass objects, there are two tags with special behaviors (script and sheetdata). The "sheetdata" tag will always "merge" based on the child control tag and name combination. Scripts will be nested with the top-most script able to call deeper scripts using the "super" tag. The "self" tag can be used to access the top-most script from a deeper level.
    • When using control templates, there is one tag with special behavior (script) and any other control template referenced will be merged as well. Scripts are nested with the top-most script able to call deeper scripts using the "super" tag. The "self" tag can be used to access the top-most script from a deeper level.
    • Any files referenced in a particular layer will be looked up at that layer. If not found, the lower layers will be checked for the file in the same relative location (in the lower layer ruleset directory). Layers above the referencing layer are never checked.

    Example 1

    • The new windowclass object can be put into a ruleset definition file with any name, then referenced in the base.xml. As mentioned above, the lower layers are not referenced unless the file is missing in the current layer.
    • Only the new windowclass definition (merge/join, replace, delete) is needed, other than general XML header and root tag.
    • The most straightforward way of modifying a windowclass (with v3.0 layering) is to add nodrag to a control is to use the merge="join" attribute in a new windowclass definition with the same name attribute. Then, include a sheetdata tag within. Next, include the control type and name just like defined in the original file, and include the "nodrag" tag within the control tag. By default, the merge="join" specified on the windowclass will apply to the behavior used for the control. (unless override using "replace" or "delete")
    • Other options include full windowclass replacement (how extensions used to work) or modifying the template (if a template is used)
    • As specified above, top-level objects automatically assume merge="replace". Within a merge="join" object definition, objects will be joined.

    Example 2

    • As specified above, referenced files will be checked for in the current layer, and will not be looked up in upper layers.
    • To replace a desktop frame graphic, you would replace the desktop frame graphic object (framedef) and reference the file in the current ruleset. If the desktopframe tag is specified at a lower level, it will use the framedef object with the given name at run-time, regardless of which layer it is defined in. This is how theme extensions are written.
    • To replace a named script file, you would need to replace the named top-level script object in the upper ruleset layer, and reference the file in the current ruleset.

    Hope that helps a bit,

  3. #3
    This is tremendously helpful! Thanks moon!

  4. #4
    Quote Originally Posted by Moon Wizard View Post
    To replace a named script file, you would need to replace the named top-level script object in the upper ruleset layer, and reference the file in the current ruleset.
    What if I were trying to do the reverse? I have a ruleset that is a child of the 3.5E ruleset in which I have overridden the "charsheet" windowclass so that I can lay things out a bit differently. In the 3.5E definition for the "charsheet" windowclass, there is a script tag that pulls in the file "campaign/scripts/char.lua". In my child ruleset I currently have an exact copy of the "campaign/scripts/char.lua" file stored and referenced from the overriding "charsheet" windowclass object. How would I go about including the script from the parent theme without having to copy it into my child theme?

  5. #5
    As long as it's the same file path, it should already work that way. FG falls through checking each layer for any file references.


  6. #6
    Quote Originally Posted by Moon Wizard View Post
    As long as it's the same file path, it should already work that way.
    And so it does... I wonder what I did that had me thinking it was otherwise. Now I can remove a few files from my ruleset and slim it down a bit

  7. #7
    damned's Avatar
    Join Date
    Mar 2011
    Blog Entries
    Quote Originally Posted by DMFirmy View Post
    And so it does... I wonder what I did that had me thinking it was otherwise. Now I can remove a few files from my ruleset and slim it down a bit
    whats your ruleset good sir?

  8. #8
    Quote Originally Posted by damned View Post
    whats your ruleset good sir?
    The ruleset that I use is a completely custom piece of work that I created for my own 3.5E campaign setting. In real life I own physical copies of hundreds of Dungeons & Dragons rulebooks, and I have spent a great deal of time and energy pulling all of the content that applies to my campaign world out of these books and creating a series of custom modules for my Fantasy Grounds ruleset.

    Not only have I added vast quantities of new races, classes, etc. from my various rulebooks, but I have also made it a point to pay special attention to the way I formatted the data in my module's XML files. For instance, if you look at the client.xml file for the 3.5E-basicrules module that is included with Fantasy Grounds and find the reference/race/human node, you will see that the node only contains two child nodes, one for the name of the race and a second for the text data to display. In my customized module, I have additional data fields for information such as creature type, size category, level adjustment, automatic and bonus languages, and several other pieces of common data between races. Using this additional data I have been able to make some pretty awesome customizations to my ruleset that would no be possible using the modules that come included with the software.

    For instance, I have made some pretty heavy modifications to the Character Sheet for my ruleset that will take advantage of these custom data points. In my ruleset you can open up my Races module, find the race you wish to play, and then drag a link from that race into the "Race" field on the character sheet (or if you type the race name and the name can be found in one of the loaded modules these effects will also be applied). This will automatically cause the XP Needed for Next Level to be re-calculated based on the Level Adjustment for the newly selected race. Similarly, the Carrying Capacity for the creature will also be recalculated, taking into account the size category of the selected race. Another example is that on the Skills page of the character sheet, each skill will automatically get a link to the appropriate module entry, where as the core functionality is that each link must be populated manually.

    These are only a couple of examples, but my ruleset takes advantage of the custom modules I created in several ways. If the modules didn't contains so much copyrighted material I would gladly share my ruleset with the community, but unfortunately without the custom modules there really isn't anything special about my ruleset. It works with all the 3.5E material included with Fantasy Grounds, but without the custom modules that I created my ruleset is little more that a new theme applied over the core 3.5E ruleset.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

Log in

Log in