New .ext delivered with Generic Actions (GenericActions.ext and now GenericActionsLayer.ext also)
Here is a snippet from .txt file:
New GenericActionsLayer.ext delivered with GenericActions.ext so it can be used in more than 5E -
"Feature: Generic Actions Layer"
(for the moment the 2E, 3.5E, 4E, 5E, PFRPG2, and SFRPG rulesets are supported)
The assets placed are very temporary and are not dynamic (do not move with anything).
The new option to place assets in the "Generic Actions" map layer will work in the following manner:
Assets that are under tokens are scaled at 2*token spacing and should be designed to take up the boundaries of the image (as map layers are always under tokens). Ranged assets are going to be 1 grid unit X range grid units in scale and have option to have different ones assigned at different ranges so these assets should also take that into consideration for design. Any melee should be along the right border of the defined boundry with space allowed for where a token would assume to be overlayed. Ranged will be simply stretched out along the width and should be moving left to right if wanting appearance of movement from source to target. Also, any source token with a ranged asset placed will be unseleted so that targeting arrows do not block the layer graphics.
Assets to be used by this feature will be accessed from the directories <FGU>/campaign/images/Generic Actions/* + <FGU>/images/Generic Actions/* including all sub-directories where all the asset names will be cached with relevant info (memory cache will only updated on a refresh asset button update) to be referenced by asset's name (minus any "_%d" range suffix). The lua pattern which does this is as follows:
local sSearchAsset = sResultAsset:gsub("[%w%p%s]*%/", "");
sName, sDist = string.match(sSearchAsset, "([%w%p%s]-)[%_%.]?(%d*)%.");
All names used to search this cache will be simplified (no punctuation or spaces) so the asset file name will be expected to match though the file can be of any case. Any duplicate names in cache will be wiped or last come first serve depending on order they are hit - so don't have duplicates. Name matching and placement will work in the following manner:
All of the following name matches below that have a range component in description can also have an "_%d" appended to end of the asset file name indicating a numeric range in the maps local units (not grid units). For example:
<FGU>/images/Generic Actions/DefaultRanged_05.webm
<FGU>/images/Generic Actions/DefaultRanged_15.webm
<FGU>/images/Generic Actions/DefaultRanged_30.webm
<FGU>/images/Generic Actions/DefaultRanged_60.webm
<FGU>/images/Generic Actions/DefaultRanged_90.webm
Where the range between source token and target token will find the closest value and apply that asset for ranged (run) placement. Of course the above is just an example and could be in the campaign/images/Generic Actions directory or any sub-directory under those respective directories (the code only cares about the asset files not where they may reside under those directories). The alphabetical order must be preserved for this to work - so if you have a range of 100 in there then all the others have to be 3 digits - like 005 etc.
ll of the following name matches will also search for the (AdvantagesPA.ext Advantages Extension) imageControl.getLastActivePtrs() function. If it is found and data is returned for the last stored pointer data (cone, circle, rectangle) then and it will append "PTRcone" or "PTRcircle" or "PTRsqr" to the current asset name being placed. If it finds the asset in the cache for the current last stored pointer shape it will place that asset on "Generic Actions Ptr" named layer (before the one going to "Generic Actions" layer is placed so that it will be overlayed with the original last pointer data - layers being layers after all) with the appropriate scale and orientation for the last stored pointer shape. To get rid of the last stored pointer shape YOU MUST use the clear last pointer data map toolbar button - otherwise the last shape placed (visible any longer or not) will be removed. All of this only works if you have "5E: Advantages Pointer Areas" extension loaded. Otherwise, ignore this option.
ActionAttack.onPostAttackResolve
- will find the name by the following lua pattern:
sMatchName = string.match(rRoll.sDesc, "%]([%w%p%s]-)%[");
or
sMatchName = string.match(rRoll.sDesc, "%]([%w%p%s]*)");
If their is a range between the source token and target token > than the source's reach then the name will have "Ranged" appended to the end of the name. Otherwise it will have "Melee" appended to the name. The name will then be simplified (all punctuation and spacing removed and lower cased). This final form of the name will then be used to access the cache of asset file names which will have their case lowered also. If no match in cache is found then "DefaultRanged" (if ranged per rules above) or "DefaultMelee" will be used to find cache. Otherwise nothing will be done if no match found. Any range match will scale ( width 1 grid unit, height - see code for math) and orient the asset and place it between the source token and target token on the "Generic Actions" map layer. Essentially this will be weapon or spell name its looking for most likely.
ActionPower.onPowerSave/ActionPower.onPowerCast (only 5E)
- will find the name by the same lua pattern searches in onPostAttackResolve.
The name will then be simplified (all punctuation and spacing removed and lower cased). This final form of the name will then be used to access the cache of asset file names which will have their case lowered also. If no match in cache is found then "DefaultPowerSave"/"DefaultPowerCast" will be used to find cache. Otherwise nothing will be done if no match found. Any range match will scale ( width 1 grid unit, height - see code for math) and orient the asset and place it between the source token and target token on the "Generic Actions" map layer. Essentially this will be spell name its looking for most likely. If this was a cast attack it will append "Cast" to end of name search.
ActionDamage.onDamage
- will find the name by the following lua pattern:
sMatchName = string.match(rRoll.sDesc, "%[TYPE:([%w%p%s]-)%(");
The name will then be simplified (all punctuation and spacing removed and lower cased). This final form of the name will then be used to access the cache of asset file names which will have their case lowered also. If no match in cache is found then "DefaultDamage" will be used to find cache. Otherwise nothing will be done if no match found. The asset will be placed on the target token at a scale of 2*token spacing. It will also append "DMGRun" to end of name (and default name) and do another asset search where any range match will scale ( width 1 grid unit, height - see code for math) and orient the asset and place it between the source and token on the "Generic Actions" map layer. This allows two assets to be placed if found - one over target and one on the run between source and target. Essentially this will be damage type name its looking for most likely.
ActionHeal.onHeal
- will find the name by the following lua pattern:
sMatchName = string.match(rRoll.sDesc, "%[HEAL%]([%w%p%s]*)");
The name will then be simplified (all punctuation and spacing removed and lower cased). This final form of the name will then be used to access the cache of asset file names which will have their case lowered also. If no match in cache is found then "DefaultHeal" will be used to find cache. Otherwise nothing will be done if no match found. The asset will be placed on the target token at a scale of 2*token spacing. It will also append "HealRun" to end of name (and default name) and do another asset search where any range match will scale ( width 1 grid unit, height - see code for math) and orient the asset and place it between the source and token on the "Generic Actions" map layer. This allows two assets to be placed if found - one over target and one on the run between source and target. Essentially this will be damage type name its looking for most likely.
EffectManager.addEffect
- will find the name by the following lua pattern:
sMatchName = string.match(rRoll.sDesc, "%[EFFECT] ([%w%p%s]*)");
The name will then be simplified (all punctuation and spacing removed and lower cased). This final form of the name will then be used to access the cache of asset file names which will have their case lowered also. If no match in cache is found then "DefaultPowerSave" will be used to find cache. Otherwise nothing will be done if no match found. The asset will be placed on the target token at a scale of 2*token spacing. Essentially this will be effect name its looking for most likely.
The "Generic Actions*" map layers may be removed manually if desired - but will also be automatically removed on the following calls:
CombatManager.showTurnMessage
Token.onClickDown
ActionsManager. performAction - only if following is true:
if not string.match(rRoll.sDesc, "%[SAVE%]([%w%p%s]*)") then
PowerActionManagerCore. performAction
Here is an example of my test file definitions and arbitrary directories under the required one plus a video that was more proof of concept (things have changed a bit but still mostly relevant and too lazy to make anther):
Attachment 58140
https://www.youtube.com/watch?v=LoN6PGeeVhg