• 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

Adding spells of a certain subschool to a spell list at lowest available level

Redcap's Corner

Well-known member
I'm trying to set up a magus archetype in Hero Lab. The archetype has the following ability:

"Spells: A transcendent wayfarer adds all spells of the teleportation subschool of 6th level or lower to his magus spell list at the lowest spell level available to any class. Any spell of the teleportation subschool already on the magus spell list he instead treats as one level lower than its magus level."

This is tricky, but I started basic. This seems to pull the majority of teleportation subschool spells onto the spell list:

POST-LEVELS/5000
Code:
foreach thing in BaseSpell where "sSubschool.Teleport & fieldval:sLevel <= 6"
  perform eachthing.pulltags[ClsAllowSp.?]
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]

Where it doesn't work?
1) It's pulling spells of all levels, even those above 6.
2) It's pulling the same spell onto the list multiple times at all of the different spell levels that spell is available, which I knew would happen, but I'm nevertheless in the market for a solution.
3) It seems to just be missing certain spells (teleport as a 4th level spell, vomit twin as a 4th level spell, word of recall as a 6th level spell, teleport structure, tree stride at any level, etc.).

Thoughts on solutions:
1) I'm guessing for problem 1 that either "fieldval" doesn't work in foreach statements (though I saw it recommended by a developer, which is why I tried it) or that it only likes equal signs, not "less thans". Either way, that's just trial and error and it seems like the smallest issue.
2) I decided to try setting up foreach statements for each spell level between 0 and 6, in ascending order, with each statement looking back at the spell list so far to see if a different "version" of the same spell is already on the spell list. This also helps me test the "equal sign theory" as a solution to problem #1. This is what I came up with:

POST-LEVELS/5000
Code:
var spellname as string
var dontadd as number
dontadd = 0

foreach thing in BaseSpell where "sSubschool.Teleport & fieldval:sLevel = 0"
  spellname = eachthing.field[sSBSortNam].text
  foreach pick in hero from BaseSpell
    if (compare(eachpick.field[sSBSortNam].text, spellname) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "sSubschool.Teleport & fieldval:sLevel = 1"
  spellname = eachthing.field[sSBSortNam].text
  foreach pick in hero from BaseSpell
    if (compare(eachpick.field[sSBSortNam].text, spellname) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "sSubschool.Teleport & fieldval:sLevel = 2"
  spellname = eachthing.field[sSBSortNam].text
  foreach pick in hero from BaseSpell
    if (compare(eachpick.field[sSBSortNam].text, spellname) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "sSubschool.Teleport & fieldval:sLevel = 3"
  spellname = eachthing.field[sSBSortNam].text
  foreach pick in hero from BaseSpell
    if (compare(eachpick.field[sSBSortNam].text, spellname) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "sSubschool.Teleport & fieldval:sLevel = 4"
  spellname = eachthing.field[sSBSortNam].text
  foreach pick in hero from BaseSpell
    if (compare(eachpick.field[sSBSortNam].text, spellname) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "sSubschool.Teleport & fieldval:sLevel = 5"
  spellname = eachthing.field[sSBSortNam].text
  foreach pick in hero from BaseSpell
    if (compare(eachpick.field[sSBSortNam].text, spellname) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "sSubschool.Teleport & fieldval:sLevel = 6"
  spellname = eachthing.field[sSBSortNam].text
  foreach pick in hero from BaseSpell
    if (compare(eachpick.field[sSBSortNam].text, spellname) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

But I'm getting this error message:

Syntax error in 'eval' script for Thing 'arMagTrWay' (Eval Script '#1') on line 13
-> Use of 'eachthing.' transition is only valid within a 'foreach' context that iterates over things


I can't tell why it doesn't like my "eachthing", since it IS within a "foreach thing" statement, and the exact same line of code worked in my original script up top.
3) Here, I'm stumped. The archetype is correctly pulling the tags for all the missing spells, some of them just aren't getting pushed to the magus.

As a side note, the only idea I had on how to take the magus teleportation spells and lower them by a spell level was:

POST-LEVELS/5000
Code:
foreach thing in BaseSpell where "sClass.Magus & sSubschool.Teleport"
  eachthing.field[sLevel].value -= 1
nexteach

Which didn't work at post-levels/5000, but I haven't investigated it much beyond that.
 
Last edited:
All right, I've made some progress. Problem #1 is solved. I don't know why I couldn't find the sLevel.? tags before, because I know I looked, but now I have them. The current script I'm using also seems to have solved problem #3, which is interesting, because it didn't solve its intended target of problem #2.

POST-LEVELS/5000
Code:
var spellname as string
var dontadd as number
dontadd = 0

foreach thing in BaseSpell where "sSubschool.Teleport & sLevel.0"
  spellname = eachthing.field[sSBSortNam].text
  foreach thing in BaseSpell where "sClass.Magus"
    if (compare(eachthing.field[sSBSortNam].text, spellname) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "sSubschool.Teleport & sLevel.1"
  spellname = eachthing.field[sSBSortNam].text
  foreach thing in BaseSpell where "sClass.Magus"
    if (compare(eachthing.field[sSBSortNam].text, spellname) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "sSubschool.Teleport & sLevel.2"
  spellname = eachthing.field[sSBSortNam].text
  foreach thing in BaseSpell where "sClass.Magus"
    if (compare(eachthing.field[sSBSortNam].text, spellname) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "sSubschool.Teleport & sLevel.3"
  spellname = eachthing.field[sSBSortNam].text
  foreach thing in BaseSpell where "sClass.Magus"
    if (compare(eachthing.field[sSBSortNam].text, spellname) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "sSubschool.Teleport & sLevel.4"
  spellname = eachthing.field[sSBSortNam].text
  foreach thing in BaseSpell where "sClass.Magus"
    if (compare(eachthing.field[sSBSortNam].text, spellname) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "sSubschool.Teleport & sLevel.5"
  spellname = eachthing.field[sSBSortNam].text
  foreach thing in BaseSpell where "sClass.Magus"
    if (compare(eachthing.field[sSBSortNam].text, spellname) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "sSubschool.Teleport & sLevel.6"
  spellname = eachthing.field[sSBSortNam].text
  foreach thing in BaseSpell where "sClass.Magus"
    if (compare(eachthing.field[sSBSortNam].text, spellname) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

I also have no idea how to lower the spell level on each of the pre-existing magus teleportation spells, as it occurred to me the reason my previous idea didn't work as that you can't edit the details of "things." It's my presumption, however, that spells aren't actually picks until you add them to your spellbook. Is that right?
 
Last edited:
You can't use a "fieldval:" logic check on Things as the field value is going to be zero because no scripts have run to fill in the value for calculated field value.

So if I set the field value on the Thing then it could be checked for but most field values are calculated after the Thing becomes a Pick.
 
That definitely makes a lot of sense. Is it possible to use "fieldval" with text-based fields? Or is there an equivalent? Maybe I can use an expression like that to do away with this faulty if-compare-then statement.
 
Actually, that's why the if-compare-then statement isn't working, isn't it? That field's empty too. Is there any way to get at the name of a thing in a script? That information has to be stored in the thing somewhere.
 
You should be able to use field[name].text or field[thingname].text against a Thing to get its name.

Another FYI "that" may help using tagvalue[sLevel.?] will let you get the numeric value of the tag from the Thing. You can't do that in the where statement but you could maybe manually test in an IF statement.
 
field[name].text seems to be working fine, but there's something wrong with the nested foreach. Can you not run a foreach nested inside an otherwise unrelated foreach?
 
I ended up with the following script (with the debug testing being done for the 4th level spells only, since there's a big concentration of teleportation spells at that level.

Code:
var addspell as string
var magspell as string
var dontadd as number
dontadd = 0

foreach thing in BaseSpell where "!sClass.Magus & sSubschool.Teleport & sLevel.0"
  addspell = eachthing.field[name].text
  foreach thing in BaseSpell where "sClass.Magus"
    magspell = eachthing.field[name].text
    if (compare(addspell, magspell) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "!sClass.Magus & sSubschool.Teleport & sLevel.1"
  addspell = eachthing.field[name].text
  foreach thing in BaseSpell where "sClass.Magus"
    magspell = eachthing.field[name].text
    if (compare(addspell, magspell) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "!sClass.Magus & sSubschool.Teleport & sLevel.2"
  addspell = eachthing.field[name].text
  foreach thing in BaseSpell where "sClass.Magus"
    magspell = eachthing.field[name].text
    if (compare(addspell, magspell) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "!sClass.Magus & sSubschool.Teleport & sLevel.3"
  addspell = eachthing.field[name].text
  foreach thing in BaseSpell where "sClass.Magus"
    magspell = eachthing.field[name].text
    if (compare(addspell, magspell) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "!sClass.Magus & sSubschool.Teleport & sLevel.4"
  addspell = eachthing.field[name].text
  debug "add: " & addspell
  foreach thing in BaseSpell where "sClass.Magus & sSubschool.Teleport"
    magspell = eachthing.field[name].text
    debug "magus spell: " & magspell
    if (compare(addspell, magspell) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "!sClass.Magus & sSubschool.Teleport & sLevel.5"
  addspell = eachthing.field[name].text
  foreach thing in BaseSpell where "sClass.Magus"
    magspell = eachthing.field[name].text
    if (compare(addspell, magspell) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

foreach thing in BaseSpell where "!sClass.Magus & sSubschool.Teleport & sLevel.6"
  addspell = eachthing.field[name].text
  foreach thing in BaseSpell where "sClass.Magus"
    magspell = eachthing.field[name].text
    if (compare(addspell, magspell) = 0) then
      dontadd = 1
    endif
  nexteach
  if (dontadd = 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  dontadd = 0
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]
perform delete[ClsAllowSp.?]

The debug output was feeding me all the addspell names, but returning blank for magspell. I couldn't figure out why, but working under the assumption that something about the nested foreach was confusing things, I decided to try a different approach:

Code:
var addspell as string
var magspell as string

foreach thing in BaseSpell where "sClass.Magus & sSubschool.Teleport"
  magspell = magspell & " " & eachthing.field[name].text
nexteach

debug "magus spells: " & magspell

foreach thing in BaseSpell where "!sClass.Magus & sSubschool.Teleport & sLevel.0"
  addspell = eachthing.field[name].text
  if (pos(addspell, magspell) < 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
    magspell = magspell & " " & eachthing.field[name].text
  endif
nexteach

foreach thing in BaseSpell where "!sClass.Magus & sSubschool.Teleport & sLevel.1"
  addspell = eachthing.field[name].text
  if (pos(addspell, magspell) < 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
    magspell = magspell & " " & eachthing.field[name].text
  endif
nexteach

foreach thing in BaseSpell where "!sClass.Magus & sSubschool.Teleport & sLevel.2"
  addspell = eachthing.field[name].text
  if (pos(addspell, magspell) < 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
    magspell = magspell & " " & eachthing.field[name].text
  endif
nexteach

foreach thing in BaseSpell where "!sClass.Magus & sSubschool.Teleport & sLevel.3"
  addspell = eachthing.field[name].text
  if (pos(addspell, magspell) < 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
    magspell = magspell & " " & eachthing.field[name].text
  endif
nexteach

foreach thing in BaseSpell where "!sClass.Magus & sSubschool.Teleport & sLevel.4"
  addspell = eachthing.field[name].text
  if (pos(addspell, magspell) < 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
    debug "add: " & addspell
    magspell = magspell & " " & eachthing.field[name].text
  endif
nexteach

foreach thing in BaseSpell where "!sClass.Magus & sSubschool.Teleport & sLevel.5"
  addspell = eachthing.field[name].text
  if (pos(addspell, magspell) < 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
    magspell = magspell & " " & eachthing.field[name].text
  endif
nexteach

foreach thing in BaseSpell where "!sClass.Magus & sSubschool.Teleport & sLevel.6"
  addspell = eachthing.field[name].text
  if (pos(addspell, magspell) < 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
    magspell = magspell & " " & eachthing.field[name].text
  endif
nexteach
perform linkage[varies].pushtags[ClsAllowSp.?]

I'm still not getting any output for the magspell debug, which makes me think it wasn't the nested foreach after all. And obviously without magspell having any value, the rest of this script just isn't doing anything. Can anyone see any problem with the first foreach that sets the string of existing magus teleportation spells? This latter version of the script seems less resource intensive, so I'd like to figure out why it isn't working. And I'm pretty sure my problem is the same regardless of which version of the script I use.

Thanks!
 
Well, I'm an idiot. The problem turns out to have been that the tag is sClass.cHelpMag not sClass.Magus. Whoops! Still haven't gotten the script fully functional, but at least I can stop banging my head against the wall.
 
Oh my god, I did it. For reference, in case anyone else ever wants to add all spells of a particular subschool to a class at the lowest available level, here's one way of doing it.

  • If you want to keep spells already on the class spell list at their normal spell level, delete all the blue code.
  • If you want those spells to lower to the lowest available spell level, then keep the code intact.

POST-LEVELS/5000
Code:
[COLOR="RoyalBlue"]var addspell as number[/COLOR]
var magspell as string
[COLOR="RoyalBlue"]var newlevel as number[/COLOR]
var newspell as string

~ Compile a list of all magus spells of the teleportation subschool.
foreach thing in BaseSpell where "sClass.cHelpMag & sSubschool.Teleport"
  magspell = magspell & " " & eachthing.field[name].text
nexteach

[COLOR="RoyalBlue"]~ Check for lower level versions of any of those spells.
foreach thing in BaseSpell where "!sClass.cHelpMag & sSubschool.Teleport"
  newspell = eachthing.field[name].text
  newlevel = eachthing.tagvalue[sLevel.?]
  foreach thing in BaseSpell where "sClass.cHelpMag & sSubschool.Teleport"
    if (compare(newspell, eachthing.field[name].text) = 0) then
      if (eachthing.tagvalue[sLevel.?] > newlevel) then
        ~ If any are found, get rid of the normal version.
        addspell = 1
        perform eachthing.pulltags[ClsDenySp.?]
      endif
    endif
  nexteach
  ~ And add the lower level version.
  if (addspell <> 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
  endif
  addspell = 0
nexteach[/COLOR]

~ Cross-reference 0-level non-magus teleportation spells with the list.
foreach thing in BaseSpell where "!sClass.cHelpMag & sClass.? & sSubschool.Teleport & sLevel.0"
  newspell = eachthing.field[name].text
  ~ Add any spell not on the list to the list at this level.
  if (pos(magspell, newspell) < 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
    magspell = magspell & " " & eachthing.field[name].text
  endif
nexteach

~ Repeat the process for each ascending spell level.
foreach thing in BaseSpell where "!sClass.cHelpMag & sClass.? & sSubschool.Teleport & sLevel.1"
  newspell = eachthing.field[name].text
  if (pos(magspell, newspell) < 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
    magspell = magspell & " " & eachthing.field[name].text
  endif
nexteach

foreach thing in BaseSpell where "!sClass.cHelpMag & sClass.? & sSubschool.Teleport & sLevel.2"
  newspell = eachthing.field[name].text
  if (pos(magspell, newspell) < 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
    magspell = magspell & " " & eachthing.field[name].text
  endif
nexteach

foreach thing in BaseSpell where "!sClass.cHelpMag & sClass.? & sSubschool.Teleport & sLevel.3"
  newspell = eachthing.field[name].text
  if (pos(magspell, newspell) < 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
    magspell = magspell & " " & eachthing.field[name].text
  endif
nexteach

foreach thing in BaseSpell where "!sClass.cHelpMag & sClass.? & sSubschool.Teleport & sLevel.4"
  newspell = eachthing.field[name].text
  if (pos(magspell, newspell) < 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
    magspell = magspell & " " & eachthing.field[name].text
  endif
nexteach

foreach thing in BaseSpell where "!sClass.cHelpMag & sClass.? & sSubschool.Teleport & sLevel.5"
  newspell = eachthing.field[name].text
  if (pos(magspell, newspell) < 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
    magspell = magspell & " " & eachthing.field[name].text
  endif
nexteach

foreach thing in BaseSpell where "!sClass.cHelpMag & sClass.? & sSubschool.Teleport & sLevel.6"
  newspell = eachthing.field[name].text
  if (pos(magspell, newspell) < 0) then
    perform eachthing.pulltags[ClsAllowSp.?]
    magspell = magspell & " " & eachthing.field[name].text
  endif
nexteach

~ Finally, apply all changes to the class spell list.
[COLOR="RoyalBlue"]perform linkage[varies].pushtags[ClsDenySp.?][/COLOR]
perform linkage[varies].pushtags[ClsAllowSp.?]
 
Last edited:
I'm still drawing a total blank on how to reduce the spell level by 1 on all the teleportation spells already on the magus list, though. Is it even possible? It can't be done the way metamagic is, because metamagic doesn't apply until the spell's a pick. I need to alter the spell level while it's still just a thing.
 
Back
Top