• Please note: In an effort to ensure that all of our users feel welcome on our forums, we’ve updated our forum rules. You can review the updated rules here: http://forums.wolflair.com/showthread.php?t=5528.

    If a fellow Community member is not following the forum rules, please report the post by clicking the Report button (the red yield sign on the left) located on every post. This will notify the moderators directly. If you have any questions about these new rules, please contact support@wolflair.com.

    - The Lone Wolf Development Team

Dynamically setting the id of a thing

TobyFox2002

Well-known member
I am trying to set up a more efficient way of handling Difficulty Class of invocation spell like abilities. Currently the DCs is hard-coded and doesn't easily allow for user editing of things such as ability mod, and other variables.

I've gotten most of it set up the way I want it, but I've hit a snag where it comes to Ability Focus since the DC is modified after all normal DC calculations are applied the Ability focus doesn't automatically apply the +2 bonus.


Final/12000
Code:
~ This script can run no earlier than Final/11000 or acts weird.
   var dcMod as number
   var DC as number
   var id as string

   if (tagis[StandardDC.aSTR] <> 0) then
       dcMod = #attrmod[aSTR]
   elseif (tagis[StandardDC.aDEX] <> 0) then
       dcMod = #attrmod[aDEX]
   elseif (tagis[StandardDC.aCON] <> 0) then
       dcMod = #attrmod[aCON]
   elseif (tagis[StandardDC.aINT] <> 0) then
       dcMod = #attrmod[aINT]
   elseif (tagis[StandardDC.aWIS] <> 0) then
       dcMod = #attrmod[aWIS]
   elseif (tagis[StandardDC.aCHA] <> 0) then
       dcMod = #attrmod[aCHA]
~ create an embeded if...else to handle undead characters.
   elseif (tagis[StandardDC.BAB] <> 0) then
       dcMod = #BAB[]
   else
       dcMod = 0
   endif

~ abValue5 is the equivilant spell level of the invocation.
      DC = 10 + field[abValue5].value + dcMod
      DC = round(DC, 0, -1)
      field[abDC].value = DC

debug "We are using " & tagnames[StandardDC.?] & " with a value of " & dcMod & " for our DC."
debug "Our DC is " & field[abDC].value

doneif (hero.childfound[fAbilFoc].field[usrChosen1].ischosen = 0)
[COLOR="Red"]id[/COLOR] = hero.childfound[fAbilFoc].field[usrChosen1].chosen.idstring
debug hero.childfound[fAbilFoc].field[usrChosen1].chosen.idstring

hero.child[[COLOR="Red"]id[/COLOR]].field[abDC].value += 2

When I try and compile this, I get a syntax error. Non-existent thing "id" used by script. It apparently doesnt like me trying to pull the idstring and stuff that into the abDC.

Is this the way I should be handling this, or am I making this needlessly difficult? Any input would be appreciated.

Once that is done, I will take this script and convert it into a procedure call to easily apply it to all invocations.
 
Alright I have used findchild and this is what I get

Code:
doneif (hero.childfound[fAbilFoc].field[usrChosen1].ischosen = 0)
id = hero.childfound[fAbilFoc].field[usrChosen1].chosen.idstring
debug hero.childfound[fAbilFoc].field[usrChosen1].chosen.idstring

Debug (and the value of id): cDfABaleGe

hero.findchild[BaseCustSp, "thingid." & id].field[abDC].value += 2
debug hero.findchild[BaseCustSp, "thingid." & id].field[abDC].value

For for future reference to anyone who has a similar issue:

They syntax for childfound[] is:
anytransition.findchild[component,"custom expression"].whateverelseyouneed

The component typically starts with the word BaseXXX such as BaseRace or BaseClass or BaseCustSp. And creating the second parameter is the same (or seems to be the same) as a creating custom expressions or foreach loops.

I tried looking on the forums for help, I had to piece this together from like 10 different posts. Hopefully this is helpful for explaining it in non-programese. If I've gotten any of this wrong. Someone hopefully can correct me.
 
Because of the nature of the Custom Ability. The custom ability functions in a similar manner to a spell. That is to say it has a level equivilant so I could not use the built in DC calculator attached to each custom. I had to create my own formula using abValue5 to hold the spell level and create the DC from there.

When I tried to do that normally I would get really funky results with any timing earlier than final/11000. It would double the DC instead of setting it properly to the specific amount I desired. As a result, simply using Ability Focus feat would never apply its bonus because the script I was using was overwritting anything that hero labs was doing. For that reason, I assumed that following the .chosen would also not work.

Furthermore, once I have the script completed and working the way I want, I will change it into a procedure to use for any invocation type custom ability.

Also, I saw that thread, it was one of like ten that I had to use to try and understand findchild.
 
This is all I'm suggesting:

Code:
hero.childfound[fAbilFoc].field[usrChosen1].chosen.field[abDC].value += 2
instead of
Code:
id = hero.childfound[fAbilFoc].field[usrChosen1].chosen.idstring
hero.findchild[BaseCustSp, "thingid." & id].field[abDC].value += 2
Your explanation seems to be talking about something else.

Also, what happens if there's more than one copy of the ability focus feat on a single character? As written, your script will pick a random one.

And, what happens if this is a monster with an ability focus feat that's pre-assigned with a Target tag?
 
I am with Mathias the you are doing ALLOT of work using findchild for really no reason.

Code:
doneif (hero.childfound[fAbilFoc].field[usrChosen1].ischosen = 0)
id = hero.childfound[fAbilFoc].field[usrChosen1].chosen.idstring
debug hero.childfound[fAbilFoc].field[usrChosen1].chosen.idstring

hero.child[id].field[abDC].value += 2
This is what you had originally. But "hero.childfound[fAbilFoc].field[usrChosen1].chosen" is POINTING to the PICK you want to modify already. You have no reason to then get an idstring to use in findchild to get back to the PICK you already have.

Lets try this way:
hero.childfound[fAbilFoc].field[usrChosen1].chosen - Points to "Evil Eye" in example. A "pointer" means a generic reference to something else in HL. This generic pointer lets you do everything you could do if you had done hero.child[EvilEyeHex]. But instead field[usrChosen1].chosen is the generic pointer/reference to that child Pick.

That means
id = hero.childfound[fAbilFoc].field[usrChosen1].chosen.idstring is going to give the "Unique ID" of Evil Eye which is the Pick. As a pick we know this means Evil Eye is "LIVE" on a character.

So sense you already have a pointer to the Evil Eye Pick just add 2 to the DC field directly:
Code:
hero.childfound[fAbilFoc].field[usrChosen1].chosen.field[abDC].value += 2

That above is all you needed to do. No find child or custom expressions required. :)
 
I have to ask a question here after I was trying to figure out what your script is trying doing. Are you trying to get Ability Focus to add +2 to the Invocation DC that the script is running on?

In example you have a new Invocation called "Shadow". You have your script running on "Shadow" Invocation. The "Ability Focus" feat then selects "Shadow" as the ability to increase the DC by 2. I am pretty sure your desired outcome is that you want to increase the Invocation DC by 2 if the "Ability Focus" feat selects a specific Invocation. Correct? If so your script above will not accomplish that at all.

Currently what you have written will keep increasing the selected ability (which does not have to a Invocation) by 2 for each "Invocation" you add to the character. Not increase the specific Invocation by 2.

So lets say I have a character with the Evil Eye hex. I take Ability Focus (Evil Eye) and I add three Invocations to my character from levels in Warlock. The DC for "Evil Eye" will be increased by 6 but nothing will change on your Invocations DC.
 
To help out here is how I would do this logic if it was me.

Pretty much toss out this idea of using the StandardDC.? tag group as it activates component scripts in the background. Instead manually assign the IsAttr.? tag with the ability score you want. Lets assume Cha so you would assign "IsAttr.aCHA" to the Custom Ability.

Then we also need a "level" for these invocations so lets use the Spell Level tag. Assuming a first level invocation you would assign sLevel.1 tag to the Custom Ability.

What is nice about this is that we are not activating any LW component scripts. Meaning we have a DC value of 0. Which is a nice place to start our calculations.

Then we add the following script at Final/12000:
Code:
~ Calc DC with base 10 and the level of the Invocation.
field[abDC].value += 10 + tagvalue[sLevel.?]

~ Set pointer to the ability score associated to the 
~ IsAttr tag group. Then take its final modified bonus 
~ and add to the DC.
field[abDC].value += hero.findchild[BaseAttr,tagids[IsAttr.?]].field[aModBonus].value

The above script calculates the DC based on the tags sLevel.? and IsAttr.? assigned to the Custom Ability.

What is also nice is the "Ability Focus" feat will work without ANY modifications or special handling. It will simply add "+2" to the DC which means adjustments will also work for anyone that wants to add or subtract from the Invocations DC value. This is nice so people can put in there own houserules easily. This is because we are using PLUS logic and not forcing the DC to a specific value. This also allow room for archetypes, feats, magic items, etc to adjust the DC value.

I am also attaching a example of this code I created as a test case. I assigned a new 'Invocation' to the Witch class just so I could get it onto a class as a proof of concept.
 

Attachments

I was using StandardDC and abValue5 because it is something that can be edited. Directly on the custom ability panel, rather than having to manually go in and twiddle with tags.

I was trying to think not just of my coding but other people, for the ease of creating new invocations. Not to mention StandardDC also has options for BAB and other.. moderately useful items. Granted I don't know how to get those to work. There was also the issue of being able to easily override for undead or overidden attr, characters with the if...else method. Though thats fairly easy to do no matter what method you go with, so thats lesser of an issue.

Is there other benefits to using sLevel.? and IsAttr.?

Either way; this is advancing my tag control by leaps and bounds, so thats a plus. Thank you for your great input sofar. I love all you guys!
 
I was using StandardDC and abValue5 because it is something that can be edited. Directly on the custom ability panel, rather than having to manually go in and twiddle with tags.
But your logic is not the Pathfinder Standard DC calculations. So isn't it very misleading to use the "StandardDC.?" tags and then override the value?

Yes it is an extra button click to get to the "Tags" on the custom ability. But sense you are doing non-standard logic it makes sense that you are not using the default tags.

I was trying to think not just of my coding but other people, for the ease of creating new invocations. Not to mention StandardDC also has options for BAB and other.. moderately useful items. Granted I don't know how to get those to work.
But what do you do when a person has a 7th ability score? Its not standard but a thread on these forums show how to do that. My method would work with the new 7th ability score but yours is hard-coded to only 6. I know doubtful to happen but often a "dynamic" script answer is nicer than a hard-coded if/elseif logic.

There is what "one" Feat in all of Pathfinder that uses BAB to calculate the DC. Yeah not thinking that is high on the list to support. :)

There was also the issue of being able to easily override for undead or overidden attr, characters with the if...else method. Though thats fairly easy to do no matter what method you go with, so thats lesser of an issue.
All methods require the replacing of a Attribute tag. IsAttr.? just won't activate any LW scripts where StandardDC.? does.

Is there other benefits to using sLevel.? and IsAttr.?
Well assuming you add a standard abCategory.? code it means writing a custom expression for a foreach loop or feat drop down is super easy. Lets assume your abCategory.? code is WarlockInv.

A custom expression to limit a choice to only level 2 warlock invocations would be:
Code:
component.Ability & abCategory.WarlockInv & sLevel.2

Not only super easy to construct but anyone can read that and pretty much understand what is being selected. It almost does not need any documentation. :)

If you "really" want to make this all super easy for the next person. Which I have been looking at doing in the Community Pack. You could create a custom component that also inherits all the normal Ability components from LW. Then you could hide your new DC logic in the component and build a custom editor tab for it. That is what I recently did for Psionic Disciplines. Not only do I keep using all of LW logic but I added my own logic that can apply to all new Disciplines created by myself or any editor.

Obviously that is the very advanced way to do things. And a procedure is a good place to start in encapsulating all the logic one time.
 
If you want to stay with you method and support Ability Focus I would change your script as follows:

Code:
~ This script can run no earlier than Final/11000 or acts weird.
var dcMod as number
var DC as number
var id as string

if (tagis[StandardDC.aSTR] <> 0) then
  dcMod = #attrmod[aSTR]
elseif (tagis[StandardDC.aDEX] <> 0) then
  dcMod = #attrmod[aDEX]
elseif (tagis[StandardDC.aCON] <> 0) then
  dcMod = #attrmod[aCON]
elseif (tagis[StandardDC.aINT] <> 0) then
  dcMod = #attrmod[aINT]
elseif (tagis[StandardDC.aWIS] <> 0) then
  dcMod = #attrmod[aWIS]
elseif (tagis[StandardDC.aCHA] <> 0) then
  dcMod = #attrmod[aCHA]
~ create an embeded if...else to handle undead characters.
elseif (tagis[StandardDC.BAB] <> 0) then
  dcMod = #BAB[]
else
  dcMod = 0
endif

~ abValue5 is the equivilant spell level of the invocation.
DC = 10 + field[abValue5].value + dcMod
DC = round(DC, 0, -1)
field[abDC].value = DC

[B]~ If ability focus has selected us apply a +2 bonus to our DC
if (tagis[Duplicate.AbilFocus] = 1) then
  field[abDC].value += 2
endif[/B]
 
Your code is much more simiple, it is more efficient and my DC is certainly not a "Standard" DC even if it does follow the normal 10+xx+abil format.

The idea of having the tags to create such custom expressions is highly attractive. And yes, I know not many use BAB, it was just for flexibility that, that looked attactive.

I will take your advice, well, except the part about creating a new component. I dont think I can do that.

As for a 7th ability score, I'd love to be able to have support for that. But, hero labs does not support having a 7th ability score.

So thank you for all your input, again you folks are awesome!
 
Back
Top