• 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

Shape Changing

I've nearly got shapechanging abilities to work in HL, such that you can select the creature you are shapechanging into and it will appropriately adjust the hero. I've still got alot to do, with all the variations, but I'm pretty close with the basic Alternate Form and Change Shape abilities of most creatures. I've got a few stumbling blocks, calling out to the community for some brainstorming.

First issue, getting the natural attack of the assumed form to appear. Since these are bootstraps, I'm not sure what the best way to do this is. I can pull the name of the natural attack just fine, and I can pull the damage, does this seem like enough to do the job? I wouldn't be able to list it in the attack portion of the hero though, but as an addendum to the shapechanging ability's custom description. Just wonder if anyone has a better idea?

Second issue, getting the movement modes of flying, swimming, climbing, and burrowing moved over. Somehow I've got to check both the natural form and the assumed form for crossover, and be able to tell from that how to proceed. Unfortunately, the way I'm currently experimenting with doesn't seem too ideal, mainly because of the timing of things. I can see if the ability is on both forms, and if so, just pull the tags and possibly the Value field over. The various manipulations needed when one has it, and the other doesn't, requires a bootstrap if I want the actual ability to show up, but doing so means bootstrapping the ability, which then means it does have the movement mode (I'm assuming childlives doesn't care if the Value tag is 0, just looks for the pick). So, my current situation has me just taking the flying livename and adding it as an addendum to the shapechanging ability's custom description. Anyone have a better idea?

When I get these working, and I will, I will post them for those who would like to use them. I've meticulously worked out timing issues in my files pretty well, but can't say for sure that the same timings will work in other files. Chances are, when I do post, and the code doesn't work for you, it will probably just be a timing issue that needs resolved in your files.
 
First issue, getting the natural attack of the assumed form to appear. Since these are bootstraps, I'm not sure what the best way to do this is. I can pull the name of the natural attack just fine, and I can pull the damage, does this seem like enough to do the job? I wouldn't be able to list it in the attack portion of the hero though, but as an addendum to the shapechanging ability's custom description. Just wonder if anyone has a better idea?

What I did for my Wild Shape work was to create a special ability that bootstrapped the natural attack. I then bootstrapped the special to the wild shape and set the damage in an eval script. Don't know if that will help you, but it did show up in the weapons tab for me.
 
I'm using a chooser to chose the race. So I would have to know beforehand what attack each race had, which is really anything at that point. So I can't really bootstrap an unknown and then set it. Plus there may be more than one attack. I'm assuming in wild shape the selection is for a specific animal/elemental/whatever, whereas I'm trying to allow selection from anything allowed. Or maybe I didn't understand what you were getting at...
 
I'm using a chooser to chose the race. So I would have to know beforehand what attack each race had, which is really anything at that point. So I can't really bootstrap an unknown and then set it. Plus there may be more than one attack. I'm assuming in wild shape the selection is for a specific animal/elemental/whatever, whereas I'm trying to allow selection from anything allowed. Or maybe I didn't understand what you were getting at...

No, you're right. I am not using a chooser so this method probably wouldn't work for you. Sorry.
 
Having a minor problem here, with pushtags and pulltags. Here is the code that is bugging me.

Code:
foreach bootstrap in field[fChosen].chosen where "thingid.xFly"
  [COLOR="Blue"][B]perform eachthing.pulltags[Value.?][/B][/COLOR]
  perform hero.child[xFly].pushtags[Value.?]
  perform eachthing.pulltags[Maneuver.?]
  perform hero.child[xFly].pushtags[Maneuver.?]
nexteach

I'm having a problem with the highlighted line. Is this because the eachthing is a "thing" and not a "pick" or a "container"? If so, why does pushtags work fine with it, and not pulltags? Perplexed...

What I'm trying to do is pull the tags from the chosen thing's fly ability, and assign them to the current thing's fly ability. Anyone have a better idea how this could be done?
 
Think I've got if figured out. Since the race pick in my chooser isn't running it's scripts and isn't live, the Maneuver and Value tags aren't being assigned at all. Now if I assign those to the Fly pick in the race I'm choosing, shouldn't it still show up as on the pick, even if it isn't live? I mean, other things on the pick do, like the rSTR field, rAC field, and the size tag of the race pick are able to be found, so why can't I find the assigned tags on the xFly pick of the race pick?
 
Last edited:
This is most likely the same limitation that keeps us from being able to display the fly speed of a race while you're choosing a race - in that case, HL can tell that fly is present, but the tags and fields that are specifically assigned to that particular bootstrap aren't accesible - only the tags and fields that are always present on xFly (those you'd see on xFly's entry on the Special tab).
 
Right, on to plan B!

Or plan C if plan B doesn't work!

Luckily, I know plan C will work, it's just not the most ideal solution, but it will work, since I've already tested the idea.
 
Well, I got it working. I had to go with the less than ideal solution, which means there are lots of gaps, so you will still need the book to look at the creature form you changed to for certain effects and damages. Again, less than ideal, but it works well enough to get by with. One thing you have to be sure about, to get the extraordinary special attack forms to be moved to the hero in HL, you have to be sure that the Special Ability Type area has a checkmark in the Attack box (located right under the Ability Classification) for each special that is Extraordinary (which also has to be active). Another thing I had to do was to create these on the Feat tab of the Editor, because I wanted to have the ability to select a race.

1. Create a new feat calling it Alternate Form (I didn't give it the fXXX, but the standard xXXX for abilities as the id, called mine xAltForm).
2. In the Custom Expression box type in "component.BaseRace" (without the quotes).
3. Check the Show in Specials box.
4. Add the following scripts.

First/5000
Code:
perform delete[SpecSource.Feat]

First/101
Code:
~ If we haven't chosen anything, get out now.
doneif (field[fChosen].ischosen = 0)

~ Determine new size.
var newsize as number
if (field[fChosen].chosen.tagis[RaceSize.Fine?] <> 0) then
  newsize = -4
elseif (field[fChosen].chosen.tagis[RaceSize.Dimin?] <> 0) then
  newsize = -3
elseif (field[fChosen].chosen.tagis[RaceSize.Tiny?] <> 0) then
  newsize = -2
elseif (field[fChosen].chosen.tagis[RaceSize.Small?] <> 0) then
  newsize = -1
elseif (field[fChosen].chosen.tagis[RaceSize.Medium?] <> 0) then
  newsize = 0
elseif (field[fChosen].chosen.tagis[RaceSize.Large?] <> 0) then
  newsize = 1
elseif (field[fChosen].chosen.tagis[RaceSize.Huge?] <> 0) then
  newsize = 2
elseif (field[fChosen].chosen.tagis[RaceSize.Gargant?] <> 0) then
  newsize = 3
elseif (field[fChosen].chosen.tagis[RaceSize.Colossal?] <> 0) then
  newsize = 4
endif

~ Set all our physical changes.
herofield[tSize].value -= newsize
foreach pick in hero from BaseRace where "thingid.r?"
  [B][COLOR="Red"]each.field[rSTR].value = field[fChosen].chosen.field[rSTR].value
  each.field[rDEX].value = field[fChosen].chosen.field[rDEX].value
  each.field[rCON].value = field[fChosen].chosen.field[rCON].value
  each.field[rAC].value = field[fChosen].chosen.field[rAC].value[/COLOR][/B]
  each.field[rSpeed].value = field[fChosen].chosen.field[rSpeed].value
nexteach

~ Change our extraordinary special attacks.
foreach pick in hero from BaseSpec where "((thingid.x? | thingid.r?) & AbilType.Extra & SpecType.Attack) | thingid.xBrthWpn | thingid.xGaze | thingid.xFly | thingid.xBurrow | thingid.xClimb | thingid.xSwim"
  perform each.assign[Helper.SpcDisable]
nexteach

~ List of new extraordinary special attacks.
var counter as number
counter = 0
foreach bootstrap in field[fChosen].chosen where "(thingid.x? | thingid.r?) & AbilType.Extra & SpecType.Attack"
  if (counter <> 0) then
    hero.child[xAltForm].field[CustDesc].text &= ", " & eachthing.field[name].text
  else
    hero.child[xAltForm].field[CustDesc].text = hero.child[xAltForm].field[descript].text & "{br}{vert 7}Extraordinary Special Attacks: " & eachthing.field[name].text
  endif
  counter += 1
nexteach
if (counter <> 0) then
  hero.child[xAltForm].field[CustDesc].text &= "."
endif

~ List our movement modes.
counter = 0
foreach bootstrap in field[fChosen].chosen where "thingid.xBurrow | thingid.xClimb | thingid.xFly | thingid.xSwim"
  if (counter <> 0) then
    hero.child[xAltForm].field[CustDesc].text &= ", " & eachthing.field[name].text
  else
    hero.child[xAltForm].field[CustDesc].text = hero.child[xAltForm].field[CustDesc].text & "{br}{vert 7}Movement Types: " & eachthing.field[name].text
  endif
  counter += 1
nexteach
if (counter <> 0) then
  hero.child[xAltForm].field[CustDesc].text &= "."
endif

~ List our attacks available.
counter = 0
foreach bootstrap in field[fChosen].chosen where "component.BaseNatWep"
  if (counter <> 0) then
    hero.child[xAltForm].field[CustDesc].text &= ", " & eachthing.field[name].text
  else
    hero.child[xAltForm].field[CustDesc].text = hero.child[xAltForm].field[CustDesc].text & "{br}{vert 7}Natural Attacks: " & eachthing.field[name].text
  endif
  counter += 1
nexteach
if (counter <> 0) then
  hero.child[xAltForm].field[CustDesc].text &= "."
endif

5. Do the same routine for the ability Change Shape, but remove the highlighted text from the script. You also need to change the xAltForm id of your ability (whatever that is for you) to the id for your Change Shape (xChgShape for my files).

From this it's not hard to figure out most the other special cases of shapechanging and code them. It's a starting point. I'm going to make improvement on this as well, as at the moment, with the current script, there is no way to deactivate the new form back to the original form, but that should be easy to fix. I just wanted to get it working first before worrying about the easy to fix stuff.
 
Last edited:
I should explain what this is actually doing. Outside of making the physical changes to the characters ability scores and size, it is listing the Extraordinary Special Abilities, Movement Modes, and Natural Attacks under the Alternate Form (or Change Shape) description. So to see those, you actually have to hover the mouse cursor over the ability to see what these are. Again, not and ideal solution, but the only one I could come up with given the limitations of HL.
 
Just a quick note. The second script is expecting this feat to be named "xAltForm".

One possible solution to the problem of returning the character back to normal. Create an adjustment that bootstraps this feat and adds it when activated. Then when the adjustment is deactivated, it will remove the feat and the character should go back to normal.

Also, nice work Kendall, and thanks for sharing it.
 
Last edited:
What I did was, I just added the Helper.ShowCharge tag to the xAltForm (or whatever you want to call yours, as I alluded to), then added an hName1 that I named "Active" that will only apply the changes while checked. Then all I needed to do was add a doneif statement checking this at the beginning of each script.

Thanks for the compliment. I've been trying various methods to improve what I have, but unfortunately, tags that are added while live are not accessible (such as wMain tags, livename fields, etc). I'm still playing around with the script, but it is a good starting point for any improvements. For example, I've already started adding Type.XXX tags to each monsters and appended each ftCandExpr (I think that is the field name off the top of my head) with inclusions of only those Type.XXX and/or RaceSize.XXX tags. Unfortunately, that lead to more upkeep, as I have to add the Type.XXX tags to each race, but no worries, it's just time. ;)
 
I've even thought of a more elaborate, but better and more thorough way to get this done. There is a "foreach actor in portfolio" command, where you can pull the idstring from the chosen race, then look in the current portfolio for that race (which could be loaded up), and then you would actually be able to pull the tags from it. It's a little more complex, since you may have to load a creature into a portfolio that isn't in the fight, but you can also pretty easily exclude them from the combat as well. It may turn out to be a better, and more thorough, shape changing solution. Stay tuned.
 
Dang. It works that I can go through each actor in the portfolio by loading up a complete creature that will be copied and accessing all its bootstraps and fields. Unfortunately, only the active hero is live, as attempts to access another hero in the portfolio results in the same as what has already been done here. So with the inactive hero not being live, this also is not a solution. I've done the best I can at this point.
 
Your work has given me a chance to take a new approach to the Wild Shape issue. Instead of creating a new class with a custom ability, I am modifying the class special Wild Shape to grant a feat (called Wild Shape) that functions basically the same as your Alternate Form feat. I modified it to only allow animals for now, and I'm seeing a problem where the ability scores aren't changing. I haven't yet figured out why, but its a far cry better than what I was doing.

Edit: Whoops. Ability scores weren't changing because I hadn't yet chosen a race for my druid.
 
Last edited:
I had a thought that might help assign natural weapons. Start with a foreach loop to look for various natural weapons then assign a custom tag. Then you could create various bootstraps that are conditional upon those custom tags being present. This would likely require making specials like I did with my custom ability. I don't have time to try it out now, but I wanted to write it down somewhere so I don't forget it. Hopefully tomorrow I can take a crack at this.
 
My code turns out to have a few errors, just so you know. It was calculating the sizes wrong, something I didn't test thoroughly enough the first time through to be aware of it.

You have to add the Helper.ShowCharge to the tags for this part to work. Then when you choose a race, you also have to select the ability as active. On each creature with the Alternate Form (or Change Shape) ability I append to the ftCandExpr field to get the right creatures up for each one.

First/105
Code:
~ Set our selector so that we can return to normal.
field[hName1].text = "Active"

Modified code:

First/110
Code:
doneif (field[hIsOn1].value = 0)

~ If we haven't chosen anything, get out now.
doneif (field[fChosen].ischosen = 0)

~ Determine new size.
var newsize as number
if (field[fChosen].chosen.tagis[RaceSize.Fine?] <> 0) then
  newsize = -4
elseif (field[fChosen].chosen.tagis[RaceSize.Dimin?] <> 0) then
  newsize = -3
elseif (field[fChosen].chosen.tagis[RaceSize.Tiny?] <> 0) then
  newsize = -2
elseif (field[fChosen].chosen.tagis[RaceSize.Small?] <> 0) then
  newsize = -1
elseif (field[fChosen].chosen.tagis[RaceSize.Medium?] <> 0) then
  newsize = 0
elseif (field[fChosen].chosen.tagis[RaceSize.Large?] <> 0) then
  newsize = 1
elseif (field[fChosen].chosen.tagis[RaceSize.Huge?] <> 0) then
  newsize = 2
elseif (field[fChosen].chosen.tagis[RaceSize.Gargant?] <> 0) then
  newsize = 3
elseif (field[fChosen].chosen.tagis[RaceSize.Colossal?] <> 0) then
  newsize = 4
endif

~ Set all our physical changes.
var oldsize as number
foreach pick in hero from BaseRace where "thingid.r?"
  [B][COLOR="Red"]each.field[rSTR].value = field[fChosen].chosen.field[rSTR].value
  each.field[rDEX].value = field[fChosen].chosen.field[rDEX].value
  each.field[rCON].value = field[fChosen].chosen.field[rCON].value
  each.field[rAC].value = field[fChosen].chosen.field[rAC].value[/COLOR][/B]
  each.field[rSpeed].value = field[fChosen].chosen.field[rSpeed].value
  if (field[fChosen].chosen.tagis[RaceSize.Fine?] <> 0) then
    oldsize = -4
  elseif (each.tagis[RaceSize.Dimin?] <> 0) then
    oldsize = -3
  elseif (each.tagis[RaceSize.Tiny?] <> 0) then
    oldsize = -2
  elseif (each.tagis[RaceSize.Small?] <> 0) then
    oldsize = -1
  elseif (each.tagis[RaceSize.Medium?] <> 0) then
    oldsize = 0
  elseif (each.tagis[RaceSize.Large?] <> 0) then
    oldsize = 1
  elseif (each.tagis[RaceSize.Huge?] <> 0) then
    oldsize = 2
  elseif (each.tagis[RaceSize.Gargant?] <> 0) then
    oldsize = 3
  elseif (each.tagis[RaceSize.Colossal?] <> 0) then
    oldsize = 4
  endif
nexteach
newsize -= oldsize
herofield[tSize].value += newsize

~ Change our extraordinary special attacks.
foreach pick in hero from BaseSpec where "((thingid.x? | thingid.r?) & AbilType.Extra & SpecType.Attack) | thingid.xBrthWpn | thingid.xGaze | thingid.xFly | thingid.xBurrow | thingid.xClimb | thingid.xSwim"
  perform each.assign[Helper.SpcDisable]
nexteach

~ List of new extraordinary special attacks.
var counter as number
counter = 0
foreach bootstrap in field[fChosen].chosen where "(thingid.x? | thingid.r?) & AbilType.Extra & SpecType.Attack"
  if (counter <> 0) then
    hero.child[xAltForm].field[CustDesc].text &= ", " & eachthing.field[name].text
  else
    hero.child[xAltForm].field[CustDesc].text = hero.child[xAltForm].field[CustDesc].text & "{br}{vert 7}Extraordinary Special Attacks: " & eachthing.field[name].text
  endif
  counter += 1
nexteach
if (counter <> 0) then
  hero.child[xAltForm].field[CustDesc].text &= "."
endif

~ List our new movement modes.
counter = 0
foreach bootstrap in field[fChosen].chosen where "thingid.xBurrow | thingid.xClimb | thingid.xFly | thingid.xSwim"
  if (counter <> 0) then
    hero.child[xAltForm].field[CustDesc].text &= ", " & eachthing.field[name].text
  else
    hero.child[xAltForm].field[CustDesc].text = hero.child[xAltForm].field[CustDesc].text & "{br}{vert 7}Movement Types: " & eachthing.field[name].text
  endif
  counter += 1
nexteach
if (counter <> 0) then
  hero.child[xAltForm].field[CustDesc].text &= "."
endif

~ List our new natural attacks.
counter = 0
foreach bootstrap in field[fChosen].chosen where "component.BaseNatWep"
  if (counter <> 0) then
    hero.child[xAltForm].field[CustDesc].text &= ", " & eachthing.field[name].text
  else
    hero.child[xAltForm].field[CustDesc].text = hero.child[xAltForm].field[CustDesc].text & "{br}{vert 7}Natural Attacks: " & eachthing.field[name].text
  endif
  counter += 1
nexteach
if (counter <> 0) then
  hero.child[xAltForm].field[CustDesc].text &= "."
endif
 
I had a thought that might help assign natural weapons. Start with a foreach loop to look for various natural weapons then assign a custom tag. Then you could create various bootstraps that are conditional upon those custom tags being present. This would likely require making specials like I did with my custom ability. I don't have time to try it out now, but I wanted to write it down somewhere so I don't forget it. Hopefully tomorrow I can take a crack at this.

I think you are being a bit ambitious with this. There is a lot of things that go into the attacks, whether they are primary or secondary, whether they do two-handed damage, a tag for each type of attack, a tag for each type of damage. That makes a bunch of custom tags, all of which have to be added to each creature (the actual attacks are easy enough, but the damage varies by which creature it is and how much it does). So each creature would have a tag for each damage and what type (primary, secondary, two-handed) and then each attack type would have a custom tag for its attack name basically (everything else is variable by creature). That's a ton of tags to assign, kind of a monumental task, and all for the possibility that the creature may be chosen as a race being mimicked. I, for one, thought of this and discarded it as far too much work for little reward.
 
You may be right, but I usually start off small. The hope is that I can find a way to carry the various flags like NatPrimary and damage dice over to the new form. It may not be possible, but I'll give it a whirl and let you know what happens.

Also, thanks for the update. I hadn't played around with size changes enough to see any problems.
 
For some reason (probably cause I'm dumb), I'm having a hard time determining if the Helper.NatPrimary tag exists on something. Here's the code I'm trying and failing with:

Code:
 foreach bootstrap in field[fChosen].chosen where "component.BaseNatWep & thingid.wBite"
  if (tagis[Helper.NatPrimary] <> 0) then
   [I]blah blah blah[/I]
  endif
 nexteach

Am I taking the completely wrong approach or is my if statement just not right?
 
Back
Top