View Full Version : New! Story Templates Enhanced
tjlee
August 10th, 2024, 17:20
I'd like to introduce to you an extension and a module that builds upon the CoreRPG story templates that is backwards compatible and with added features.
It was developed to be only dependent upon the CoreRPG ruleset but is currently only tested on D&D 5E, Shadowdark, and Pathfinder 2E, but should work with any CoreRPG-based ruleset.
Here are some highlights:
New Parser
New Table Multipliers (sorted, unique, specific table rolls)
Comments in templates.
Modular Templates (include simple templates in other templates)
Advanced Templates (to generate Advanced Stories)
New Slash Command (/et) to evaluate template syntax in chat.
Added Function-based syntax (2024.10.02 Update)
As a point of clarification, stories and advanced stories generated using templates created for this extension are exportable and shareable with non-extension users.
Templates (especially Advanced Templates) that use the newly supported syntax by this extension when exported in a .mod file will require use of this extension in order to generate new stories from those templates.
For more information:
Story Template Enhanced (extension) (https://forge.fantasygrounds.com/shop/items/1870/view) - the extension itself.
Story Template Enhanced (examples) (https://forge.fantasygrounds.com/shop/items/1871/view) - a module containing sample/test templates demonstrating CoreRPG and new story template features.
Release Log:
2024.10.06 Update: Maintenance release - code clean-up and examples update.
2024.10.02 Update: Added complete set of functions to support new function-based template syntax (more details (https://www.fantasygrounds.com/forums/showthread.php?82322-New!-Story-Templates-Enhanced&p=727306#post727306), documentation (https://www.fantasygrounds.com/forums/showthread.php?82322-New!-Story-Templates-Enhanced&p=727373&viewfull=1#post727373), and examples (https://www.fantasygrounds.com/forums/showthread.php?82322-New!-Story-Templates-Enhanced&p=727376&viewfull=1#post727376)).
2024.09.30 Update: Added functions! See New Release 2024.09.30 (https://www.fantasygrounds.com/forums/showthread.php?82322-New!-Story-Templates-Enhanced&p=727131#post727131) below.
2024.08.29 Update: Added a few features. See New Release 2024.08.29 (https://www.fantasygrounds.com/forums/showthread.php?82322-New!-Story-Templates-Enhanced&p=724301#post724301) below.
2024.08.16 Update: Updated the extension to accommodate changes made in FGU 4.5.10.
2024.08.11 Update: For those of you who got the module without the extension, I've put up a new version with the templates rendered as stories so you can see the end products. It's helpful to view the templates and the results side-by-side. Without the extension, you won't be able to view the Advanced Templates, but at least you can see the resulting render. You should be able to view the Simple Templates included (majority of them) either way.
2024.08.10 Initial Simultaneous Public Release of the extension and module.
Cheers!
TJ Lee
Zacchaeus
August 10th, 2024, 20:48
Jolly well done.
Jiminimonka
August 10th, 2024, 21:38
Isn't this already built into Story Templates?
https://www.fantasygrounds.com/forums/showthread.php?63527-Story-Template-PRO-(Extension-for-Unity)
This was added to FGU a couple of years ago.
What does your one do that this one doesn't, is it easier to understand?
Jiminimonka
August 10th, 2024, 21:51
Comparing screenshots with text in the original Story Templates Pro - massive coincidence?
61493
tjlee
August 10th, 2024, 22:20
Isn't this already built into Story Templates?
https://www.fantasygrounds.com/forums/showthread.php?63527-Story-Template-PRO-(Extension-for-Unity)
This was added to FGU a couple of years ago.
What does your one do that this one doesn't, is it easier to understand?
I appreciate your question.
With the newly rewritten parser, you can nest table expressions arbitrarily deeply.
For instance, this sequence of table callouts and value references just works with my extension, but doesn’t with CoreRPG:
[:?Race:bardrace]
[:?Gender:bardgender]
[:?<bardrace> <bardgender> Name:bardname]
All of the above silently assign values to bardrace, bardgender, and bardname by rolling on the respective tables.
You can then reference the values as <bardrace>, <bardgender>, and <bardname> later in the template.
Kind of obvious, right? Except things break down in CoreRPG with the last one. It just doesn’t work because the CoreRPG parser and generator only makes a few passes across the syntax and ends up falling short.
Furthermore, the above can be included as column values in tables and still work even with deeply nested tables.
Additionally, with the introduction of Advanced Stories earlier this year, this extension allows the creator to make corresponding Advanced Story Templates that support text, dual column text, header text, image with text, and image with side text (left or right) blocks which the CoreRPG story template generator does not support.
Additionally, this extension introduces new syntax for table multipliers that sort, remove duplicates, or specify a different table roll:
Original multiplier supported by CoreRPG and my extension:
[1d4x][NPC Name] roll on table NPC Name 1-4 times
New multipliers in the extension:
[1d4s][NPC Name] roll on same table 1-4 times, sort ascending the results.
[1d4u][NPC Name] roll on same table 1-4 times, sort ascending and return unique results (by removing duplicates).
[1,4r][NPC Name] returns table rows that correspond with values 1 and 4. You can also specify a comma separated list of die rolls and numbers to pick from a subset of rows in the table.
Also, the extension supports Modular Templates. You can include a Simple Template in another using new syntax:
!^Simple Template^!
This allows you to reuse content generation and formatting in multiple places in other templates and maintain changes in one place rather than employing cut/paste reuse which is your only option in CoreRPG.
The product page for the extension has a little more detail about additional features and the module (free) has some examples which can be used as a tutorial to learn more.
I hope this helps with illustrating the benefits of this extension over the built-in story generator.
TJLee
tjlee
August 10th, 2024, 22:24
Comparing screenshots with text in the original Story Templates Pro - massive coincidence?
61493
It’s on purpose to demonstrate backwards compatibility.
I didn't scroll further down in my screenshot, but there's another section of example templates that demonstrate all of the new functionality.
Here's the rest of the list:
61494
LordEntrails
August 11th, 2024, 17:55
I'll add that I've been talking with tj about this for a while as he has been developing it. Though I haven't tested it yet, I'm really looking forward to getting some time to do that this week. All of the enhancements we've talked about have been pretty impressive. I know most people may never need or want the advanced features he's added, but it's taking the work that JimSocks did with Templates Pro and expanding on it. For those who really want an even more powerful tool for templates and tables, this is what you want to be looking at.
Laerun
August 11th, 2024, 19:15
Video demo time.
tjlee
August 11th, 2024, 19:21
Video demo time.
Are you asking or volunteering? ;)
LordEntrails
August 13th, 2024, 16:08
Video demo time.
I've been trying to convince tj he should come on one of your streams ;)
Of course, you would have to make the offer...
tjlee
August 13th, 2024, 18:07
I've been trying to convince tj he should come on one of your streams ;)
Of course, you would have to make the offer...
I’m game - let me know what to expect and when.
Update: looks like the ball is in my court - I discussed this with Laerun and I'm to prep a Story Template scenario to demonstrate. I've been busy releasing the Table Edit extension (https://forge.fantasygrounds.com/shop/items/1881/view) as well as adding features to this extension. Perhaps the demonstration will make use of both extensions in a 2-fer.
tjlee
August 30th, 2024, 06:58
This release adds the following:
Added logic to remove empty text blocks in Advanced Stories generated from Advanced Story Templates.
Formalized support for use of Link IDs in place of Table names and Story Template names (see Story Template Enhanced - examples (https://forge.fantasygrounds.com/shop/items/1871/view)).
Added a click action to the Toolbar Drag Record Link button (top left corner) to report the Link ID associated with the window to chat.
Additionally, the Story Template Enhanced - examples (https://forge.fantasygrounds.com/shop/items/1871/view) have been updated to clarify existing examples and add examples to illustrate the above.
tjlee
September 21st, 2024, 05:38
I went ahead and re-tested the extension with the 2024 D&D Ruleset update to make sure everything works as expected.
If you do experience any issues, please reply to this thread with a description of the issue and I'll try to reproduce and address it in a timely manner.
tjlee
October 1st, 2024, 07:46
This release adds functions!
Story Template Enhanced extension now supports function invocations with a syntax of functionName(stringExpression). The six functions supported are:
capitalize - the first letter of the string expression is made uppercase.
date - the system date according to the [DATE:format] callout is evaluated. Ex. date(format)
fgdate - the game date (based upon selected calendar) according to the [FGDate:format] callout is evaluated.
lower - the string expression is made all lower case. Ex. LOWER(Hi) is substituted by hi.
titlecase - the string expression is made title case. Ex. titlecase(hello there) is substituted by Hello There
upper - the string expression is made all lower case. Ex. upper(hi) is substituted by Hi.
These functions can be nested and can be co-mingled with the other template syntax elements where it makes sense. The results of the function are substituted in place of the function callout.
Example:
capitalize([NPC Name]) - capitalizes the result of calling the table named NPC Name (first letter is capitalized).
Note: if the results of the table callout is not a string expression (such as formatted text), the function may produce unexpected results.
2024.10.01 Update: Story Template Enhanced (examples module) has been updated to include examples for functions (Story Template 2.2).
tjlee
October 3rd, 2024, 10:24
Update: The following has been released 2024/10/02. Documentation (https://www.fantasygrounds.com/forums/showthread.php?82322-New!-Story-Templates-Enhanced&p=727373&viewfull=1#post727373)and examples (https://www.fantasygrounds.com/forums/showthread.php?82322-New!-Story-Templates-Enhanced&p=727376&viewfull=1#post727376)follow this post.
I'm excited to tease a more fully fleshed out function-based syntax for story templates that might be easier for folks to learn.
In total, there are 41 functions across 6 categories that include the 6 formatting functions already released (and soon to be enhanced with the next release).
The categories of Story Template Enhanced function syntax include:
Control Functions (delim, get, set, setg, xget, xset, xsetg)
String Functions (capitalize, cat, date, dcat, dice, fgdate, lower, pre, post, reverse, rsort, sort, titlecase, uniq, upper)
Number Functions (avg, count, max, min, total)
Formatting Functions (bold, bullets, italic, lines, underline, znum)
Access Functions (head, pick, select, tail)
Table and Template Functions (import, mult_import, mult_table, table)
Teaser: With the above, you can implement a counter to include in your template.
set(a,1) - iniitailze alias 'a' to 1
setg(a,total(get(a),1))
The above computes a + 1 (total of get(a) and 1) and assigns it back to 'a' (setg), then returns the new value 2 (setg). setg is short for "set get". The xset/xget/xsetg are the cross-template versions for values you want to persist across template evaluations.
set/xset happen quietly and are similar to the original template syntax: [:?1:a] (except that this doesn't work). ? means quiet (no value is returned)
setg is equivalent to [:1:a] (except that it doesn't work either - the value '1' has to come from a table in order for it to work).
get is equivalent to <a>.
Teaser: You can also format dates beyond what CoreRPG supports.
dcat(/,znum(2,date(mm),date(dd)),date(yyyy))
The above is broken down as:
Concatenate (dcat) the values and delimit the results with /
Zero left pad (znum) date(mm) and date(dd) to two places
Include date(yyyy)
The result looks something like: 09/01/2024, depending on the system date of course. The CoreRPG [Date:mm/dd/yyyy] produces 9/1/2024 (without the leading zeros).
From the list of functions above, you can speculate how you might make use of them in your creative endeavors. These and the original plus enhanced story template syntax may be co-mingled in your story templates. Yes, they inter-operate. For example, you can store values in aliases using the original syntax and retrieve the values using the function syntax and vice versa!
If you have ideas for additional functions, feel free to message me or reply to this thread. The rewritten story template parser allows me to support these and future enhancements relatively easily (even though the code is densely complicated).
Everyone who has purchased this extension through the Forge - thank you! You will automatically get the new version once I release it along with the Story Template Enhanced Examples that will be updated with new documentation and examples to illustrate the above.
tjlee
October 4th, 2024, 09:43
The following is included in the Story Template Enhanced (examples module) (https://forge.fantasygrounds.com/shop/items/1871/view).
You will need the extension (https://forge.fantasygrounds.com/shop/items/1870/view)enabled in order to use the new syntax.
Functions
Story Template Enhanced extension now supports function invocations with a syntax of functionName(values).
These functions can be nested and can be co-mingled with the other template syntax elements where it makes sense.
The results of the function are substituted in place of the function callout (sometimes with an empty string).
Reference
Control Functions
The values stored may be individual values or a list of values separated by the delimiter (defaults to comma).
FunctionDescriptionExampleResult
delimSets the function delimiter. Only the first character is used.1 - delim( )
2 - delim(/)
3 - delim()
1 - Sets the delimiter to space.
2 - Sets the delimiter to forward slash.
3 - Resets the delimiter to the comma default.
getRetrieves the named values.get(a,b)Returns a delimited string whose values are determined by named values a and b.
setSets the named value.set(a,1,2,3)Sets the named value a to: 1,2,3
setgSets the named value and returns the value stored.setg(a,1,2,3)Sets the named value a to: 1,2,3 and returns the values: 1,2,3
xgetRetrieves the named cross template value.xget(a,b)Returns a delimited string whose values are determined by the named cross template values a and b.
xsetSets the named cross template value.xset(a,sample,data)Sets the named cross template value a to: sample,data
xsetgSets the named cross template value and returns the value stored.xsetg(a,example)Sets the named cross template value a to: example and returns the value: example
String Functions
The values passed to the functions depend on the function. Usually, each function accepts one or more values. Sometimes the first value has special meaning to the function.
FunctionDescriptionExampleResult
capitalizeThe first letter of each string is made uppercase.capitalize(hello there)Hello there
catReturns a string value with the values concatonated and separated by a space character.cat(Hello,there)Hello there
dateReturns the system date according to the DATE:format syntax.date(mm/dd/yyyy)9/30/2024
dcatReturns a string value with the values concatonated separated by the specified first character in the the list of values.dcat(/,09,30,2024)09/30/2024
diceReturns a set of values of dice evaluations.dice(2d4,2d4+10,hi)8,13,0
fgdateReturns the game date according to the FGDate:format syntax.fgdate(mm/dd/yyyy)Similar to date example.
OR
No Calendar Mod Loaded
lowerEach string expression is made all lower case.lower(HELLO,THERE)hello,there
postReturns a list of values with the first parameter appended to each of the remaining values.post(:,1,2,3)1:,2:,3:
preReturns a list of values with the first parameter prepended to each of the remaining values.pre(-,1,2,3)-1,-2,-3
reverseReturns a list of values in reverse order.reverse(1,2,3)3,2,1
rsortReturns a list of reverse sorted values.rsort(01,2,003)003,2,01
sortReturns a list of sorted values.sort(hello,10,02,hi)hello,hi,02,10
titlecaseEach string expression is made title case.titlecase(hello there)Hello There
uniqReturns a list of unique values in sorted order.uniq(1,1,2,3,3,3,4,4)1,2,3,4
upperEach string expression is made all upper case.upper(hello,hi,bonjour)HELLO,HI,BONJOUR
Number Functions
FunctionDescriptionExampleResult
avgReturns the average of the numeric values. Non numeric values are ignored.avg(1,2,3,hello)2
countReturns a count of values.count(1,2,3)3
maxReturns the largest of the numeric values or the value list if there are no numbers in the list.max(1,2,Hello,5)5
minReturns the smallest of the numeric values or the value list if there are no numbers in the list.min(10,02,-1)-1
totalReturns the sum of the numeric values or zero if there are no numbers in the list.total(1,2,3)6
Formatting Functions
FunctionDescrptionExampleResult
boldReturns the values bolded.bold(hello,there)hello, there
bulletsReturns the values as a bullet list.bullets(item 1,item2)
item 1
item 2
italicReturns the values italicized.italic(bonjour)bonjour
linesReturns the values separated by newline.lines(line 1,line 2)line 1
line 2
underlineReturns the values underlined.underline(hi)hi
znumReturns the numeric values left padded with zeros. The default is 2 places. When more than one value is supplied, the first numeric value specifies the amount of padding.znum(4,1,2,3)0001,0002,0003
Access Functions
FunctionDescriptionExampleResult
headReturns the first n values based on the first value.head(2,1,2,3)1,2
pickReturns a randomly selected value from the values.pick(1,2,3,4,5,6)One of: 1,2,3,4,5,6
selectReturns a specificly selected value from the values based on the first value.select(3,a,b,c,d,e)c
tailReturns the last n values based on the first value.tail(3,A,b,C,d,E,f,G)E,f,G
Table and Template Functions
FunctionDescriptionExample*Result
importImports a simple template.import(dateFormat)09/30/2024
mult_importImports a simple template with the first value specifying a multiplier.mult_import(3ud,Drink)Something like:
Bashful Porter,Cobbler's Ale,Yellow Camel Stout
mult_tableMakes a table callout with the first value specifying a multiplier.mult_table(3ud,Drinks)Equivalent to:
[3ud][Drinks]
tableMakes a table callout.table(Drinks)Something like:
Sneezy Thatcher's,Lager
Note: * the "3ud" parameter specifies a multiple of up to 3 unique values using the system delimiter (default is comma) to separate the multiples in the output. See the delim() function above to set the delimiter to some other value. When 'd' is not specified (as in '3u'), the delimiter defaults to a space instead of the delimiter specified by the delim() function.
tjlee
October 4th, 2024, 10:11
The following is included in the Story Template Enhanced (examples module) (https://forge.fantasygrounds.com/shop/items/1871/view).
You will need the extension (https://forge.fantasygrounds.com/shop/items/1870/view)enabled in order to use the new syntax.
Functional Equivalence
The following tables illustrate functional equivalence between the traditional CoreRPG-style syntax and the Function-style syntax.
PurposeCoreRPG Extended SyntaxFunction syntax
Dice Expression[1d4+10]dice(1d4+10)
Table Multiplier[1d4+1x][Female Name]mult_table(1d4+1x,Female Name)
Table Callout[a]cat(table(a))
Assuming default delimiter is a comma, use cat() to concatenate the values with a space instead.
Column Referencing#a|1#select(1,get(a))
Custom Naming[:Colors:eyes]
<eyes>
[:?Colors:teeth]
<teeth>setg(eyes,table(Colors))
get(eye)
set(teeth,table(Colors))
get(teeth)
Callout Internal Rolling[:[Race] [Gender] Name:Bartender]
<Race>
<Gender>
#<Race> <Gender> Name|3#setg(Bartender,table(table(Race) table(Gender) Name))
get(Race)
get(Gender)
select(3,get(get(Race) get(Gender) Name))
Hidden rolls (using "?") and Cross Template Referencing[:NPC:first]
<first>
[:?NPC:TavernKeep]
<TavernKeep>
[?NPC] {:?NPC:theruler}setg(first,table(NPC))
get(first)
set(TavernKeep,NPC)
get(TavernKeep)
xset(theruler,table(NPC))
Date Calls with formatting[Date:mm/dd/yyyy]
[FGDate:mm/dd/yyyy]date(mm/dd/yyyy)
fgdate(mm/dd/yyyy)
Better formatting (month and day with leading zeros):
dcat(/,znum(2,date(mm),date(dd)),date(yyyy))
Results: 09/01/2024 intead of 9/1/2024
Cross Template Referencing{theruler}xget(theruler)
Simple Template Includes[2d4+2u]!^Drink^!mult_include(2d4+2u,Drink)
tjlee
October 7th, 2024, 02:46
After adding a bunch of code for the last release, this effort was all about tidying up the code and examples.
Code: the extension got some rework and optimizations to bring the CoreRPG syntax execution and the Function-based syntax execution in proper alignment.
Examples: I fixed a few typos and elaborated on some of the existing examples.
Other than that, nothing groundbreaking this time.
You should pick up the new versions next time you perform a live update.
Enjoy!
Powered by vBulletin® Version 4.2.1 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.