View Single Post
Senior Member
Volunteer Data File Contributor
Join Date: Jan 2010
Location: Chicago, IL (USA)
Posts: 10,695

Old February 16th, 2015, 03:52 PM
So "foreach" loops. Want to talk about them for a minute here. I would like people to consider Foreach loops the MOST EVIL thing ever invented! In other words they should be the "LAST" type of script we write instead of the first type of script we write.

The reason you ask? Good question. The amount of CPU it takes is massive. Apply this onto the iPads or a small windows tablet and it will BURN through the battery or simply cause the iPad to close. Then I get nasty grams from gamers say how the "Community" stuff broke the iPad.

In a small way they are right because we use far too many foreach loops to solve problems. They are everywhere in almost every script.

So here is an example. Sorry I just saw this posted to GitHub and its the perfect situation to talk about:

The ability is trying to give Mind Blades the Agile special ability.
A nimble blade of 7th level treats his mind blade as if it had the agile weapon special ability. This does not count toward the nimble blade’s mind blade’s enhancement bonus. This replaces the mind blade enhancement increase gained at 7th level.

We see the code is doing a Foreach loop to find all the mind blades.
<eval phase="PostLevel" priority="10000"><![CDATA[
  ~ If the hero doesn't have this ability, ignore the following.
  doneif (tagis[Helper.ShowSpec] = 0)

  foreach pick in hero from BaseWep where "IsWeapon.wMindBlade"
    perform eachpick.assign[DamageOpt.aDEX]
In this case we have access to all the "Things" that make up the Mind Blade weapon. What we should be doing instead is setting a bootstrap of the "Agile" Item Power onto each Mind Blade weapon. Then setting a bootstrap condition that says if it finds the "MindBlade.Agile" tag on the hero then allow the bootstrap for Agile to work. So this means the "agile" text will get displayed on the Mind blade and no foreach loop required.

In matter of fact the above script simply becomes:
<eval phase="First" priority="100"><![CDATA[
  ~we're earlier than the normal test for whether we've reached the correct level, so we'll recreate that test here
  doneif (root.linkage[varies].field[cTotalLev].value + field[xExtraLev].value + field[xEffectLev].value < tagvalue[ClSpecWhen.?])

  ~ Set agile tag onto the hero
  perform hero.assign[MindBlade.Agile]
If we don't want to deal with "Bootstrap" conditions we could instead set this script on to the Mind Blade weapon:
~ Pre-levels/10000
~ If we should have the Agile weapon property give Dex to damage
if (hero.tagis[MindBlade.Agile] = 1) then
Then the above argument could be made that we have 4 mind blade weapons so we would have to add the above script "four" times. What if something in the future changes then we have to adjust four scripts. Ah well this is why they invented Procedures. A procedure which can now easily be seen and worked with in the editor "General->*Procedures" allows you to write the script "ONE" time and call it from all the mind blades. If in the future we need to change or enhance the script we do it in one place.

You will find all current procedures for Psionics in "COM_3PPPack_UltimatePsionics - Procedures.user". If you look HERE you will see we already have a procedure designed to run at Pre-Levels/10000 called SetMindBl. So really the last script just needs to be added to the SetMindBl procedure and no "Foreach" loop needed.

Hero Lab Resources:
Pathfinder - d20pfsrd and Pathfinder Pack Setup
3.5 D&D (d20) - Community Server Setup
5E D&D - Community Server Setup
Hero Lab Help - Hero Lab FAQ, Editor Tutorials and Videos, Editor & Scripting Resources.
Created by the community for the community
- Realm Works kickstarter backer (Alpha Wolf) and Beta tester.
- d20 HL package volunteer editor.
ShadowChemosh is online now   #19 Reply With Quote