I have one character sheet view so far, but I do intend on adding at least one more when I have time (Paizo stat block style, maybe classic 3.5 char sheet after that).
Normal Character sheet: http://prpg.imarvintpa.com/ACharacter.php?ID=8
Data structures used to build it: http://prpg.imarvintpa.com/RawCharacter.php?ID=8
The structure is a specialized key-value pair type thing where the value is a delayed calculation until after everything is done being added.
The critical properties of the object are a "Attribute flag", CachedValue and an array of source objects. The Attribute flag is used because I gave the same name to the Int total as the Int Bonus and the flag gives them a different behavior than the the other values. By default for attribues, you get the bonus when looking up its value where is other variables you get the value..
Each source object has a "Type", CachedValue, ModType, Expression, ConditionExpression, and a SourceID. The type is a DnD Bonus Type for stacking rules. The CachedValue is the total previously calculated for performance. You must/should clear all cached values in the whole structure to recalculate. Modifier Types are Mod, Pen, Bon, Ceiling, and Floor. Mods are normal modifiers, Pens are 0 or less, Bons are 0 or higher, Ceiling gives the variable a maximum value cap, and Floor gives the variable a minimum value limit. Penalties stack differently from Mods and Bons.
The math symbols processed are ()^*/%+- and conditionals are <, >, >=, <=, =, ==, !=, and Booleans &&, ||.
Conditionals and Booleans return 0 or 1 values which can be used as part of the value expression. The carat is an exponent and % is modulo.
Sample JSON:
Code: Select all
{"Name":"FORT","VariableType":"Normal","CacheValue":"2"
,"Derivation":[{"BonusType":"Base","CacheValue":"1"
,"ModifierType":"Mod","CacheConditionResult":"1"
,"Expression":"1","Condition":"1","SourceId":"Base"}
,{"BonusType":"Ability","CacheValue":"1"
,"ModifierType":"Mod","CacheConditionResult":"Yes"
,"Expression":"CON","Condition":"1","SourceId":"CON"}
,{"BonusType":"Racial","CacheValue":"0"
,"ModifierType":"Mod","CacheConditionResult":"No"
,"Expression":"2","Condition":"EFFECT_ENCHANTMENT"
,"SourceId":"Ability:Situational Save Modifiers (Enchantment)"}]}
To get a particular variable's value for a bonus type, use a dot notation. FORT.ABILITY would fetch Ability's contribution to Fort (this ignores the ceiling and floor). Again, defaults to 0 if not found.
There are Prefix semi-functions which are separated by a colon:
P:Fort would return 0 if Fort is higher than 0 or the current value for the fortitude save penalty. More likely used on an attribute.
T for Total (Used with Attributes to get the actual value.)
R is a synonym for .Ranks or .Base
ABS returns absolute value.
Bool returns 0 or 1 from a number
NBool returns 1 or 0 from a number
B is a bonus Max(value, 0)
P is a penalty Min(value, 0)
Resize is a function caller that is used to resize the dice expression that comes with it.
Anything else returns the modifier value.
More later,
IMarv
PS, I'm trying to figure out whether to implement similar logic in a a lib token or convert the elements to work in the properties values.