• 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
MQ2React

Release MQ2React

Anyone have one that allows you to remove a buff if you get join a raid?
I can never remember to take off Righteousness.
 
Could /react list show the enabled ones in green ?

#3 -- Reacts are triggered every 50 pulses or so. That's done to reduce load on the system. I plan to offer a configuration on how often they're checked in the future.
Would be nice if this is per react e.g configure it to summon some axes for zerks. do not need to recheck those but once an hour or so.

Removed "ExampleReact" but when I load the plugin on new toons it still adds "ExampleReact: enabled" for that toon.
 
Last edited:
Could /react list show the enabled ones in green ?


Would be nice if this is per react e.g configure it to summon some axes for zerks. do not need to recheck those but once an hour or so.

Removed "ExampleReact" but when I load the plugin on new toons it still adds "ExampleReact: enabled" for that toon.

#1) Yah it probably could. Next big push as I think the bugs are worked out, is to do a UX pass and add some more printouts and some colors and such.
#2) I don't have plans to enable per-react custom check times as currently that defeats the purpose of the "sleeping" react for 50 pulses to save folks CPU. If I had per react pulse times I'd needed to check every pulse if their specific duration was up. I do have plans to let folks configure the global pulse sleep period at some point.
#3) ExampleReact is working as intended. It hard codes it there to make sure you have a representation of a working structure. It then disables itself on execution. This is all part of the code that makes sure you have a properly formatted react file you can work off of if you clobber it for some reason.
 
For #2, I had a similar idea when I was thinking about this initially. You'd probably still skip pulses for that scenario (a pulse is very fast) but it's a savings of processing overall since instead of every 50 pulses needing to check something you know isn't going to happen for an hour, you just check that condition when it's time.

For #3, one idea might be to only create that if there's an issue (or nothing exists to begin with). Not processing was a good move, but building on that from a "clean file" standpoint.
 
My may concern with #2 is avoiding looking through the list of reacts to begin with to save some of that time as well. It's certainly easy to add in the option to the config to do it per react at some point. I think this would be more beneficial if we could relate a pulse to some conceivable period of time (as most folks don't think in pulses).

#3 is potentially doable in the future. Basically we _could_ set a local bool that just sets itself to true if we create the file. We look for that when we write out the example react. Right now it just assumes if it doesn't see ExampleReact "there's an issue".

EDIT: In general I'm not discounting them but the biggest priority on my list when getting back to mq2react is fixing double-quote escaping in serialization and get the UX pass. #3 will probably be included in that as well. #2 is useful but not particularly high on my list at the moment.
 
Yes, the config I was thinking of would be in time, both from the user side and the plugin side. You don't need to relate pulse to that, but you would need to handle time in the pulse.
 
#3) ExampleReact is working as intended. It hard codes it there to make sure you have a representation of a working structure. It then disables itself on execution. This is all part of the code that makes sure you have a properly formatted react file you can work off of if you clobber it for some reason.

Im fine with that, actually meant the ExampleReact code is not in the file anymore and it actuall adds an enabled condition but not the example.
Have not looked at the code which havoc this broken file will cause, seems none using it like this.
e.g (changed toon names, actual file)
Code:
  newtoon:
    ExampleReact: enabled
  othertoon:
    ExampleReact: enabled
  zerker:
    BERcomponent: enabled
    ExampleReact: disabled
    Summon2Inv: enabled
    SummonDemolisher: enabled
    SummonMangler: enabled
    SummonVindicator: enabled
globals:
  NotCasting: "!${Me.Casting.ID}"
  Resting: >-
    ${Me.CombatState.NotEqual[COMBAT]} && !${Me.Invis} && !${Me.Casting.ID}
    && !${Me.Moving}
reacts:
  BERcomponent:
    action: /bc Need Masterwork Axe Components
    condition: >-
      ${React.Global[Resting]} && ${FindItemCount[Masterwork Axe Components]}
      < 50
  Summon2Inv:
    action: /autoinv
    condition: "${Cursor.ID} && ${Cursor.Name.Find[Axe of]}"
  SummonDemolisher:
    action: /disc Axe of the Demolisher
    condition: "${React.Global[Resting]} && ${FindItemCount[Axe of the Demolisher]}<300"
  SummonMangler:
    action: /disc Axe of the Mangler
    condition: "${React.Global[Resting]} && ${FindItemCount[Axe of the Mangler]}<300"
  SummonVindicator:
    action: /disc Axe of the Vindicator
    condition: "${React.Global[Resting]} && ${FindItemCount[Axe of the Vindicator]}<300"


There is a timing issue that end up leaving just the example behind:
If I have 6 loaded in and do /react reload it rewrites the file but since more than 1 is writing to the file it messes up
Need to implement some file locks before writing.
 
Last edited:
Im fine with that, actually meant the ExampleReact code is not in the file anymore and it actuall adds an enabled condition but not the example.
Have not looked at the code which havoc this broken file will cause, seems none using it like this.
e.g (changed toon names, actual file)
Code:
  newtoon:
    ExampleReact: enabled
  othertoon:
    ExampleReact: enabled
  zerker:
    BERcomponent: enabled
    ExampleReact: disabled
    Summon2Inv: enabled
    SummonDemolisher: enabled
    SummonMangler: enabled
    SummonVindicator: enabled
globals:
  NotCasting: "!${Me.Casting.ID}"
  Resting: >-
    ${Me.CombatState.NotEqual[COMBAT]} && !${Me.Invis} && !${Me.Casting.ID}
    && !${Me.Moving}
reacts:
  BERcomponent:
    action: /bc Need Masterwork Axe Components
    condition: >-
      ${React.Global[Resting]} && ${FindItemCount[Masterwork Axe Components]}
      < 50
  Summon2Inv:
    action: /autoinv
    condition: "${Cursor.ID} && ${Cursor.Name.Find[Axe of]}"
  SummonDemolisher:
    action: /disc Axe of the Demolisher
    condition: "${React.Global[Resting]} && ${FindItemCount[Axe of the Demolisher]}<300"
  SummonMangler:
    action: /disc Axe of the Mangler
    condition: "${React.Global[Resting]} && ${FindItemCount[Axe of the Mangler]}<300"
  SummonVindicator:
    action: /disc Axe of the Vindicator
    condition: "${React.Global[Resting]} && ${FindItemCount[Axe of the Vindicator]}<300"


There is a timing issue that end up leaving just the example behind:
If I have 6 loaded in and do /react reload it rewrites the file but since more than 1 is writing to the file it messes up
Need to implement some file locks before writing.

So I'm aware of those race conditions as well. Putting blocking locks in a pulse worries me because you're now locking the EQ client. An easier solution would be to not reload all at once but do a /timed with Math.Rand as an interval. That will disperse your reloads without effecting client performance with blocking the thread.

Eventually I may add something but it'll require deep conversation with those who better understand the client/ mq2 interactions. Near term it is easily solved on the user side as a workaround.
 
So I'm aware of those race conditions as well. Putting blocking locks in a pulse worries me because you're now locking the EQ client. An easier solution would be to not reload all at once but do a /timed with Math.Rand as an interval. That will disperse your reloads without effecting client performance with blocking the thread.

Eventually I may add something but it'll require deep conversation with those who better understand the client/ mq2 interactions. Near term it is easily solved on the user side as a workaround.
Or don't write to the yaml when doing a reload. Kind of unexpected behaviour
 
Or don't write to the yaml when doing a reload. Kind of unexpected behaviour
Due to the way the mini-yaml parser/serializer works, this isn't an option. It'll cause de-sync issues.

Believe it or not I painfully think through this stuff when I first engineered the plugin and made conscious decisions that certain things -- at least for the time being -- have to be the user's problem.
 
Hey @drwhomphd

Was wondering is there a way to do /react toggle Cheetah

That way I can set one social button to send a message to my other character to enable or disable a react? So you don't need to do both commands. Unless something like this exists already.
 
You can do something like a '/${If[${React.Enabled[reactname]},react disable reactname,react enable reactname]}' (may be typos, do an /echo in game first :P )
 
See I knew one of you code wizards would figure it out. Thank you @Rooster
 
Finally got around to testing this.

/${If[${React.Enabled[Cheetah]},react disable Cheetah,react enable Cheetah]}
does not change anything
/echo /${If[${React.Enabled[Cheetah]},react disable Cheetah,react enable Cheetah]}
pipes out into the MQ2 window, /react enable Cheetah or /react disable Cheetah depending on what would be opposite of current.

Doing "/${If[${React.Enabled[Cheetah]},react disable Cheetah,react enable Cheetah]}" shows no response in mq2 window and changes nothing. I can live without just a cool thought I had.

Oh and typing /react enable Cheetah and enter does turn it on, and disable does work in turning it off, just the if thing not working weirdly.
 
Hey,
I really like this idea. I ended up not using MQ2Melee because it came with stuff that it would just do and I found that sometimes trying to figure out what was causing some type of unwanted behavior (your ini or mq2melee) just got frustrating so I just unloaded MQ2Melee and never looked back. This looks like it wont do anything you dont specifically tell it to do.

Now the questions. I read through the Overview and the discussion here and thought, easy. Then I went to plug in what I wanted the program to do and the confusion started. First question, when you bring up the .yaml there is an example. I am not sure what parts of the example you need to keep and what parts are what you need to change for my custom behavior. I am guessing the Dark Blue stuff you keep and the black and grey stuff you can customize (other than maybe renaming "GlobalExample" and "ExampleReact" to your behavior discription. I am using Notepad++ if that makes a difference in where the colors come from. Am I correct here?

Second question is concerning "globals". If I dont have any Globals can I delete that or does the "global" command need to stay in the .yaml folder even if it is blank? Is the "global" always automatically "enabled" or can it be toggled with "GlobalExample" (or my global term) for each character? Seems logically, there would be no reason to toggle a global since then it would by definition not be global but didnt see anything definitive on this.

Thirdly, I saw in some post where someone was referring to putting things in the correct .yaml syntax and the response was "Use the CODE tag before and then /CODE after. Put those words in brackets [ ]". This threw me a curve since I saw nothing here about putting syntax and none of the examples have that type of structure. Is this something happening behind the scenes and all of use end users have to do is get the spacing and indents right? Or am I missing something?

I have a simple thing I am trying to do that only has 3 behaviors I want to happen. I have yet to get it to work and the above questions are what is holding me up. I know this is probably simple stuff for some, but for those of us that are lucky to get things already written for us to run correctly this is a steep learning curve. As I have said before, I am better at breaking other peoples stuff than creating anything on my own. So that said, any hand holding on this stuff would be appreciated. I tried to be as descriptive with my questions as I could but not knowing much on this topic I may not have provided enough info or background. If that is the case, I would be happy to provide more info. Thanks, AnotherJohn
 
Last edited:
Hey,
I really like this idea. I ended up not using MQ2Melee because it came with stuff that it would just do and I found that sometimes trying to figure out what was causing some type of unwanted behavior (your ini or mq2melee) just got frustrating so I just unloaded MQ2Melee and never looked back. This looks like it wont do anything you dont specifically tell it to do.

Now the questions. I read through the Overview and the discussion here and thought, easy. Then I went to plug in what I wanted the program to do and the confusion started. First question, when you bring up the .yaml there is an example. I am not sure what parts of the example you need to keep and what parts are what you need to change for my custom behavior. I am guessing the Dark Blue stuff you keep and the black and grey stuff you can customize (other than maybe renaming "GlobalExample" and "ExampleReact" to your behavior discription. I am using Notepad++ if that makes a difference in where the colors come from. Am I correct here?

Second question is concerning "globals". If I dont have any Globals can I delete that or does the "global" command need to stay in the .yaml folder even if it is blank? Is the "global" always automatically "enabled" or can it be toggled with "GlobalExample" (or my global term) for each character? Seems logically, there would be no reason to toggle a global since then it would by definition not be global but didnt see anything definitive on this.

Thirdly, I saw in some post where someone was referring to putting things in the correct .yaml syntax and the response was "Use the CODE tag before and then /CODE after. Put those words in brackets [ ]". This threw me a curve since I saw nothing here about putting syntax and none of the examples have that type of structure. Is this something happening behind the scenes and all of use end users have to do is get the spacing and indents right? Or am I missing something?

I have a simple thing I am trying to do that only has 3 behaviors I want to happen. I have yet to get it to work and the above questions are what is holding me up. I know this is probably simple stuff for some, but for those of us that are lucky to get things already written for us to run correctly this is a steep learning curve. As I have said before, I am better at breaking other peoples stuff than creating anything on my own. So that said, any hand holding on this stuff would be appreciated. I tried to be as descriptive with my questions as I could but not knowing much on this topic I may not have provided enough info or background. If that is the case, I would be happy to provide more info. Thanks, AnotherJohn
Start by adding Reacts via the in-game command line. Doing so will populate the yaml file in the correct syntax. You can do everything you want from in the game.
 
Start by adding Reacts via the in-game command line. Doing so will populate the yaml file in the correct syntax. You can do everything you want from in the game.

Thanks, that is a good idea. If I add anymore reacts I will give that a try. I have continued to play around a bit and I think I got it to mostly work. I didnt have to do anything with /code command so thinking that post was misleading. I am still not sure about the global situation. I think the example is default set to ignore which is good since my reacts are to happen during combat and I was afraid the prefilled example would have to be changed but guessing that it does not at this point.
 
/code command
That was in response to someone sharing an example react in this thread because they didn't use the code blocks to format their post like so:
Code:
here is some code
They just pasted the raw text into their post. YAML is sensitive to white spaces, meaning the double space indents you see at the beginning of a line in the file actually mean something. Generally, programming languages don't care about indents, it's only there for visual clarity.
 
Ahh, so the other stuff is sort of "behind the scenes" for us non coders. I just plugged in my statements at the appropriate indents and it seems to be working with limited testing. I need to get a few more toons qualified for the instance it is to work in.
 
Finally got around to testing this.

/${If[${React.Enabled[Cheetah]},react disable Cheetah,react enable Cheetah]}
does not change anything
/echo /${If[${React.Enabled[Cheetah]},react disable Cheetah,react enable Cheetah]}
pipes out into the MQ2 window, /react enable Cheetah or /react disable Cheetah depending on what would be opposite of current.

Doing "/${If[${React.Enabled[Cheetah]},react disable Cheetah,react enable Cheetah]}" shows no response in mq2 window and changes nothing. I can live without just a cool thought I had.

Oh and typing /react enable Cheetah and enter does turn it on, and disable does work in turning it off, just the if thing not working weirdly.


Sorry I missed this

but make your key "/docommand /${If[${React.Enabled[Cheetah]},react disable Cheetah,react enable Cheetah]}"

Keeping in mind any named you have for the react will be cast sensitive (though you should of seen an error if that was the case for you)
 
${Me.CombatState.Equal[COMBAT]} && ${Me.Standing} && !${Me.Moving} && ${React.Global[NotCasting]} && ${Group.Member[0].MainTank} && ${Spell.Duration[Clinging Darkness]} > 40

I am building this in MQ2 React and trying to get it to cast the spell with 40secs or less left on the duration. I can get it to spam but not under the conditions and I would like.
 
Based on that condition raidien, it's going to spam because you are checking that the spell duration is GREATER than 40 sec. Flip your > to a < and try
 
Based on that condition raidien, it's going to spam because you are checking that the spell duration is GREATER than 40 sec. Flip your > to a < and try
So when i do that all it does is chain cast the spell as soon as it is available.

So > is never cast. This way < is just spams.
 
Given current discussion of combat and casting above...

A general best practice I'd suggest is start working the general "environment" conditions together in a Global. So you may have Globals for:
OutOfCombat
InCombat
CastIdle

That way you can reuse these across reacts as well.

Also -- always create backups of your last known good mq2react yaml.
 
iam new to MQ2react and was trying to create my first condition. but i got a problem with one condition for my chanter. Getting the "error unparsable in calculation R"

here is the cond

INI:
Manadrain:
    action: "/cast Theft of Thought"
    condition: >-
      ${Select[${Target.Class.ShortName}, ENC,CLR,WIZ,DRU,SHM,NEC,MAG]}&&
      ${Me.PctMana} > 30 &&
      ${Target.PctHPs} < 60 &&
      ${Target.PctHPs}> 0 &&
      ${React.Global[NotCasting]}

maybe someone can help me with that.... thanks a lot

Update: Problem solved got a spelling error in global condition
 
Last edited:
So, when you /bcaa //plugin mq2react it'll erase your .yaml. Thankfully I keep backups :D
There's a race condition that gets triggered occasionally I believe and I need to write a wrapper around the yaml library's serializer or some such. I've been meaning to get back around and tighten those things up. There's a reason the plugin still says Beta and keep backups of your yaml in the information page. :-)
 
The occasional need to replace the yaml just gives me a reason to work on my reacts! Thanks for all the work on this plugin, I love it.
 
Interferences with kissassist_12001 : Description see my post in: Kissassist Beta
when I load the plugin mq2react the 2 toons which have active reacts wont run kissassist anymore.

If someone doubt its maybe an erratic react causing the probs, here my reacts
[CODE lang="yaml" title="Reacts"]globals:
GlobalExample: "${Me.CombatState.NotEqual[COMBAT]} && ${Me.PctHPs} <= 25"
IC: "${Me.CombatState.Equal[COMBAT]}"
NIC: "${Me.CombatState.NotEqual[COMBAT]}"
NmoveNinvNsit: "!${Me.Moving} && !${Me.Invis} && !${Me.Sitting}"
NotCasting: "!${Me.Casting.ID}"
TNamed: "${Target.Named}"
Tank: "${Group.Member[0].MainTank}"
reacts:
BrdSelos:
action: /alt activate 3704
condition: "!${Me.Buff[Selo's Accelerato].ID} && !${Me.Invis} && !${Me.Sitting}"
ClickBP:
action: "/useitem ${InvSlot[Chest].Item.Name}"
condition: "${React.Global[IC]} && ${React.Global[TNamed]} && ${Cast.Ready[${InvSlot[Chest].Item.Name}]}"
EtherealArrows:
action: "/useitem Huntsman's Ethereal Quiver"
condition: >-
${FindItemCount[=Ethereal Arrow]} < 50 && ${FindItemCount[Huntsman's
Ethereal Quiver]} == 1
ExampleReact:
action: >-
/multiline ; /echo Default Example react Disables itself when you're
at 100%HP and out of Combat ; /delay 5 ; /react disable ExampleReact
condition: "${Me.PctHPs} == 100 && ${Me.CombatState.NotEqual[COMBAT]}"
GoDBuy:
action: /alt buy 5304
condition: "${AltAbility[Glyph of Destruction (115+)].CanTrain}"
GoDUse:
action: /alt act 5304
condition: "${Me.AAPoints} > 200 && ${Me.AltAbilityReady[Glyph of Destruction(115+)]}"
JoinTask:
action: /notify ConfirmationDialogBox Yes_Button leftmouseup
condition: >-
${Window[ConfirmationDialogBox].Child[TextOutput].Text.Find[join
the shared task]}>0
MagPetWard:
action: /alt activate 2066
condition: >-
!${Me.PetBuff[Second Wind Ward]} && !${Me.Casting.ID} && ${React.Global[NmoveNinvNsit]}
&& ${React.Global[IC]}
ShdAASnare:
action: /alt activate 826
condition: >-
${Me.CombatState.Equal[COMBAT]} && ${React.Global[NmoveNinvNsit]}
&& ${React.Global[NotCasting]} && ${React.Global[Tank]} && (${Target.PctHPs}
< 75) && ((${Target.BuffDuration[Encroaching Darkness].TotalSeconds}
< 35) && (${Target.BuffDuration[Entombing Darkness].TotalSeconds}
< 35)) && ${Target.Type.Equal[NPC]} && ${Me.AbilityReady[Encroaching
Darkness]}
ShdCeriseBlade:
action: /disc Cerise Blade
condition: >-
${Me.CombatAbilityReady[${Spell[Cerise Blade].RankName}]} && ${React.Global[IC]}
&& ${Target.PctHPs}>50 && ${React.Global[TNamed]}
ShdThwart:
action: "/disc ${Spell[Thwart].RankName}"
condition: "${Me.CombatAbilityReady[${Spell[Thwart].RankName}]} && ${React.Global[IC]}"
ShmCheetah:
action: /alt activate 939
condition: "!${Me.Buff[Communion of the Cheetah].ID} && ${React.Global[NmoveNinvNsit]}"
ShmEpic:
action: /useitem Blessed Spiritstaff of the Heyokah
condition: >-
!${Me.Casting.ID} && ${Me.CombatState.Equal[COMBAT]} && !${Me.Invis}
&& ${FindItemCount[=Blessed Spiritstaff of the Heyokah]} && ${Target.PctHPs}>50
&& ${Me.ItemReady[Blessed Spiritstaff of the Heyokah]}
ShrinkPet:
action: /useitem Curious Companion Compactor
condition: "${Pet.Height} > 2.04"
Taunt:
action: /doability Taunt
condition: >-
${Me.CombatState.Equal[COMBAT]} && ${Me.Standing} && ${React.Global[NotCasting]}
&& ${React.Global[Tank]} && ${Me.TargetOfTarget.ID}!=${Me.ID} &&
${Target.Type.Equal[NPC]}
[/CODE]
 
Followup:
there must be an error on atleast one of the reacts causing the errormessages at kissassist

I disabled all reacts but the shd's Thwart and kissassist works without problems, having mq2react loaded on all toons.
Goging to narrow down the error, reactivating the reacts one by one.
 
next step:
react: "ShdCeriseBlade" does not cause any problems
react: "ClickBP" as soon as activated, kissassist continues to throw error messages
...

leaving ClickBP off for now, continue to check the others
 
Release MQ2React

Users who are viewing this thread

Back
Top
Cart