• 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

Fork / Mod While functions and MQ2Cast vs Spell Routines (1 Viewer)

TheNomadMan

New member
Joined
Feb 8, 2014
RedCents
451¢
Recently, the development of KissAssist has moved away from using the asynchronous plugin MQ2Cast in favor of the in-line macro MQ2Cast_Spell_Routines. Doing so assures that all cast functions are handled in a liner fashion and prevents "sync issues" that had previously been compensated for (to varing degrees of success) through the use of hardcoded delays. However, this also represents a complete loss of all advantageous asynchronous behavior while casting and creates artificial lag in KissAssist itself.

Allowing for, taking advantage of, and staying in sync with asynchronous plugins requires the use of While loops. MQ2 does not support actual while functions. However, while loops can be simulated through the use of no-delay loops to a bookmark. For example:

- This will effectively monitor the MA's HP while a DPS spell is casting. Thusly allowing us to interrupt the DPS spell if the MA's HP hits an ini defined threshold while the spell is still casting. In this example the macro would then move to Sub CheckHealth to ensure heals are sorted out before another DPS is attempted. Below the HP monitoring loop is a casting status monitor. This will hold all "If cast result equals" lines until after there is an actual cast result or the lack there of. Thusly keeping the KA macro and MQ2Cast plugin in sync. This is not possible with Spell Routines as it runs in-line, rather than parallel to, KissAssist and therefore will not reach the monitoring loop until after spell casting is complete.

Rich (BB code):
 /if (${Cast.Ready[${castWhat}]} && !${IAmABard}) {
                /casting "${castWhat}"
			| Monitor MA HP While Casting. Abort if InterruptHP is hit.
				:MonitorHPWhileCasting
				/if (${sentFrom.Equal[DPS]} && ${Spawn[${MainAssist} ${MainAssistType}].PctHPs}<=${InterruptHP}) {
					/docommand /stopcast
					/echo ${sentFrom} spell ${castWhat} ABORTED to CAST A HEAL!
					/call CheckHealth
				}
				/if (${sentFrom.Equal[DPS]} && ${${Cast.Status}.Equal[C]}) /goto :MonitorHPWhileCasting
                                | Wait while casting
				:Stillcasting
				/if (${${Cast.Status}.Equal[C]}) /goto :Stillcasting
                                /varset CastResult ${Cast.Return}
		/if (${Debug}) /echo DEBUG CastWhat cast Spell result: ${Cast.Return}
                /doevents
                /call CheckCasting 50
            }

Because there will be conditions that escape us on occasion, reliability can be ensured with catch-all while looping at the beginning of any cast related subroutine. For example:

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} || ${DebugAll}) /echo DEBUGHEALS SingleHeal Spell ${i}: ${SingleHeal[${i}]}  ${SingleHeal[${i}].Arg[1,|]}   ${SingleHeal[${i}].Arg[2,|]}   ${SingleHeal[${i}].Arg[3,|]}
            /if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS SingleHeal SpellSkip: !${SingleHeal[${i}].Length} || ${SingleHeal[${i}].Arg[2,|].Equal[0]}}
            /if (!${SingleHeal[${i}].Length} || ${SingleHeal[${i}].Arg[2,|].Equal[0]}) /goto :SNextHeal
          :tooofast
	    /if (!${IAmABard} && !${Cast.Ready[${SingleHeal[${i}]}]} && !${Me.SpellReady[${Me.Gem[1].Name}]} && !${Me.SpellReady[${Me.Gem[3].Name}]} && !${Me.SpellReady[${Me.Gem[5].Name}]} && !${Me.SpellReady[${Me.Gem[7].Name}]}) /goto :tooofast
	    /if (!${IAmABard} && !${Cast.Ready[${SingleHeal[${i}]}]} && (${Me.SpellReady[${Me.Gem[1].Name}]} || ${Me.SpellReady[${Me.Gem[3].Name}]} || ${Me.SpellReady[${Me.Gem[5].Name}]} || ${Me.SpellReady[${Me.Gem[7].Name}]})) /goto :SNextHeal

Simulated while loops can also be used to replace many other delays and improve general responsiveness.

This segment, used to check for globalcool down, can use this loop behavior to trim off a little time

Rich (BB code):
 :Waitforcooldown
            /if (!${IAmABard} && !${Cast.Ready[${castWhat}]} && !${Me.SpellReady[${Me.Gem[1].Name}]} && !${Me.SpellReady[${Me.Gem[3].Name}]} && !${Me.SpellReady[${Me.Gem[5].Name}]} && !${Me.SpellReady[${Me.Gem[7].Name}]})  /goto :Waitforcooldown

as opposed to the current

Rich (BB code):
 :Waitforcooldown
             /if (!${IAmABard} && !${Me.SpellReady[${castWhat}]} && !${Me.SpellReady[${Me.Gem[1].Name}]} && !${Me.SpellReady[${Me.Gem[3].Name}]} && !${Me.SpellReady[${Me.Gem[5].Name}]} && !${Me.SpellReady[${Me.Gem[7].Name}]}) {
                /delay 2
                /goto :Waitforcooldown     
            }

While this segment can be removed all togather to trim off a big chunk of time:

Rich (BB code):
/delay 3s ${Me.SpellReady[${MezSpell}]}

Because the aforementioned simulated while loops already sort out the necessary delay down to as fine a grain as can be done, removing the above line safely brings about a very significant improvement in the over all time-cost of mob mezzing.

Rich (BB code):
A targeting example would be like this:

| -------------------------------------------------------------------------------------
| SUB: CombatTargetCheck
| -------------------------------------------------------------------------------------
    Sub CombatTargetCheck
        :fixtarget
        /squelch /target id ${MyTargetID}
        /if (${Target.ID}!=${MyTargetID} && ${Spawn[${MyTargetID}].ID}) /goto :fixtarget
        /return
| -------------------------------------------------------------------------------------

OR

| -------------------------------------------------------------------------------------
| SUB: CombatTargetCheck
| -------------------------------------------------------------------------------------
    Sub CombatTargetCheck
        :fixtarget
        /if (${Target.ID}!=${MyTargetID} && ${Spawn[${MyTargetID}].ID}) {
            /squelch /target id ${MyTargetID}
            /goto :fixtarget
        }
    /return
| -------------------------------------------------------------------------------------

rather than

| -------------------------------------------------------------------------------------
| SUB: CombatTargetCheck
| -------------------------------------------------------------------------------------
    Sub CombatTargetCheck
        /if (${Target.ID}!=${MyTargetID} && ${Spawn[${MyTargetID}].ID}) {
            /squelch /target id ${MyTargetID}
            /delay 10 ${Target.ID}==${MyTargetID}
        }
    /return
| -------------------------------------------------------------------------------------

And; because simulated-while looping gives us such a sure and fast response to events, code such as fast Nuke-Healing becomes viable as well as true chaining of heals, runes as heals, stuns, nukes, etc. This, because there is no guessing as to the delay nessiacary to compensate for lag, slow machines, or unforeseen events. The delay to allow for proper targeting and spell selection becomes dynamic and always as precisely what we need as possible. And; less code is run through due to "skips" than otherwise possiable without accounting for every single condition in EQ.

Rich (BB code):
| Check For Nuke Heals
            /if (${SHealTag.Find[Mob]}) {
	        /if (!${AggroTargetID}) /goto :SNextHeal
		/doevents Switch
		/if (!${MyTargetID}) /call Assist
                /if (${MyTargetID} && ${Spawn[${MainAssist} ${MainAssistType}].PctHPs}<=${SHealPct} && ${Spawn[${MyTargetID}].ID} && ${Spawn[${MyTargetID}].Distance}<=${SHealRange}) {
                    /call CastWhat "${SHealSpell}" ${Spawn[${MyTargetID}].ID} Heal
                    /if (${Macro.Return.Equal[CAST_SUCCESS]}) {
                        /call BroadCast ${IRCOn} ${EQBCOn} o "${SHealSpell} for ${SHealThem} >> Heal Nuke << aginst ${Spawn[${MyTargetID}].ID} "
			/call CheckHealth
                        /return
                    }
                } else {
                    /goto :SNextHeal
                }

To conclude this post: simulated-while loops can improve KA's progression speed thru in-line code, reduce the occurrence of skipped events, and can extend KA's functionality by taking advantage of, rather than being hindered by, asynchronous plugins.

Below is a functional example of how using asynchronous plugins and simulated-while loops can improve your KissAssist experience. I'd suggest allowing it to make a fresh ini; if you'd like to try out the nuke healing, dps cast interrupting, chain healing with DPS enabled, and ooc rezzing features. Be aware there are other changes in this example, too (no AE's or Mez's if extended target window is clear, check health after successful heals, and other such tweeks).
 

Attachments

Last edited:
Your efforts are epic and hacking a macro can be as much fun as writing on. I keep this in mind while writing Kiss so people can hack it for the own needs. Thats why like 20% of the macro is comments. Something no other macro I have ever seen does. Its lets you find the code you need to hack a lot faster. Also when a macro becomes so efficient it out performs players becomes obvious well its obvious. One of my MAIN Kiss parameters is SAFETY as in not being detected. I want Kiss to kill the mob, keep you tank alive, etc but still kind of look like someone could be behind the computer.

That said the following is an explanation of why the code is written the way it is.

The mez delay may no longer be needed with MQ2cast_spell_routines. I haven't gotten to that section yet. the last week or so I have been working on finishing the hunter role.

Part of the heal section was restored due to reports of slowness in 7.4. I have also incorporated the extra heal check from ctaylor. The heal section is working very now.

You are forgetting about server delay. This is specifically to wait for the server to recognize your target. Anything less will cause problems.

Rich (BB code):
| -------------------------------------------------------------------------------------
| SUB: CombatTargetCheck
| -------------------------------------------------------------------------------------
    Sub CombatTargetCheck
        /if (${Target.ID}!=${MyTargetID} && ${Spawn[${MyTargetID}].ID}) {
            /squelch /target id ${MyTargetID}
            /delay 10 ${Target.ID}==${MyTargetID}
        }
    /return

Having MQ2 cycle through loops as fast as possible in my experience can cause lock ups depending on the amount of toons on a computer etc. That delay is 1/5th of a second as well.

Rich (BB code):
 :Waitforcooldown
             /if (!${IAmABard} && !${Me.SpellReady[${castWhat}]} && !${Me.SpellReady[${Me.Gem[1].Name}]} && !${Me.SpellReady[${Me.Gem[3].Name}]} && !${Me.SpellReady[${Me.Gem[5].Name}]} && !${Me.SpellReady[${Me.Gem[7].Name}]}) {
                /delay 2
                /goto :Waitforcooldown     
            }

This kind of check doesn't jive with the kiss healing system well. Since I eliminated static heal types like spotheal, Hotheal, CH. This is just an arbitrary number outside of the Kiss healing system that has to check it anyways once you send Kiss to the checkhealth sub.

Rich (BB code):
:MonitorHPWhileCasting
	/if (${sentFrom.Equal[DPS]} && ${Spawn[${MainAssist} ${MainAssistType}].PctHPs}<=${InterruptHP}) {
		/docommand /stopcast
		/echo ${sentFrom} spell ${castWhat} ABORTED to CAST A HEAL!
		/call CheckHealth
	}

This kind of stuff will kind of mess kiss up. The entire macro is built around handling all casting in CastWhat. Its Kiss spell/aa/disc/item casting engine. It makes it much easier to debug 5600 lines of code.

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} || ${DebugAll}) /echo DEBUGHEALS SingleHeal Spell ${i}: ${SingleHeal[${i}]}  ${SingleHeal[${i}].Arg[1,|]}   ${SingleHeal[${i}].Arg[2,|]}   ${SingleHeal[${i}].Arg[3,|]}
            /if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS SingleHeal SpellSkip: !${SingleHeal[${i}].Length} || ${SingleHeal[${i}].Arg[2,|].Equal[0]}}
            /if (!${SingleHeal[${i}].Length} || ${SingleHeal[${i}].Arg[2,|].Equal[0]}) /goto :SNextHeal
          :tooofast
	    /if (!${IAmABard} && !${Cast.Ready[${SingleHeal[${i}]}]} && !${Me.SpellReady[${Me.Gem[1].Name}]} && !${Me.SpellReady[${Me.Gem[3].Name}]} && !${Me.SpellReady[${Me.Gem[5].Name}]} && !${Me.SpellReady[${Me.Gem[7].Name}]}) /goto :tooofast
	    /if (!${IAmABard} && !${Cast.Ready[${SingleHeal[${i}]}]} && (${Me.SpellReady[${Me.Gem[1].Name}]} || ${Me.SpellReady[${Me.Gem[3].Name}]} || ${Me.SpellReady[${Me.Gem[5].Name}]} || ${Me.SpellReady[${Me.Gem[7].Name}]})) /goto :SNextHeal

Keep coding. This is exactly how I learned to write macros only I didn't have the author or the community to help me.
 
MQ2 does not support actual while functions.
FWIW, /while loops have existed for at least 8 years via mq2loops, and within the last few months eqmule added /while command to core compile. It would appear you didnt see that memo.
 
Say, the plugin supported while looping isn't real while looping any more than what's posted above. As far as I'm aware that simply takes advantage of the same async behavior the OP discusses to create the same effect. At last read, the looping currently in the core compile is still getting the kinks worked out. I'm sure, that'll eventually be a great path to use on the regular. For the time being, MQ2 does not "fully" support while loops. And; what while loops are supported by various means are not currently in use in KissAssist. So, regardless of how one does decide to go about their while looping, my post still holds for those that wish to mod down this path. Async plugins require whiles to sync. You can while my way or anyway you wish, but you must say "while casting check this" if you want to have interrupt thresholds or similar features. This can not be done with inline code like spell routines, but can be done with async plugins like mq2cast. Which is the point of this post.

From all indications, one does not need to wait for the server to acknowledge your current target, only ensure the client has the right target at the time of cast. It'll tell the server which target you had at the time the event was sent. Correct targeting under heavy lag (Raids) was one of the goals here. And; fast target switching for nuke-heals has played out for us just as it should in our farming of all CoTF raids, including ToR, with all 54 slots filled. Verification has not only been by the user but also by heavy parsing and log checking.

As yet, no one who's tried this has had there's lock up due to the loops spinning too fast. Having a bad loop of any sort will hold up a machine, tho. So, yes, each loop needs to be looked at carefully and adding tattle-tale code for debugging is a good idea. It's impossible for me or my guild to test everyone's hardware/software configs, tho. So, yeah, if fast looping locks you up, don't do it. But even old slow machines seem to improve their handling of things when using these sorts of modifications. The example splinter build, above, is functional and can be tested at leisure for those who are concerned with this.

Adding ready checks outside of castwhat wasn't my idea of an ideal solution, either. However, the way KissAssist is currently doing it, every single condition under which a spell might not be ready has to be accounted for in castwhat and the condition has to exist before castwhat is called. This is currently not true of KissAssist and, as is, KA will send a number of spells down to castwhat that can't actually cast. This causes a slowdowns (the skipped events I mention in the OP) in getting to to what can cast, while it tries to cast a number of things it can't cast, and can cause spells to cast out of the order called for by all other logic. A simple check at the the beginning of subroutines that can call castwhat cuts out a great deal of this.

As far that heal typing check. KA is still has those checks, even if they don't do much. You may have noticed I like to copy/paste where I can, to keep using already established variables and routines. But, yeah, it doesn't seem to be hindering what is meant to checked: the MA's HP. So, sure, that variable can be changed to be more specific and doesn't need to check type. I'll look in to that for my splinter build. Either way, the extra info doesn't present a problem. If it did, well, as I say, that checking is still in the official build....

So, the long and short of it, while looping and async plugins can improve KA's performance, extend KA's functionality, and reduce the need to account for every single condition in EQ. This is not currently the design path of the official macro and it may never be the design path of the official macro. However, KA is just about the perfect platform for customizing a bot that does exactly what you want: it's very easy to read and manipulate. So, if you like the sound of features that require a while, check this stuff out.

As yet, I've haven't seen anyone take this down a path where the bots are doing anything a person couldn't do. But this is certainly starting down a path of things that most folks don't do. That is to say a bot running the above splinter macro as a healer, will likely out preform a real healer on any given single target. This because the bot doesn't mind switching targets to nuke-heal, where most players are just too lazy/busy/whatever to do so. And; of course, the bot doesn't have anything better to do than be a very observant/diligent player.

Thanks for the feedback. I hope some of you take the time to test the splinter build I posted and/or try these things out on your own. I've had a ton of fun doing so. And; now, my guild and I have some amazing support boxes for raids and other heavy situations. At least, so far as our desires for a bot go.
 
Last edited:
FWIW, /while loops have existed for at least 8 years via mq2loops, and within the last few months eqmule added /while command to core compile. It would appear you didnt see that memo.

There is no point in mentioning, MQ2Loops, or any other plugin that is not available to Macroquest2 community at RG or macroquest2.com.

And /while command added to MQ2 recently has not worked as expected since released and is primary in beta.

The correct answer is to check out MQ2Bucles included in our compile and available at macroquest2.com
http://www.redguides.com/community/showthread.php/24741-MQ2Bucles
 
There is no point in mentioning, MQ2Loops, or any other plugin that is not available to Macroquest2 community at RG or macroquest2.com.

And /while command added to MQ2 recently has not worked as expected since released and is primary in beta.

The correct answer is to check out MQ2Bucles included in our compile and available at macroquest2.com
http://www.redguides.com/community/showthread.php/24741-MQ2Bucles
Mq2bucles is the spanish version of mq2loops. So you do have mq2loops in your compile, you just didnt translate it's name to English.

Also, eqmule did an update to /while after people did the beta testing and it should be final now.

09 Jun 2014 by eqmule
- Fixed? /while
Feel free to test it and report any bugs.
- Added /GetWinTitle and /SetWinTitle Commands
- Added WinTitle to the Character TLO: it returns a pStringType
- Added PID (Process ID) to the Character TLO: it returns a pIntType
Usage:
/SetWinTitle [${Me.PID}] EverQuest - ${Me.Name} (Lvl:${Me.Level} ${Me.Class})
/echo ${Me.WinTitle}
[MQ2] [2319] EverQuest - Eqmule (Lvl:100 Shadow Knight)
 
Well, if they are fixed.... Will look for posts with feedback about the current state of the core whiles.

Say, the bucles/loops... have you played with it much? Anything I should know before tinkering with it? I am wondering if this isn't going to add another layer of complexity to maintaining sync. If MQ2Cast is casting, and MQ2Bucles is While'ing, what's KA up to? Waiting for a return, I'd hope, kinda like it does when spell_routines is called... But the spell_routines is in-line where I expect MQ2Bucles is async...
 
There was like 1500 too many words in your second post, so honestly I stop reading. But what you want is access to the mq2cast status info. Is it memorizing a spell? Is it trying to cast something already? Did it already try casting what i wanted but failed or succeeded?

All that info exists in the TLO.
http://www.redguides.com/docs/projects/mq2cast/
Rich (BB code):
string ${Cast.Status}
Returns a string containing all the pending events. This string often contains multiple events (eg. when /casting still has to immobilize you and then memorize the spell before it can cast). The list of possible pending events is:

    I: idle and waiting for you
    A: advpath pause
    F: stick pause
    S: immobilize in progress
    M: memorize in progress
    E: item swapped
    D: ducking casting
    T: targeting
    C: spell casting in progress
I think the intention you are asking for is to just have a pause routine because too many hands are in the cookie jar at the same time trying to control what is happening.

Sub Pause
/while (${Cast.Status.NotEqual})
{ /delay 1 }
/return

Then /call that sub periodically so it just hangs out while you are trying to cast. Obviously you could do a CheckHP routine or whatever else in there supposing you want to interrupt.

I could be misreading what you are attempting to accomplish, if so then obviosly ignore my advice!
 
I'm not trying for anything specific. Only providing examples of ways I use async behavior as a benefit, to achieve results not possible with the current in-line behavior, rather than a hindrance. And; expressing that, in my opinion, throwing out async plugins rather than while'ing to support them is limiting KA's potential. I also provided examples of other ways that while'ing can be used to speed up and error correct KA.

The biggest of those errors being that:
Adding ready checks outside of castwhat wasn't my idea of an ideal solution, either. However, the way KissAssist is currently doing it, every single condition under which a spell might not be ready has to be accounted for in castwhat and the condition has to exist before castwhat is called. This is currently not true of KissAssist and, as is, KA will send a number of spells down to castwhat that can't actually cast. This causes a slowdowns (the skipped events I mention in the OP) in getting to to what can cast, while it tries to cast a number of things it can't cast, and can cause spells to cast out of the order called for by all other logic. A simple check at the the beginning of subroutines that can call castwhat cuts out a great deal of this.
 
/****************************************************************************
Plugin Name : MQ2Bucles
Version : 1.0
Made by : el_nene
EMail : [email protected]
Description : MQ2Bucles adds while and do bucles to macros
*****************************************************************************
Commands :
-----------------------------------------------------------------------------
/while (<condition>)
...
...
/endwhile
- Executes a bucle, evaluating the condition on each iteration.
-----------------------------------------------------------------------------
/do
...
...
/until (<condition>)
- Executes a bucle, evaluating the condition on each iteration but on first
one.
-----------------------------------------------------------------------------
/break
- Stops a /while, /do or /for bucle.
-----------------------------------------------------------------------------
/continue
- Stops a /while, /do or /for bucle, reevaluating the condition.
*****************************************************************************
History :
-----------------------------------------------------------------------------
- Version 1.0 - Date: 21-01-2008
-> ADDED Functions
--> /while
--> /endwhile
--> /do
--> /until
--> /break
--> /continue
*****************************************************************************/

We are just using the names the author call their plugins. Changing stuff just seems confusing. Doesn't look like Spanish version to me lol.
 
Word. I plan on writing an internal method to cast for my mq2bot plugin because of the inefficiencies you mention. I intend on using deques to just store up the spells you want to cast, in the order you want to cast them, then process those spells as available after doing a last minute check to make sure it is all still needed just before casting. Then pop off the front of the deque and move to the next spell.

Additionally, I can have casting status by gem rather than just overall. So ok, you are waiting for a refresh on gem1 that will be 8 seconds.. great i can use gem2-12 still though. No need to hang up everything. There is plenty of room for spell deconfliction. MQ2Cast and spell_routines.inc both need some solid updating. I'm not sure if I want to write a full blown plugin version vice just handling spells/aa/items/discs/abilities and create a new /command instead. I redid an internal mq2twist for the same reason and was quite happy with the results considering it only took 2 small routines to make it happen. Though I used a vector instead of a deque since I didnt need to modify the twist list once you started. But if a song isnt ready, it stays in its relative position in the queue and gets handled when it is ready.
 
I think Maskoi and Pete touched on why you need to be careful on how you implement while loops. This applies to any programming language not just MQ2 scripting. While loops that do nothing but logic testing will use up every available CPU Cycle available, just to execute the loop. Now take that and multiply it by the number of characters you play at a time and you should get the picture. I am glad to see they have added the /while command, there have been many instances where I would of liked to use one. If I ever do use the /while loop, I will be careful on how I implement it.

There are some things I would like to see added to kissassist, stopping a heal or a slow or a nuke that is no longer needed is a great idea. I know there is many a time I have said to myself I wish Kiss could do that. I am sure that 1 day it will, but till then I will just keep annoying Maskoi, and keep asking him what's taking so long.

Maskoi keep up the hard work and TheNomadMan never stop asking.

ctaylor
 
I think Maskoi and Pete touched on why you need to be careful on how you implement while loops. This applies to any programming language not just MQ2 scripting. While loops that do nothing but logic testing will use up every available CPU Cycle available, just to execute the loop. Now take that and multiply it by the number of characters you play at a time and you should get the picture. I am glad to see they have added the /while command, there have been many instances where I would of liked to use one. If I ever do use the /while loop, I will be careful on how I implement it.

There are some things I would like to see added to kissassist, stopping a heal or a slow or a nuke that is no longer needed is a great idea. I know there is many a time I have said to myself I wish Kiss could do that. I am sure that 1 day it will, but till then I will just keep annoying Maskoi, and keep asking him what's taking so long.

Maskoi keep up the hard work and TheNomadMan never stop asking.

ctaylor


One of the old afclerics would duck a heal if the tanks hp went over 90%.

It's in the spell_routines.inc. You can actually do /stopcast while mounted now. He could easily do.

Rich (BB code):
/if (${AutoInterrupt} && (${Target.PctHPs}>=${StopHealPoint})) /call Interrupt

Rich (BB code):
Sub Interrupt
/if (!${Defined[DismountToInterrupt]}) /declare DismountToInterrupt bool outer ${Ini[MySpellIni,Settings,DismountToInterrupt,FALSE]}
/if (${Me.Mount.ID} && !${Dismount}) /goto :skipinterrupt
/if (${Me.Mount.ID}) /dismount
/delay 1s !${Me.Mount.ID}
/stopcast
/if (${Defined[castReturn]}) /varset castReturn CAST_CANCELLED
:skipinterrupt
/if (${Me.Mount.ID}) /varset castReturn MOUNTED
/return ${castReturn}
 
Thank you TheNomadMan for your first post, I did read all of the thread btw. I will be testing your version as soon as possible. My experience on loops is in fact, that they freeze my comps and they are decent. Sure I take em to the limit myself by allways running the maximum of instances for EQ to still run stable. I made a sub for my version to check for the spells memmed and the spells setup within the ini and then memorize as many spells from the setup, rather then to let KA start with too many spells not on the spellbar.

This routine makes my EQ instances freeze for about 5s on initial KA start, which I dont care about. But from my previous experience on coding I know exactly where it comes from. It comes from alot /for loops which get processed, even with skipping where possible. In my previous works I had to account for it to not let the macro run too many lines while the toon is moving or acting simultanously. So I had to build in delays 1 sometimes to give the comp a chance to process other things than just the loops from one macro.

And yes tweaking a macro and its delays to fit for the broadest range of users is one of the most complex things in MQ. Thats why I mostly do only delays with conditional checks.
And am happy to learn from your examples as much as possible to further boost my toons performances and reduce delays, while still maintaining a fluid run of my clients.
 
Say, that's interesting. My disk-drive systems lock up for a few seconds when starting this build or the official build. I took this for the seek/read delay of the drive while loading the macro, ini, and such in to memory and figured most folks see this. My ram-drive system loads this or the official version with no appreciable delay at all (16 gig ramdrive from a 32 gig bank, was subject to the same delay before utilizing the ramdrive).

My understanding of the MQ2 macro system is that it's articially limited in the number of commands that can execute in a given timeframe, anyway. Just what this limit is being defined by the #Turbo setting (or the lack there of to use the default Turbo setting). This should prevent your cpu from getting clocked-out. Or; am I reading this wrong?
 
Last edited:
You can change the max turbo setting if you wanted to. I got eqmule to up it to 80 months ago but a decent CPU could handle much higher.
 
So then there's no real worry about the loops spinning faster than MQ2 would allow any macro to run, eh?
 
Yes there is. Its rare but it can happen. MQ2 still has a lot code from 8-9 years ago.
 
To make it clear, I cant recal any freeze up of a single instance of EQ with MQ2 on any of my comps. But I am talking about multiple instances of EQ with respective MQ and each client running its own macro. So peaks can add up pretty heavy if not taken care of beforehand.
 
So... What I'm gathering from this discussion is that, for those interested in having KA maintain control of async plugins and dynamic delays:
The #Turbo feature may not be safe enough for us to hang our hats on, when spinning loops like whiles, and that the current state of MQ2's /while function needs be verified as a stable option.

- - - Updated - - -

Message subject: Re: While Function
From: EqMule
Sent: Tue Jul 01, 2014 8:38 am
To: TheNomadMan

Latest post about this was http://www.macroquest2.com/phpBB3/viewtopic.php?f=48&t=19302
I never did get a reply so I don't know if it works as expected though.
 
Last edited:
I think that's the jest of it. I don't see anyone saying too NOT use them, just be careful how you implement them. You can simulate /while loops with :Labels and /goto, but I was taught to never use /goto and to always program with a top down flow. I know that with MQ2 scripting that not using /goto is impractical.

ctaylor
 
Fork / Mod While functions and MQ2Cast vs Spell Routines

Users who are viewing this thread

Back
Top
Cart