Lone Wolf Development Forums

Lone Wolf Development Forums (http://forums.wolflair.com/index.php)
-   HL - Pathfinder Roleplaying Game (http://forums.wolflair.com/forumdisplay.php?f=62)
-   -   Hero Lab scripting 201: Location, Location, Location (http://forums.wolflair.com/showthread.php?t=21663)

Mathias June 17th, 2012 03:08 PM

Hero Lab scripting 201: Location, Location, Location
 
This article is part of a collection of editor and scripting articles: http://forums.wolflair.com/showthread.php?t=21688

I decided to add an article on a topic I don't think we've covered in much detail anywhere else. The principles I'm discussing apply to all game systems in Hero Lab, but for this article I'll be drawing my examples from Pathfinder.

In a character in Hero Lab, there are many items - each attribute is an item, each feat, level of a class, archetype, weapon, etc. is its own individual item. For the rest of this article, I'll refer to them as picks.

Very often, while writing a script, you'll want to look up information on another pick (perhaps to set the number of uses equal to an attribute modifier), or you'll want to change something about another pick (like adding a bonus to a skill). I'll be discussing how to travel around the set of picks that make up your character and the sorts of things you can do once you get somewhere and that sorts of questions you can ask once you get there.

In Hero Lab's scripting language, the period: . is used as the transition from one place to another. You are allowed to make more that one transition in a row - it's actually very common to use many transitions in a row in order to travel from one pick to another.

Every pick in a Hero Lab character is stored within a container. 98% of the picks in a character will be in a container called "hero", and there's only one "hero" container for each character. The rest will be in containers called gizmos - those are containers that exist within other picks. Each pick can only have one gizmo, and most picks will not actually have a gizmo. Gizmos are used in cases where at item is customizable - the custom versions of armor, weapons, scrolls, potions, wands, spells, and wordspells.

Although I'm using the term container here, that isn't actually related to what you'd commonly call a container - things like backpacks and houses. If you tell Hero Lab that the group of alchemist's fire bottles you own should be stored within your belt pouch, it doesn't change the underlying container for either the alchemist's fire or the belt pouch. What it does do is to set up a new relationship between the alchemist's fire and the belt pouch. Within the scripting language, that relationship is referred to as gearholding, and I'll cover that later in this article.


Let's take a look at some transitions:

hero.child[skClimb].field[Bonus].value

Breaking that down:

hero
.
child[skClimb]
.
field[Bonus]
.
value

So, what that's saying is: first, travel to the hero, then travel to the child of the hero whose Id is "skClimb" (which is the climb skill), then travel to the field on that child whose Id is "Bonus" (which is for untyped bonuses), then report the value of that field.

Here's how you might use that:

Code:

hero.child[skClimb].field[Bonus].value = hero.child[skClimb].field[Bonus].value + 2
Or in other words: "set the untyped bonus of our climb skill equal to whatever bonus has already been applied, + 2". Or, "You get +2 to climb."

That one's actually so commonly used that we've added some abbreviations, so that it takes less typing to get the same effect:

Code:

#skillbonus[skClimb] += 2
Example #2:
hero.child[skClimb].tagis[Helper.ClassSkill]

hero
.
child[skClimb]
.
tagis[Helper.ClassSkill]

In other words: "travel to the hero container, and then to the climb skill pick that's in that container, and then report whether a Tag whose Id is "Helper.ClassSkill" is present on that pick". In simpler terms: "Is climb a class skill right now?"

tagis[], like all the other TRUE/FALSE questions in Hero Lab, will report it's answer in the form of a number. It will report "0" if the answer is FALSE, and "1", if the answer is "TRUE".


Example #3:
field[usrChosen1].chosen.field[skRanks].value

field[usrChosen1]
.
chosen
.
field[skRanks]
.
value

That's saying: travel to the field (on us) called "usrChosen1" (which stores the user's choice from a drop-down menu), then travel to the pick the user chose, then travel to the skRanks field on that pick (which tells you how many ranks the user has applied to that skill), and report the value of that field.

Here's how you might use that:
Code:

if (field[usrChosen1].ischosen <> 0) then
  if (field[usrChosen1].chosen.field[skRanks].value >= 10) then
    field[usrChosen1].chosen.field[Bonus].value += 6
  else
    field[usrChosen1].chosen.field[Bonus.value += 3
    endif
  endif

"Travel to the drop-down menu on us - has the user selected a skill yet? If so, travel to the skill they selected - does that skill have 10 ranks in it yet? If so, add an untyped bonus of +6 to that skill. If not, add an untyped bonus of +3 to that skill." aka the Skill Focus feat.

Example #4:
hero.findchild[BaseRace].field[livename].text

hero
.
findchild[BaseRace]
.
field[livename]
.
text

That's saying: Travel to the hero container, then search among all the picks in that container for the first one you find that uses the BaseRace component, then travel to the livename field on that pick (livename stores the version of the name that will be displayed to the user), and report the text stored in that field.

Here's how that might be used:
Code:

hero.findchild[BaseRace].field[livename].text = "Mountain " & hero.findchild[BaseRace].field[livename].text
"Find our race and change its name to 'Mountain ' and whatever name is already there" ("Dwarf" would become "Mountain Dwarf", for example) (note the space in 'Mountain ', so that you don't get 'MountainDwarf'). This might be used by an Alternate Racial Trait, to rename its race.

In the next few posts, I'll look at each of the types of locations you might visit, and list where you can go from there, what questions you can ask while you're there, and what orders you can give Hero Lab while you're there.

If you're writing an Eval Script or an Eval Rule, you'll start out in the pick context. If you're writing a Prereq or an Exprreq, you'll start out in the container context (either hero or gizmo, depending on what container this item will be in once it's added).

Mathias June 17th, 2012 03:31 PM

Hero Context



Places you can travel to:
  • childfound[Child's Id] or child[[Child's Id]
    • test: childlives[Child's Id]
    • This travels to the pick context of a specific child. If there is more than one child with that Id, it will pick one at random to travel to. Generally, use childfound[] as opposed to child[] - if that child isn't actually there to travel to, child[] will report errors will be hard to understand. Childfound[] won't report any errors.
  • herofield[Field's Id]
    • This travels to the field context of a specific field on the special "herofield" pick that's used to store hero-wide information (this is actually a shortcut for hero.child[Totals].field[Field's Id]).
Questions you can ask:
  • tagis[Group Id.Tag Id]
    • TRUE/FALSE: Is the listed tag present here?
  • tagcount[Group Id.Tag Id]
    • How many of the listed tag are present here?
Instructions you can give:
  • assign[Group Id.Tag Id]
    • Add 1 copy of the listed tag here.
  • delete[Group Id.Tag Id]
    • Delete ALL copies of the listed tag here.
  • tagreplace[Group Id.Tag Id,Group Id.Tag Id]
    • Delete all copies of the first of those listed tags, then assign 1 copy of the second of those listed tags (this is a shortcut for delete[], then assign[]).
(Those lists are actually just the most common operations - a more complete list is available here: http://hlkitwiki.wolflair.com/index....tainer_Context and http://hlkitwiki.wolflair.com/index.php5/Hero_Context)

Mathias June 17th, 2012 04:01 PM

Pick Context



Places you can travel to:
  • field[Field Id]
    • This travels to the field context of the specific field that's within this pick.
  • hero
    • Travels to the hero container on the character.
  • container
    • Travels to whatever container this pick is in - either the hero or to a gizmo
  • parent
    • Only use this if you are sure you're in a gizmo, not the hero.
    • This travels to the pick context of the pick that contains the gizmo that contains this pick.
  • root
    • Test: isroot
    • Travels to the pick that bootstrapped this pick. Usually, this is used to get from a class special to the class.
  • linkage[varies]
    • Test: islinkage[varies]
    • This is only available on an archetype.
    • Travels to the pick context of the class that this archetype modifies.
  • linkage[skillattr]
    • Test: islinkage[skillattr]
    • This is only available on a skill.
    • Travels to the pick context of the attribute that this skill is linked to.
  • linkage[table]
    • Test: islinkage[table]
    • This is only available for Cleric Domains and Custom Abilities (like Rogue Talents, Wizard Schools, Barbarian Rage Powers, Sorcerer Bloodlines, etc.).
    • Travels to the pick context of the class this ability was added to.
  • gizmo
    • Test: isgizmo
    • This travels to the gizmo container that's within the pick. Remember that most picks will not have a gizmo.
  • gearholder
    • Test: isgearheld
    • This travels to the pick context of the pick this item is held within.
  • herofield[Field's Id]
    • This travels to the field context of a specific field on the special "herofield" pick that's used to store hero-wide information (this is actually a shortcut for hero.child[Totals].field[Field's Id]).
Questions you can ask:
  • tagis[Group Id.Tag Id]
    • TRUE/FALSE: Is the listed tag present here?
  • tagcount[Group Id.Tag Id]
    • How many of the listed tag are present here?
  • isuser
    • TRUE/FALSE: Was this added by the user? (If it's false, it must have been bootstrapped).
  • isgearlist
    • TRUE/FALSE: Are we allowed to hold other gear?
  • isholdable
    • TRUE/FALSE: Are we allowed to be held by another piece of gear?
  • gearcount
    • How many items are we currently holding?
Instructions you can give:
  • assign[Group Id.Tag Id]
    • Add 1 copy of the listed tag here.
  • delete[Group Id.Tag Id]
    • Delete ALL copies of the listed tag here.
  • tagreplace[Group Id.Tag Id,Group Id.Tag Id]
    • Delete all copies of the first of those listed tags, then assign 1 copy of the second of those listed tags (this is a shortcut for delete[], then assign[]).
These lists are the most common things you'll do in the pick context. A more complete list is available at: http://hlkitwiki.wolflair.com/index....xt#transitions

Mathias June 17th, 2012 04:12 PM

Field Context

There are three types of fields - numerical, text, or menu, and each has different operations that can be performed.




Places you can travel to:
  • pick
    • Travels to the pick that contains this field
  • chosen
    • Test: ischosen
    • Menu fields only
    • Travel to the pick context of whatever the user chose in this menu
Questions you can ask:
  • isempty
    • Text fields only
    • TRUE/FALSE: Is this field empty/blank? (this will return 1 if the text is blank, and return 0 if there is some text in it).
Operations Available



(This can either be used to look up information on the field or to change the value of the field):
  • value
    • Numerical fields only
    • Returns the value stored in this field
  • text
    • Text fields only
    • Returns the text stored in this field
This list is only the most common things you'll do in the field context. A more complete list is available at: http://hlkitwiki.wolflair.com/index....xt#transitions

Mathias June 17th, 2012 04:15 PM

Gizmo Context



Places you can travel to:
  • childfound[Child's Id] or child[[Child's Id]
    • test: childlives[Child's Id]
    • This travels to the pick context of a specific child. If there is more than one child with that Id, it will pick one at random to travel to. Generally, use childfound[] as opposed to child[] - if that child isn't actually there to travel to, child[] will report errors will be hard to understand. Childfound[] won't report any errors.
  • hero
    • Travels to the hero context
  • parent
    • Travels to the pick context of the pick this gizmo is within
  • herofield[Field's Id]
    • This travels to the field context of a specific field on the special "herofield" pick that's used to store hero-wide information (this is actually a shortcut for hero.child[Totals].field[Field's Id]).
Questions you can ask:
  • tagis[Group Id.Tag Id]
    • TRUE/FALSE: Is the listed tag present here?
  • tagcount[Group Id.Tag Id]
    • How many of the listed tag are present here?
Instructions you can give:
  • assign[Group Id.Tag Id]
    • Add 1 copy of the listed tag here.
  • delete[Group Id.Tag Id]
    • Delete ALL copies of the listed tag here.
  • tagreplace[Group Id.Tag Id,Group Id.Tag Id]
    • Delete all copies of the first of those listed tags, then assign 1 copy of the second of those listed tags (this is a shortcut for delete[], then assign[]).
(Those lists are actually just the most common operations - a more complete list is available here: http://hlkitwiki.wolflair.com/index....tainer_Context)

Mathias June 17th, 2012 04:16 PM

Special Transition: Focus

Often, you'll need to do a lot of typing in order to travel to a particular thing. There's a special transition called the focus transition that you can use to "save your place", so that you don't have to do lots of typing if you need to do multiple things there.


Places you can travel to:
  • focus
    • Test: state.isfocus
    • travels to the pick context that's been assigned as the focus
Instructions you can give:
  • setfocus
    • Only available in a pick context
    • Sets the focus to this pick
  • state.clearfocus
    • Available from all contexts
    • Clears the focus if it's been set (and does nothing if no focus was set).

Mathias June 17th, 2012 04:16 PM

Special Transitions: Searching

Often, you don't know exactly what child you want to transition to, but you know some things about what it will be like. For example "I want to find a light weapon that deals piercing damage and is made of metal". Other times, you know there are multiple picks with the same Id. The child[] transition would only take you to one of them, and it would pick that one at random, so, you need a way to find all of them. That's handled by searching through a container to find those picks.

Code:


foreach pick in container from component where "test expression"
  nexteach

Replace container with either hero or gizmo. To use gizmo, you'll need to be starting in a pick that has a gizmo, or set up some set of transitions that ends in gizmo.

In that, replace component with the Id of a component that all of the things you're searching for have in common. To find this, add some examples of a few of the things you're trying to find to a test character, and look at their tags. There will be a section of tags whose Group Ids are all "component". Pick one of these - one that all of the things you're looking for will have.

Replace test expression with a tag expression that narrows down the list even further than just the component does. To find these tags, look at the tags on the example items you added, and compare them to the tags on things that are like those examples, but not quite.

If just the component will do the trick and will identify all the things you're searching for, you can leave out 'where "text expression"' entirely.

While you're in that foreach, you can use a special transition:
  • eachpick
    • Travels to the pick context that's currently being worked on
Remember that if you don't use the eachpick transition, you're still in the default place for this script, and from there, you can go to all the places you normally would, and do all the things you normally would.

An example:

Code:


foreach pick in hero from BaseSkill where "Helper.ClassSkill"
  eachpick.field[Bonus].value += 1
  nexteach

That will search through all the picks in the hero container that have the BaseSkill component and have the Helper.ClassSkill tag.

On each of the picks it finds, it will travel to the Bonus field for that pick, and add 1 to its value. In other words; "All our class skills get +1".


Once you're done with all the operations that apply to the things you're searching for, close your foreach with the following line:
Code:


nexteach

Sometimes, you know there will only be exactly one thing that matches what you're searching for (for example, you know that a character will have a single race, but you don't know which race the user will actually pick).

This is a special transition you can do from either the hero or gizmo contexts:

findchild[component,test expression]

component is the same as in a foreach, and test expression is also the same as in a foreach. As in a foreach, if you don't need an expression, you can leave it out (if you do, leave out the comma, too).

It's very common to use the setfocus instruction after findchild[] - that way, you don't need to repeat the search if there are lots of questions you want to ask on that pick and/or many things to change. Think of it as findchild[component,test expression].setfocus

Mathias June 17th, 2012 04:18 PM

Special Case: Prereqs

The context of a prereq or an exprreq is the container (either the hero or the gizmo) that this item is being added to (or is currently in, if the user has selected this item). This is different from the eval scripts, where the initial context is the pick that the script is running on.

In a prereq or an exprreq, there are some special instructions and special transitions that are available, and there are some restrictions on what you'll be able to accomplish.



Questions you can ask
  • @ispick
    • You can only use this by itself
    • It's a TRUE/FALSE test - it will return 1 if this has been added to the character and 0 if it's still in the list of things to test.
Operations you can perform
(these can either look up the current value of this special operator, or you can change its value)
  • @valid
    • You can only use this by itself
    • This stores whether the prereq has failed or not.
    • At the beginning of a prereq script, it is already set to 0.
    • To make the prereq succeed, set it to 1 (or any other value that's not 0).
Places you can travel
  • altthing & altpick
    • These travel to the pick the prereq is actually on - remember that the initial context for a prereq is the container. That differs from the initial context of an eval script, which is the pick. So, if you need to look up information on the pick for a prereq
    • If @ispick = 0, you must use altthing to travel to the pick. If @ispick = 1, you must use altpick.
Here's how altthing and altpick are used in practice:

Code:


if (@ispick <> 0) then
  altpick.something
else
  altthing.something
  endif

the .something is the same in each branch.

Mathias June 17th, 2012 04:20 PM

(just in case I find another topic I want to add)

Mathias June 17th, 2012 04:20 PM

(just in case I find yet another topic I want to add)


All times are GMT -8. The time now is 01:06 PM.

Powered by vBulletin® - Copyright ©2000 - 2024, vBulletin Solutions, Inc.
wolflair.com copyright ©1998-2016 Lone Wolf Development, Inc. View our Privacy Policy here.