Author Archives: Armin

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.)

Package Updates

* Package Updater (v1.0.9.2)

The updater will now recheck the calling program version, and the version check data for each manifest, when rebuilding the available packages UI. This will allow for GCA to be updated and then version-locked packages to be installed afterward in the same session, if they then satisfy the needed version requirement. Previously, you had to leave the updater and then re-run Check For Updates again from GCA to run a new session of the Updater in order to install a package that was version locked to the version that you just installed.

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.

 

Package Updates

Delvers to Grow.gdf
[LISTS]
<Wizard Upgrades>
Added TE:Spellslinger

GURPS Magic – Least of Spells.gdf
Requires=”GURPS Basic Set 4th Ed.–Characters.gdf”,”GURPS Magic 4e.gdf”
LoadAfter=”GURPS Basic Set 4th Ed.–Characters.gdf”,”GURPS Magic 4e.gdf”
Added.

[SPELLS]
<Fire:Fi>
Oven Mitts
Puff
duplicate type() tag removed. Thanks DeathDaisy.

GURPS Thaumatology 4e.gdf
[ADVANTAGES]
Increased Threshold
added Supernatural Mental to cat()

Pyramid 3-65 – Half-Stat Defaults.gdf
[SKILLS]
#ReplaceTags in “SK:Riding (%beast%)”
#ReplaceTags in “SK:Riding (Big Cats)”
#ReplaceTags in “SK:Riding (Dogs)”
#ReplaceTags in “SK:Riding (Equines)”
#ReplaceTags in “SK:Riding (Raptors)”
added to match Basic Set. Thanks DeathDaisy.

#ReplaceTags in “SK:Riding”
removed

Pyramid 3-65 – Half-Stat Defaults (Rule of 20 Off).gdf
[SKILLS]
#ReplaceTags in “SK:Riding (%beast%)”
#ReplaceTags in “SK:Riding (Big Cats)”
#ReplaceTags in “SK:Riding (Dogs)”
#ReplaceTags in “SK:Riding (Equines)”
#ReplaceTags in “SK:Riding (Raptors)”
added to match Basic Set. Thanks DeathDaisy.

#ReplaceTags in “SK:Riding”
removed

Pyramid 3-83 – Knowing Your Own Strength.gdf
New file added.

Version 5.0.199 Released

GURPS Character Assistant 5.0.199.0 has been released. Get the updated installer from your Warehouse 23 downloads page.

This update includes all the changes mentioned in Build Notes posts since the last Release.

Note: You get the updated installer by re-downloading GURPS_Character_Assistant.zip from your Warehouse 23 account, and running the gca5setup_5.0.199.release.exe program that it contains. There is no separate update-only installer, you have to download and reinstall the program. It will not overwrite your personal data, it will overwrite your installation of GCA with the new and updated version.

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.

b197 Issues

We’ve had a few bugs reported, including Select dialogs not correctly limiting trait selection levels or points, and Party Log crashing. We hope to have another update posted soon to address these issues.

Things Writers of Plugins Should Know

Since release, and as of 5.0.197, there have been some important changes to be aware of:

* Notes/Notes()

As mentioned in the build notes, the purpose of the notes() tag on traits has been pretty muddled over time due to a variety of folks using it in ways that were not intended. That tag was meant to be used in a tiny space to show table notes references such as “[1,2]” for weapon or armor footnotes. Yes, notes() was a bad name for it, but it originated back when GCA did far less.

The notes() tag is now enforced as a mode-specific tag for the original intended purpose (and even that is now discouraged in favor of using itemnotes() instead), and any use of notes() that was intended by a user to be general item-related notes or commentary should be changed to usernotes() or included in the description(), instead.

* Each trait’s Description() and UserNotes() tags are probably RTF formatted strings.

This may not work for you.

The new functions GetNotes(Optional ByVal AsPlainText As Boolean = True) As String and GetDescription(Optional ByVal AsPlainText As Boolean = True) As String allow for retrieving the usernotes() and description() tags of a trait, as normal RTF or as plain-text.

Line breaks (as LF characters) will be preserved.

* The Notes property on GCATrait has been will now return usernotes() as plain-text.

If you set it, it sets usernotes() with that text.

* Character.Settings has an ApplyDBToActiveDefenses property.

When TRUE, all active defense scores (block, parry, dodge) *will* include the DB value for the active shield (one equipped on an arm). When FALSE, those scores won’t include the DB (which is the traditional way GCA has done it).

If your application needs the scores *not* to include the shield DB but this setting is TRUE, you can set the value to FALSE, call RecalculateAll(True, False), do your exporting, then reset things for the user by setting the value back to TRUE and calling RecalculateAll(True, False) before quitting.

You can get the current DB being applied in the DefenseBonus() As Integer or DB() As Integer functions. The applied DB may be 0 if no shield is equipped.

* Each shield will have a charblockscore() tag.

This contains the character’s Block level when using that shield. This will include the DB for the shield, but if ApplyDBToActiveDefenses is TRUE, then the better of the two values (this shield’s DB or equipped shield’s DB) will be included.

* GCA provides the VTTNotes() tag.

This is per-trait as a way for the user to include VTT-specific notes or formulas, such as OTF expressions for Foundry. On an attack-mode level, GCA provides the mode-specific VTTModeNotes() tag for the same purpose.

* I have added Public Function DamageDisplayText() As String to the Mode object.

This function returns a string that represents the standard damage notation including damage, armor divisor, damage type, and radius. Example: 2d+1 (2) cut (2). You can also access this using Item.DamageModeTagItem() with “DamageDisplayText” as the tag, if you’re accessing mode values that way. This should obviate the need for you to build damage strings yourself, and it will correctly show the new comma-separated mini-modes if those are used by a trait.