Bits of melted brain


* Miscellaneous

Altered a parsing routine to fall in line with how my parsing is intended to work these days. (Intention is: when matching containers, you can include a mis-matched paren or brace within quotes, or a mismatched paren inside braces, but can’t include any mismatched quotes anywhere. GCA’s older code is currently rather inconsistent as to when it’s honoring matching quotes, braces, parens, just two of those, or all three. I’m trying to fix that as I come across it.)

Added a new set of parsing routines that should simplify processing many of the keyword-clause based features.

Added Bonus Classes to Resynchronizing.

* Solver

Updated the GetItemVal routine, and the @ItemHasMod() function handling. Both should now support the ability to find a trait with various possible name extensions, using the base name and one of several special directives in place of a name extension: #any, #best, #worst. So, if you have several possible Flight advantages, but any one of them works just to say that you have Flight, you could use a reference like “SK:Flight (#any)” to find any of them.

The values work like this: #any will return the first valid non-zero trait with the given name; #best will return the best (highest non-zero); and #worst will return the worst (lowest non-zero). Note that #best and #worst can be tricky, and should be used cautiously, as results may not be as expected in all cases, depending on what tag or value you’re looking for.

Notes: The intention here is to allow for accepting variations of a trait via name extensions. Only numeric values can be judged.

Also updated the GetItemTextVal routine. Should be smarter about duplicate and inactive items now, and support #any, #best, #worst; although because it returns text, there’s no good way to determine best or worst, and it therefore treats all of them as #any, where any non-empty value satisfies the request.

* Bonuses

Reworked the routine in the Bonus object that converts the given bonus text into the proper bonus data. This uses the new parsing routines, which means we can now allow for any of the different clauses to be used in any order within the text; just the actual bonus part needs to be listed first, as before. For example, you could now use

gives(+2 to “SK:Acrobatics” when “on Earth” listas “native gravity bonus” upto 4 onlyif target::points > 0)

or you could use

gives(+2 to “SK:Acrobatics” onlyif target::points > 0 listas “native gravity bonus” upto 4 when “on Earth”)

and either should work correctly and without issue.

Note: spaces around the keywords aren’t required any more, except for the ” to ” and ” from ” keywords in the basic bonus block, but you must enclose other blocks in quotes or braces if they might include any of the other keywords: “onlyif”, “unless”, “listas”, “class”, “upto”, “when”. GCA will strip the containers after parsing. (Yes, parsing should now honor braces as well as quotes as containers for these clauses.)

* Bonus Classes

BonusClasses exist to provide rules for limiting bonuses from defined “classes” of bonuses. Bonuses include themselves in a BonusClass, and the rules for the classes are defined in the data files. Support is specific and limited at this time, but allows for limiting the total bonus levels applied from a class of bonuses to an item, or might prevent stacking, and so forth. At this time, Bonus Classes are applied only to addition/subtraction bonuses (whether variable or static) affecting only points or levels.

To include a bonus in a particular BonusClass, just use the “class” keyword and specify the name or names of the classes to which it should belong after that (in quotes/braces if needed) within the bonus text. It might look like this:

gives(+1 to “SK:Acrobatics” upto 4 class “Talents, Acrobatics”)

That would include the bonus as a member of the classes “Talents” and “Acrobatics”.

Here’s how you define BonusClasses in the data files:

ClassName, [ { affects | appliesto } { levels | points }] [ stacks { yes | no } ][ upto X ][ downto Y ][ best A ][ worst B ]

X, Y, A, and B can be expressions, and they’ll be sent to the Solver, but you can’t use me:: references because Bonus Classes aren’t tagged items.

Affects and AppliesTo (one word!) are synonyms, use the one you’re comfortable with, but don’t use both. Affects Levels means the class applies to bonus levels only. Affects Points means the class applies to bonus points only. The default is Affects Levels, so that’s what will happen if the Affects clause isn’t specified.

Stacks specifies if multiple bonuses from the same class can apply. Stacks Yes is the default behavior in GCA for all bonuses. Stacks No means only 1 bonus from the class will be allowed (usually the best one, unless you also specify Worst 1).

Upto specifies an upper limit on the total bonus value that may be applied by all bonuses in the class. If exceeded, GCA will create an Adjustment to apply, which will correct for the excess value. If Affects Points, do *not* include “pts” in the value.

Downto specifies a lower limit on the total bonus value that may be applied by all bonuses in the class. If exceeded, GCA will create an Adjustment to apply, which will correct for the excess value. If Affects Points, do *not* include “pts” in the value.

Best specifies the maximum number of bonuses that may be applied, and that the highest values upto that number should be used.

Worst specifies the maximum number of bonuses that may be applied, and that the lowest values upto that number should be used.

For example:

Talents, stacks yes upto 4 best 2
Acrobatics, stacks no worst 1

The Talents class allows stacking as usual, but limits the total bonus from Talents to 4, and only allows the best 2 bonuses (which, if totaling over 4, will have an adjustment created so that the net bonus is 4).

The Acrobatics class doesn’t allow bonuses to stack, and only wants the worst possible non-zero bonus to apply. Rough.

Notes: This can get conceptually confusing. Remember that any particular bonus will only be applied *once*, no matter the number of classes to which it belongs. If a bonus is excluded for any reason by any BonusClass rule, it will not be applied *at all* regardless of how many other classes it might belong to that didn’t exclude it.

A hodge podge of bits and bobs


* Transforms

Made an adjustment to the Transform Manager window so that the “All unassigned items” column will have the correct points.

Also, see the Solver section below.

* Updates

I have created a new Login dialog to gather your login credentials for downloading updates.

GCA will now save your credentials for downloading updates. They are encrypted. The new Login dialog has an option you can check to tell GCA not to save your credentials.

* Campaign Settings dialog

Changed the Other Settings box title to Tech Level.

Added a first draft of a Wealth & Money box to the right side.

* Miscellaneous

Added a couple more utility routines to GCACharacter.

GCA will now, for the time being, stick Features, such as those added by a template’s features() tag, into a simple Features collection on the character. (Nothing else being done with them, yet.)

I have added Money entries to the Campaign Log and related data structures. This allows for entering earned or lost money via the Campaign Log, just like you can enter earned or lost points.

For the time being, the Equipment: $XXX value on the Points bar at the bottom of the GCA window will now be offset by the character’s Campaign.TotalMoney value for purposes of hitting the ‘red’ value.

The following items have been made accessible through the character’s tagitem(), all for the corresponding Campaign values: “campaigntotalmoney”, “campaigntotalpoints”, “campaignothermoney”, “campaignotherpoints”, “campaignloggedmoney”, “campaignloggedpoints”. The ‘total’ values are the total of the ‘logged’ and ‘other’ values, while ‘logged’ is the total of all log entry values of that type (points or money).

Corrected text in Character menu from Multiplicities to Transforms.

* Solver

Updated the GetItemVal routine. Should be smarter about duplicate items now.

Updated the @ItemHasMod() function handling. Should be smarter about duplicate items now.

As an experimental testing feature for Transforms and inactive traits, the GetItemVal routine will now return a 0 value for any trait found that is inactive. We’ll see how this works out….

As an experimental testing feature for Transforms and inactive traits, the @ItemHasMod() function will now only consider traits that are not inactive. We’ll see how this works out….

Bits be transformed, yo


* Miscellaneous

Made a slight adjustment to how trait list boxes in Unified view are updated, due to a drawing issue.

Adjusted how the option that requires GCA to always allow you to select a library for the character when creating a new character works. It will now allow you to select the ‘New, with Default Library’ toolbar option to use the default library without actually having to select it again from the Library Manager dialog. This is more consistent with the ‘inversion of normal’ behavior that the option is meant to offer.

* Transforms

Multiplicities have been renamed to Transforms; this should follow through to all windows and whatnot.

Altered some Needs checking processing to disallow inactive traits as valid.

GCA will now save/load transform data.

Updated transforms section of character calculation routine a bit.

Added option for the show/hide Transform dialog explainer to Options.

* Templates

A component owner adding new traits should now always automatically force duplicate items, rather than popping up a dialog about them. A non-owner (such as most types of character templates) should still ask about duplicates.

* Defaults

Expanded the Text Function Solver support in default() to be processed first thing, so that you can use text functions to completely alter the way that a default may be processed. This means you could do something like this:

default( $if(1=2 then “Calc 1 @default(10)” else “Calc 2 @default(12)”) )

which is combining the idea of the text function solver and the @default() function into a single statmement to return the whole definition.

or this:

default( $if(1 = 2 then “SK:Whatever”-2 else “SK:Whatever Else”-6) )

to just return the default statement you want, depending on the evaluation of the $If comparison.

Bits of default hell


* Miscellaneous

Tried again to have the Alt Attacks panel stop showing up uninvited on the Simple Edit window.

A certain circumstance could crash GCA when editing an item that might default to another. That has been addressed.

Added a new option to Options, in a new New Character block, that requires GCA to always allow you to select a library for the character when creating a new character. (If you make a lot of characters with various different libraries, this will help you. This is Off by default.)

When using TagItem() to check a trait’s ‘needscheck’ or ‘taboofailed’ GCA will now ensure that they’re returned as the numeric values (-1 or 0) rather than ‘True’ or ‘False’, which aren’t useful in numeric comparisons.

* Windows

Moved the Groups option from the View menu to the Character menu on the main window.

Changed the order of groups displayed in the Groups window to show Character groups first, then Library groups.

The Messages dialog should now respect Tablet Mode.

The Character Tags and the Groups dialogs should now respect Tablet Mode.

The Select X dialogs should now respect Tablet Mode.

* Right-Click Bait

Changed the right-click menu (on Classic and Unified views) sub-menu option “Bonus Granting” to “Active/Inactive” instead.

Added a Loadout sub-menu to the right-click menu (on Classic and Unified view) to allow adding the currently selected items to, or removing them from, the current loadout.

* Library Books and Bins

If you load a character with a library file that doesn’t exist (such as when opening an old GCA4 character), GCA should be a bit smarter about placing a new library file in the correct bin, if you select the option to create a new one with the same files.

GCA will now attempt to use the gcaaliaslist.ini file to find missing library books.

GCA will now attempt to search more diligently through the various bins when trying to find missing library books referenced by libraries. (This is usually a problem when a new library is created based on an old character’s referenced books.)

* Solver

Added a trap for one known type of crash error when bad data is in a Solver expression. GCA will now put a warning in the log, and return a 0 for the expression, since it can’t solve it.

* Defaults

I haven’t touched the code for defaults in a long while, but there were some things I wanted to do with it. Of course, I didn’t want to break it, either. I think I succeeded, but please be warned that I *did* mess with some things (gently, I hope) that may have broken it.

First, parsing the default() tag should now honor quotes, braces, and parens. Before, it only honored quotes, so if you had a trait name that included a comma within the name extension, it would parse on that unless you put quotes around it. Now, you should only need quotes or braces around traits that have commas that aren’t otherwise contained.

Second, I have allowed some non-trait defaults to pass as valid within GCA, primarily for reasons in the next bit. This shouldn’t break anything because such things, on their own, should still evaluate to 0 if they’re nonsense, but if they’re numeric, they allow for defaults from numbers and such. (Any non-trait item gets a deffromid() of 0, since such things obviously have no IDKey.)

Finally, I have added special support for finally allowing a complex expression to be used to set the default level. Doing this requires the use of the @default() specialty function, which isn’t really a function so much as a wrapper around your expression, but anything inside the @default() is sent to the full Solver. The @default() function should be at the end of the default item, while at the beginning of it should be the text that will be shown to the user as the deffrom() text. So, it should look something like this:

default(Some Expression @default(@max(10, 12))

which would give us deffrom(Some Expression) and deflevel(12). That’s a dumb expression, but that’s the idea. Also, the text portion is Text Function enabled, so you could do this kind of thing:

default( $if(1=2 then “Calc 1” else “Calc 2”) @default( @if(1=2 then 10 else 12) ) )

Since 1 <> 2, the user would see “Calc 2” as the deffrom(), and 12 as the deflevel().

Transmogrified bits


Made a slight change to how GCA locks the UI, which should be a tad less annoying when there are characters loaded.

Made a small adjustment to the system that activates/deactivates items based on loadout, so that items deactivated by the user manually should be respected and stay deactivated.

The logic for identifying component traits for activating/deactivating has been fixed.

Adjusted the ‘frozen columns’ feature a bit in the Loadout Manager.

* Multiplicities

Started on support for the ‘multiple forms loadouts’ thingy. I don’t know what to call this system, so I’m currently calling these things ‘multiplicities’, or a ‘multiplicity’ for the singular. This isn’t a GURPS name, though, so we’ll likely want to rename it, but at least this will be easy to find and change when a better name comes up.

The Multiplcity Manager window now exists. GCA will now activate/deactivate traits based on the ‘active’ multiplicity selected in this window (if that Loadout option is set!), and the traits assigned to it. Currently, only Advantages, Perks, Disadvantages, Quirks, and Templates are valid traits for this system.

IMPORTANT: I realized that handling activation/deactivation just like loadouts currently does would be a problem, in that managing All Unassigned Items as *not* being a part of the active multiplicity is likely to be unexpected behavior. So, All Unassigned Items are considered to be active parts of ALL multiplicities, which means you don’t have to actively assign everything, only those things that belong specifically to one multiplicity or another. So, basically, GCA only deactivates traits that belong to some other multiplicity than the active one, and ignores unassigned traits. This greatly simplifies the system for the user, albeit at the price of not working exactly like loadouts.

Added a new item to the toolbars and the Character menu, for the Multiplicity Manager window. It’s next to the Loadouts Manager option.

Move bits


* Miscellaneous

The Attributes section in data files may now specify categories for attributes, and GCA will now also allow using the format, just like every other type of trait.

The Attributes tab in Classic View now supports changing categories for the All Attributes list (the one on the right side). You will find the Category drop-down list at the top, and it works like it does for other trait types. (The Attributes dialog uses the same system, so you’ll find this change there, too.)

Added an option to lock the toolbars: View > Toolbars > Lock Toolbars.

The Movement boxes in GCA have been fixed to show the correct basic movement rate for the various movement types the character has. Any enhanced movement rate will be shown after that, separated by a slash, such as “4 / 8”, if the option for that is set in Options (in the Display box of Program Options; it is On by default).

* Loadouts Window

Added Copy and Delete buttons

Changed grid selection so you can more easily tell which row you’re on

Moved buttons & selected loadout column name above the grid

Added a ‘gear’ icon, which allows you to ‘freeze’ the first few columns of the grid.

* Updater

Changed the hash used to SHA-256.

* Plugins

OfficialCharacterSheet: Updated Move column of the Encumbrance & Move block to show values based off of Basic Move as stated by the labels.

ColorBlockSheet: Updated Encumbrance & Move block to show correct move values. Added option to show Enhanced Move values as well, and if On (default is On) then it shows them on the following line of the table.

Bits of housekeeping inactivity


* Miscellaneous

Fixed a crash bug in Unified view trait lists when using field buttons to change a list item’s values, and trait grouping is being displayed.

Fixed CollectionKey for GCATrait to String, which for some reason it wasn’t. (Sorry sheet authors, pretty sure this breaks binary compatibility, so you’ll have to recompile again.)

Added some small utility stuff to modTools.

Ensured all code related to inactive items checked for ‘inactive’ status against a non-empty state, rather than checking for “yes”.

Some drawing code related to trait lists was modified to support graying out inactive items.

* Loadout Handling

I’ve added an option that should be considered ‘experimental’ for now, although since it can be disabled, and is Off by default, it shouldn’t be a big problem.

The new option is winningly named RenderNonLoadoutItemsInactive, but can be found in the Options dialog on two new Loadouts blocks under Current Character Options and Default Character Options, as “Render ‘inactive’ any items not in the current loadout.”

This option does what it says on the tin: any equipment item not in the current loadout is made “inactive”, and will grant no gives() bonuses.

There is a bit of a performance hit when changing loadouts, so folks can decide for themselves if it’s worth it, I guess.

There is also a companion option, GrayOutInactiveItems, which will ‘gray out’ the inactive items if you wish, using the same transparency setting option used for hidden items. (This option is On by default, but only applies if you’re using RenderNonLoadoutItemsInactive anyway.)

Allowing for this did require making some minor changes internally, but they shouldn’t affect much in the way of print or export sheet authors: if you were checking for TagItem(“inactive”) = “yes” instead of TagItem(“inactive”) <> “” or something similar, then you may now need to correct for that. GCA needs to be able to re-activate all items that have been deactivated, should the user turn Off the RenderNonLoadoutItemsInactive option, so GCA now sets TagItem(“inactive”) to the name of the current loadout, if the item isn’t already inactive. This way, GCA can undo things as cleanly as possible just by checking inactive() tags against existing Loadouts, and the inactive() tag can still be used as a flag tag.

* Mode Handling

Added reachbasedon() to tags handled by the mode manager.

* TagDefs.XML:

Added these tags: inactive, magery, units

* GCA5.XSD and saved files:

Added these tags to the ‘weaponmodesdata’ block: reachbasedon

Added these tags to the ‘armordata’ block: coverage, charlocation, locationcoverage

Added these tags to the ‘ref’ block: units

Added these spell-oriented tags to the ‘ref’ block: shortcat, prereqcount, magery, class, time, duration, castingcost

Added these equipment-oriented tags to the ‘calcs’ block: preformulacost, preformulaweight, postformulacost, postformulaweight, prechildrencost, prechildrenweight

* Updater

GCA will now pass along its installation folder to the downloaded setup program, which should allow it to correctly default to that target folder during the setup process.

* Included Sheets

All pre-compiled ones have been rebuilt against the current versions of the engine and interfaces.

* GCA5 Changes.GDF

Included the user-targetable version of Weapon Master from entry b

Data File Features

I haven’t done a preview in a while, so for something a bit different, I thought I’d post some of the additions to what data files can support. This also provides a peek into what kinds of new features traits support, as well, since one follows on the other.

Since I made a pretty document about it recently, I figure I’ll just link to that, and let you check it out if you’d like.

Here it is:

GCA5 Updated Data File Info (PDF Doc)

GCA5 Updated Data File Info (PDF Doc)

For want of a bit


In b82, I made a change to some Updater code, to avoid an issue when a book file of the same name was found in another folder. That change broke the system used to determine if GCA had matching files that needed to be updated, because it could no longer determine that any files matched those in the update.

I have implemented a fix for this. Older versions of GCA may see complaints logged about some XML stuff, but the older updater should still work fine to update to this version, it’ll just think every data file needs to be updated, when it really doesn’t. That’s fixed once this update is applied.

Bits of verbosity


* Miscellaneous

Added a bit of code to the MiserOptionsBlock control.

Rebuilt the category warnings on classic view (shows when categories between character and library don’t match) to avoid using a third-party control I no longer want to use.

Adjusted Updater to examine library data beyond simply *.gdf files.

Updated a bunch of the error messages in the GCALibrary object to be more standardized, and to provide line numbers for the lines causing problems during the loading and processing of data files. (Still more to do here.)

* Unified View

Rebuilt the newbie box in the Unified view (the green one that appears only when no characters are loaded) to avoid using a third-party control I no longer want to use.

Adjusted how the Unified view handles locking/disabling the display, so that the newbie box is readable even when the rest of the stuff is disabled.

* Data Files: #Verbose

I have added the command #Verbose to data files. This has only two options, On or Off, like so:

#Verbose On
#Verbose Off

This allows you to turn on VerboseBookProcessing for a specific file, or portion of a file, for testing purposes, without having to have full-on verbosity for every file you’re loading. (Technically, this sets a different property, and does not affect the user’s VerboseBookProcessing setting at all; if they have that turned on, this will have no impact on it at all, and they’ll get the verbosity they desire.)

It should be considered polite to remove these directives from files before they’re made publicly available, as many users will find verbose book processing quite annoying.

* Data Files: #IF

I have added limited support for #IF blocks in data files. The structure is like this:

#IF want = value [THEN]
[#ELSEIF want = value [THEN]]

Notice that the [THEN] parts are optional; GCA will remove them, but they’re not necessary. Same with the IF in #ENDIF; GCA considers any #END to be the end of the current #IF structure.

You may nest #IF..#END blocks.

Note that there is *no* expression evaluator involved here. Support exists for a tiny set of very specific comparisons, which I’ll cover here. If you try anything else, GCA will consider the block FALSE and continue on, happily ignoring that section (and provide an error in the log if you have verbose book processing turned on).

The two types of ‘want = value’ comparisons currently supported are these:

1) fileloaded = “name of file”

This allows you to see if a file has been loaded before this one. The file currently being processed does *not* count. You must use the exact file name that GCA has loaded (ignoring path information, and ignoring case).

GCA supports the following aliases for ‘fileloaded’, so you may use whichever you remember: fileloaded, loadedfile, fileisloaded, loaded, bookloaded, bookisloaded.

“name of file” may be in quotes or braces.


2) traitloaded = “name of trait”

This allows you to see if a particular trait exists in the current library data. Anything loaded before this comparison is a possibly valid subject.

GCA supports the following aliases for ‘traitloaded’, so you may use whichever you remember: traitloaded, traitexists, traitpresent, loadedtrait.

“name of trait” may be in quotes or braces, and must be in the standard fully qualified format, with prefix and full name and extension, as applicable.