Whole lotta bits goin’ on

Simple Edit should no longer allow changes to the names or extensions of attributes.

The mergetags() and replacetags() trigger tags have been updated to allow targeting ‘char’ or ‘character’ with tag values. For example: replacetags( in char with “race(gremlin),laugh(cackle)” ).

Zooming out in Sheet view will now reduce the size, to the built-in minimum, of any interactive editing buttons that may have grown bigger from zooming in.

Added the ITaggedObject Interface to the GCASystem.

Added a form to edit character tags. Added an option to the Character menu to access it. (This is ‘shallow’ in that it only displays any extended tags, not all property values that might also be accessible through the TagItem property. So things like Name, Player, and Race will not appear here, even though they can be accessed through TagItem.)

Updated the Advanced Edit Grid to fix some bugs, and to allow editing of Character tags.

Added Copy Tags and Paste Tags to the right-click menu in the advanced edit grid.

Updated the Add Tag dialog to fill the drop-down box from, and to show help references for, the correct class of item (traits, modifiers, or characters) rather than always using the traits references. Note that there are currently no defined character references, because characters have been more property oriented than tag oriented so far.

Updated character saving/loading to remember character tags.

Updated the GCA5.xsd to include the character Tags block.

Reconstructed parts of the Options dialog to remove problematic third-party controls.

Hooked up the option to group trait modifiers by type.

Hooked up the options for child ordering within parent/child relationships. Changing this will force a refresh of the UI upon exiting Options. Note that setting an Order By in the UI orders the displayed children as well.

Changed ‘Alternative Attacks’ reference on Simple Edit to ‘Alternative Abilities’.

Built custom Enumerator for my custom sorted collections to allow For..Each iteration in sorted order (for multi-sort enabled collections, this is the default sort order of alphabetical by name). Implemented IEnumerable on all of those collections.

Added some functionality to the loadout and the loadout manager objects; and made a couple internal changes.

Updated headers of Loadout Manager dialog to make it more clear that the values in the third row for the various loadout columns are for total weight and encumbrance level

Added support for the new trigger tag loadout() which automatically adds the item being added to the character into a particular loadout or loadouts. For example, loadout(Crime, Punishment) will add the item to both the Crime and Punishment loadouts when added to the character. If the loadouts don’t exist, they’ll be created.

Added the new #loadout() #command to the adds() and creates() tags, allowing you to specify loadouts that equipment items should be added to automatically. This works like the loadout() trigger tag. Note that owned items will not be added to loadouts through this command, because owned items are always included with their parent items in loadouts.

Addressed a small issue in the creates() tag so that created items aren’t owned automatically, which it was doing even when owns(yes) wasn’t included in the creating item.

Fixed a display issue with the checkboxes in the library lists for Compact and Sheet views if explainers were dismissed and then reset in Options.

Found a bug in saving/loading data that could change character damage values (due to my missing how things worked in the writing/reading of the XML). If the value saved for an XML tag is an empty string, the XML saves an empty version of the tag, instead of a full tag with an empty string value. The XML reader then doesn’t return any value for the empty tag, so default values are used for that data, rather than the data getting filled with a ‘new’ empty value. In Basic Damages, this resulted in incorrect values for any levels in the chart that had no adds to the dice (because the defaults weren’t 0). Those defaults are now 0. I believe this is the only case where default data wasn’t set to ’empty’ or ‘null’ values. If you’re using saved .GCA5 characters, you should Resync the Basic Damage List for those characters to correct this.

I found the bug above because I finally atomized down to the object level most of the XML Read and Write handling, where it should have been all along.

Fixed a crash bug in equipment items related to calculating child values when children and parents are being removed from the character.

Data Files:

Updated: GCA5 Changes.gdf: Fixed included versions of the ~Fortify and ~Deflect modifiers to load as modifiers, not advantages.

Bits of complex interaction

Named Modifiers dialog correctly.

Added an explainer to the paper doll panel in the Protection window.

Since the items affecting a location on the paper doll in the Protection window are highlighted in gold/yellow when the location is selected, I have turned off the redundant marking of those items with the shield icon.

Addressed some drag & drop issues in Classic trait lists.

Pressing the Enter key will now end the in-list editing of values in a Classic trait list.

Updated the Compact View trait lists so that the buttons on the selected item will no longer display if the trait is locked, or the increment/decrement buttons will not display if the trait is not leveled.

The TL of an equipment item will now be displayed in the DisplayName if a TL() tag exists.

Changing the name of the character or the player will now update the tab text for that character immediately.

Added new support for fortify()/charfortify() and deflect()/chardeflect() item tags. Recent discussion in the GURPS forum has alerted me to the fact that the Fortify and Deflect enchantments aren’t intended to stack when coverage would otherwise allow them to do so; only the best of the bonuses should apply. These tags are part of the work needed to support this. If there is a fortify() or deflect() value on the item, it’s used as the base value for calculating these new tags. The charfortify() value will be automatically applied as a bonus to the item’s dr() value when figuring chardr(), and the chardeflect() value will be automatically applied as a bonus to the item’s db() value when figuring chardb(). The Fortify and Deflect modifiers should be adjusted to give their bonuses to the owner::fortify and owner::deflect targets, respectively. *NOTE* that the needed stacking rules in Protection aren’t implemented yet.

Did a bunch of work to customize the Sheet View’s preview pane to allow for additional needed functionality.

Finally have a working draft of the interactive editing features for the Sheet view. Double click on an area in the sheet when it’s highlighted to activate the editing features that the sheet author has implemented.

GCA should now remember your settings for Zoom and Sheet in Sheet View between sessions.

Data Files:

Updated: GCA5 Changes.gdf: Included updated versions of the ~Fortify and ~Deflect modifiers from Magic, changing their gives() to the new targets.

Sheets:

ColorBlockSheet updated to use the updated SheetActionField system for interaction in Sheet View, and to demonstrate how it works right now. Double click on a area when it’s highlighted to activate the editing features within GCA.

A few bits and new pieces

Classic View and Sheet View should now clean up better when the last open character is closed.

Fixed recently introduced bug that zoomed in the Sheet View when clicking on the page (only double-clicking should do that).

Views should now refresh better when the Protection window is closed with OK.

Protection window should now remember the layer pane’s orientation and size (when activated).

Updated the Library’s book loading function to correctly read [Languages] and [Cultures] sections from book files. These are just like [Advantages] in structure.

Updated processing to add Languages and Cultural Familiarities at the correct starting level.

Changed the character closing and program shut-down process a bit to allow for canceling the program exit and closing of some characters.

Revamped all the current explainer panels.

Fixed the Getting Started box in Compact view to work with zooming.

GCA will now offer to load any auto-backups it finds when restarting GCA after a crash. If you don’t load them, they’ll be lost when GCA does a normal shut down and cleans things up. (They’re now stored in C:\Users\[USER]\AppData\Roaming\Steve Jackson Games\GURPS Character Assistant 5\autobackup\ when they exist.)

Fixed a drawing refresh issue in the trait boxes in Compact view.

I’ve implemented the first draft of support for ‘gains’ type bonuses. Gains bonuses are bonuses that a trait claims for itself, based on some other trait, rather than having to edit that other trait to have it give a bonus. Right now, these are implemented through the existing gives() tag, but the format requires the use of the ‘from’ keyword, instead of the ‘to’ (actual or implied) keyword. For example, the tag gives(+1 from AD:Magery) would apply a bonus of +1/level of the Magery advantage to the trait containing the gives(+1 from AD:Magery) tag. This implies a ‘to Me’ clause, but actually including such is not supported. The ‘gains’ feature should support expanded keywords such as ‘onlyif’ and ‘upto’ and whatnot, but doesn’t currently support drawing from specific tags of the given source.

Data Files:

Added: GCA5 Changes.gdf to the system books. This includes Languages and Cultural Familiarities sections, but doesn’t remove them from the Advantages section yet, since all other places that add/need them would need to be updated too. It’ll include other needed changes as they occur to me.

Updated: GCA5 Changes.gdf: Added updated version of Language Talent, to reflect that the bonus shouldn’t apply if there are no levels in the language.

Plugins:

Once again, updated controls required recompiling Plugins. This is annoying.

Bit of interaction

* Started work on allowing for some kind of user interaction with the Sheet View. This uses the new SheetActionField object in the engine.

This system relies on the ability of C1 render objects to store user data. Unfortunately, neither table cells nor table rows support UserData, so if you’re using a table, as I am for almost everything in ColorBlockSheet, you’ll need to assign the text for the cell to a RenderText, then assign that as the cell’s render object, in order to also assign a SheetActionField to the RenderText’s UserData object. See this in the PrintTraitBlocks procedure of ColorBlockSheet.

GCA will look at the rendered items under the mouse pointer in Sheet View, and if one of the render objects has a SheetActionField in the UserData then it’ll allow highlighting of that object (and change the mouse pointer).

Right now, no matter what else is set, so long as the SheetActionField has an ActionObject that is a GCATrait, then GCA will allow the user to double-click the field to open the Edit window. That’s the only bit of this currently working (although you can also change the HighlightPen to change the color and size of the highlight box around active items).

All other bits of this are in flux.

* Fixed points bar not updating when switching between characters in Sheet View.

* GCA will now automatically enter into the Log the plugin.Name and plugin.Version of the sheet the user has switched to in Sheet View. This should mean that the sheets themselves no longer need to do that, which means they won’t keep filling up the log with version notices.

* OfficialCharacterSheet updated to reflect user font/color options in Reaction Modifiers box.

* Both included sheets updated to no longer print name and version to log.

* ColorBlockSheet updated to use the new SheetActionField to allow interaction in Sheet View, and to demonstrate how it works right now.

Finally, bits return

Added @ceiling(value) and @floor(value) functions to the solver (@ceil may also be used for @ceiling). @Ceiling(value) returns the smallest integer value that is greater than or equal to the given value. @Floor(value) returns the largest integer that is less than or equal to the given value.

Added some additional house-keeping to the end of the process that adds new traits to characters.

Updated GCACharacter events to include sender in all cases.

MultiSortedModCollection now Implements IEnumerable.

Modified the Undo handling of the Modifiers window to correct a crash issue when working on modifiers to modifiers.

Addressed an issue in startup with arranging the splitters.

Modified startup sequence slightly.

Fixed crash bug related to experimental feature when closing last open character.

Due to another print engine update, and some changes to GCACharacter, sheet plug-ins were re-compiled.

teeny bits

Added a new Box option type to Sheet Options. Like Header or Caption, this has no persistent data. This option allows for the sheet options to be displayed in a style a bit more like the regular Options window and the Compact view. If you use the Box type, any other option types following the Box will be loaded into the Box in the Sheet Options window. ColorBlockSheet has been updated to show this option in use.

Added DisplayScore() function to match DisplayName() function. Returns score for attributes, count for equipment, and level for everything else. Also added corresponding BaseDisplayScore() function.

GCA now supports displayscoreformula() to customize display of score/level values, if needed. This is primarily intended for use supporting split tech levels, but folks may find other uses.

Character Sheets will need to be updated to support DisplayScore for TL, if they’re just referencing the attribute score right now. (If they’re using Character.TL then they’re probably okay.)

Added an Advanced button to the Campaign Settings window in the TL display. This allows for building a DisplayScore for the TL.

I updated the print engine, which broke compatibility with older character sheets, so they’ve been recompiled. C1 still hasn’t fixed the clipping bug for text in defined areas.

Happy Holidays

I wish everyone a happy holiday season and a joyous new year.

There haven’t been updates here lately due to my day job. I’m in the middle of some things, though, so updates are pending.

Rebuilt bits

** Many of the changes in this update will improve performance and robustness. If I did them correctly. If not, we could see data corruption and/or an increase in odd behavior and crashes. **

I have changed how trait handling, tag lists, and the rollback of changes, are handled in the Edit Items, Advanced Edit Items, and Modifiers windows. This should make things more robust and less prone to damage from bad data.

I have adjusted the code that determines relationships between traits (which is what determines which traits are recalculated when you change something). Relationship determination should be done a bit more quickly now.

I have rebuilt a number of the parser routines to be more robust, which should reduce (hopefully eliminate) the instances where an errant open or close paren within braces or quotes was still being counted as a valid part of another container pair.

Given the change above, the %closeparen, %openparen, %closebrace, and %openbrace special variables mentioned in b 5.0.0.36 for @EndsWith and @StartsWith should no longer be necessary, if the corresponding characters are enclosed within quotes in the function, such as @endswith(“)”). The %quotes variable is still required, as there is no way to enclose the double quote character safely, but it’s also the least likely to be needed for anything. I’m leaving all of the variables available, though.

Vars are now run through the Text Function Solver during the trait’s calculation phase. This should speed things up when they’re used.

GCA will now read tag help information, for use in edit windows, from the tagdefs.xml file.

I changed a few things in various support routines to use certain Enums rather than Integers, which broke binary compatibility.

Overhauled bits

* Because I can’t get the long-press on touch screens to work inside the listboxes, and my potential work-around isn’t working to my satisfaction, I have currently made it so that double-clicking the title area (above the sub-heads, because those do OrderBy) of the character list in Compact and Classic view will call up the context menu for that list–IF you have selected items in the list box.

* Addressed font scaling issue in Advanced Edit display grid.

* GCA should now create a default library on startup if none exists.

* Addressed misplaced options button issue in Portrait box.

* The Protection box will no longer display information when no character is loaded.

* Updated the handling of some things in the Colors & Layout dialog.

* Overhauled the look of the Options window.

* Added a ‘Getting Started’ box to the Compact view, which offers some suggestions as to what to do once GCA has started up. This only displays if no character is loaded.

* Added support for a displaynameformula() tag. When using the DisplayName property of a Trait (which most trait lists inside GCA use), if displaynameformula() exists, GCA will use that to generate the name beging returned, instead of the built-in functions. In conjunction, the BaseDisplayName() function, or “me::basedisplayname” will return the same info as DisplayName, but will not use the formula, so it can be used within formulas to alter the output that GCA would have generated.

* Added functions to Solver:

@Len(<text>) returns the length of the given text.
@EndsWith(<text>, <check value>) returns 1 if <text> ends with <check value>, 0 if not. Case is ignored.
@StartsWith(<text>, <check value>) returns 1 if <text> starts with <check value>, 0 if not. Case is ignored.

@EndsWith and @StartsWith both use a few specialty variables instead of a few characters that GCA uses internally for parsing purposes. So, if you want to check for parens (), braces {}, or quotes “, you should instead use these variables as needed: %closeparen, %openparen, %closebrace, %openbrace, %quotes.

* Added to Text Function Solver:

$InsertInto( <target string>, <insert string>, <at position> ) which puts some text inside other text.

* The special case substitution $val() has been added to the Text Function Solver. This is identical in function to $textvalue(), just shorter.

* GCA will now support defining variables at the trait level. Variables are defined using the vars() tag, with the format vars(<name1>=<value1> [, <name2>=<value2>] [, <more name value pairs as needed>]). This allows for greatly reducing the complexity of certain types of formulas, such as the new displaynameformula() mentioned above. These are simple substitution variables; if you use vars(%name% = me::name), then the %name% variable stores the text “me::name”, not the actual name of the trait.

For example, to create a DisplayName that uses the same name that GCA would generate, but adds additional text of “Bonus Text” *within* the parenthetical information (if any), the straight formula might look like this:

displaynameformula($if(@endswith($val(me::basedisplayname), %closeparen) then $insertinto($val(me::basedisplayname), “; Bonus Text”, @len($val(me::basedisplayname))-1) else “(Bonus Text)” ))

Notice that we have to keep repeating the ‘$val(me::basedisplayname)’ bit over and over again (And $val() is necessary, because the Text Function Solver won’t replace any value references unless explicitly told to do so with the $val() or $textvalue() functions). And imagine the additional complexity if we wanted to include a trait value or tag reference instead of the simple constant “Bonus Text”.

So, we can simplify with a variable:

vars(%name% = $val(me::basedisplayname))

and the new displaynameformula() that makes use of it:

displaynameformula($if(@endswith(%name%, %closeparen) then $insertinto(%name%, “; Bonus Text”, @len(%name%)-1) else “%name% (Bonus Text)” ))

In this case, not drastically shorter as text goes, but much more readable.

Note that because GCA will replace the variable name indiscriminately within the target area, as the first step of evaluating an expression, you should ensure that your variable names are unlikely to conflict with other types of text. I recommend using a percent sign % at the beginning and end of each variable name, to ensure no accidents are likely to occur.

* It’s now possible to copy one or more tag/value pairs from inside the Advanced Edit window as an XML fragment, and to paste that fragment into another Advanced Edit window, in order to copy specific tags from one trait to another. To copy tags, select each of the tags you want to copy in the grid, then press CTRL+SHIFT+C to copy them (CTRL+C just copies the text value of those cells). You’ll now have an XML fragment which you can paste anywhere that accepts text. To paste such a fragment into GCA as tags, click on the edit grid in Advanced Edit to ensure that it’s active (but you don’t want to be editing a value, or the paste will go into that field as text), then press CTRL+V to insert the tags.

Dropped bits

I have updated children to be kept as references in a SortedTraitCollection. This is a significant change, and may cause things to explode. Importantly, this change allows for more easily feeding through OrderBy requests, and for customizing the display order of child items in the future. However, this does create some additional hoops to jump through when loading characters, because not everything being referenced will exist yet.

ChildKeyList() and ParentKey() will no longer be returned when a TagList is requested. They will no longer appear in the Advanced Edit Traits window.

I apparently broke binary compatibility for plugins again, by changing the ChildKeyList property to allow an optional parameter.

I also updated the versions on the included plugins, and on the Interfaces assembly, while attempting to fix an issue with the setup program not correctly updating things.

When changing the OrderBy by double-clicking the header of a trait list, GCA will now apply the new order to the children being displayed in the list. Of course, children will still be listed under their parents, so the ordering will only affect how they’re shown within their own block.

Drag and drop visual indicators should display correctly now, even when the listbox has been scrolled.

Drag and drop in the lists should now allow dropping items to become children of other items, although it does currently require dropping onto an existing child of the intended parent.

Dragging a child item onto a non-child item will remove that child from its current parent.

Dragging a trait over a parent item should now also display a ‘drop zone’ indicator labeled “Make child of” on the right-hand side of the list box. Dropping onto that ‘drop zone’ should make the trait a child of the parent.

I have added a button, called “Easier Dragging”, to the third toolbar. When active, this option makes it simpler to begin a drag and drop operation in the trait boxes, but makes it harder to select traits by dragging. I don’t know if I’ll leave it there, but for now that’s where it is.