• You've discovered RedGuides, an EverQuest multi-boxing and scripting community 🧙‍♀️⚙️. We want you to play several EQ characters at once, come join us and say hello! 👋

  • A TLP without truebox has thawed (Very Vanilla ready)
    Frostreaver

Problem - for loop in modpull.inc crashes bot

Joined
Dec 30, 2010
RedCents
44¢
I have set up the bot to pull.

My INI for the pull section looks like this:
Rich (BB code):
[AdvPull]
APCheckTime=0
APRadius=40
APMobMax=3
APScript=pull_script
APPath=pull_path
APRetPath=
APBefore=
APAfter=
APAnnounce=/gsay Incoming -[ %t ]-
APRetries=1

While the bot is looking for targets, it crashes at line 84 of modpull.inc with a "/next without matching /for" error. The loop is below:

Rich (BB code):
/if (!${tTargetID}) {
    /for a 1 to ${ADMobMax}
      /if (!${NearestSpawn[${a},pet].ID}) /next a
      /for b 1 to ${ADMobMax}
        /if (!${ADMobList[${b}]}) /next b
        /if (${ADMobList[${b}]} && ${NearestSpawn[${a},pet].ID}==${ADMobList[${b}]}) /multiline ; /varset tTargetID ${ADMobList[${b}]};/goto :tGotTarget
      /next b
    /next a <---- THIS IS THROWING THE ERROR
  }

UPDATE
I started messing around the script a little bit and figured out it crashes at the next for loop also.
 
Last edited:
Finally got it working. It was because /next a was able to be called in more than one place. Changes were made to the /for loops to make them like this:

Rich (BB code):
/for a 1 to ${ADMobMax}
    /if (!${NearestSpawn[${a},pet].ID}) /goto :skip_a
    /for b 1 to ${ADMobMax}
    /if (!${ADMobList[${b}]}) /goto :skip_b
      /if (${ADMobList[${b}]} && ${NearestSpawn[${a},pet].ID}==${ADMobList[${b}]}) /multiline ; /varset tTargetID ${ADMobList[${b}]};/goto :tGotTarget
	:skip_b
    /next b
  :skip_a
  /next a
  }
 
I'm glad you got it sorted out. I want to profer some assistance on how the existing for loop setups work and options you have to use instead of /goto tags.


Rich (BB code):
/for i 1 to 10
    /if (TRUE) /goto :skip
    /superawesome command
:skip
/next i

can be replaced with

Rich (BB code):
/for i to 10 
    /if (TRUE) /continue
    /superawesome command
/next i

where continue will skip all remaining code and proceed to the next number in the iteration and start from the stop. This effectively does the same exact thing as your /goto :tag

Additionally you have the /break command. this would be like putting the goto AFTER the /next i.

Rich (BB code):
/for i 1 to 10
    /if (TRUE) /goto :skiploop
    /superawesome command
/next i 
:skiploop
/echo The loop is finished.

is the same as

Rich (BB code):
/for i 1 to 10
    /if (TRUE) /break
    /superawesome command
/next i 
/echo The loop is finished.

Below is an example of both used in a single block of code using nested for loops.

Rich (BB code):
/for i 1 to 10
    /for j to 10
        /if (${i}%2) /continue
        /echo I am on i:${i} j:${j}
    /next j
    /if (${i} == 5) /break
/next i

In this case if ${i}%2 (meaning the remainder of any i/2 so if i is 1 and you divide by 2 then it's 0 with a remainder of 1, where 1 is the result of the modulus operation. So it means that anytime ${i} is odd it will skip the echo and go to the next ${j} in in the loop.

Then you have if ${i} is ever equal to 5, then I want to "break" out of the loop. meaning once i is 5 then the loop will skip past the /next i statement and continue processing code.

Which means that the /for i 1 to 10 is actually /for i 1 to 5

The /break and /continue commands are used on the currently loop they are inside of. In the event of nexted loops it applies to the last loop entered unless they have exited that loop. so /continue in the above applies to the J loop and /break applies to the I loop. if I switched it and put the break inside the J loop and the /continue in the J loop then they would apply to their respective loops. In this manner you can apply what is called "base cases" where if some condition is met then you skip or exit the loop accordingly. An example would be anywhere inside of KA where casting is done (such as the healing subs).

Rich (BB code):
/for i 1 to ${SingleHeal.Size}            | If heal is null or off |0 or spell/aa/item not ready skip it
            /if (${DebugHeal}) /echo \amDEBUGHEALS SingleHeal \awSpell ${i}: ${SingleHeal[${i}]}  ${SingleHeal[${i}].Arg[1,|]}   ${SingleHeal[${i}].Arg[2,|]}   ${SingleHeal[${i}].Arg[3,|]} \agLine#: ${Macro.CurLine}
            /if (${DebugHeal}) /echo \amDEBUGHEALS SingleHeal \awSpellSkip: !${SingleHeal[${i}].Length} || ${SingleHeal[${i}].Arg[2,|].Equal[0]} \agLine#: ${Macro.CurLine}
            /if (!${SingleHeal[${i}].Length} || ${SingleHeal[${i}].Arg[2,|].Equal[0]}) /continue
            /varset SHealSpell   ${SingleHeal[${i}].Arg[1,|]}
            /varset SHealPct     ${SingleHeal[${i}].Arg[2,|]}
            /varset SHealTag     ${SingleHeal[${i}].Arg[3,|]}
            /varset SHealRange ${Spell[${SHealSpell}].Range}
            /call CastReady "${SHealSpell}" singleheal
            /varset SpellReadyL ${Macro.Return}
            /if (!${SpellReadyL}) /continue

Above is a copy of a section of the singleheal sub

You'll see it enters a for loop. And then you will find that based on some checks it determines if it wants to "skip that iteration" for a couple of cases. Such as the SingleHeal doesn't have a text length (nothing was provided as the spell to cast) or if they spell isn't ready (based on /call CastReady)

This is done for the sake of clarity and code flow. Technically you could just chain all the base cases in a very long "/if (This || This || This || This || This) /continue" statement.

But, strings have limitations in mq2 and keeps the code easier to read.

Hope this information was informative and assist you with future creations.
 
Problem - for loop in modpull.inc crashes bot

Users who are viewing this thread

Back
Top
Cart