genbot.mac Generic Bot macro for any class. V8 with ini

A forum for you to dump all the macros you create, allowing users to use, modify, and comment on your work.

Moderator: MacroQuest Developers

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

Post by grimjack » Tue Dec 02, 2003 6:37 am

Ok here is an example of autoblast.

Code: Select all

   /varset Commands(0,46) autoblast
   /varset ArrayPers 46


Ini section:

Code: Select all

   /declare BlastPct global
   /varset BlastPct "$ini(@IniFile,"Personal",BlastPct)"
   /if "@BlastPct"=="NOTFOUND" {
      /ini "@IniFile" Personal BlastPct 70
      /varset BlastPct 70
   }
   /declare AutoBlast global
   /varset AutoBlast "$ini(@IniFile,"Personal",AutoBlast)"
   /if "@AutoBlast"=="NOTFOUND" {
      /ini "@IniFile" Personal AutoBlast 0
      /varset AutoBlast 0
   }
   /declare BlastSpell global
   /varset BlastSpell "$ini(@IniFile,"Personal",BlastSpell)"   
   /if "@BlastSpell"=="NOTFOUND" /ini "@IniFile" Personal BlastSpell "Spell used with autoblast"
New PersonalMain section:

Code: Select all

Sub PersonalMain
   /if n @ReportLom==1 /call CheckMana
   /if n @AutoBehind==1 {
      /if n @Combatstatus==1 {
         /if $target()==TRUE {
            /if n $distance($calc($target(y)-$cos($target(heading))*10),$calc($target(x)-$sin($target(heading))*10))>6 {
               /call Do-behind
            }
         }
      }
   }
   /if n @Supportstatus==1 {
      /if "$target(name,clean)"=="@FollowTarget" {
         /varset Supportstatus 0
         /return
      }
      /if n @AutoBlast==1 {
         /if "$target()"=="TRUE" {
            /if n $target(hp,pct)<=@BlastPct {
               /call ChatOut 5 @MasterName "Blasting %t. with @BlastSpell."
               /call SpellSub "@BlastSpell"
            }
         }
      }
   }        
/return

And a command to toggle it in game.

Code: Select all

Sub Do-autoblast
   /if n @AutoBlast==1 {
      /call ChatOut 5 @MasterName "Auto Blast is now off."
      /varset AutoBlast 0
      /return
   }
   /if n @AutoBlast==0 {
      /call ChatOut 5 @MasterName "Auto Blast is now on."
      /varset AutoBlast 1
      /return
   }
/return 
Untested but it should work.

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

JimJohnson
a grimling bloodguard
a grimling bloodguard
Posts: 1299
Joined: Sat Oct 11, 2003 6:00 am

Post by JimJohnson » Tue Dec 02, 2003 8:36 am

doesnt loop maybe I put it in wrong..

Code: Select all

/varset Commands(0,54) autoblast 
/varset ArrayPers 54 

Code: Select all

Sub SetupPersonalVars
   /declare BlastPct global 
   /varset BlastPct "$ini(@IniFile,"Personal",BlastPct)" 
   /if "@BlastPct"=="NOTFOUND" { 
      /ini "@IniFile" Personal BlastPct 70 
      /varset BlastPct 70 
   } 
   /declare AutoBlast global 
   /varset AutoBlast "$ini(@IniFile,"Personal",AutoBlast)" 
   /if "@AutoBlast"=="NOTFOUND" { 
      /ini "@IniFile" Personal AutoBlast 0 
      /varset AutoBlast 0 
   } 
   /declare BlastSpell global 
   /varset BlastSpell "$ini(@IniFile,"Personal",BlastSpell)"    
   /if "@BlastSpell"=="NOTFOUND" /ini "@IniFile" Personal BlastSpell "Spell used with autoblast"
   /declare FireSpell global 
   /varset FireSpell "$ini(@IniFile,"Personal",FireSpell)" 
   /if "@FireSpell"=="NOTFOUND" /ini "@IniFile" Personal FireSpell "Fire Spell" 
   /declare IceSpell global 
   /varset IceSpell "$ini(@IniFile,"Personal",IceSpell)" 
   /if "@IceSpell"=="NOTFOUND" /ini "@IniFile" Personal IceSpell "Ice Spell" 
   /declare NukeSpell global 

replaced the old Sub PersonalMain and replaced with

Code: Select all

Sub PersonalMain 
   /if n @ReportLom==1 /call CheckMana 
   /if n @AutoBehind==1 { 
      /if n @Combatstatus==1 { 
         /if $target()==TRUE { 
            /if n $distance($calc($target(y)-$cos($target(heading))*10),$calc($target(x)-$sin($target(heading))*10))>6 { 
               /call Do-behind 
            } 
         } 
      } 
   } 
   /if n @Supportstatus==1 { 
      /if "$target(name,clean)"=="@FollowTarget" { 
         /varset Supportstatus 0 
         /return 
      } 
      /if n @AutoBlast==1 { 
         /if "$target()"=="TRUE" { 
            /if n $target(hp,pct)<=@BlastPct { 
               /call ChatOut 5 @MasterName "Blasting %t. with @BlastSpell." 
               /call SpellSub "@BlastSpell" 
            } 
         } 
      } 
   }        
/return 
and just put Sub Do-autoblast at the end

Code: Select all

Sub Do-autoblast 
   /if n @AutoBlast==1 { 
      /call ChatOut 5 @MasterName "Auto Blast is now off." 
      /varset AutoBlast 0 
      /return 
   } 
   /if n @AutoBlast==0 { 
      /call ChatOut 5 @MasterName "Auto Blast is now on." 
      /varset AutoBlast 1 
      /return 
   } 
/return 

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

Post by grimjack » Tue Dec 02, 2003 9:51 am

JimJohnson wrote:doesnt loop maybe I put it in wrong..

Code: Select all

/varset Commands(0,54) autoblast 
/varset ArrayPers 54 

Code: Select all

Sub SetupPersonalVars
   /declare BlastPct global 
   /varset BlastPct "$ini(@IniFile,"Personal",BlastPct)" 
   /if "@BlastPct"=="NOTFOUND" { 
      /ini "@IniFile" Personal BlastPct 70 
      /varset BlastPct 70 
   } 
   /declare AutoBlast global 
   /varset AutoBlast "$ini(@IniFile,"Personal",AutoBlast)" 
   /if "@AutoBlast"=="NOTFOUND" { 
      /ini "@IniFile" Personal AutoBlast 0 
      /varset AutoBlast 0 
   } 
   /declare BlastSpell global 
   /varset BlastSpell "$ini(@IniFile,"Personal",BlastSpell)"    
   /if "@BlastSpell"=="NOTFOUND" /ini "@IniFile" Personal BlastSpell "Spell used with autoblast"
   /declare FireSpell global 
   /varset FireSpell "$ini(@IniFile,"Personal",FireSpell)" 
   /if "@FireSpell"=="NOTFOUND" /ini "@IniFile" Personal FireSpell "Fire Spell" 
   /declare IceSpell global 
   /varset IceSpell "$ini(@IniFile,"Personal",IceSpell)" 
   /if "@IceSpell"=="NOTFOUND" /ini "@IniFile" Personal IceSpell "Ice Spell" 
   /declare NukeSpell global 

replaced the old Sub PersonalMain and replaced with

Code: Select all

Sub PersonalMain 
   /if n @ReportLom==1 /call CheckMana 
   /if n @AutoBehind==1 { 
      /if n @Combatstatus==1 { 
         /if $target()==TRUE { 
            /if n $distance($calc($target(y)-$cos($target(heading))*10),$calc($target(x)-$sin($target(heading))*10))>6 { 
               /call Do-behind 
            } 
         } 
      } 
   } 
   /if n @Supportstatus==1 { 
      /if "$target(name,clean)"=="@FollowTarget" { 
         /varset Supportstatus 0 
         /return 
      } 
      /if n @AutoBlast==1 { 
         /if "$target()"=="TRUE" { 
            /if n $target(hp,pct)<=@BlastPct { 
               /call ChatOut 5 @MasterName "Blasting %t. with @BlastSpell." 
               /call SpellSub "@BlastSpell" 
            } 
         } 
      } 
   }        
/return 
and just put Sub Do-autoblast at the end

Code: Select all

Sub Do-autoblast 
   /if n @AutoBlast==1 { 
      /call ChatOut 5 @MasterName "Auto Blast is now off." 
      /varset AutoBlast 0 
      /return 
   } 
   /if n @AutoBlast==0 { 
      /call ChatOut 5 @MasterName "Auto Blast is now on." 
      /varset AutoBlast 1 
      /return 
   } 
/return 
Did you edit the ini settings and turn it on? Also how are you trying to get it to nuke? Currently when you call assist it will watch the mob to 70 percent then start nuking.
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

ml2517
a grimling bloodguard
a grimling bloodguard
Posts: 1216
Joined: Wed Nov 12, 2003 1:12 am

Post by ml2517 » Tue Dec 02, 2003 6:07 pm

Thanks Grimjack :D

JimJohnson
a grimling bloodguard
a grimling bloodguard
Posts: 1299
Joined: Sat Oct 11, 2003 6:00 am

Post by JimJohnson » Tue Dec 02, 2003 7:37 pm

hehe yea I turned it on in the ini and I changed it to 90 % to start nuking. use Bow or SEWs so I dont really have agro issues and the spell I want to chain nuke is low agro. i will redo it and try agian might just been a stupid mistake on my part

uglyshaman

Post by uglyshaman » Tue Dec 02, 2003 11:01 pm

This work with a Jaundiced Bone Bracer?

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

Post by grimjack » Wed Dec 03, 2003 1:10 am

uglyshaman wrote:This work with a Jaundiced Bone Bracer?
This as in what?

The code I posted for autoblast will not use items as is. You would not need to change it too terrably much to get that functionality, however.

On a side note I like how autonuke is working at home so once I tweak it a bit more I'll be adding it to the example personal.inc(basicly the one I use). I'm going to add an option so you can set a pct the bot will stop nuking at. For instance if the target is at 3 percent and your nuke takes 7 seconds... no point in nuking.

Next on my list is making a Mana Robe/Mana Stone sub.

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

uglyshaman

Post by uglyshaman » Wed Dec 03, 2003 11:08 am

Aye I just mean, after the shaman slows the mob, he starts auto-clicking his equipped JBB until the mob is at 10% life, at which point he stops.

uglyshaman

Post by uglyshaman » Wed Dec 03, 2003 11:12 am

Ok very dumb question...

I've played with the macro some and was easily able to understand the commands you send to the bot (follow, invis, etc) - and thank you Grim for your help on this. My question is, is most of the functionality built upon sending commands to the bot in order to get them to perform actions? Just making sure I understand. Ie: in order to get a shaman to stand, cast Malo, pause a couple of seconds, Cast Slow (autodetect if it is resisted and recast if necessary), watch the tank's health, and JBB appropriately, im trying to determine if that is a multitude of commands sent from the "master" or if can all be tied into one command.

My apologies for my very limited intellect :P

mackster
a ghoul
a ghoul
Posts: 95
Joined: Mon Sep 09, 2002 3:02 pm

Post by mackster » Wed Dec 03, 2003 12:19 pm

uglyshaman wrote:Ok very dumb question...

I've played with the macro some and was easily able to understand the commands you send to the bot (follow, invis, etc) - and thank you Grim for your help on this. My question is, is most of the functionality built upon sending commands to the bot in order to get them to perform actions? Just making sure I understand. Ie: in order to get a shaman to stand, cast Malo, pause a couple of seconds, Cast Slow (autodetect if it is resisted and recast if necessary), watch the tank's health, and JBB appropriately, im trying to determine if that is a multitude of commands sent from the "master" or if can all be tied into one command.

My apologies for my very limited intellect :P

As it stands now, you'd have to send individual commands to cast slow and malo etc. You could tie it into 1 hokey, something like (very generic example)

/t bot cast malo
/pause 20
/t bot cast slow

The /pause would be because I've found that rapid tells sometimes wont go thru to your bot.

Or you could create a custom command in the macro itself to slow and malo in one shot if you knew how.

uglyshaman

Post by uglyshaman » Wed Dec 03, 2003 2:12 pm

Grim - thanks for your reply. It looks like all that would be required to have the bot use a clickable object instead of a spell in a loop (such as a Jaundiced Bone Bracer) would be to replace...

Code: Select all

/call SpellSub "@BlastSpell"
with a /press 6 command (6 is my hotkey for JBB).


Was thinking it would be neat if it could be triggered with a autoblast command from the "master" and then ended in the same fashion with a tell, in the event the bot is needed for another reason (heal, etc).

Unfortunately, I'm not sure how to integrate that in.

Also, would a line such as the one below be appropriate for checking to see if the bot is already chain casting the item, so that it doesn't generate tons of the "You cannot use that command while casting" string...

Code: Select all

if $char(casting)==TRUE /goto :jbb
Thanks for your patience - still learning.

Achy Wrists
a lesser mummy
a lesser mummy
Posts: 36
Joined: Wed Aug 27, 2003 4:17 pm

Post by Achy Wrists » Wed Dec 03, 2003 4:31 pm

I was thinking that it would be very cool to tie blue ninja's ae rezz macro into this so that I could send a command to my cleric to ae rezz. The original macro is here: http://macroquest2.com/phpBB2/viewtopic.php?t=3804

After looking at blue ninja's code, I decided that it would be best to make his click.mac a click.inc instead of trying to add it to personal.inc because of it's size and complexity. Ok, so don't laugh at my sophomoric efforts, but this is what I have so far.

In genbot.mac:

Code: Select all

#define personal-array 0 
#define botcore-array 1 
#define botcombat-array 2 
#define botspell-array 3 
#define bothealer-array 4 
[color=red]#define click-array 5[/color]
#include botcore.inc 
#include botspell.inc 
#include botcombat.inc 
#include bothealer.inc 
#include personal.inc 
[color=red]#include click.inc[/color]
#turbo 40 

Sub Main 
   /zapvars 
   /declare MasterCount global 
   /declare ArrayCore global 
   /declare ArraySpell global 
   /declare ArrayComb global 
   /declare ArrayHeal global 
   /declare ArrayPers global 
   [color=red]/declare ArrayClick global [/color]
   /declare IniFile global 
   /varset IniFile "genbot_" 
   /varcat IniFile $char(name) 
   /varcat IniFile ".ini" 
   |Core variables 
   /call SetupCoreVars 
   |Spell Module Variables 
   /call SetupSpellVars 
   |Combat Module Variables. 
   /call SetupCombatVars 
   |Healer Module Variables. 
   /call SetupHealerVars 
   |Personal Module Variables. 
   /call SetupPersonalVars 
   [color=red]|Click Module Variables. 
   /call SetupClickVars [/color]
   /if $defined(Param0)==FALSE { 
      /echo Usage: /macro generic <Master Name1> <Master Name2>... 
      /endmacro 
   } 
   /varset MasterCount 0 
   :MasterLoop 
   /if $defined(Param$int(@MasterCount))==TRUE { 
      /varset MName($int(@MasterCount)) @Param$int(@MasterCount) 
      /varadd MasterCount 1 
      /goto :MasterLoop 
   } 
   /varsub MasterCount 1 
   /varset MasterName @MName(0) 
|||This is where the commands the bot can take is set up 
   /call CoreCommands 
   /call SpellCommands 
   /call CombatCommands 
   /call HealerCommands 
   /call PersonalCommands 
   [color=red]/call ClickCommands[/color]
   :MainLoop 
   /doevents 
   |||Sub from bothealer.inc 
   /call CheckGrpHealth 
   ||| Sub From bothealer.inc 
   /call PalGrpHealChk 
   ||| Sub From bothealer.inc 
   /call PalHealChk 
   |||Sub from botcombat.inc 
   /call Combatcheck 
   |||Sub from botcombat.inc 
   /if n @Combatstatus==0 { 
      /if n $DoTraps==1 /call TrapFinder 
   } 
   /if n @Combatstatus==1 /call RangeSub 
   /if n @Combatstatus==1 /call MeleeAbility 
   /if n @Combatstatus!=1 { 
      /if n @Supportstatus!=1 { 
         /if n @IsAnchored==0 { 
            /if n @Afollow==1 { 
               /target @FollowTarget 
               /call Do-moveto foo @FollowTarget 
            } 
         } 
      } 
      /if n @IsAnchored==1 { 
         /if n $distance(@AnchorX,@AnchorY)>@AnchorRadius { 
            /call MoveToAnchor 
         } else /if n @SitAfterCast==1 { 
            /if $char(state)==STAND /sit 
         } 
      } 
   } 
   /if $combat==TRUE { 
      /if $target()==TRUE { 
         /if "$target(name,clean)"!="$char(name)" { 
            /if n @AutoEngage==1 /varset Combatstatus 1 
         } 
      } 
   } 
   /call PersonalMain 
   /doevents 
   /varset CmdArrayNum 0 
   /goto :MainLoop 
/return
In click.inc ( which is really click.mac with my attempted changes )

Code: Select all

| Click.mac - v2.21 - Resurrect corpses around you - by blueninja 
|    Resurrects all corpses within a radius using the cleric epic or spell 
|    Resurrects high priority classes first as defined in the ini file 
| 
|    Usage: 
|       /macro click [radius] [only] [con/nocon] [racecheck/noracecheck] [useblacklist/noblacklist] 
|                    [usespell/useepic] [sit/stand] [spellname] <nameofspell> [spellslot] <X> [prioritygroup0] 
|                    [prioritygroup1] [prioritygroup2]... 
|       /macro click buildraces 
|           [radius]                   - set radius to look for corpses in, default value is in ini file 
|           [only]                     - stop ressing after corpses in priority groups have been ressed 
|           [con/nocon]                - toggle /consider to test if corpse is pc or npc 
|           [racecheck/noracecheck]    - toggle check for race to test if corpse is pc or npc 
|                                        (requires ini file) 
|           [useblacklist/noblacklist] - toggle check for blacklisted corpses 
|                                        (requires ini file) 
|           [usespell/useepic]         - use epic or spell to resurrect 
|           [sit/stand]                - toggle sitting while not casting to regen mana 
|           [spellname] <nameofspell>  - name of spell to use if using spell 
|           [spellslot] <X>            - spell gem number to use for spell if using spell 
|           [prioritygroupX]           - names of groups to res before others 
| 
|           [buildraces]               - update list of player races in ini file 
| 
|    Example: 
|       /macro click 200 nocon dps healers 
|       /macro click 200 only cr 
|       /macro click usespell 150 only cr spellname resurrection spellslot 5 
|       /macro click buildraces 
| 
|    Make sure you set CLICKINIFILE a few lines down to a valid filename 
|    You probably want to run this with '/filter macros enhanced' to avoid targeting spam 

#turbo 

|Make sure you set this to point to a valid location 
#define CLICKINIFILE "c:\t\datafiles\ini\click.ini" 
#define MEMDELAY 30 
#define DEFAULTSPELL Reviviscence 

#event interrupt "Your spell is interrupted" 
#event notequipped "You cannot use this item unless it is equipped." 
#event notmemmed "You do not seem to have that spell memorized." 
#event willdecay "This corpse will decay in" 
#event restime "This corpse's resurrection time will expire in " 
#event corpsetooold "This corpse is too old to be resurrected." 
#event clickedoldcorpse "This player cannot be resurrected. The corpse is too old." 
#event corpseexpire "This corpse is waiting to expire." 
#event couldnotrez "You were unable to restore the corpse to life, but you may have success with a later attempt." 
#event youmustbestanding "You must be standing to cast a spell." 
#event fizzle "Your spell fizzles!" 
#event oom "Insufficient Mana to cast this spell" 


[color=red]Sub SetupClickVars

/return

Sub ClickCommands
   /varset Commands(5,0) rezz 
   /varset Commands(5,1) aerezz 
   /varset ArrayClick 2 
/return

Sub TellCmds-click 
   /declare counter local 
   /declare cmds local 
   /varset cmds "" 
   /for counter 0 to @ArrayHeal 
      /varcat cmds "@Commands(4,@counter), " 
   /next counter 
   /msg @MasterName @cmds 
/return[/color]

Sub Event_restime 
|Got a message that the corpse has time left on rez timer 
   /varset ispccorpse 1 
/return 

Sub Event_willdecay 
|Since the rez time message comes before the expiry time message the 
|event should fire now 
   /doevents restime 

|Small pause to be sure 
   /if n ispccorpse!=1 { 
      /delay 5 
      /doevents restime 
   } 
   /varset gotconmsg 1 
/return 

Sub Event_corpsetooold 
|Corpse too old to rez, treat as npc corpse 
   /varset gotconmsg 0 
/return 

Sub Event_corpseexpire 
|Corpse about to poof, treat as npc corpse 
   /varset gotconmsg 0 
/return 

Sub Event_couldnotrez 
   /varadd couldnot 1 
/return 

Sub Event_clickedoldcorpse 
| Tried to resurrect a corpse that was too old 
| Remove from statistics 
   /varsub clicked 1 
   /varset status 1 
/return 

Sub Event_interrupt 
   /if "$char(state)"=="DUCK" { 
      /varset status 1 
      /varsub clicked 1 
      /call output 4 "Ducked, moving to next.." 
   } else { 
      /varset status 2 
   } 
/return 

Sub Event_fizzle 
   /varset status 2 
/return 

Sub Event_oom 
   /varset status 3 
/return 

Sub Event_notequipped 
   /beep 
   /call output 1 "ERROR: Epic is in an inventory slot, need to equip it in primary" 
/return 

Sub Event_notmemmed 
   /call sitdown 
   /if n "@usespell"==0 { 
      /beep 
      /call output 1 "ERROR: Epic is bagged or banked" 
      [color=red]/return[/color]
   } else { 
| Memorize spell 
      /call output 3 "Spell @spellname not memorized" 
      /memspell "@spellslot" "@spellname" 
      /delay MEMDELAY 
| Check if it's memmed now, otherwise quit 
      /if "$char(gem,@spellslot)"!="@spellname" { 
         /call output 1 "Couldn't memorize spell @spellname" 
         [color=red]/return[/color] 
      } 
      /varset status 4 

   } 
/return 

Sub Event_youmustbestanding 
   /varset status 2 
   /call output 4 "Standing up.." 
   /call standup 
/return 


[color=red]Sub Do-aerezz [/color]

   /declare status global 
   /declare ispccorpse global 
   /declare gotconmsg global 
   /declare oldtargetid local 
   /declare radius local 
   /declare contimer timer 
   /declare timeouts global 
   /declare corpses global 
   /declare skippedrace global 
   /declare skippedcon global 
   /declare skippedblacklist global 

   /declare clicked global 
   /declare couldnot global 
|prios(x,y) - contains name of profile in (x,0) and number of filters in profile in (x,1) 
   /declare prios array2 
   /declare priocount global 
|priofilters(x,y) - y=0..prios(x,1) contains the values of the filters for prios(x,0) 
   /declare priofilters array2 
   /declare only local 
   /declare argloop local 
   /declare racecount global 
|List of valid player races 
   /declare races array 
   /declare curid global 

   /declare spellmaxrange local 

   /declare noiselevel global 
   /declare contimeout global 
   /declare defaultradius local 
   /declare showstats local 
   /declare useraces global 
   /declare consider global 
   /declare usespell global 
   /declare spellname global 
   /declare spellslot global 
   /declare useblacklist global 
   /declare sit global 
       
   /varset noiselevel 0 

|Read configuration 
   /call getconfig "noiselevel" 2 
   /varset noiselevel $return 
   /call getconfig "contimeout" 50 
   /varset contimeout $return 
   /call getconfig "defaultradius" 100 
   /varset defaultradius $return 
   /call getconfig "showstats" 0 
   /varset showstats $return 
   /call getconfig "useraces" 0 
   /varset useraces $return 
   /call getconfig "consider" 1 
   /varset consider $return 
   /call getconfig "useblacklist" 0 
   /varset useblacklist $return 
   /call getconfig "usespell" 0 
   /varset usespell $return 
   /call getconfig "spellname" DEFAULTSPELL 
   /varset spellname $return 
   /call getconfig "spellslot" 8 
   /varset spellslot $return 
   /call getconfig "sit" 0 
   /varset sit $return 

   /varset corpses 0 
   /varset clicked 0 
   /varset skippedrace 0 
   /varset skippedcon 0 
   /varset timeouts 0 
   /varset skippedblacklist 0 
   /varset couldnot 0 
   /varset only 0 
   /varset radius @defaultradius 
   /varset priocount -1 
   /varset spellmaxrange 200 


|Check if parameter is passed 
   /for argloop 0 to 10    
   /if "$defined(Param@argloop)"=="TRUE" { 
      /call IsNumeric "@Param@argloop" 

      /if "$return"=="false" { 
|non-numeric argument 
         /if "@Param@argloop"=="only" { 
            /varset only 1 
         } else /if "@Param@argloop"=="buildraces" { 
            /call buildini 
            [color=red]/return[/color] 
         } else /if "@Param@argloop"=="noracecheck" { 
            /varset useraces 0 
         } else /if "@Param@argloop"=="racecheck" { 
            /varset useraces 1 
         } else /if "@Param@argloop"=="noblacklist" { 
            /varset useblacklist 0 
         } else /if "@Param@argloop"=="useblacklist" { 
            /varset useblacklist 1 
         } else /if "@Param@argloop"=="usespell" { 
            /varset usespell 1 
         } else /if "@Param@argloop"=="useepic" { 
            /varset usespell 0 
         } else /if "@Param@argloop"=="sit" { 
            /varset sit 1 
         } else /if "@Param@argloop"=="stand" { 
            /varset sit 0 
         } else /if "@Param@argloop"=="nocon" { 
            /varset consider 0 
         } else /if "@Param@argloop"=="con" { 
            /varset consider 1 
         } else /if "@Param@argloop"=="spellname" { 
            /varadd argloop 1 
            /varset spellname "@Param$int(@argloop)" 
         } else /if "@Param@argloop"=="spellslot" { 
            /varadd argloop 1 
            /varset spellslot "@Param$int(@argloop)" 
         } else { 
            /varadd priocount 1 
            /varset prios(@priocount,0) "@Param@argloop" 
            /call buildprios "@Param@argloop" @priocount 
            /varset prios(@priocount,1) $return 
         } 
             
      } else { 
|Numeric argument, set radius 
         /varset radius @Param@argloop 
      } 
   } else { 
|No argument passed, default 
      /goto :argsdone 
   } 
   /next argloop 

:argsdone 
   /call sitdown 
   /if n "@usespell"==1 { 
      /varset spellmaxrange $spell(@spellname,range) 
   } 
   /if n "@radius">@spellmaxrange { 
      /call output 2 "WARNING: Radius larger than range of spell, setting to @spellmaxrange" 
      /varset radius @spellmaxrange 
   } 
   /varadd priocount 1 
|If we havent found any profiles on command line, set first one to default 
   /if n @priocount==0 { 
      /varset prios(@priocount,0) "default" 
      /call buildprios "default" @priocount 
      /varset prios(@priocount,1) $return 
      /varset priocount 1 
   } 

|Build an array of valid player races from ini file 
   /if n @useraces==1 { 
      /varset racecount -1 

      :iniloop 
         /varadd racecount 1 
         /varset races($int(@racecount)) "$ini("CLICKINIFILE","races",$int(@racecount))" 
         /if "@races($int(@racecount))"=="NOTFOUND" /goto :leaveloop 
      /goto :iniloop 
   } 

:leaveloop 
|Read the blacklist after the normal profiles 
   /varset prios(@priocount,0) "blacklist" 
   /call buildprios "blacklist" @priocount 
   /varset prios(@priocount,1) $return 


|First loop through high priority classes.. 

   /varset curid 0 

   /for argloop 0 to $calc(@priocount-1) 
      :loopprio 
         /doevents 
         /varset status 0 
         /varset oldtargetid @curid 
             /varset curid $searchspawn(corpse,range:1:65,radius:@radius,next,id:@oldtargetid) 

|If we didn't get a new target move on to low priority 
          /if n @curid==0 /goto :clicktherest 

|Check if this is a high priority corpse 
         /call HasPriority @prios(@argloop,0) @curid 
         /if $return!="true" /goto :loopprio 
         /call clickit @curid 
|Gather statistics 
         /doevents couldnotrez 
      /goto :loopprio 

   :clicktherest 
   /next argloop 

|If parameter 'only' is specified don't move on to low priority corpses 
   /if n @only==1 /goto :end 
   /varset curid 0 

|.. then everyone else 
   :restloop 
      /doevents 
      /varset status 0 
      /varset oldtargetid @curid 
      /varset curid $searchspawn(corpse,range:1:65,radius:@radius,next,id:@oldtargetid) 
|If we didn't get a new target quit 
      /if n @curid==0 /goto :end 

|Check that this isn't a priority corpse 
      /for argloop 0 to $calc(@priocount-1) 
         /call HasPriority @prios(@argloop,0) @curid 
         /if $return=="true" /goto :restloop 
      /next argloop 
      /call clickit @curid 
|Gather statistics 
      /doevents couldnotrez 
   /goto :restloop 

:end 
|Gather statistics 
   /call sitdown 
   /doevents couldnotrez 
   /if n @showstats==1 /call statsub 

/return 

Sub getconfig 
|Read the value of a [config] parameter in ini file 
|/call getconfig "paramname" "defaultvalue" 
|Returns value 
   /if "$defined(Param0)"=="false" /return "false" 
   /if "$defined(Param1)"=="false" /return "false" 

   /declare inivalue local 

   /varset inivalue $ini("CLICKINIFILE","config","@Param0") 
|Not set in ini file, return default value 
   /if "@inivalue"=="NOTFOUND" /varset inivalue "@Param1" 
/return "@inivalue" 

Sub output 
|Echo that uses the noiselevel setting 
   /if "$defined(Param0)"=="false" /return 
   /if "$defined(Param1)"=="false" /return 
   /if n "@Param0"<=@noiselevel { 
      /echo @Param1 
   } 
/return 

Sub IsNumeric 
|Returns true if Param0 is numeric, false if not 
   /if "$defined(Param0)"=="false" /return "false" 
   /if n $strlen("@Param0")==0 /return "false" 
   /declare counter local 

   /for counter 0 to $strlen("@Param0") 
      /if n $instr($mid(@counter,1,"@Param0"),"0123456789")<0 /return "false" 
   /next counter 
/return "true" 

Sub statsub 
|Display stats 
   /declare runtime local 
   /declare runstring local 
   /varset runtime $running 
   /echo Corpses found: $int(@corpses), ressed: $int(@clicked), could not restore: $int(@couldnot) 
   /echo Skipped race: $int(@skippedrace), Skipped con: $int(@skippedcon), Skipped blacklist: $int(@skippedblacklist) 
   /varset runstring "Time taken $int($calc(@runtime/60)) minutes $int(@runtime%60) seconds" 
   /if n @timeouts>0 /echo Consider timeouts: @timeouts 
   /if n @corpses>0 /varset runstring "@runstring (avg time per corse: $calc(@runtime/@corpses)s)" 
   /echo @runstring 
/return 

Sub buildprios 
|Builds priority lists from ini file into priofilters(@Param1,y) 
|@Param0 is the name of the profile 
   /declare filters local 
   /declare temp local 
   /declare curfilt local 
   /declare pipeloc local 
   /declare nextpipe local 
   /declare filtercount local 
   /if "$defined(Param0)=="FALSE" /return 
   /varset filters "$ini("CLICKINIFILE","@Param0")" 
   /if ("@filters"=="||" || "@filters"=="NOTFOUND||") { 
      /if "@Param0"=="default" { 
||If default is empty, set defaults to bards and clerics 
         /varset priofilters(@Param1,0) "cBard" 
         /varset priofilters(@Param1,1) "cCleric" 
         /return 2 
      } else { 
         /return -1 
      } 
   } 

   /varset filters $left($calc($strlen(@filters)-2),@filters) 

   /varset filtercount 0 

   /varset nextpipe $instr("|",@filters) 

   /if n @nextpipe<0 { 
      /varset priofilters(@Param1,0) $left(1,@filters)"$ini("CLICKINIFILE","@Param0","@filters")" 
      /goto :leavebuildprios 
   } 

:loopfilters 
   /varset curfilt $mid(0,@nextpipe,@filters) 
   /varset filters $right($calc($strlen(@filters)-@nextpipe-1),@filters) 
   /varset temp $ini("CLICKINIFILE","@Param0",curfilt) 

   /varset priofilters(@Param1,@filtercount) $left(1,@curfilt)"$ini("CLICKINIFILE","@Param0","@curfilt")" 
   /varset nextpipe $instr("|",@filters) 
   /varadd filtercount 1 

   /if n @nextpipe<0 { 
      /varset priofilters(@Param1,@filtercount) $left(1,@filters)"$ini("CLICKINIFILE","@Param0","@filters")" 
      /goto :leavebuildprios 
   } 

   /goto :loopfilters 
    
:leavebuildprios 
   /varadd filtercount 1 

/return @filtercount 

Sub HasPriority 
|Test if corpse with id @Param1 has high priority in profile @Param0 
   /declare test local 
   /declare hpcount local 
   /declare filtnum local 
   /if "$defined(Param0)"=="FALSE" { 
      /varset test default 
   } else { 
      /varset test @Param0 
   } 

   /call findprioinarray "@test" 
   /if n @prios($return,1)<=0 /return "false" 

   /varset filtnum $return 

   /for hpcount 0 to $calc(@prios(@filtnum,1)-1) 
      /if $left(1,"@priofilters(@filtnum,@hpcount)")=="c" { 
         /if "$spawn(@Param1,class)"=="$right($calc($strlen("@priofilters(@filtnum,@hpcount)")-1),"@priofilters(@filtnum,@hpcount)")" { 
            /return "true" 
         } 
      } else    /if $left(1,"@priofilters(@filtnum,@hpcount)")=="n" { 
         /if "$spawn(@Param1,name)"~~"$right($calc($strlen("@priofilters(@filtnum,@hpcount)")-1),"@priofilters(@filtnum,@hpcount)")" { 
            /return "true" 
         } 
      } else    /if $left(1,"@priofilters(@filtnum,@hpcount)")=="g" { 
         /if "$spawn(@Param1,guild)"=="$right($calc($strlen("@priofilters(@filtnum,@hpcount)")-1),"@priofilters(@filtnum,@hpcount)")" { 
            /return "true" 
         } 
      } 

   /next hpcount 
/return "false" 

Sub findprioinarray 
|Search array for @Param0, returns the location or -1 if not found 
    
   /declare counter local 
   /for counter 0 to @priocount 
      /if "@Param0"=="@prios(@counter,0)" /return @counter 
   /next counter 
/return -1 

Sub IsPCRace 
|Test if race of corpse with id @Param0 is in the array of valid races 
   /declare loopcounter local 
   /for loopcounter 0 to @racecount 
      /if "$spawn(@Param0,race)"=="@races($int(@loopcounter))" /return "true" 
   /next loopcounter 

/return "false" 

Sub clickit 
   /declare counter local 
   /declare giveup local 
   /declare castwait local 

|Test if valid race 
   /if n @useraces==1 { 
      /call IsPCRace @Param0 
      /if "$return"=="false" { 
         /varadd skippedrace 1 
         /return 
      } 
   } 


   /if "@useblacklist"==0 /goto :skipblacklist 
|Check if corpse is blacklisted 
   /call HasPriority "blacklist" @curid 
   /if "$return"=="true" { 
      /call output 3 "Skipping blacklisted $spawn(@curid,name)" 
      /varadd skippedblacklist 1 
      /return 
   } 

   :skipblacklist 

|Target corpse 
   /tar id @Param0 
   /if $target()=="FALSE" /return 

   /varadd corpses 1 

|Doevents to get stats and flush /con messages 
   /doevents 

   /if n @consider==1 { 
      /varset ispccorpse 0 
      /varset gotconmsg 0 

      /consider 

|Set timer so we don't get stuck waiting for a /con message 
      /varset contimer @contimeout 

   :waitcon 
      /doevents corpseexpire 
      /doevents willdecay 
      /delay 1 
|After a few seconds give up and assume it's a pc corpse 
      /if n @contimer==0 { 
         /call output 3 "Timeout waiting for /con message, assuming pc corpse" 
         /varadd timeouts 1 
         /varset gotconmsg 1 
         /varset ispccorpse 1 
      } 
      /if n @gotconmsg==0 /goto :waitcon 

      /if n @ispccorpse!=1 { 
         /varadd skippedcon 1 
         /call output 3 "Skipping $target(name)" 
         /return 
      } 
   } 
   /varadd clicked 1 

|Counter to give up after 4 attempts at rezzing a corpse 
|that fail either by interrupt or if we can't cast for 3 seconds 
   /varset giveup 0 

:tryagain 
   /varadd giveup 1 

|Too many tries, move on to next 
   /if n @giveup>4 /return 

   /varset status 0 
   /varset castwait 0 

|Wait until we are not casting, if we wait too long, treat as an interrupt 
:waitforcast 
   /if $char(casting)!="TRUE" /goto :castit 
   /delay 5 
   /varadd castwait 1 
   /if n @castwait>5 /goto :tryagain 
   /goto :waitforcast 

:castit 
   /call output 3 "Resurrecting $target(name)" 
   /if n "@usespell"=="0" { 
| Use epic 
      /call standup 
      /cast item "water sprinkler of nem ankh" 
   } else { 
| Use spell 

      :waitspellrefresh 
| Check if enough mana, if not med until there is enough 
      /if n $char(mana,cur)<$spell("@spellname",mana) /call medup 

| Wait until spell is refreshed 
      /if n $char(gem,"@spellname")==-2 { 
         /delay 1 
         /goto :waitspellrefresh 
      } 
      /call standup 

      /cast @spellname 
   } 

|Wait until not casting anymore 
:castdelay 
   /delay 5 
   /doevents 
   /if n @status==4 { 
      /varsub giveup 1 
      /goto :tryagain 
   } 
   /if n @status==3 { 
      /varsub giveup 1 
      /call medup 
      /goto :tryagain 
   } 
   /if n @status==2 /goto :tryagain 
   /if n @status==1 { 
      /call sitdown 
      /return 
   } 
   /if $char(casting)=="TRUE" /goto :castdelay 

   /call sitdown 

/return 

Sub medup 
   /call sitdown 
| Loop until enough mana to cast 
   :medloop 
      /delay 1s 
   /if n $char(mana,cur)<$spell("@spellname",mana) /goto :medloop 

   /call standup 
/return 

Sub sitdown 
| Don't bother sitting if full mana 
   /if n "$char(mana,pct)"==100 /return 
| Check sit setting 
   /if n "@sit"==0 /return 
| Don't try to sit if on a mount 
   /if "$char(mounted)"=="TRUE" /return 
| If not sitting, sit down 
   /if "$char(state)"!="SIT" /sit 
/return 

Sub standup 
| Don't try to stand if on a mount 
   /if "$char(mounted)"=="TRUE" /return 
| If not standing, stand up 
   /if "$char(state)"!="STAND" /stand 
/return 

Sub buildini 
|Loop through the players in zone and compare their race to the list of valid 
|player races in ini file and add new races 
   /declare currace local 
   /declare curid local 
   /varset racecount -1 

|Read races from ini file 
   :buildiniloop 
      /varadd racecount 1 
      /varset races($int(@racecount)) "$ini("CLICKINIFILE","races",$int(@racecount))" 
      /if "@races($int(@racecount))"=="NOTFOUND" /goto :buildleaveloop 
   /goto :buildiniloop 

:buildleaveloop 
   /declare oldtarget local 
   /declare added local 

   /varset added 0 
   /declare pccount local 

   /varset pccount 0 
|Get first pc 
   /varset curid $searchspawn(pc) 
   /varset currace "$spawn(@curid,race)" 

:buildloop 

   /varadd pccount 1 
|See if race is in array already 
   /call buildisinarray "@currace" 
   /if n $return==0 { 
|New race, add to ini 
      /if ("$defined(currace)"!="FALSE" && "@currace"!="NULL") { 
         /ini "CLICKINIFILE" "races" $int(@racecount) "@currace" 
         /varset races(@racecount) "@currace" 
         /varadd racecount 1 
         /varadd added 1 
         /call output 2 "Added race: @currace" 
      } 
   } 
   /varset curid $searchspawn(pc,next,id:@curid) 
   /varset currace "$spawn(@curid,race)" 
   /if n @curid==0 /goto :buildend 

   /goto :buildloop 
:buildend 
   /call output 2 "Players counted: $int(@pccount) Races in ini: $int(@racecount), added $int(@added)" 

/return 

Sub buildisinarray 
|Search array for @Param0 
   /declare loopcounter local 
   /for loopcounter 0 to $calc(@racecount-1) 
      /if "@Param0"=="@races($int(@loopcounter))" { 
         /return 1 
      } 
   /next loopcounter 
/return 0
My problem is I'm not sure how to pass parameters to click.inc. Like the rezz radius and such from the initial call.

Anyone with more experience want to take a peek at this and tell me what I'm not doing correctly?

uglyshaman

Post by uglyshaman » Wed Dec 03, 2003 7:00 pm

Thanks :) Actually have it somewhat working - posted on the help forum for some fine-tuning as to how to STOP the bot from clicking even when I send him a command to stop.

Thanks again!

Cash42
orc pawn
orc pawn
Posts: 23
Joined: Sat Nov 22, 2003 1:38 pm

Wow

Post by Cash42 » Wed Dec 03, 2003 9:02 pm

For Christs sake Grim, could you be any nicer? Thanks so much man.
Cash42

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

Post by grimjack » Thu Dec 04, 2003 12:46 am

uglyshaman wrote:Ok very dumb question...

I've played with the macro some and was easily able to understand the commands you send to the bot (follow, invis, etc) - and thank you Grim for your help on this. My question is, is most of the functionality built upon sending commands to the bot in order to get them to perform actions? Just making sure I understand. Ie: in order to get a shaman to stand, cast Malo, pause a couple of seconds, Cast Slow (autodetect if it is resisted and recast if necessary), watch the tank's health, and JBB appropriately, im trying to determine if that is a multitude of commands sent from the "master" or if can all be tied into one command.

My apologies for my very limited intellect :P
You can make 1 command that does multiple things. Look at the buff command to see an example in the personal.inc.

If you want auto recast on resist you just need to modify the SpellSub a bit. Currently it sets it to fail on resist. If you change it to retry (look at the fizzle event) it should auto recast on resist. If the bot is set to healer it will auto watch all group members health at all times. If you wanted to use JBB instead of a spell in autoblast you would need to change the line that says /call SpellSub "@BlastSpell" to be something along the lines of /cast item "Jaundice Bone Bracer". I'll try to post a mod for AutoBlast that uses JBB sometime when I get a chance.

Also, with autoblast you don't need to give it a command once it's on. It will wait for assist call, target mob, wait till mob is at the pct you set to start at, and nuke until dead. The version I'm using at home stops nukeing at a set percent as well.

Things that are coming(mostly using already at home and tweaking):
AutoNuke tweaks
AutoManaRobe(could be easily modded for manastone)
AutoCani

These will most likely just be additions to the example personal.inc.

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