Genbot.mac 12.38 -- Updated 6/4/2004

Post your completed (working) macros here. Only for macros using MQ2Data syntax!

Moderator: MacroQuest Developers

Vexix
Genbot Janitor
Posts: 245
Joined: Sat Apr 17, 2004 10:10 am

Post by Vexix » Tue Jun 01, 2004 11:44 am

Rassilon -- Fixed the ceiling or floor look after returning to anchor thingy.

Oddball -- Thanks for the code fix. Added into botspell.inc.

Blueninja -- Thanks for the comment on stand. I'll change the code from ${Me.State.Equal[SIT]} to ${Me.State.NotEqual[STAND]} and hopefully that will take care of it.

--Vexix

Vexix
Genbot Janitor
Posts: 245
Joined: Sat Apr 17, 2004 10:10 am

Post by Vexix » Tue Jun 01, 2004 12:40 pm

Fez,

Thanks much for the reply. Cool to hear the thinking behind those two vars. I think I know what I'd like to do with them now. SupportStatus will be changed to a DoMelee boolean. (Nah, I'll name it "GetPhysical" instead. ;) ). I'm not sure yet if I'm going to keep CombatStatus or not, but we need some kind of an "aggrolist" variable, with the IDs of all the mobs that have pissed us off. Order should be roughly order to attack. This will work well with a routine I am planning, call SurveyBattle, which will tally up the number of MOBs in camp, and who they are attacking. This will be used for debuff routines, calling evacs, deciding who to heal first, etc.

The cleric thing is prolly because he's attacking current target, and has no memory of what he was fighting before.

I would like to know what you have improved on in in the genbot code. If you could send me a copy of your code with some notes on what you think is good, or a rough explanation, it would be appreciated.

The overuse of /doevents as compensation for process hogging routines is something I'm going to hack apart. Any routine that could take more than half a second should be broken down into component parts. My goal is for there to be only 1 /doevents call in the entire code, and that located in the main loop. Right now I'm targetting SpellSub and RangeSub. Any other particular Subs you think take too much time? We'll separate the Subs into Tasks, and Spells, each with their own step variable. Kind of like: TaskName=LootAll, TaskStep=3, and SpellName=Complete Heal, SpellStep=3. If the Step variable is set to zero, that means it's not doing that task at the moment. Flow will be controlled something like what I've done here:

Code: Select all

Sub PersonalMain 
   /if (${String[ Buffing Fighting ].Find[${TaskName}]}) {
      /call Task-${PerBotState}
   }
/return 

Sub Task-Buffing
    /call ExecCommand batbuff
 /return 

| --------------------------------------------------
| Subroutine of PerPulling
| --------------------------------------------------
Sub Task-Pulling
   /if (${String[|1|2|3|4|5|6|7|8|9|].Find[|${TaskStep}|]}) {
      /goto :GPullState${TaskStep}
   } else {
      /echo PerStateStep = ${TaskStep} -- No corresponding goto found.  Returning.
      /return
   }
:GPullState1  
   /echo Go pull, young man.  Go pull!
   /varset PerAggTemp ${Aggressive} 
   /varset Aggressive 1 
   /varset PerPullList ${String[|]}
   /varset PerAggroList ${String[|]}
   /varset PerPullTurn 1
   /varset PerPullTry 1
   /call PlayFunction "${Zone.ShortName}Pull1 1 cf nopp noz"
   /varset TaskStep 2
   /return
:GPullState2
   | Are we there yet?
   /if (!${PathingFlag}) /varset TaskStep 3
   /return
:GPullState3
   |  Who's available to pull?
   /call PerMakePullList
   /varset TaskStep 4
   /return
/return
I might change from the funky DataVar /goto case statement to /if else chains if that parses faster. Gotta run some speed tests.

A spell queue with prioritization was exactly what I was thinking as well. How did you implement it? I like to use coupled lists with | separators. Arrays are the devil.

Those are my thoughts for now. Just with I had more coding time!

--Vexix

User avatar
Seagreen500
crash test
Posts: 47
Joined: Mon Nov 10, 2003 1:04 am

Post by Seagreen500 » Tue Jun 01, 2004 1:31 pm

I wish you had more coding time. . .

and for myself also. could contribute more.


Great things are happening here !

fez_ajer
a ghoul
a ghoul
Posts: 106
Joined: Fri Apr 23, 2004 6:44 pm
Location: If I was up your ass you'd know where I was...

Post by fez_ajer » Tue Jun 01, 2004 1:36 pm

A spell queue with prioritization was exactly what I was thinking as well. How did you implement it? I like to use coupled lists with | separators. Arrays are the devil.
In a very ugly and partially working way :) I'm using several arrays for it and have built a doubly linked list out of them to allow for easy traversal/insertion/deletion. It may be prettier to manage a coupled text list of array indices to manage the queue though... I'll take a look into that.

One of the problems I ran into with queueing spells is that I needed to queue up the spell cast/success/failure messages with each spell so that they would get squawked when the spell was actually cast as opposed to when it was queued up. I was also storing a priority and a 'recast count' which would retry the spells on failure up to a max count or retry forever if the count was zero.

The other problem I ran into was with the way I do my personal.inc logic... I frequently bot a necro and I change my DoT tactics based on remaining mana/hp and the target remaining hp. Doing this is close on impossible if you just stuff spells into a queue unless you have a way to put conditions on each queued cast. Also, synchronizing spell casts to with other things becomes more problematic (like switching out extended range/buff duration items).

I suppose you could get around this by having a way to block on a spellcast, but if you block in an event you screw the whole thing up again.

Another thing I did do to SpellSub which should be done ASAP IMHO is to add a return status variable like in spellcast.inc. It's important to know that a spell failed with CAST_IMMUNE rather than CAST_RESISTED when you are retrying an aggro-generating dot 3 times ;) Any dead necro-bot can tell you that. I'll try to send you a patch for that soon.
- Fez

El
a ghoul
a ghoul
Posts: 108
Joined: Mon Dec 29, 2003 12:34 pm

Buff recasting times?

Post by El » Tue Jun 01, 2004 7:14 pm

I was playing around with this script last night, using it for powerleveling a lowbie rogue with my mid-level druid. The rogue was not grouped with the druid.

I was seeing some odd behavior with DS buff timings. I was using the 19th level druid DS, and it would often wear off without being refreshed on time. Usually, since I was in combat, I would issue a manual buff command, it would be rebuffed, and then 30-60 seconds later, the druid would recast the DS, as if the original timer was active, but just wrong on the duration of the spell. After some time, I would manually refresh the DS, and it would be as if each had its own timer... I would have the DS cast and recast several times over the course of a minute or so.

So, obviously the macro keeps separate timer lists for each cast of a spell, even if it's the same spell -- I'm not sure that makes sense. Also, for this one spell, it appears that the duration is wrong.

Any ideas?

fez_ajer
a ghoul
a ghoul
Posts: 106
Joined: Fri Apr 23, 2004 6:44 pm
Location: If I was up your ass you'd know where I was...

Post by fez_ajer » Tue Jun 01, 2004 9:02 pm

Yup, this is a problem with MQ2.

See: http://macroquest2.com/phpBB2/viewtopic.php?t=7278

There is a patch. We're trying to get eyes on it and voices behind it so devs will commit it.
- Fez

El
a ghoul
a ghoul
Posts: 108
Joined: Mon Dec 29, 2003 12:34 pm

Post by El » Tue Jun 01, 2004 9:45 pm

As a short term workaround, would it make sense to keep a single timer for the same spell/character combo?

fez_ajer
a ghoul
a ghoul
Posts: 106
Joined: Fri Apr 23, 2004 6:44 pm
Location: If I was up your ass you'd know where I was...

Post by fez_ajer » Tue Jun 01, 2004 11:52 pm

Erm, huh?

You mean a timer for each spell/character combo? How would you know how much time to put on the timer without casting the spell on yourself first?

Honestly, there's no good way of determining the duration without updating the formulas. Even then it won't take into account focus items. If you'd like to help get the new formulas in place, post in the other thread so folks in charge can see that this affects more than just me.

Also, the changes to the duration formula that Cyber posted do pretty well for me here in addition to fixing some bard issues in other macs. If you can compile MQ2, you should be able to try the routine for yourself. The more folks who do (and say so in the other thread) the more chance we have of a dev putting the changes in CVS.
- Fez

Vexix
Genbot Janitor
Posts: 245
Joined: Sat Apr 17, 2004 10:10 am

Post by Vexix » Wed Jun 02, 2004 11:51 am

I think what El is referring to is to enter in manually a duration for your char for that spell. A pain, but it would work.

My druid got toasted today from one of the /doevents in SpellSub setting something wrong, and sending him into an infinite loop. Ouch. So I've moved redoing the SpellSub to the top of my list! Set phazors for ATOMIZE! Basically, I will be using ml2517's SpellCast.inc as a base, and then replacing all of the /delays with /returns. I thought about what I said before about not allowing /delays longer than 5s, and I've changed my mind. I'm going to take out all the /delays entirely. All time should be active processing time. To do this, we'll have a few general timers, SpellTimer and TaskTimer, for instance, which will be pulled out to the main loop, and used to inform the main loop when it's time to go back and check the substep.

That might not sound so clear. Hopefully it'll make sense once I post some code.

Fez, I hope we can pull you back to using the core genbot code. I have a lot of ideas for new features, and I could definitely use some help with bringing it all together. For instance, just stripping out the /delays will touch just about every routine. If I can get a hand with that, things will move faster.

--Vexix

fez_ajer
a ghoul
a ghoul
Posts: 106
Joined: Fri Apr 23, 2004 6:44 pm
Location: If I was up your ass you'd know where I was...

Post by fez_ajer » Wed Jun 02, 2004 12:18 pm

I'll definitely do what I can :)
- Fez

fez_ajer
a ghoul
a ghoul
Posts: 106
Joined: Fri Apr 23, 2004 6:44 pm
Location: If I was up your ass you'd know where I was...

Modified botspell.inc

Post by fez_ajer » Wed Jun 02, 2004 1:24 pm

Vex,

I know you're about to rip apart botspell. Here's some changes to consider before you do:

1) I fixed a couple of typos
2) I fixed the buff command
3) I move the chunk of buff code from Event_timer in botcore.inc into a /call ManageBuffList sub which lives in botspell.inc... Seemed like the thing to do
4) I added CastReturn as a global var which returns the result of the cast
5) I set SpellSub's return value to 0 or 1 on *EVERY* /return including Breakout.... This could be what waxed your drood.

Since there is alot of junk in this, I'm posting the whole file. I diffed my mods versus your latest botspell.inc from page 1. I can't currently test it, but it should work.

***BIG CAPS NOTE TO ALL***

I'm posting this for Vex to use... I use it here myself, and it should be 100% compatible with existing genbot, but I can't be sure. I would strongly urge you all to continue with the base code and wait for mods from Vex.

botspell.inc (fezified)

Code: Select all

|botspell.inc
|Bot spell module.
|Version 12.37-fez
|Date:06/02/2004
|
||**
[botspell]
version=12.37-fez
**||
|

#event Collapse "Your gate is too unstable, and collapses."
#event RootOff "Your Immobilize spell has worn off."
#event NoLOS "You cannot see your target."
#Event CastStart "You begin casting #*#"
#Event CastFizzle "Your spell fizzles!"
#Event CastInterrupt "Your spell is interrupted."
#Event CastInterrupt "Your casting has been interrupted."
#Event CastNoMana "Insufficient Mana to cast this spell!"
#Event CastTooFar "Your target is out of range, get closer!"
#Event Recovered "You haven't recovered yet..."
#event Recovered "Spell recovery time not yet met."
#Event CastResist "Your target resisted #*#"
#Event Distracted "You are too distracted to cast a spell now!"
#Event NoTarget "You must first select a target for this spell!"
#Event Sitting "You must be standing to cast a spell."
#Event NoMem "You do not seem to have that spell memorized."
#Event Stunned "You can't cast spells while stunned!"
#event Stunned "You *CANNOT* cast spells, you have been silenced!"
#event MissedNote "You miss a note, bringing your song to a close!"
#event ImmuneSlow "Your target is immune to changes in its attack speed."
#event ImmuneRoot "Your target is immune to changes in its run speed."
#event NoOverWrite "Your spell would not have taken hold on your target."

Sub Init-Spell
   /declare cmds-SPELL string outer Spell:
   |For each command
   |/call AddCommand "Command Section" "Command Phrase" "Called Sub"
   |Command Section - where the command will be listed in response to the cmd phrase
   |Command Phrase to trigger bot - End User can change to suit prefferences
   |Called Sub - Routine to execute in response to Command Phrase
   /call AddCommand SPELL sn Do-sn
   /call AddCommand SPELL mana Do-mana
   /call AddCommand SPELL evac Do-evac
   /call AddCommand SPELL loadlist Do-loadlist
   /call AddCommand SPELL snt Do-snt
   /call AddCommand SPELL setlompct Do-setlompct
   /call AddCommand SPELL chainnuke Do-chainnuke
   /call AddCommand SPELL chainstun Do-chainstun
   /call AddCommand SPELL buff Do-buff
   /call AddCommand SPELL SelfBuff AddSelfBuff
   /call AddCommand SPELL spellgem Do-spellgem
   /call AddCommand SPELL buffs Do-bufflist
   /call AddCommand SPELL buffq Do-buffqueue
   |/declare Vars
   /declare DefaultSpellSet string outer
   /declare EvacSpell string outer
   /declare DoAgain bool outer FALSE
   /declare StartCast bool outer FALSE
   /declare SpellSlot int outer
   /declare CastTime int outer
   /declare SitAfterCast bool outer FALSE
   /declare LastSn string outer NA
   /declare ReportLom bool outer FALSE
   /declare LomMsg string outer
   /declare DoCanni bool outer FALSE
   /declare DoYaulp bool outer FALSE
   /declare CanniSpell string outer
   /declare YaulpSpell string outer
   /declare ChainNuke string outer
   /declare ChainStun string outer
   /declare ChainStunNum int outer
   /declare IsBard bool outer FALSE
   /declare SpellFail bool outer FALSE
   /declare DelayBeforeSit string outer 3s
   /declare Remem bool outer FALSE
   /declare BuffList[50,2] string outer
   /declare BuffListTimes[50,2] int outer 0
   /declare BuffListCount int outer 0
   /declare SelfBuffList string outer
   /declare SelfBuff[15] string outer
   /declare SelfBuffInt[15,2] int outer 0
   /declare SelfBuffCount int outer 0
   /declare SelfBuffPass int outer 0
   /declare SpellGem int outer
   /declare CTimer timer outer
   /declare OOMtimer timer outer
   /declare LomTimer timer outer
   /declare CannTimer timer outer
   /declare CannAATimer timer outer
   /declare YaulpTimer timer outer
   /declare ChainStunTime timer outer
   /declare BuffListAdvance timer outer
   /declare SitTimer timer outer
   /declare CastResult string outer
   /declare CastImmune bool outer

   /call LoadSetting DelayBeforeSit Spell DelayBeforeSit 3s
   /call LoadSetting SpellGem Spell SpellGem 8
   /call LoadSetting SitAfterCast Spell SitAfterCast 0
   /call LoadSetting DefaultSpellSet Spell DefaultSpellSet Default
   /call LoadSetting EvacSpell Spell EvacSpell NONE
   /call LoadSetting ReportLom Spell ReportLom 0
   /call LoadSetting LomMsg Spell LomMsg "Warning I'm running low on Mana."
   /call LoadSetting CanniSpell Spell CanniSpell Canniblize
   /call LoadSetting DoCanni Spell DoCanni 0
   /call LoadSetting YaulpSpell Spell YaulpSpell yaulp
   /call LoadSetting DoYaulp Spell DoYaulp 0
   /call LoadSetting ChainStun Spell ChainStun "Your Chain Stun Spells sperated with |."
   /call LoadSetting ChainNuke Spell ChainNuke "Your Chain Nuke Spells sperated with |."
   /call LoadSetting SelfBuffList Spell SelfBuffList "Buffs you wish to maintain of yourself separated with |"
   /varset IsBard ${Me.Class.Name.Equal[Bard]}
   /call LoadSetting Remem Spell Remem 0

   /call LoadSelfBuffs
/return

Sub SpellMain
   /if (${DoCanni}) /call CheckCann
   /if (${DoYaulp}) /call CheckYaulp
   /if (${SelfBuffPass}>40) {
      /call CheckSelfBuffs
   } else {
      /varcalc SelfBuffPass ${SelfBuffPass}+1
   }
/return

Sub LoadSelfBuffs
   /declare NewBuff string local
   /declare ArgNum int local 1
   /if (${SelfBuffList.Equal[Buffs you wish to maintain on yourself separated with |]}) /return
   :SelfBuffLoad
      /if (${SelfBuffList.Arg[${ArgNum},|].Length}) {
         /varset NewBuff ${SelfBuffList.Arg[${ArgNum},|]}
         /call AddSelfBuff "${NewBuff}"
      }
      /varcalc ArgNum ${ArgNum}+1
   /if (${SelfBuffList.Arg[${ArgNum},|].Length}) /goto :SelfBuffLoad
/return

Sub ManageBuffList
  /declare counter int local
  /for counter 1 to ${BuffListCount}
     /varcalc BuffListTimes[${counter},1] ${BuffListTimes[${counter},1]}-5
     /if (${BuffListTimes[${counter},1]}<5 && !${Combatstatus}) {
        /call StandardTarget "${BuffList[${counter},1]}"
        /if (${Target.CleanName.Equal[${BuffList[${counter},1]}]}) {
           /echo DBG ${Target.CleanName} is ID ${Target.ID}
           /call SpellSub "${BuffList[${counter},2]}"
           /if (${Macro.Return}==0) /varset BuffListTimes[${counter},1] ${Spell[${BuffList[${counter},2]}].Duration.TotalSeconds}
           /if (${Macro.Return}==1) /varcalc BuffListTimes[${counter},2] ${BuffListTimes[${counter},2]}+1
           /if (${BuffListTimes[${counter},2]}>5) {
              /varset BuffListTimes[${counter},1] 900
              /varset BuffListTimes[${counter},2] 0
           }
        }
     }
  /next counter
  /for counter 1 to 15
     /if (${SelfBuffInt[${counter},1]}> 1) /varcalc SelfBuffInt[${counter},1] ${SelfBuffInt[${counter},1]}-5
  /next counter
  /varset BuffListAdvance 50
/return

|SpellSub
|Main spell casting sub.
|Used to handle all spell casting.  Auto mems spells and handles fizzles.
|Will need to set the DefaultSpellSet var to your default spell set.
|
|Usage /call SpellSub "spellname"
|
Sub SpellSub(string SpellName)
   /varset CastImmune FALSE
   /varset CastResult CAST_CTIMER
   /if (${Me.State.Equal[FEIGN]}) {
     /call ChatOut 5 ${MasterName} "I'm feigning... Not standing to cast"
     /varset CastResult CAST_FEIGNED
     /return 1
   }
   /if ((${Me.Casting.ID} || ${CTimer}>0) && !${IsBard}) /return 1
   /varset CastResult CAST_NOSPELL
   /if (${SpellName.Equal[NA]}) /return 1
   /varset SpellFail 0
   | This is set big to prevent sitting *DURING* the cast
   /if (${SitAfterCast}) /varset SitTimer 1140m
   /If (${Target.Distance}>${Spell[${SpellName}].Range} && ${Spell[${SpellName}].Range}>0) {
      /varset SpellFail 1
      /call ChatOut 7 ${MasterName} "Too far away. "
      /varset CTimer 0
      /varset CastResult CAST_TOOFAR
      /return 1
   }
   /if (${Me.Sitting}) /stand
   /varset Remem 0
   /if (!${IsBard}) {
      /if (${Me.Moving}) {
            /keypress FORWARD
            /keypress BACK
            /delay 1s
      }
      :WaitForStop
      /doevents
      /if (${BreakOut}) /return 1
      /if (${Me.Moving}) {
            /echo moving
            /delay 1s
            /goto :WaitForStop
      }
   }
   /if (${IsBard}) /stopsong
   |Check if character Knows the Spell requested
   /if (${Me.Book[${SpellName}]}<1) {
      /call ChatOut 5 ${MasterName} "Don't know the spell ${SpellName} so failing to cast"
      /goto :SpellFail
   }
   |Check if Spell is mem'd on a gem
   /if (!${Me.Gem[${SpellName}]}) {
      /call ChatOut 3 ${MasterName} "memorizing the spell ${SpellName}"
      /memspell ${SpellGem} "${SpellName}"
      :MemWait
         /if (${BreakOut}) /return 1
         /delay 1
         /if (!${Me.Gem[${SpellName}]}) /goto :MemWait
   }
   /varset SpellSlot ${Me.Gem[${SpellName}]}
   /doevents
   /if (${SpellFail}) /goto :SpellFail
   |Check if spell is ready to cast
   /if (!${Me.SpellReady[${SpellSlot}]}) {
      /echo waiting on refresh
      :refreshwait
         /if (${BreakOut}) /return 1
         /delay 1
         /if (!${Me.SpellReady[${SpellSlot}]}) /goto :refreshwait
   }
   /varset CastTime ${Spell[${SpellName}].MyCastTime.Int}
   /if (!${IsBard}) /varcalc CastTime ${CastTime}+1
   :BeginCast
   /varset SpellFail 0
   /varset DoAgain 0
   /varset StartCast 0
   /call WaitForStart
   :TimerLoop
   /doevents
   /if ((${IsBard})&&(${Combatstatus})) /call RangeSub
   /if (${DoAgain}) /goto :BeginCast
   /if (${SpellFail}) /goto :SpellFail
   /if (${CTimer}>0) /goto :TimerLoop
   /if (${IsBard}) {
      /call Delay 1
   } else {
      /call Delay 2
   }
   /doevents
   /if (${DoAgain}) /goto :BeginCast
   /if (${Remem}) {
      /memspellset ${DefaultSpellSet}
      :loadsploop1
      /delay 1s (!${Window[SpellBookWnd].Open})
      /if (${Window[SpellBookWnd].Open}) /goto :loadsploop1
   }
   /return 0
   :SpellFail
   /varset SpellFail 0
   /if (${Remem}) {
      /memspellset ${DefaultSpellSet}
      :loadsploop2
      /delay 1s (!${Window[SpellBookWnd].Open})
      /if (${Window[SpellBookWnd].Open}) /goto :loadsploop2
   }
   /if ((${Me.Standing})&&(${SitAfterCast})) /sit
   /varset CTimer 0
/return 1

|WaitForStart
|Used by SpellSub to determine when to start spell ObstacleCheck.
Sub WaitForStart
   /cast ${SpellSlot}
   :StartLoop
   /doevents
   /if (${SpellFail}) /return
   /if (${DoAgain}) /return
   /if (!${IsBard} && !${StartCast}) /goto :StartLoop
   /varset CTimer ${Math.Calc[${CastTime}*10]}
/return

Sub Event_CastStart
   /varset CastResult CAST_SUCCESS
   /varset StartCast 1
/return

Sub Event_CastFizzle
   /varset CastResult CAST_FIZZLE
   /call Delay 2
   /varset DoAgain 1
/return

Sub Event_MissedNote
   /varset CastResult CAST_MISSEDNOTE
   /call Delay 2
   /varset DoAgain 1
/return

Sub Event_CastInterrupt
   /varset CastResult CAST_INTERRUPT
   /call Delay 2
   /if (${SpellFail}) /return
   /varset DoAgain 1
/return

Sub Event_Sitting
   /varset CastResult CAST_SITTING
   /stand
   /call Delay 2
   /varset DoAgain 1
/return

Sub Event_CastTooFar
   /varset CastResult CAST_TOOFAR
   /varset SpellFail 1
   /call ChatOut 3 ${MasterName} "Too far away. "
   /varset CTimer 0
/return

Sub Event_ImmuneSlow
   /varset CastImmune TRUE
   /varset CastResult CAST_IMMUNE
   /varset SpellFail 1
   /call ChatOut 3 ${MasterName} "Cannot Slow this Target (Immune)!"
   /varset CTimer 0
/return

Sub Event_ImmuneRoot
   /varset CastImmune TRUE
   /varset CastResult CAST_IMMUNE
   /varset SpellFail 1
   /call ChatOut 3 ${MasterName} "Cannot Root or Snare this Target!"
   /varset CTimer 0
/return

Sub Event_Distracted
   /varset CastResult CAST_DISTRACTED
   /call ChatOut 5 ${MasterName} "I can't cast. I'm too distracted. "
   /varset SpellFail 1
   /varset CTimer 0
/return

Sub Event_NoTarget
   /varset CastResult CAST_NOTARGET
   /varset SpellFail 1
   /call ChatOut 3 ${MasterName} "I don't know what target to cast on. "
   /varset CTimer 0
/return

Sub Event_NoOverWrite
   /varset CastResult CAST_NOOVERWRITE
   /varset SpellFail 1
   /call ChatOut 3 ${MasterName} "The spell won't take hold on the target."
   /varset CTimer 0
/return

Sub Event_NoMem
   /varset CastResult CAST_NOTMEMMED
   /call ChatOut 5 ${MasterName} "That spell is not memed. "
   /varset SpellFail 1
   /varset CTimer 0
/return

Sub Event_RootOff
   /call ChatOut 5 ${MasterName} "Root has worn off. "
/return

Sub Event_CastNoMana
   /varset CastResult CAST_NOMANA
   /if (${Combatstatus} || ${Me.Combat}) {
      /varset SpellFail 1
      /if (${OOMtimer}<=0) {
         /call ChatOut 5 ${MasterName} "I am OOM!"
         /varset OOMtimer 100
         /return
      }
   }
   /if (${OOMtimer}<=0) /call ChatOut 5 ${MasterName} "OOM. Medding... "
   /varset DoAgain 1
   /if (${Me.Standing}) /sit
   /varset OOMtimer 130
   :meddingwait
   /delay 1
   /doevents
   /if (${OOMtimer}>0) /goto :meddingwait
   /sit off
/return

Sub Event_Stunned
   /varset CastResult CAST_STUNNED
   /call ChatOut 5 ${MasterName} "Stunned waiting 3 seconds to try again. "
   /delay 3s
   /varset DoAgain 1
/return

Sub Event_Recovered
   /varset CastResult CAST_NOTRECOVERED
   /call Delay 2s
   /varset DoAgain 1
/return

Sub Event_CastResist
   | Immunity also sends a resist message... BLECH!
   /if (!${CastImmune}) {
     /varset CastResult CAST_RESISTED
     /call ChatOut 3 ${MasterName} "${Target.CleanName} Resisted."
     /varset SpellFail 1
   }
/return

Sub Event_Collapse
   /varset CastResult CAST_COLLAPSED
   /varset DoAgain 1
/return

Sub Event_NoLOS
   /varset CastResult CAST_NOLOS
   /call ChatOut 10 ${MasterName} "I can't see my target. "
   /varset SpellFail 1
   /varset CTimer 0
/return

Sub Event_CastFizzle
   /varset CastResult CAST_FIZZLE
   /call Delay 2
   /varset DoAgain 1
/return

sub CheckSelfBuffs
   /if (${Combatstatus} || ${Me.Combat}) /return
   /declare counter int local
   /varset SelfBuffPass 0
   /for counter 1 to ${SelfBuffCount}
      /if (!${Me.Buff[${SelfBuff[${counter}]}].ID} && ${SelfBuffInt[${counter},1]}<1) {
         /call Target myself
         /call SpellSub "${SelfBuff[${counter}]}"
         /if (${Macro.Return}==1 && ${SelfBuffInt[${counter},2]}<6) {
            /varset SelfBuffInt[${counter},1] 5
            /varset SelfBuffInt[${counter},2] ${SelfBuffInt[${counter},2]}+1
         }
         /if (${Macro.Return}==1 && ${SelfBuffInt[${counter},2]}>=6) {
            /varset SelfBuffInt[${counter},1] 900
            /varset SelfBuffInt[${counter},2] 0
         }
      }
   /next counter
/return

Sub CheckMana
   /if (${LomTimer}<=0) {
      /if (${Me.PctMana}<${LomPct}) {
         /call ChatOut 5 ${MasterName} "${LomMsg}"
         /varset LomTimer 2m
      }
   }
/return

Sub CheckCann
   /if (!${Me.Moving}) {
      /if (${Me.PctMana}<80 && ${Me.PctHPs}>=60 && ${Me.CurrentHPs}>1900 && ${CannAATimer}<=0) {
         /alt activate 47
         /varset CannAATimer 3m
      }
      /if (${Me.PctMana}<95 && ${Me.PctHPs}>=40 && ${CannTimer}<=0) {
         /call SpellSub "${CanniSpell}"
         /varset CannTimer 4s
      }
   }
/return

Sub CheckYaulp
   /if (${Me.Class.ShortName.Equal[PAL]} && (!${Combatstatus} || !${Me.Combat})) /return
   /if (${Me.Class.ShortName.Equal[CLR]} && (!${Combatstatus} || !${Me.Combat}) && ${Me.PctMana}>95) /return
   /if (!${Me.Moving} && ${Me.PctMana}<95 && ${YaulpTimer}<=1) {
      /call SpellSub "${YaulpSpell}"
      /varset YaulpTimer 25s
   }
/return

Sub NextStun
   /if (${BreakOut}) /return
   /if (!${Target.ID}) /return
   :JumpStunSpell
      /if (${Me.Gem[${ChainStun.Arg[${ChainStunNum},|]}]}) {
         /cast "${ChainStun.Arg[${ChainStunNum},|]}"
         /varset ChainStunTime 50
      } else {
         /varcalc ChainStunNum ${ChainStunNum}+1
         /goto :JumpStunSpell
      }
   /varcalc ChainStunNum ${ChainStunNum}+1
   /if (!${ChainStun.Arg[${ChainStunNum},|].Length}) /varset ChainStunNum 1
/return

|||||||||||||||Bot command subs
Sub AddSelfBuff(string newBuff)
   /if (!${Defined[newBuff]}) /return
   /if (${newBuff.Equal[off]}) {
      /varset SelfBuffCount 0
      /return
   }
   /varcalc SelfBuffCount ${SelfBuffCount}+1
   /varset SelfBuff[${SelfBuffCount}] ${newBuff}
/return

Sub Do-sn(string newSpell)
   /call Assist "${MasterName}"
   /if ( !${Defined[newSpell]} && ${LastSn.Equal[NA]}) /return
   /if (!${Defined[newSpell]}) /varset CommandParam "${LastSn}"
   /call ChatOut 1 "${MasterName}" "Casting ${CommandParam}  on ${Target.CleanName}"
   /if (${CommandParam.Arg[1].Lower.Equal[item]}) {
      /varset ${CommandParam} ${CommandParam.Right[-${CommandParam.Arg[1].Length}]}
      /cast item "${CommandParam}"
   } else {
      /call SpellSub "${CommandParam}"
   }
   /varset LastSn ${CommandParam}
/return

Sub Do-mana
   /if (!${Me.Class.CanCast}) /return
   /declare RoundMana int local ${Math.Calc[${Math.Calc[${Me.PctMana}/5].Int}*5].Int}
   /if (${RoundMana}==100) {
     /call ChatOut 2 ${MasterName} "fm"
   } else {
     /call ChatOut 2 ${MasterName} "${RoundMana}m"
   }

/return

Sub Do-loadlist(string Spellset)
   /if (!${Defined[Spellset]}) /return
   /memspellset ${Spellset}
/return

Sub Do-evac
   /if (${EvacSpell.NotEqual[None]}) /call ChatOut 5 ${MasterName} "Moving to you and casting ${EvacSpell}!"
   /call Do-moveto ${MasterName}
   /call Delay 2s
   /if (${EvacSpell.NotEqual[None]})  /call SpellSub "${EvacSpell}"
/return

Sub Do-itemcast
   /if (!${Defined[Param0]}) /return
   /if (${Me.Sitting}) {
      /stand
      /delay 3
   }
   /call Assist "${MasterName}"
   /cast item "${CommandParam}"
   /call ChatOut 3 ${MasterName} "Using ${CommandParam} on ${Target.CleanName}"
/return

Sub Do-snt
   /if (!${Defined[Param0]}) /return
   /if (${Param0.Equal[on]} && ${LastSn.NotEqual[NA]}) /return
   /declare SpellNameParam string local ${Param0}
   /declare TargetName string local
   /declare ParamCount int local 1
   /if (${Param0.Equal[on]}) {
      /varset SpellNameParam ${LastSn}
      /goto :Do-sntTargetStart
   }

   :Do-sntSpellLoop
      /if (${Defined[Param${ParamCount}]}) {
         /if (${Param${ParamCount}.Equal[on]}) /goto :Do-sntTargetStart
         /varset SpellNameParam ${SpellNameParam} ${Param${ParamCount}}
         /varcalc ParamCount ${ParamCount}+1
         /goto :Do-sntSpellLoop
      }
   :Do-sntTargetStart
   /varcalc ParamCount ${ParamCount}+1
   /if (${Defined[Param${ParamCount}]}) {
      /varset TargetName ${Param${ParamCount}}
      /varcalc ParamCount ${ParamCount}+1
      :Do-sntTargetLoop
         /if (${Defined[Param${ParamCount}]}) {
            /varset TargetName ${TargetName} ${Param${ParamCount}}
            /varcalc ParamCount ${ParamCount}+1
            /goto :Do-sntTargetLoop
         }
      /echo Target SHOULD be ${TargetName}
      /call StandardTarget "${TargetName}"
      /if (!${Target.ID}) {
         /call ChatOut 5 ${MasterName} "I failed to get a target."
         /return
      }
   }
   /if (${SpellNameParam.Arg[1].Lower.Equal[item]}) {
      /varset SpellNameParam ${SpellNameParam.Right[-${SpellNameParam.Arg[1].Length}]}
      /cast item "${SpellNameParam}"
   } else {
      /call SpellSub "${SpellNameParam}"
   }
   /if (${SitAfterCast}) /varset SitTimer ${DelayBeforeSit}
   /varset LastSn ${CommandParam}
/return

Sub Do-setlompct
   /if (!${Defined[Param0]}) /return
   /varset LomPct ${Param0}
   /call ChatOut 3 ${MasterName} "I'll let you know if I get below ${LomPct} percent mana"
/return

Sub Do-ChainNuke
   /declare NukeNum int local 1
   /call StandardTarget "${CommandParam}"
   :ChainNukeLoop
      /if (${BreakOut}) /return
      /if (!${Target.ID}) /return
      /if (${Me.Gem[${ChainNuke.Arg[${NukeNum},|]}]}) /cast "${ChainNuke.Arg[${NukeNum},|]}"
      /varcalc NukeNum ${NukeNum}+1
      /if (!${ChainNuke.Arg[${NukeNum},|].Length}) /varset NukeNum 1
   /goto :ChainNukeLoop
/return

Sub Do-ChainStun
   /call StandardTarget "${CommandParam}"
   /if (!${Target.ID}) /return
   /varset ChainStunNum 1
   /call NextStun
/return

Sub Do-buff(string buffCommand)
   /if (!${Defined[buffCommand]}) /return
   /if (${buffCommand.Equal[off]}) {
      /varset BuffListCount 0
      /return
   }
   /declare TargetName string local
   /declare SpellName string local
   /declare CmdLen int local ${buffCommand.Length}
   /declare StrPos int local ${buffCommand.Find[ on ]}
   | Is there an 'on' clause?
   /if (${StrPos}) {
     | Grab the target and spell name
     /varset SpellName ${buffCommand.Left[${Math.Calc[${StrPos}-1]}]}
     /varset TargetName ${buffCommand.Right[${Math.Calc[${CmdLen}-${StrPos}-3]}]}
   } else {
     /varset SpellName ${buffCommand}
     /varset TargetName ${MasterName}
   }
   /if (${TargetName.Equal[me]}) {
     /varset TargetName ${MasterName}
   } else /if (${TargetName.Equal[yourself]} || ${TargetName.Equal[${Me.CleanName}]}) {
      /call AddSelfBuff "${SpellName}"
      /return
   }
   /call StandardTarget "${TargetName}"
   /call Delay 5
   /if (!${Target.ID}) {
      /call ChatOut 5 ${MasterName} "I failed to get a target."
      /return
   }
   /call SpellSub "${SpellName}"
   /if (${Macro.Return}==0) {
      /declare NewBuff local
      /varset NewBuff ${BuffListCount}
      /varcalc NewBuff ${NewBuff}+1
      /varset BuffList[${NewBuff},1] ${Target.CleanName}
      /varset BuffList[${NewBuff},2] ${SpellName}
      /varset BuffListTimes[${NewBuff},1] ${Spell[${SpellName}].Duration.TotalSeconds}
      /varset BuffListCount ${NewBuff}
      /varset BuffListAdvance 50
   }
   /if (${SitAfterCast}) /varset SitTimer ${DelayBeforeSit}
/return

Sub Do-SpellGem
   /if (!${Defined[Param0]}) {
      /call ChatOut 3 ${MasterName} "I Gem ${SpellGem} when I need to mem new spells."
      /return
   }
   /varset SpellGem ${Param0}
   /call ChatOut 3 ${MasterName} "I will now use Gem ${SpellGem} when I need to mem new spells."
/return

Sub Do-bufflist
   /declare counter int local
   /call ChatOut 1 ${MasterName} "I've still got..."
   /for counter 1 to 15
       /if (${Me.Buff[${counter}].ID}) /call ChatOut 1 ${MasterName} "${Me.Buff[${counter}]}"
   /next counter
/return

Sub Do-buffqueue
   /declare counter int local
   /if (${BuffListCount}) {
     /for counter 1 to ${BuffListCount}
        /call ChatOut 3 ${MasterName} "${BuffList[${counter},2]} needs to be refreshed on ${BuffList[${counter},1]} in ${BuffListTimes[${counter},1]} seconds"
     /next counter
   }
   /if (${SelfBuffCount}) {
     /for counter 1 to ${SelfBuffCount}
        /call ChatOut 3 ${MasterName} "${SelfBuff[${counter}]} needs to be refreshed on me in ${Me.Buff[${SelfBuff[${counter}]}].Duration.TotalSeconds} seconds"
     /next counter
   }
/return
event_timer from botcore.inc

Code: Select all

Sub Event_timer(string TimerName,string OldValue)
   /if (${TimerName.Equal[SitTimer]}) {
      /if (${Me.Standing}) /sit
   } else /if (${TimerName.Equal[ChainStunTime]}) {
      /call NextStun
   } else /if (${TimerName.Equal[BuffListAdvance]}) {
      /call ManageBuffList
   }
/return
- Fez

User avatar
Seagreen500
crash test
Posts: 47
Joined: Mon Nov 10, 2003 1:04 am

Post by Seagreen500 » Wed Jun 02, 2004 11:29 pm

I have done some work on the genbotdoc.txt file.
Some commands should be removed.

If any of the commands don't work the way I've described them.
Then they should be changed so that they do.

I hope to test all the commands, and clean it up for a final post in a week or so. I also hope to keep up with the changelog and post changes and new commands as they are implemented.

Vex - I made some very slight changes to your comments.
I went through the rest of the document and made whatever syntax and grammar changes I thought were necessary.

Code: Select all

|GenbotDoc.txt
|Manual for the Generic bot macro
|Version 12.37
|Date:06/03/2004
|
||**
[genbotDoc]
version=12.37
**||
|

Welcome to Genbot, probably the easiest way to multibox characters in Everquest.

To start genbot type /macro genbot <mastername> with <mastername> being the name of the character that will be in control of the bot.

By default your bot will respond to any command the master character /tells him.
By changing the values of listengroup, listenchat (in genbot_botname.ini), or by sending the toggle commands listenGroup, listenChat
you can start the Bot listening for commands sent either in group or in a chat channel. 
The bot will still only respond to characters on it's list of masters but will do it in these other channels.

Additionally if you have the IRC plugin properly set up on your system the bot can listen in an IRC channel for commands.

By default the Bot will respond to it's Master in Tells. By changing the INI value ChatIn or by sending the command ChatIn,
the bot can respond in tells, group, channel or IRC. (IRC requires functional IRC Plugin)

The first time you run Genbot on a character the macro will create a default INI file. (genbot_botname.ini)
You probably want to start the macro and /endmacro it the first time so that you check/modify the INI settings.

SELF BOT COMMANDS:
   /echo genbot - Send commands to yourself. EXAMPLE /echo genbot sit
   /gb - alias for /echo genbot. EXAMPLE /gb sit
   
MASTER TO BOT COMMANDS:
   /tell bot command <parameter> <parameter> ... 
 * IF checkname is false, you can use group and chat commands like this;
   /1 command <parameter> <parameter> ... 
   /g command <parameter> <parameter> ... 
 * IF checkname is true, then use group and chat commands like this;
   /1 bot command <parameter> <parameter> ... 
   /g bot command <parameter> <parameter> ... 

MISC:
   shortcuts <shortcutname> - Display what <shortcutname> does, default will list all your shortcuts.
	
   lootup - Commands bot to loot the corpse of the last target.
   lootall - Commands bot to attempt to loot all corpses around it.
   
   setvar - Sets a var to new setting
   rptvar - Commands bot to reply with the current value of a variable
   
   target <Me|Yourself|TargetName|clear> - Causes the bot to change it's target;
			- <Me> targets master 
			- <Yourself> bot targets itself
			- <TargetName> name of target\
			- <clear> clears your current target
   notarget - Commands bot to clear it's target.
   face - Commands bot to face it's current target.
   assist - Commands bot to assist the master, how the bot acts when assisting is controlled by toggles.
   
   accept - Command bot to accept the current group invite.
   invite - Command bot to invite it's current target to group.
   reject - Command bot to reject the current group invite.
   
   camp - Commands bot to camp out.
   consent <playername> - Commands bot to give consent to <playername>, default will consent it's master.
   reload - Commands bot to re-init the macro
   trade - Commands bot to hit the trade button in a trade window.
   yesres - Commands bot to hit yes on a ressurection confirm box.  
   
MOVEMENT:
   anchor - Causes the bot to remember it's current location and return there between fights.
   anchorradius <distance> - Tells bot to stop moving when it is within <distance> of its anchor point.
   door - Causes the bot to attempt to open the closest door.
   duck - Commands the bot to duck.
   
   follow <blank|name> - Command bot to follow the master or his designated target;
			- <blank>	- if master has no target, tells the bot to follow you.
			- <blank>	- if master has a target, tells the bot to follow master's target.
			- <name>	- tells the bot to follow name, name can be your name,pcname or npcname.
			- EXAMPLE /tell bot follow
   followmode <1|2|3> - Sets how the bot follows;
			- <1> (Combat mode) is facing you constantly and attempting to move directly towards you.
			- <2> (AdvPathFollow) is plotting the path of it's target, and then following that path
			- <3> (Eq's /follow) is the native /follow command used by EQ (group members only?)
			- EXAMPLE /tell bot followmode 2
   stay - Commands bot to stop following
   pause - Pauses the advanced follow command
   
   moveto <Me|Loc|TargetName> - commands the bot to move to a point, then stop;
			- <Me>			moves bot to you
			- <225,-300>	moves bot to the location 225 , -300
			- <%T>			moves bot to your target
			- EXAMPLE. /tell bot moveto Me
   movetomode <1|2> - Sets how the bot movesto;
			- <1> (normal) Genbot Anchor type
			- <2> (AdvPathGoto)
			- EXAMPLE. /tell bot movetomode 1
			
   mount - Commands bot to get on it's mount (defined in genbot_botname.ini)
   stop - Forces the bot to stop, will duck, dismount and stop moving.
			

COMMUNICATION:
   checkname - if set to true, bot will only respond to commands in group or chat if the command is preceeded with <botname>
   exp - Commands bot to reply with it's current exp percent
   norelay - Stops bot from sending received tells to it's master
   relay - Starts bot sending received tells to it's master
   saytarget - The bot will tell you what it's currently Targeting.
   reportbuffs - Commands bot to tell it's master a list of currently active buffs.
   cmds - Asks bot to return a list of available commands
   verbosity - Changes what level chat the bot actually sends to it's master.
   chatin <channelname> - Changes what channel the bot will use for replying to it's master.


COMBAT:
   attack - Commands bot to start attacking
   noattack - Commands bot to Stop attacking
   
   behind - Commands bot to move behind it's current target
   getbehind - Commands bot to move behind the specified target
   
   petattack - Assist's master for target and then issues the bot /pet attack command.
   
   hide - Commands bot to use it's Hide ability
   rmod <distance> - Changes relative distances in combat
   rset <distance> - Changes the range settings used in combat
   shield - Commands bot to /shield it's master
   sneak - Commands bot to use it's sneak ability
   
   
CASTING:
   buff <spell> - Commands bot to cast <spell> on it's master
   buff <spell> on <target> - Commands bot to cast buff <spell> ON <target>, bot will automatically refresh it.
   chainnuke - Commands bot to start chaining nukes on <target>
   chainstun - Commands bot to start chaining stuns on <target>
   evac - Commands bot to move to it's master and cast it's evac spell
   heal - Commands bot to heal <target>
   itemcast <itemname> - Commands bot to trigger the specified item.
   loadlist <listname> - Commands bot to load a spell list
   mana - Commands bot to reply with it's current mana
   
   sn <spell|item> - Commands bot to cast the specified spell on master's target.
		<spell> - will cast <spell> on master's target.
		<item> - will right click item on master's target.
   snt <spell|item> on <target> - Commands bot to cast <spell|item> ON <target>,if "on <target>" is not specified, it will cast on bot's target
		<spell> - snt brell's stalwart shield on PlayerName
		<item> - snt Regent Symbol of Innoruuk on NPCName
		
   spellgem <number> - This sets the spell gem used when bot is required to memorize a new spell. (1 to 8)
   setlompct <percent> - Sets the mana percent at which the bot will report low mana
   
   settankheal <spell> - Sets the spell used to heal tanks, if no <spell> is specified then the current spell is reported.
   setcasterheal <spell> - Sets the spell used to heal casters, if no <spell> is specified then the current spell is reported.
   setpetheal <spell> - Sets the spell used to heal pets, if no <spell> is specified then the current spell is reported.
   setdefaultheal <spell> - Sets the spell used for the heal command, if no <spell> is specified then the current spell is reported.
   setpatchheal <spell> - Sets the spell used to patch heal, if no <spell> is specified then the current spell is reported.

   setcasterhealpct <percent> - Sets the HP % at which caster's will be healed, if <percent> is not specified, the current % is reported.
   settankhealpct <percent> - Sets the HP % at which tank's will be healed, if <percent> is not specified, the current % is reported.
   setpethealpct <percent> - Sets the HP % at which pet's will be healed, if <percent> is not specified, the current % is reported.

   watchtarget - Commands bot to monitor the hit points of <target>. Needs to have autoheal on for target to be healed.
   resetwatch - Commands bot to reaquire the ID's of it's targets, good to execute after zoning


TOGGLES:  COMMAND - DESCRIPTION - DEFAULT
Most toggles can have there default starting value set in your genbot_botname.ini file
One example,when we are telling the bot to bash during combat, is the line: DoBash=1

   listengroup - Toggles bot listening for commands in group chat - OFF
   listenchat - Toggles bot listening for commands in the Chat Channel - OFF
 
   aona - Toggles bot attacking targets on assist - OFF
   bona - Toggles bot attacking from behind on assist - OFF
   petona - Toggles bot doing /pet attack on assist - OFF
   beagg - Toggles bot automatically fighting back when attacked - OFF
   puller - Controls if the bot will return to it's anchor point when attacked - OFF
   autoengage - Controls if the bot will close and engage when in combat - OFF
   autobehind - Controls if the bot will automatically attempt to fight behind all targets during combat - OFF 
   
   backstab - Toggles bot using backstab while fighting - OFF
   bash - Toggles bot using Bash during fighting - OFF
   disarm - Toggles bot using disarm while fighting - OFF
   evade - Toggles bot using Hide during fighting - OFF
   flyingkick - Toggles bot using flyingkick while fighting - OFF
   frenzy - Toggles bot using frenzy while fighting - OFF
   incite - Toggles bot using incite while fighting - OFF
   kick - Toggles bot using kick while fighting - OFF   
   slam - Toggles bot using Slam during fighting - OFF
   taunt - Toggles bot using taunt while fighting - OFF

   archery - Toggles bot using archery while fighting - OFF
   run - Toggles run setting on bot
   traps - Toggles bot trying to find and disarm traps - OFF

   aftercastsit - Controls if the bot will sit after casting spells - OFF
   autoheal - Controls if the bot will automatically use heals on group and watch targets - OFF
   autohealpets - Controls if the bot will automatically use heals on pets - OFF
   patchheal - Controls if the bot will automatically patch heal targets below half their heal percent - OFF
   reportlom - Controls if the bot will automatically report when it's low on mana - OFF
   yaulp - Toggles if bot will use yaulp (Yaulp spell is defined in genbot_botname.ini) when low on mana - OFF
   canni - Toggles if bot will cannibalize when low on mana - OFF
   
   
OBSOLETE COMMANDS
These commands will be removed, all of them can be replaced by the native command support now built into genbot.

"Implemented /commands natively into genbot. 
Any command to the bot which begins with a / will be executed by the bot. 
For example, "/wave" or "/yell" or "/target id 1234" or "/call MySubroutine" are all valid bot commands." -	Vexix

   afk <message> - Turn bot's afk on with optional <message>.			USE: /tell bot /afk <message>
   autoinv - Commands bot to use the /autoinv command					USE: /tell bot /autoinv
   dismount - Commands bot to /dismount.								USE: /tell bot /dismount
   disc <discname> - Commands bot to fire the specified /disc.			USE: /tell bot /disc <discname>
   group <message> - Commands the bot to /gsay <message>.				USE: /tell bot /g <message>
   petback - Commands bot to execute it's /pet back command.			USE: /tell bot /pet back
   petguard - Commands bot to execute it's /pet guard command.			USE: /tell bot /pet guard
   random - Commands bot to /ran.										USE: /tell bot /random <value>
   say <message> - Commands the bot to /say <message>.					USE: /tell bot /say <message>
   sit - Makes bot sit													USE: /tell bot /sit
   stand - Makes bot stand												USE: /tell bot /stand
   tell <name> <message - Commands the bot to /tell <name> <message>.	USE: /tell bot /tell <name> <message>



SHORTCUTS - Vexix
Genbot also includes shortcuts, which can run any everquest, macroquest, or genbot command.
For instance, the following would be a valid Genbot .ini section:

[Shortcuts]
eyepatch=itemcast Eyepatch of Plunder
nukeit=sn Lure of Fire
sowon=buff spirit of wolf on
uberaa=/alt activate 33
takemehome=/echo play:PoKtoNexxus 1 f nopp z;NexxustoBazaar 10 cr nopp z;BazaartoShadHav 1 cf nopp noz 

Shortcuts give an easy way to abbreviate long commands, like interzone advpaths, and also have some really cool possibilities for controlling parties. 
For instance, you could have your leader say nukeit in groupsay, and each of the PCs in the party could respond with an appropriate nuke as defined 
in their .ini file. The wizzy Lures it, the enchanter smacks it with his DD+stun, the druid casts wildfire, and the warrior, um, slams it!

Similarly, if you called evacuate, with the .ini's set up right, the druid could cast his evac, the cleric might automatically heal the druid 
to make sure he survives, and the warrior could hit AE taunt to pull aggro from the druid. Fun, fun!

To show what shortcuts you have defined in your .ini file while running the macro, I added the shortcuts command. 
Type "shortcuts" for a list of available shortcuts, and type "shortcuts name_of_shortcut" to see what that particular shortcut does.

Shortcuts can be used to do some very cool stuff.  For instance, shortcuts can also call other shortcuts.  
If the above "mark" shortcut had the " on" removed to allow it to cast on the current target instead of expecting you to provide one, then:

Mark=snt Mark of the righteous|snt Mark of kings|/target clear

Then you could make another shortcut:

markparty=/target clear|/keypress F1|markon|/keypress F2|markon|/keypress F3|markon|/keypress F4|markon|/keypress F5|markon|/keypress F6|markon

Which would buff your entire party for you.  If you didn't have 6 people in your party, it would still try to target them and cast, 
but it would immediately get an error and time out, so no real loss.

Likewise this could be done for items, but in order to do so, a /delay command to account for the casting time would need to be included, 
since the /itemcast command doesn't wait for a response.  To shrink your entire party use:

shrink=/itemcast "cobalt bracer"|/delay 8s|/target clear
shrinkparty=/target clear|/keypress F1|shrink|/keypress F2|shrink|/keypress F3|shrink|/keypress F4|shrink|/keypress F5|shrink|/keypress F6|shrink

Unfortunately, this shortcut would still wait after trying to all 6 party members, even if you only had 2.

NOTE:  You can use DataVar expressions in shortcuts, but be warned they will be evaluated by the first MQ2 char they hit.  
In otherwards, if you are running MQ2, and give your bot the command /say My name is ${Me.Name}, the bot will say, 
My name is MasterName, since the datavar is evaluated by the master MQ2.  If you're not running MQ2, and give the same command, 
the bot will say, "My name is Bot."

CAUTIONS:
With great power, comes great responsibility.  ;)  
Since shortcuts can call other shortcuts, it's possible to create shortcuts which would endlessly loop.  
I don't recommend that.  :P

Shortcuts take full control of your bot during execution.  
It would be easy to make a long cleric buff shortcut chain which would cast every buff on every member of your party, 
but remember that until your buff chain finished, your cleric bot will do no healing or moving.  
I hope nothing spawns or wanders into your party! 

User avatar
grimjack
Macro Author
Macro Author
Posts: 525
Joined: Thu Nov 07, 2002 6:51 am
Contact:

Post by grimjack » Thu Jun 03, 2004 4:13 am

Vexix wrote:Fez -- Thanks for the clarification on the SitTimer 19h thing. ;) As I'm working through the code, it certainly helps to hear some history of why things were done in a certain way.

Mort -- Sorry about the rework! Hopefully the increased flexibility of these shortcuts will be worth it.

--Vexix
If you need any more information on why some things where done some ways, feel free to PM me. I may or may not remember or it may be something that was done after I stopped playing and others took over genbot, but I'll be glad to help any way I can.

Thanks
GrimJack
When they come to me, they're in trouble, or they want some. I bust people out of prison, hunt down vampires, fight alien gods -- All the fun jobs people are too squeamish or too polite to do themselves.

Call me a mercenary. Call me an assassin. Call me a villain. I am all that and more.

My name's John Gaunt, but out on the streets of Cynosure, I am called...
GrimJack

User avatar
grimjack
Macro Author
Macro Author
Posts: 525
Joined: Thu Nov 07, 2002 6:51 am
Contact:

Post by grimjack » Thu Jun 03, 2004 4:16 am

Vexix wrote:Actually, the /face without the nolook has it's use. The reason Rassilon is looking up after his mobs is probably because he's fighting tall mobs, like giants. If you're fighting little things, afterwards you'll be looking at the ground.

I kinda like looking at what I'm fighting, so what I'll try to do is just add a /keypress Home after the battle is done. Seeing if I can put that in now.

--Vexix
The main reason look was used was so that you could follow with levitate one or underwater.

Thanks
GrimJack
When they come to me, they're in trouble, or they want some. I bust people out of prison, hunt down vampires, fight alien gods -- All the fun jobs people are too squeamish or too polite to do themselves.

Call me a mercenary. Call me an assassin. Call me a villain. I am all that and more.

My name's John Gaunt, but out on the streets of Cynosure, I am called...
GrimJack

User avatar
grimjack
Macro Author
Macro Author
Posts: 525
Joined: Thu Nov 07, 2002 6:51 am
Contact:

Post by grimjack » Thu Jun 03, 2004 4:35 am

fez_ajer wrote:One big one that causes all kinds of oddities is that SpellSub can be called from events as well as from the main loop. That means that if you call /doevents from inside SpellSub (like we do) another command can call SpellSub, which does some wierd things for sure. I've tried to fix this here by two things:

Another option is to do what spellcast.inc does and only call the /doevents that you need for casting spells to work (ie: Just call /doevents for the fizzle and spellcast checks)

Does all this stuff need to happen in Genbot? Prolly not. I did some really odd stuff just to make it work here. In alot of cases, what I tried was a truly horrendous idea :)

The above info *IS* useful though, because when you start to think about how individual events can affect the Main Loop, and visa versa, you can start to debug alot of the wierder things that can happen with your bots.

Sorry this is long, I've got about a fifth of bourbon in me... Memorial day and all!
The Spellsub was designed so that I could interupt something being cast at any time. That is one of the reasons there are so many /doevents in the Sub. I think at one time I also had it set up to cancel the current spell if another was called from the master(the idea was if you where calling for another spell it must be more important). If it was a heal, it would resume after the spell called for finished(in the case of auto-heals) since the autoheal sub would be entered again and the bot would once again notice someone needed healed. Things have probably changed quite a bit since then but that was the original intent.

Thanks
GrimJack
When they come to me, they're in trouble, or they want some. I bust people out of prison, hunt down vampires, fight alien gods -- All the fun jobs people are too squeamish or too polite to do themselves.

Call me a mercenary. Call me an assassin. Call me a villain. I am all that and more.

My name's John Gaunt, but out on the streets of Cynosure, I am called...
GrimJack