I was going to rant a bit about Accessibility, but just rambled on a bit instead

Accessibility stuff can be challenging. I’ve spent hours trying to figure out how I can have listboxes correctly report their underlying values through the Accessible properties, and have completely failed to find any solution. Even finding how listbox items are used in such a context has proven more than I can find. Searches of all sorts just bring up either the most basic stuff (how do I use a listbox level stuff) or leads me to the Microsoft docs, which are useless. Very frustrating.

What I’ve ended up doing is a mix of two things: (1) rebuilding the list during the refresh of data, or (2) replacing the dirty items in place during the refresh. I tended toward the full rebuilding on smaller lists in places where there’s already less robust handling, and I have so far used the replace-in-place method for the Classic View trait lists. Either way is a performance hit versus the simple repainting that I was doing, or what I wanted to do which was create a new AccessibleObject that could report itself correctly. However, at least now I have something that works, so I’m just not going to waste my time trying to find the best solution I was looking for.

Now I think I only have to write a new InputBox for simple ‘enter a value’ options used by the Input directives in lots of places. InputBox is a built-in feature from Microsoft, so I was pretty surprised that it appears to have no Accessibility support. Anyway, once that’s done, I think I’ll have the current set of Accessibility issues clear.

And there are a lot of places with terrible tab orders, which I should try to find and fix as well.

Package Updates

* Official Character Sheet (now 1.0.24)

Official Character Sheet updated so that the names of weapons in the weapons list will match the names in the Equipment lists. (Now using DisplayName instead of FullNameTL, so no more /TL)

Package Updates

* Old-Style XML Export (1.0.1)

Initial release of this new export plugin.

Exports a character in the XML format exported by GCA4. GCA5 save files are natively XML, but complex, and this format allows for continued use of third-party tools that were created to use the simplistic CDATA-heavy XML output that GCA4 exported.

Package Updates

————————————————————
Dungeon Fantasy RPG.gdf
————————————————————
[ATTRIBUTES]
ST

initmods() Size formula() changed “& owner::score > 0” to “& owner::level > 0” because Size Mod only applies for ST increases.

————————————————————
GURPS Banestorm 4e.gdf
————————————————————
[TEMPLATES]
Djinn Ascended Ones (Banestorm)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))"=2,_

Gargoyles (Banestorm)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))",_

Elves (Banestorm)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" _

Dark Elves (Banestorm)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" _

Goblins (Banestorm)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))"=2 _

Halflings (Banestorm)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))"=3,_

Kobolds (Banestorm)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))"=2 _

Great Eagles (Banestorm)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))"=2 _

Wise Owl (Banestorm)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))"=4 _

In all of these, removed the initimods() from the created ST disad because Size Mod only applies for ST increases.

————————————————————
GURPS Basic Set 4th Ed.–Characters.gdf
————————————————————
[ATTRIBUTES]
ST

initmods() Size formula() changed “& owner::score > 0” to “& owner::level > 0” because Size Mod only applies for ST increases.

————————————————————
GURPS Bio-Tech 4e.gdf
————————————————————
[TEMPLATES]
Ishtar [TL9] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" _

Siduri [TL9] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" _

Light Worlder [TL9] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 2 _

Brownie [TL9] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" _

Spacer [TL9] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 2_

Spacer Bioroid [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 2_

Camazotz [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 2_

Camazotz Bioroid [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 2_

Camazotz Chimera [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 2_

Void Dancer [TL11] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 3,_

Dark Angel Bioroid [TL11] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" _

Eros Bioroid [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))",_

Eros Fugu Bioroid [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))",_

Eros Furry Bioroid [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))",_

Eros Gothic Bioroid [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))",_

Felicia [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" _

Felicia Bioroid [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" _

Felicia Chimera [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" _

Lepus [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" _

Lepus Bioroid [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" _

Lepus Chimera [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" _

Tek-Rat [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 6 _

Tek-Rat Bioroid [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 6 _

Tek-Rat Chimera [TL10] (Bio-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), _
initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 _
THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 6 _

In all of these, removed the initimods() from the created ST disad because Size Mod only applies for ST increases.

————————————————————
GURPS Dragons 4e.gdf
————————————————————
[TEMPLATES]
Petty Drake (Dragons)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))"=3_

Petty Drake - Wild (Dragons)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))"=3_

Petty Drake - Cute Shoulder Dragon (Dragons)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes) | No Fine Manipulators, -40%, group(No Fine Manipulators Stat), formula(-@if(ST:No Fine Manipulators >0 then 40 else 0)), forceformula(yes))"=8_

Petty Drake - Venomous Dragonet (Dragons)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))"=3_

Chinese Water Snake (Dragons)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes) | No Fine Manipulators, -40%, group(No Fine Manipulators Stat), formula(-@if(ST:No Fine Manipulators >0 then 40 else 0)), forceformula(yes))"=1,_

In all of these, removed the initimods() from the created ST disad because Size Mod only applies for ST increases.

————————————————————
GURPS Dungeon Fantasy 2 – Dungeons.gdf
————————————————————
[TEMPLATES]
Doom Child (Dungeon Fantasy)
creates(_
{DI:Racial ST Penalty, -10/-20, cat(Attributes), mods(Extra ST, Size, No Fine Manipulators), gives(-1 to ST:ST), initmods({"Size", -10%, group(Size ST), page(B15), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes)} ) } = 2,_

Toxifier (Dungeon Fantasy)
creates(_
{DI:Racial ST Penalty, -10/-20, cat(Attributes), mods(Extra ST, Size, No Fine Manipulators), gives(-1 to ST:ST), initmods({"Size", -10%, group(Size ST), page(B15), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes)} )} = 10,_

Giant Rat (Dungeon Fantasy)
creates(_
{DI:Racial ST Penalty, -10/-20, cat(Attributes), mods(Extra ST, Size, No Fine Manipulators), gives(-1 to ST:ST), initmods({"Size", -10%, group(Size ST), page(B15), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes)} )} = 1,_

Erupting Slime (Dungeon Fantasy)
creates(_
{DI:Racial ST Penalty, -10/-20, cat(Attributes), mods(Extra ST, Size, No Fine Manipulators), gives(-1 to ST:ST), initmods({"Size", -10%, group(Size ST), page(B15), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes)} )} = 10,_

Flaming Skull (Dungeon Fantasy)
creates(_
{DI:Racial ST Penalty, -10/-20, cat(Attributes), mods(Extra ST, Size, No Fine Manipulators), gives(-1 to ST:ST), initmods({"Size", -10%, group(Size ST), page(B15), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes)} )} = 10,_

In all of these, removed the initimods() from the created ST disad because Size Mod only applies for ST increases.

————————————————————
GURPS Dungeon Fantasy 5 – Allies.GDF
————————————————————
[TEMPLATES]
Insect Swarm
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -10%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes) | No Fine Manipulators, -40%, group(No Fine Manipulators Stat), formula(-@if(ST:No Fine Manipulators > 0 then 40 else 0)), forceformula(yes))" = 8_

Removed the initimods() from the created ST disad because Size Mod only applies for ST increases.

————————————————————
GURPS Dungeon Fantasy 9 – Summoners.gdf
————————————————————
[TEMPLATES]
Embodied Animal-Spirit - Huge Bird (Dungeon Fantasy)
creates(_
"DI:Racial ST Penalty, -10/-20, gives(-1 to ST:ST),_
cat(Exotic Physical, Exotic, Physical, Attributes), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 3 _

Removed the initimods() from the created ST disad because Size Mod only applies for ST increases.

————————————————————
GURPS Fantasy 4e.gdf
————————————————————
[TEMPLATES]
Elf (Fantasy)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" _

Halfling (Fantasy)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))"=5,_

In all of these, removed the initimods() from the created ST disad because Size Mod only applies for ST increases.

————————————————————
GURPS Lite 4th Ed.gdf
————————————————————
[ATTRIBUTES]
ST
initmods( Size, -10%, group(Size ST),_
formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)),_
forceformula(yes) _

changed to

initmods( Size, -10%, group(Size ST),_
formula(-@if(ST:Size Modifier::score > 0 & owner::level > 0 THEN ST:Size Modifier::score * 10 else 0)),_
forceformula(yes) _

because Size Mod only applies for ST increases.

Hit Points
initmods( Size, -10%, group(Size),_
formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)),_
forceformula(yes) _

changed to

initmods( Size, -10%, group(Size),_
formula(-@if(ST:Size Modifier::score > 0 & ST:Hit Points::level > 0 THEN ST:Size Modifier::score * 10 else 0)),_
forceformula(yes) _

because Size Mod only applies for HP increases.

[TEMPLATES]
Elf (Basic Set)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))",_

Removed the initimods() from the created ST disad because Size Mod only applies for ST increases.

————————————————————
GURPS Traveller Interstellar Wars 4e.gdf
————————————————————
[TEMPLATES]
Bwap (Traveller: Interstellar Wars)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical, Attributes), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 2,_

Nugiiri (Traveller: Interstellar Wars)
creates(_
"DI:Racial ST Penalty, -10/-20, cat(Exotic Physical, Exotic, Physical, Attributes), gives(-1 to ST:ST), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 3 _

In all of these, removed the initimods() from the created ST disad because Size Mod only applies for ST increases.

————————————————————
GURPS Ultra-Tech 4e.gdf
————————————————————
[TEMPLATES]
Android - Child Body (Ultra-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, gives(-1 to ST:ST), cat(Exotic Physical, Exotic, Physical, Attributes), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 3 _

Petbot (Ultra-Tech)
creates(_
"DI:Racial ST Penalty, -10/-20, gives(-1 to ST:ST), cat(Exotic Physical, Exotic, Physical, Attributes), initmods(Size, -0%, group(Size ST), formula(-@if(ST:Size Modifier::score > 0 THEN ST:Size Modifier::score * 10 else 0)), forceformula(yes))" = 3 _

In all of these, removed the initimods() from the created ST disad because Size Mod only applies for ST increases.

Calculating a bit of context (b214)

b214

* Miscellaneous

Made a fix to how GCA returns baseweightconverted() for baseweight(). It should now work properly and more safely.

For backward compatibility reasons there were two different but nearly identical versions of the damage special-case substitution handling routine. I have now updated one to just call the other.

* Mode-Specific Calculations

People often lose track of the context required for bonuses to modes and the use of mode-specific values. It’s not possible for GCA to get or use the value of a mode-tag from outside of the calculation of that mode. That’s why bonuses that make use of mode-specific values, such as ‘chareffectivest’ or ‘charskillscore’ have to be done as bonuses to ::damage$. Bonuses to ::damage$ are simply aggregated with the existing damage() tag and then calculated all together, along with normal bonuses. This allows GCA to have on hand the values needed for mode-specific requests made with $modetag().

This is very easy to lose track of, and can be confusing, I know, but it’s just not possible for a bonus to know the values of the mode it’s being applied to in advance, when there are so many possible modes to which it might apply..

In the existing data files, this necessary context was lost for some bonuses, causing them to return inaccurate or non-context-sensitive results.

In light of this, and to render those bonuses functional again, I added some new features which should address the issue.

First, I have added support for a Mode to return BaseSwDice and BaseThDice for itself. It does this by checking to see if it has a ‘chareffectivest’ value, and if so uses that with the @BaseSWDice() or @BaseTHDice() function of the Solver and returns the result; otherwise it returns the BaseSWDice or BaseTHDice from the Character.

Second, I have added some new special case damage substitutions. If the damage text being calculated contains ‘owner::basethdice’ or ‘me::basethdice’, GCA will replace that text with the Mode’s new BaseThDice result. Likewise, if the damage string contains ‘owner::baseswdice’ or ‘me::baseswdice’, GCA will replace that text with the Mode’s new BaseSwDice result. Note that this is because owner:: is only used from modifiers, and isn’t applicable in a late-resolution bonus string such as those to ::damage$, so it’s assumed that it’s intended to be the target item’s score, the same as me:: would be.

Note that you can now also use $modetag(basethdice) or $modetag(baseswdice) to get those mode-specific results, even though they aren’t technically mode tags, and using this construction is preferable to owner::baseXXdice for clarity.

These changes together with those in Special Damage Text section below should fix the known problems with these bonuses, in place, without users having to make changes to existing character data.

* Special Damage Text

There are sometimes problems calculating certain specialty damage types. For example, calculating something like ‘slam+3’ and granting it bonuses might result in ‘slam+3+lots of nonsense code’ or such, usually because of the hoops that need to be jumped through to do mode-specific adjustments to damages. On the other hand, something like an affliction with damage() of ‘HT-$solver(me::level – 1)’ correctly returns HT+X, but if it too gets a bonus, it might also return ugly unhelpful results.

My previous attempt at addressing this incorrectly resulted in damage for afflictions and some weapons returning empty damages, because I didn’t realize the full impact at the time.

My new attempt tries to work around the issue by recognizing that some damages are based on a ‘prefix’ such as ‘slam’ or ‘HT’ and calculating the stuff that isn’t the prefix, then returning it at the end recombined with the prefix.

This new method includes support for user-specified prefixes simply by enclosing them in square brackets [] as the very first part of the damage() tag for that mode. Support for ‘slam’ is built in without needing the brackets, and for things like afflictions you shouldn’t need to use it unless you’re adding bonuses and don’t like the resulting HT+X+Y that may occur. But if you do change it to ‘[HT]+$solver(me::level – 1)’, then GCA should use the new method to return a more pleasing HT+X result with the combined values.

Currently, if the calcs result in a prefix+0, that +0 will still be shown, it will not be dropped. In addition, if the prefix isn’t explicitly specified (or built-in like ‘slam’), then it may be lost if a damage bonus includes some number of dice, and then you’ll need to add brackets around the prefix, such as in the affliction example above..

Package Updates

GURPS Dungeon Fantasy 5 – Allies.gdf

[TEMPLATES]
Cat
gives() ‘-2 to ST:Basic Speed’ changed to ‘-0.5 to ST:Basic Speed’

Hawk
gives() ‘+2 to ST:Basic Speed’ changed to ‘+0.5 to ST:Basic Speed’

Up a bit, down a bit (b213)

b213

Added some safety checks to the CalcApplicableModeTargetTagXXX(Mode, String) routines, because it is possible to try to use them without an actual mode set, and that is bad.

The special #note() directive for Select() list items has been improved. Displayed notes are now indented to make a more clear separation between the note and the general list items. Also, you can now use limited BBCode formatting in the note, and if you do that, you should use ‘[BB]’ or ‘[BBCode]’ as the first characters in the #note(); they will be stripped off, but tell GCA to use the BBCode engine to draw the text.

GCA will now remove packageupdater2.exe from the appdata folder during the startup process that cleans up after updates.

* SkillScore and Parry for Attacks

Most of the time, a bonus to an attack’s SkillScore is intended to raise the general use of the skill for the attack, including Parry for melee attacks. However, there are certain times where the bonus is intended to apply only to the attack usage, and not to the parry usage. The way to reflect that in the bonus was to subtract back out the bonus from the calculated Parry, and that was quite complex and confusing because it would get applied after all normal calculations for parry were already made. Here’s an example of that:

gives(+1 to owner::skillscore, 
      =-(@int($modetag(charskillscore)/2) - @int(($modetag(charskillscore) - $solver(me::level))/2)) to owner::parryscore$ _
)

I have now added a new bonus target for use during the calculation of ParryScore: preparryscore. This allows you to simply apply an adjustment to the version of charskillscore that will be used in the parryat() calculation, before the parryat() calculation is made. This means that you can now simply apply a negative version of the positive bonus going to ::skillscore to ::preparryscore to counter it out for parry purposes. Here’s an example:

gives(+1 to owner::skillscore, 
      -1 to owner::preparryscore _
)

This should be faster and easier for everyone.

* Ammo

I did all the code necessary to convert ammo() to charammo() and store charammounits() for reference. And then I discovered that Ultra-Tech uses ammo() for something completely different, which looks like letter codes of some kind. That’s obviously incompatible, so I’ve disabled the ammo() calc stuff until I can figure out what that’s all about and if I can move things around or if I’ll just have to ignore that for a while.

* Weights and unit conversions

GCA will now create two new calculated tags when calculating equipment items: baseweightconverted() and baseweightunconverted(). The value in baseweightunconverted() is the solved value of baseweight(), or the result of baseweightformula() if that is used, before any automatic unit conversion is performed. The value of baseweightconverted() is that value after automatic unit conversion is performed.

Now, when GCA processes a reference to ::baseweight or TagItem(“baseweight”) it will return the value from baseweightconverted() instead. If you really need the unconverted value, reference it explicitly.

This change comes about due to the discovery that all the calculations for items are using the units-converted value, but bonuses referencing ::baseweight would be getting the unconverted original tag value from GCA. So calculations proceeding from that point would include values using two different scales of units, and the final result would be incorrect.

If you’re not using unit conversion, then this should not affect any results, and all three values should be the same.

* Solver

Added a new function, @getnum(<text>) which returns the first numeric portion found in the given text, as best as it can determine. Note that special case substitutions and $ functions will be resolved before the function is called (that’s how the solver works), but embedded @ functions will not be resolved within this function because the purpose of the function is to get a number out of text, and if you need it solved, you don’t need this function.

The text is searched from left to right to find the first number. If it finds a – it will allow for a negative number, but only if the – is immediately to the left of the first numeric character. It will allow for decimal values if the decimal follows a number or is the first character of the text being checked and is followed by a number.

* TagDefs.xml

Added entries for baseweightconverted and baseweightunconverted.