Category Archives: Build Notes

Excerpts from the change log and other notes related to new builds.

Biographical imperial bug bits (b206)

b206

* Bug Fixes

When reading a book file, if the last character of content in the file was a line-continuation character, GCA could get stuck in an infinite loop. Fixed.

* Options dialog

In the Characters box, the option ‘Show all status messages when processing templates’ makes more sense as a book-processing option since the output is for debugging. That option has been moved to the Book Processing box.

* Metric and Unit Conversions

Since GCA attempts to perform automatic unit conversions when various values are in standard/metric and the character is set to the other, checking or unchecking the Metric checkbox on the General Information box should trigger a character recalculation so that items can be converted to match the new setting. That will now happen.

Previously, GCA’s automatic unit conversions only used the Game Metric values (p. B9). GCA now supports either Game Metric or Real Metric (p. B9). Game Metric uses simpler, ‘close-enough’ conversion constants while Real Metric uses more exact conversion constants (to 3 decimal places). This support is GCA-specific, not character-specific, so all loaded characters use the same conversion values.

You can change GCA between the available sets of conversion constants in the new Unit Auto-Conversions box in Options. This box also offers the option of turning automatic conversion off, and leaving units and values alone. Some traits have unit conversion built into their calculations, and these will still calculate themselves based on the Metric setting regardless of your setting for Unit Auto-Conversions.

* Per-Die result caps

You can now cap the results returned by the functions that return the dice for base swing (@baseswdice) and base thrust (@basethdice) damage. I believe the recommended dice cap is 7; any positive integer value is allowed. These functions are primarily used for giving per-die bonuses to Boxing, Brawling, and karate, but would also affect Weapon Master damage bonuses or any other such usages.

There are now default character options and character options to set these, in the respective Rules boxes.

Because these are new options settings that can be set by files, also, the FastLoad file version has been changed, and FastLoad files will be rebuilt. The book file settings are “CapDamageBonusPerDie=True” to turn capping on, and “CapDamageBonusPerDieAtXDice=X”, where X is the cap to set (default is 7).

These settings are now also included in Build Campaign Book.

* Appearance / Biographical Data

The Appearance dialog has been updated, and it is now called Appearance / Biographical Data. The updated dialog now has two tabs: Appearance, which contains everything from the existing dialog; and Biographical Data, which contains a grid of biographical data fields. The Biographical Data tab also includes everything from the Appearance tab, so if you prefer it, you can simply use this tab and won’t have to switch between them.

Biographical data includes a bunch of possible default fields which you can use. All of these are stored in the character’s tags (except for those fields also on the Appearance tab, which have custom data slots on the character). The character will also get a tag called ‘biodatacontrols’, which tracks what all of these tags are, whether they are visible, and what prompt is shown to the user if it isn’t the same as the tag name (which is the case for most of them since this system uses tag names such as ‘bio_dob’ for ‘Date of Birth’ and ‘bio_family’ for ‘Family’).

You can rearrange the order of entries on the grid using drag-and-drop. You can hide fields you have no interest in using the right-click menu. If you change your mind, you can also use Show Hidden on the right-click menu to see the hidden items, then select them and pick Show to unhide them.

I’ll probably also add the ability to create new fields to include here, but that’ll require another dialog for tag names and prompts and such, so probably not right away.

The defaults are currently created by GCA, but the show/hide settings are per-character. There’s currently no way to universally hide any of the fields to make them hidden by default on new characters.

 

Bits of requests fulfilled (b205)

b205

* Select(), SelectX()

Select() lists can now use the new #tags() directive for list items. This is used similarly to #codes(), in that it’s just tacked on to the name of a list item, and GCA will parse it out and extract the contents. If you use both #tags() and #codes() remember not to use a comma between them.

#tags() allows you to replace the contents of any tags on the library item being referenced, before the item is sent to the Select dialog. List all the tags desired inside the #tags() parens, bearing in mind the usual nesting requirements.

This new support allows you to customize items without having to use #newitem, if the item is one that can be easily based on an existing item. Replace name(), nameext(), initmods(), whatever you need–just remember that the tags must be Library tags because the items shown in Select are Library items until added to the character.

For example, if you have a Select() with a list() like this:

list(_
SK:Performance #tags(nameext(Singing), page(TESTING))#codes(upto 16, downto 10),_
SK:Photography #tags(name(Holography), page(TESTING))#codes(upto 16, downto 10)_
)_

the user will be presented with a list of options that includes “Performance (Singing)” and “Holography/TL” (because Photography is a /TL skill). Aside from the name change and the new TESTING page number, everything else for those two skills will be identical to Performance and Photography, respectively..

List items can now also use the new #note() directive to specify a special note to include on the Library list itself. This special note will be displayed directly under the trait name on the list, and that list entry will be taller to accommodate it.

* Functions

Added the @sumlist() function, which returns the sum of the values in a comma separated list. Each value in the list may be a fenced Solver-enabled expression.

Added the $modifiers() function, which returns a list of the modifiers applied to the trait. This is probably only useful with displaynameformula(), but that’s why I added it. Use $modifiers() without parameters to get the usual captions (shortnames), but *without* values, enclosed in parentheses. Use a comma separated list of parameters to modify this behavior: ‘captions’ explicitly sets captions (the default) while ‘fullnames’ sets fullnames instead; ‘values’ will include the values of the modifiers; and ‘noparens’ will turn off the enclosing parens. (Note that if there are no modifiers for the trait, the return value will be empty, not a set of empty parens.) Example: $modifiers(values, fullnames) will return the full names of the modifiers along with their values.

* Adds(), AddsOrIncreases()

When a trait is being added, and no name extension is provided, and GCA looks for versions with name extensions included, and finds some, it will pop up a dialog asking the user to choose which one they want. GCA does this even if only one option is found. Now, GCA will automatically add the found selection if only one is found.

* Options

Added some additional error traps to try and catch weird cases where something is crashing GCA because some option is set wrong or maybe missing.

Damage mini-modes were supposed to be On by default, but were actually Off by default. They are now On by default, as intended. If you want them disabled, you’ll have to go into Options, Experimental Features, and turn them off again.

* Edit Traits

If displaynameformula() is being used, a section near the top, just above applied modifiers, should be displayed showing the current Display Name and the current displaynameformula(). You can edit the displaynameformula() there. You will need to Add Tag displaynameformula() or turn on ‘Show all fields’ to show the display name fields if they’re not visible.

Bit of a party (b204)

b204

GCA had a helper function called PlainText() to return plain text from RTF. However, it was not robust enough, so I’ve updated it to use the newer RTFtoPlainText() function which is more robust.

When dragging and dropping a parent item within a trait list, GCA was not correctly preventing the user from dropping onto a child or grandchild, which would cause GCA to crash. That should now be fixed and the move will not happen.

When dragging items within a trait list, GCA should now use a red insertion point indicator, instead of the usual black one, to indicate when the drop location is not valid due to one or more of the dragged items being ancestors of the item at that point. Dropping anyway will have no effect and the dragged items will not move.

I think I’ve restored the ability of the Info pane to deal with user notes or descriptions of traits that have embeded RTF codes without being full RTF blocks. This should allow for those fields in book files to use bold or italics, for example, without having to embed a complete RTF header along with it.

* Party View

You can now copy and paste character card designs. Added to the bottom of the gear menu on each card are two new options: Copy Card Design and Paste Card Design. Copy Card Design will copy the card design elements into an XML text string, which you can then paste elsewhere, send to a friend, or paste it into another card using Paste Card Design. Paste Card Design will only be enabled if the clipboard contains XML text that looks like it might contain card design data, and if so, you can select it to paste the design in. Once pasted, the card will replace it’s current design with the one contained in the XML.

* Build Campaign Book

I’m trying to rebuild this dialog to actually display properly for users in Windows 11. Since I don’t have a Windows 11 development machine, this is problematic. However, my first attempt is now done.

Having the option enabled to display an LC column in Equipment lists caused the program to crash when switching to the Equipment.list. That is now fixed.

The Library list for Equipment should also now honor the formatted display of costs and/or weights, if that option is turned on.

The list headers should now display subheads/column headers for each list.

A bit tired (b203)

b203

* Bug fixes

There was a bug in the logic for calculating modifiers, so that rounding UP was restored if every modifier on a tier didn’t set it to DOWN. It’s supposed to set to DOWN if any modifier sets it to DOWN, and keep it that way for the tier. So, for a single modifier it worked correctly, but for cases where there were normal UP modifiers listed after a DOWN modifier, it would be wrong.

Some users have reported GCA crashing when one or more of the support files (usually an XSD file) is missing. GCA can still function without those files, so crashing is a pretty negative outcome. I have added checks to ensure those files exist before GCA tries to use them. GCA will now also send a message to the Log when it sees that such a file is missing, so that the user can try to Check for Updates to possibly restore it. (Of more concern is why those files are going missing. I suspect there may be a bug in the Updater that is deleting them but not updating them when it runs. I will be looking into that.)

When using Save as Template for saving a character as a template in a book file, GCA should now correctly *not* include traits that are already components of other traits that will be added. For example, if you included the Quadruped template on your character, and then saved it as a template, GCA would include Quadruped as an item to be added, and also include all the components of Quadruped as items to be added. That will no longer happen.

* Miscellaneous

Swapped the order of processing techlvl -> TL and TL -> TL to do TL first. This way, custom items can keep the standard techlvl() tag for when items of that type become available, and use tl() to set the TL of the specific item. GCA will no longer attempt the techlvl -> TL procedure if TL is already set for the item.

I’ve extended the #any and #none keyword support for name extensions to bonus targeting. So you can now target a bonus to a trait with a name extension of (#any) to target any variant of that name, and (#none) to exclude any that have a name extension. As with other such uses, you can use ‘of’ and ‘except’ clauses as well, so you could target a bonus to any Animal Handling specialty except Big Cats by using gives(+1 to SK:Animal Handling (#any except “big cats”)), or you could target only Big Cats by using gives(+1 to SK:Animal Handling (#none except “big cats”)). This extension also works with Conditionals.

Added ‘displaycost’ to the list of tags removed from trait tags when they’re being created from system tags or being resynced.

I’ve added the ability to change the order of your character’s log entries on the Campaign Log. You can now drag entries to new positions in the list, or you can use Ctrl+Up or Ctrl+Down to move the current entry up or down a position.

* BookCodes.xml

Added GURPS Power-Ups 4: Enhancements.

* TagDefs.xml

Added ’round’ to the list of modifier tags. Adjusted the text slightly for ’round’ in trait tags.

Functionally more bits (b201)

b201

You can now check if the character is currently processing a randomized template by checking char::random or char::randomized. It will return “1” if it is and “0” if it is not.

* Book Processing

I found a number of checks for duplicate values that were being done inside the check for Verbose status for error reporting. Those checks needed to happen outside that check since only the reporting matters for Verbose, not the safety of the data and avoiding a crash. Fixed the ones I found, which were related to duplicate hit location tables or duplicate notes within those tables.

* TL

GCA did not assign a TL to equipment items. These items had a techlvl() tag showing when they typically became available, but GCA didn’t create a TL tag for them when taken by the character. Now it does. The tl() assigned will be the techlvl() if its higher than the character’s TL, or the character’s TL if it’s higher than the techlvl() (as it is assumed to be a product of the character’s TL). This shouldn’t affect much of anything within GCA itself, but may affect malf numbers for a small number of items where GCA calculates those. (If the character’s TL is easily determinable as a numeric value, that numeric value is used for comparison, if not, it’s simply assigned to the tl() because GCA can’t do any of the other checks.)

With the change to always try to generate TL for equipment items, this would also result in the default Display Name routine always appending /TLx to every equipment item. That’s likely far more annoying than useful, since most characters use items manufactured for their TL. I have therefore added an option to show the /TLx appendix on equipment names, and it is Off by default. You can turn it on in Options on the Lists panel of the the Program Options tab.

* Bonuses

Gains bonuses (+X to me from Y) had an issue where any ‘from’ reference that didn’t use a prefix type and was not found, such as “+1 to me from hell”, would result in a bonus of +1. That should now be fixed.

I have added support to Gains bonuses for ‘from’ references of ‘char’ for the character itself, and of ‘parent’ for children and/or template components.

Gains bonuses should now be able to gain bonuses from the tags of ‘from’ references, such as points, level, or whatever. For example: gives(+1 to me from char::example) would give a bonus equal to the value of the ‘example’ tag on the character (or 1 if it is not a numeric tag value, while a char:: tag that is empty or doesn’t exist would result in a bonus of 0). You can also use this with traits, such as gives(+1 to me from SK:Acrobatics::points), which would give a bonus of +1 per point spent in the Acrobatics skill to the trait. Same for using a ‘from parent’ construction, such as gives(+1 to me from parent::points) which would give +1 per point spent on the parent trait.

* Functions

GCA will now remember the last value returned for the @Roll, @Random, and $RollValues functions. Bear in mind that these saved results will change each time these functions are called, so they’re only really useful inside the same operation, such as in an @if, and only reliable even then if you only use one of that function in the evaluation.

Note that all of these saved values are universal to GCA, *not* to the character or the trait.

To get the last returned value, use one of these functions. Note that they don’t have parameters, but you still must include the ().

@LastRoll()

Returns the last value returned by the @Roll() function.

@LastRandom()

Returns the last value returned by the @Random() function.

$LastRollValues()

Returns the last value returned by the $RollValues() function.

@NamedRandom(name, value1 [, value2] )
@NamedRoll(name, number [, sides] )
$NamedRollValues(name, number [, sides] )

These functions each work the same as their unnamed counterparts. The only difference is that you can name the roll by specifying the name as the first parameter. By using these functions and specifying unique names, you can retrieve them later by name and be less concerned that another use of the unnamed functions will overwrite the values.

These named versions do *not* place their results into the the LastX values used by the unnamed functions, so you can’t retrieve a value generated here with the LastX() functions (but you can with the LastNamedX functions). This allows you to use named results for longer storage and unnamed ones for transitory values without one messing up the other.

Note that all of these named results and their stored values are universal to GCA, *not* to the character or the trait.

@LastNamedRoll( name )

Returns the last stored/returned result for the given name. Returns 0 if there is no such name.

@LastNamedRandom( name )

Returns the last stored/returned result for the given name. Returns 0 if there is no such name.

$LastNamedRollValues( name )

Returns the last stored/returned result for the given name. Returns “0” if there is no such name.

@HasModIncludesText( text )

Searches the item’s modifiers (name and name extesion only, and each is checked separately) for all those that include the text specified, and returns the highest level among those that include it. Returns 0 if none found.

@HasModIncludesTextMin( text )

Searches the item’s modifiers (name and name extesion only, and each is checked separately) for all those that include the text specified, and returns the lowest level among those that include it. Returns 0 if none found.

@HasModWithTag( tagname [, tagvalue] )

Searches the item’s modifiers for all those that include the tag specified, and returns the highest level among those that match the tagvalue given (ignoring case as usual). If no tagvalue is given, any value for the tag counts as a match. Returns 0 if none found. (This performs text matching, so “0” matches “0” but does *not* match “0.0” or any other variation that would match numerically. See also @HasModWithTagValue.)

@HasModWithTagMin( tagname [, tagvalue] )

Searches the item’s modifiers for all those that include the tag specified, and returns the lowest level among those that match the tagvalue given (ignoring case as usual). If no tagvalue is given, any value for the tag counts as a match. Returns 0 if none found. (This performs text matching, so “0” matches “0” but does *not* match “0.0” or any other variation that would match numerically. See also @HasModWithTagValueMin.)

@HasModWithTagValue( tagname [, tagvalue] )

Searches the item’s modifiers for all those that include the tag specified, and returns the highest level among those that match the tagvalue given. If no tagvalue is given, any non-zero value for the tag counts as a match. Returns 0 if none found. (This matches tagvalue with candidate tag values numerically, so all values will be converted to numbers before comparisons are made. Tags with non-numerical values will evaluate to zero. This is a direct conversion, not a math-enabled Solver evaluation. See also @HasModWithTag.)

@HasModWithTagValueMin( tagname [, tagvalue] )

Searches the item’s modifiers for all those that include the tag specified, and returns the lowest level among those that match the tagvalue given. If no tagvalue is given, any non-zero value for the tag counts as a match. Returns 0 if none found. (This matches tagvalue with candidate tag values numerically, so all values will be converted to numbers before comparisons are made. Tags with non-numerical values will evaluate to zero. This is a direct conversion, not a math-enabled Solver evaluation. See also @HasModWithTagMin.)

Apparently random bits of miscellany and functionals (b200)

b200

* Miscellaneous

GCA should no longer claim #Verbose On is a bad data file command (but still work) when it is a good command. Same for the #ModifierGroupWarnings command.

The #Clone data file command should now work with templates, and should better handle unsupported prefix tags.

Addsorincreases() didn’t correctly increase equipment counts. Now it does.

The combination attacks version of Edit Traits was crashing when trying to add a new combination. That is now fixed.

Added a system flag so I can have some system messages not go to the log when I’m doing things where they are repetitive or unnecessary. And then added support for that flag to a number of messages (such as new character and library loaded messages in randomized templates).

When handling an adds() or addsorincreases() for a trait name without an extension, and GCA only finds versions with extensions, GCA would pop up a dialog asking the user to pick one of those found. When doing a random template, this pop-up still popped up and waited for user input. That is now fixed and a random selection is made from the items found.

I have added a new engine option for verbose template processing. This option is off (False) by default. The idea is that nearly every message that gets logged during template processing is actually only useful for template writers, but not for users. Having all those messages get sent to the log cheapens the log for the typical user by filling it with what appears to be nonsense. (And much of what gets sent to the log is just noise to users, since many templates these days rely on certain behaviors to work correctly, but those behaviors also often send messages to the log). So, with this new option, just about every template processing message that used to get sent to the log now only gets sent if this new option is turned on (True). This option is available in Options, on the Program Options tab, on the Characters pane as the “Show all status messages when processing templates.” checkbox.

In Select dialogs, sometimes the options meant to be available are built from things that were chosen in previous dialogs. This sometimes means that an option may have a different name extension on the character than in the library. Previously, GCA wouldn’t find it in the library and would just give up on that item. Now, if GCA doesn’t find the specified item in the library, it will see if it can find a version on the character, and if so, use that as the template for the item in the selection list..

The new template tag setloadout() can be used to change the character’s active loadout to the loadout specified in the tag. This can be used inside triggers().

* Random Character dialog

I have restructured the order of things in the process that the Random Character dialog (called from either Randomized Template option in the Tools menu) uses when adding random templates. First it names the character, then runs the template. This will allow for templates to be built that apply random character names.

Also, the character names are no longer modified to include “- but Canceled” if it looks like the template didn’t complete properly. GCA will now wait until all the random characters have been built, then print one “Randomized template issues:” block to the Log pane, with a message about that for each such character.

I have also made the system check for the #deleteme command in the initial template, so that it will not assume a canceled template just because the initial template deleted itself once finished.

* Functions

@ItemsInLibraryGroup( GroupName )

This function returns the number of items for the GroupName specified, as found in the character’s loaded library’s Group collection. This is specifically the Library count, as currently loaded, just as it would be referenced if you were creating a group list for use in a Select dialog.

@ItemsInLibraryList( ListName )

This function returns the number of items for the ListName specified, as found in the character’s loaded library’s Lists collection.

Be aware that List usage is not the same as Group usage in GCA, as a List is just a collection of text lines, while a Group is specifically a collection of items, one per line. This means that a List may consist of many items per line, and its usage by the file author will likely not correspond to one item per line, but may result in many items in the destination output. Instead of counting the items in the List, you may want to use @ItemsInList to count the items in an equivalently constructed text list instead.

@ItemsInList( [ #codes() ] item list )

This function allows you to count the items in the given list and return that value. The #codes() special directive allows you to specify special commands to control how the list is processed.

By default, the list of items is considered to be comma separated, and each individual entry may be enclosed in quotes or braces as usual.

The only code currently supported for #codes() is #codes(sep=X) to change the separator from a comma to some other character. NOTE: If you specify multiple characters, each one individually is a separator, NOT the whole string as a single unit. You may enclose the separator in quotes or braces, such as #codes(sep=” “).

@Random( value1 [, value2] )

The @random() function returns a random integer value. Note that the values are applied differently depending on whether one or two values are supplied.

The templates for this are:

For an integer 1 to max: @random(<max>)”)
For an integer min to max : @random(<min>, <max>)”)

If only <max> is specified, then the value returned ranges from 1 to the <max> value. If both <min> and <max> are specified then the value returned ranges from the <min> to the <max>.

@Roll( number [, sides] )

The @roll() function returns the sum total for a series of random results simulating rolled dice.

The templates for this are:

For rolling Xd6: @Roll(<number>)
For rolling XdY: @Roll(<number>, <sides>)

If <sides> is not specified it uses six-sided dice. So using @roll(2,4) would ‘roll’ 2 4-sided dice, and would return the total sum of all ‘rolled’ values.

$RollValues( number [, sides] )

The $rollvalues() function returns a text value that is a sequence of values separated by + signs, representing every roll made for the given parameters

The templates for this are:

For rolling Xd6: $RollValues(<number>)
For rolling XdY: $RollValues(<number>, <sides>)

If <sides> is not specified it uses six-sided dice. So using $rollvalues(2,4) would ‘roll’ 2 4-sided dice, and would return the value as something similar to ‘1+4’, so that it can be included in a math expression.

$ListNoBlanks( [ #codes() ] item list )

This function allows you to process a list of items and remove the empty entries. The #codes() special directive allows you to specify special commands to control how the list is processed.

By default, the list of items is considered to be comma separated, and each individual entry may be enclosed in quotes or braces as usual.

You may specify #codes(hasprefix) or #codes(prefixtags) to tell the function that the entries in the list are expected to be trait names tagged with prefix tags and therefore any item that does not have both, or where either part is not specified, are considered to be blank items.

You may specify #codes(sep=X) to change the separator from a comma to some other character. NOTE: If you specify multiple characters, each one individually is a separator, NOT the whole string as a single unit. You may enclose the separator in quotes or braces, such as #codes(sep=” “).

If you specify multiple codes entries, separate them with commas.

* #Loadout() / Loadout()

Support for using the #loadout() special directive has been added to adds(), addsorincreases(), and creates().

If you use the #loadout() special directive to add an item to a loadout, then GCA will now automatically apply protection from any armor or shield items so added. This seemed to be the most likely desired action, so it was made the default. If you do NOT want that to happen, include #noarmor as part of the loadout name inside the #loadout() directive for each loadout not receive protection.

If you are adding a shield, you can use #arc() as part of the loadout name to specify the protected arc. At this time, the supported arcs are ‘none’ (the default), ‘back’, ‘left arm’, and ‘right arm’.

Example:

Loadout Tester (Adds),
displaycost(0),
cost(0),
page(User),
noresync(yes),
adds(_
{EQ:Backpack, Small #loadout(Pack)}=1,
{EQ:Blanket #loadout(Pack)}=2,
{EQ:Canteen #loadout(Pack)}=1,
{EQ:Leather Jacket #loadout(Pack, Combat)}=1,
{EQ:Heavy Leather Leggings #loadout(Pack, Combat)}=1,
{EQ:Gauntlets #loadout(Pack #noarmor, Combat)}=1,
{EQ:Small Shield #loadout(Pack #arc(back), Combat #arc(left arm) ) }=1,
{EQ:Steel Breastplate #loadout(pack #noarmor)}=1_ 
)

This template will apply all items to the ‘pack’ loadout, and some of the armor to the ‘combat’ loadout. The Steel Breastplate is not being worn, so it’s flagged as #noarmor in the ‘pack’ loadout where it resides. The Small Shield is worn on the back in the ‘pack’ loadout but on the left arm in the ‘combat’ loadout. And since gauntlets are annoying to wear casually, they’re also not being worn in the ‘pack’ loadout.

Note that the loadout() tag, which inserts the item with that tag into loadouts in a similar fashion, now also applies protection by default and also supports the #noarmor and #arc() directives.

You can also use this feature to assign protection for the virtual ‘All unassigned items’ loadout by leaving the loadout name portion blank, or by explicitly referencing a blank loadout using empty quotes “”. Note that this means using an empty loadout() tag on a trait will trigger GCA trying to assign it to a loadout and to apply protection, so don’t include empty loadout() tags unless that’s what you want to happen.

* Plugins

In compile.xml, you may now use the variable %home% in a ‘reference’ element to point at the plugin’s home install folder. This should allow for the compiler to properly find and reference additional DLLs that you may need to include with your plugin.

* Export to Roll20

A new exporter from Mad Coder that creates a json export file for importing into the Roll20 VTT.

 

Ever more bits of bug fixing (b198)

b198

Fixed issue that prevented limits on traits in Select dialogs from being handled.

Fixed crash bug related to calculating charblockscore() if no charskillscore() was found.

Made some changes to RTF handling so that it uses the system-returned default font rather than an assumed MS Sans Serif font for the default font used.

Made a minor initialization change to Party Log dialog, to hopefully address an issue that I don’t see but a user does.

One bit fixed, two bits extra (b196)

b196

* #AsChild

You can now use the special directive #AsChild in an adds(), addsorincreases(), or creates() tag to specify that the trait being added should be added as a child. Using #AsChild automatically forces #DoNotOwn as well, so be aware that the child will not be owned and will not appear in the needs() automatically. As with #NoNeeds and #DoNotOwn you should include #AsChild in the main clause of the tag data, before any ‘respond’ or ‘with’ portion, else it be considered part of the other clauses and not work correctly; sticking it into the name section is usually good.

* #InputX directives

There was a processing bug in the code that handles processing the #input(), #inputreplace(), #inputtotag(), and #inputtotagreplace() directives. This bug would occur when the tag data included a custom tag that ended with the # character. The processing code would find that character, correctly identify it as being part of a tag, but still exit processing before looking at the rest of the tag data. That is now fixed, and these directives should now be processed correctly regardless of where they fall in the tag list.

* Respond

I have adjusted adds() and addsorincreases() to allow any included ‘respond’ keywords to use a $ function to process the ‘respond’ text before it gets pushed onto the response stack. You can use this to completely change responses, or to respond with an evaluated expression. If you want to respond with text that includes an unprocessed $ function, escape it as ‘$/function()’ rather than simply ‘$function()’ and GCA will change the ‘$/’ to “$’ before it pushes the responses onto the stack. The $ function processing happens before any quotes or braces are stripped from around the response expression (which itself happens before the response is split into list items if it is a list).

Still more bits of cleanin’ (b195)

b195

There was a bug in how GCA removed nested components when deleting a template. That is now fixed.

The Recycle Bin didn’t properly support multiple levels of components. That is now fixed.

Added Public Function NonAttackModes() As ModeManager to the ModeManager class, which returns all contained modes that are not melee or ranged attacks (denoted by having charreach() or charrangemax() tags respectively) as a ModeManager.

Updated the Attack boxes in Unified to show DisplayName for the trait.

Adjusted filling of the Description and User Notes fields in Edit Traits to better support the possibility of there being partial RTF fragments (such as \par for paragraph breaks) in the original data, without there being full RTF. This basically converts the text with RTF fragments into full RTF before putting it into the editor by including a small RTF header. Since it would come out of the editor as full RTF anyway, this just ensures that the fragments aren’t ‘lost’ by being converted into embedded text rather than the intended RTF codes.

Cleanin’ up some bits (b194)

b194

GCA should now be cleaning up .tmp files correctly in its AppData folder

GCA should now be cleaning up those empty 5.0.X.X folders in its AppData and ProgramData folders.

I belatedly realized that changing Item.Notes from a property to a function in the last build could unnecessarily break some things that plugins might be doing. So I changed Item.Notes back to a property, and it now returns usernotes() as plain text. If you set it, it sets usernotes() with that text.

I’ve changed the new function that was briefly Notes() to GetNotes(Optional ByVal AsPlainText As Boolean = True) As String instead, and added GetDescription(Optional ByVal AsPlainText As Boolean = True) As String for getting Description as well.

When building protection values, it seems that I didn’t properly trap for non-Equipment traits (such as Damage Resistance) that may have been made children of Equipment items. When a Loadout then tried to calculate protection values, it would crash because it would create a duplicate reference to that item. (Traits that provide protection are separately gathered because they’re not technically part of a loadout, so could still provide protection regardless of the loadout in use.) I have added a trap for the duplicate, which should fix the crash.

GCA wasn’t properly updating the total costs for various types of traits when adding or removing children. Now it should be.

The attack boxes in the Party View cards should now integrate a bit better. Also the gear menu should now be hidden since the options aren’t available here.

Refactored some of the code in the process that finds and initializes plugins. This eliminated a ton of redundant code.

In the Plugins dialog, if you Enable a currently disabled plugin, but GCA isn’t able to activate it when you Close the dialog, it will no longer add it back to the Disabled list as it was doing. It’s possible that GCA isn’t able to reload a plugin if there was some kind of conflict, but that it may be able to load it when restarted; therefore it makes sense to assume it should not be on the Disabled list if the user requested that.

Added a bunch of additional pre-checks and error traps for possible issues related to duplicate entries of various sorts of tracked and keyed objects during program initialization, even in many situations where it shouldn’t be possible to get duplicates.

Dmg() was missing from the tags being processed into mini-modes for Mode.GetMiniModes(). Fixed now.