Moderator: MacroQuest Developers
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
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.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.



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
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
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!
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.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
The main reason look was used was so that you could follow with levitate one or underwater.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 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.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!