Future Features:
- Fight behind (for when you aren't MT or something... not that that ever happens right?)
- "disc X" command to manually set off a disc
Updates:
*NEW* - Smart Kick/Bash. At start of fight, it decides weather the mob is a caster, caster and gater or plain old melee. If it is a caster or gater, it only kick/bashes when the mob tries to cast or gate. If regular melee, it should spam kick.
*FIX* - this entire time i had no idea why the "Zoning" event wasn't working AT ALL. it turned out to be that i called the sub "Event_Loading" and all the references were to #Event Zoning (duh, hello).
* added a "UseDisc" variable so you can control weather bot uses /disc evasive or /disc defensive. Default is to use evasive on 64 and below, defensive on mobs 65 and above. Tweak the levels if you want, around line 700 (search for /disc). At some point I will probably add a "disc X" so you can manually trigger a /disc if you like.
* modified the keep close to mob code to be a bit more rog and rear fighting class friendly. when the mob is moving very slow (.20, where rs3 walk speed is about .40) it will use /press to get close instead of /sendkey down. If the mob is moving faster, it uses sendkey so it can keep up easily.
* Gating and Gated detection SHOULD work. A gating mob will cause the bot to do a "/g $t trying to gate". fairly simple and shouldn't be to obvious. Could add a miss spelling or perhaps randomly choose from 1 of 5 messages to make it look more "real". If the mob gates, attack should cease so we don't go running off after mobs (3 guesses why i added this... and the first 2 don't).
* Taunt clean up. If taunt is off, the bot will not beg or disarm. Otherwise if taunt is on smart mode (recommended) or dumb mode, it will continiously taunt.
* added an "offtank" command and a taunt default. Now, even if you have taunt off (to be NOT mt on a raid maybe) but need to actually tank a mob for some reason... just "offtank <mob id>" (like attack).
* Smart Taunting! If the mob is facing us, we don't use taunt. That is how most warriors play, and it has a few advantages. As soon as the mob turns, taunt is up and used. In limited testing, agro was kept much better. It is also believe that continiously using taunt is detrimental to a warrior keeping agro. The syntax is "/tell bot taunt smart" to turn it on, "taunt dumb" to turn it off.
* Mez, Break Mez and Enrage SHOULD only be triggered if it is a mob with the same name as the one targeted. This isn't ideal, but it should help a lot more. The detect mez sucks though because there are so many different Mez lines from chanter spells.
* There were a lot of places where strings did not have " " around them, so you may have noticed a few "could not find comparison operator in 'a'" or some shit like that. I think i have made all numerical comparisons have a "n" and all string compares have " " around both the left and right part of the comparison operator.
* Evasive should be engaged for mobs that are like 59 - 63, and defensive for mobs 63+. I will add a "use disciplines" option, and probably a Min/Max level for each so it can be tweaked better. From what I have read, evasive is the prefered /disc for about 98% of mobs, especially the ones you would be killing for exp.
* Some general code tweaking and fixes, I have been doing small things here and there as i noticed them.
* Added some code to the Attack portion that checks to see if the target is kind of high and will try to use /disc evasive or /disc defensive if its high enough
* Added a few checks to see if the "target" was a merchant or a PC (we don't need him trying to attack one of those on accident).
* I found quite a few behavioral problems that could be traced down to doing a numeric comparison but forgetting the "n" in "/if n $X". I also traced down quite a few instances where i had "/if X" when it should have been "/if $X" which explained another bunch of bugs.
* Added the farm command :)
Features:
*NEW* farm command given (i think?) a single "word" the bot will continiously go after them until they are all dead!
* behaves very much like any eq pet with similar commands
* semi-intelligent watching for mezes, broken mezes, enrage and end of enrage
* guard a spot or the master (responding to creatures who attack it)
* follow the master (doesn't respond to being attacked)
* sit and stand (omg, wow how did i do that!)
* pull a creature (careful how you use it!) by running to it, tagging it and running back
* turn on and off taunting, as well as sending pet in to just taunt (eq pets can't do that!)
* report his health and hopefully his buffs (coming soon maybe?)
* joins your group when you invite it
* watches its own health and cries like a sissy if he thinks he is going to die
* will get you all the chicks
Drawbacks:
* the master needs to be IN the zone when you start the script, and if you both zone... and it zones first you will need to /tell bot reset. sometimes even if you zone first he will need a reset.
* pretty much requires that you group with it, perhaps we can fix this later
* it may not behave entirely as expected, be ready to /tell bot exit!
* not a plat macro
Code: Select all
|Summary: allows one to control a melee charactor (specifically warrior right now) in much the
|the same way as a pet. The commands used to control are very similar and the behavior is also.
|you probably want to find the "/varset Debug 1" line and change it to 0 so you are not spammed.
|Command Usage:
|Attack - /tell bot attack $target(id) #id of the target, so mq needs to run on Master
|Taunt - /tell bot taunt [$target(id)] OR [on] OR [off] OR [smart] OR [dumb]
| $target(id) - bot will run to target and taunt until told to stop
| on - bot will taunt during attack
| off - bot will NOT taunt during attack
| smart - uses intelligent taunting, only taunts when mob is NOT facing bot
| dumb - switches back to taunt all the time (same as issuing "on" again)
|Sit - /tell bot sit #bot will sit down (turns revenge off)
|Stand - /tell bot stand #bot will stand up (turns revenge on)
|Goto - /tell bot goto Y X #note that it looks reversed, but just put in same order as what you see in /loc
|Follow - /tell bot follow #bot follows Master (turns revenge off)
|Guard - /tell bot guard [me] [here] OR [y] [x] (turns revenge on)
| here - bot will guard where he is standing, retaliating against anything that attacks him
| me - bot will follow you, retaliating against anything that attacks him
| x y - bot will guard loc, retaliating against anything that attacks him
|Report - /tell bot report #returns pct hp cur hp/max hp and buffs
|Back - /tell bot back #bot will back off and return
|Stop - /tell bot stop #bot stops what its doing (turns revenge off)
|Exit - /tell bot exit #stops the macro (no more commands!)
|Reset - /tell bot reset #if the bot zones and the Master is not in the zone, the script loses MastID, this fixes it
|Details:
|When done attacking, the bot will return to the Master and /follow OR return to loc if guard has been defined.
|The bot should also stop attacking at enrage OR mez (or both?). Upon un-enrage, it should start attacking again.
|Not sure what happens if mobs near by are mezed/enraged, probably confuses the script... but better than attacking
|a mezed/raged mob. I have also added a check for being attacked, and IF the bot is in certain modes (guarding) it
|will wait 5 seconds then start attacking.
|Things YOU DO!:
|Set the "Master" to your chars name, set the "Botname" to the pets name. Also might need to change the "Forward"
|and "Backward" keys if you have them set to something different.
|Also check in the Sub Main for the |# Commented variables and set as you like.
|Future Additions:
|-Possibly add looting commands (probably not though)
|Thanks:
|to codewarrior who posted his petwarrior.mac which i used as a basis for understanding
|macro quests syntax and for ideas on how to accomplish certain things. I'm sure I have also
|taken parts from others scripts, so thanks to them as well.
|Master and Bots name
#define Master Master!
#define Botname Bot!
|Forward and Backward keys
#define Forward up
#define Backward down
|Easier to read variables
#define BreakLoop v0
#define TargetID v1
#define TargetName v2
#define OkToFight v3
#define X v5
#define Y v6
#define MastID v7
#define Debug v9
#define MyXLOC v10
#define MyYLOC v11
#define Retaliate v12
#define DoTaunt v13
#define CheckHealth v14
#define DefaultStance v15
#define TempVar v16
#define GuardHeading v17
#define MobShouldFace v20
#define TauntDefault v21
#define MobEnraged v22
#define UseDisc v23
#define MobGates v24
#define MobCasts v25
#define SmartKB v26
#define StopOnMezBreak v27
|Special events
#Event Zoning "LOADING, PLEASE WAIT..."
#Event Enrage "has become ENRAGED."
#Event UnEnrage "is no longer enraged."
#Event BrokeMez "has been awakened by"
#Event Invited "To join the group, click on the 'FOLLOW' option, or 'DISBAND' to cancel"
#Event GettingHit "YOU for"
#Event MobGating "begins to cast the gate spell."
#Event MobGated "Gates."
#chat tell
#turbo
Sub Main
|************************************************************************************|
| Variables that are user modifiable |
|************************************************************************************|
|# Set this to 1 if you want the bot to start out vendictive
/varset Retaliate 0
|# Set this to 0 if you want the bot to start out NOT taunting
/varset DoTaunt 1
|# Set this to 0 if you dont want the bot to check its health
/varset CheckHealth 1
|# Set this to 1 if you want to see Debuging info
/varset Debug 0
|# Set this to 1 for none, 2 for follow, 3 for guard me, 4 for guard here for startup
|# and after zoning
/varset DefaultStance 1
|# Set this to 0 for no taunt, 1 for dumb taunt and 2 for smart taunt
/varset TauntDefault 2
|# Smart Kick/Bash will try to kick/bash when a CASTER MOB tries to cast a spell OR gate.
|# On non-casting mobs, it will just spam bash/kick like normal.
/varset SmartKB 1
|# If you want the bot to stop attacking when it sees mez broken, set to 1.
/varset StopOnMezBreak 1
|# Set to 0 to NOT use /disc, set to 1 to use. If you want to modify which /disc is
|# used, search the file for /disc and replace with what ever you want. You can also
|# tweak the level set offs if you like. approx line 700
/varset UseDisc 1
|************************************************************************************|
/if n $Debug==1 /echo Starting Slightly Improved Warrior Pet script...
/press ctrl
/press shift
/press alt
|# I had to pick a number to signify that we shouldn't go back to a loc.
|# I doubt that any zone has two elite points :)
/varset X 31337
/varset Y 31337
/varset DoTaunt $TauntDefault
/call SetMastID
/call DoStance $DefaultStance
|# This is where we start to loop and actually become the bot
:MainLoop
/doevents Zoning
/doevents Invited
/doevents GettingHit
/doevents Chat
/if $MastID==NULL /call SetMastID
/if $target()==TRUE /if $target(type)!="NPC" /target clear
/if $gm==TRUE /tell Master There is a GM in the Zone
/varset BreakLoop 0
|/delay 5
/if n $CheckHealth==1 /if n $char(hp,pct)<=20 /tell Master OMG I am at $char(hp,pct) health... I am going to die master!
|# Sends us back to the top to start over again
/goto :MainLoop
/return
|# The main handler, the Event_Chat that is called any time a /tell comes in
Sub Event_Chat
/if "$p1"=="Master" {
|# Out of group follow
/if "$arg(1,"$p2")"=="stick" {
/target id MastID
:Follow
/call StickToTarget
/delay 4
/doevents
/if BreakLoop!=1 /goto :Follow
}
|# The offtank command will tank a mob using taunt no matter what
/if "$arg(1,"$p2")"=="Tank" {
/if n $DoTaunt==0 {
/varset TempVar $DoTaunt
/varset DoTaunt $TauntDefault
}
/sit off
/press Backward
/target id $arg(2,"$p2")
|# Some checks to make sure what we are about to attack is what we were TOLD to attack
/if n $target(id)==$arg(2,"$p2") /if "$target(type)"!="PC" {
/tell Master OFF TANKING: $target(level) $target(name,clean) master!
/varset OkToFight 1
/call Attack "$arg(2,"$p2")"
/call AfterAttack
/if n $TempVar>0 {
/varset DoTaunt $TempVar
}
} else {
/tell Master That is not a valid target, master!
}
/varset BreakLoop 1
}
|# The pull command, takes $target(id) and runs to it, smacks it and comes back
/if "$arg(1,"$p2")"=="Pull" {
/press Backward
/target id $arg(2,"$p2")
/if n $target(id)==$arg(2,"$p2") /if "$target(type)"!="PC" {
/tell Master Pulling $target(name,clean) from $target(distance) away master!
/call GotoBody $target(id)
|# We dont to get hit on the way back and start attacking it
/if n $Retaliate==1 {
/varset TempVar 1
/varset Retaliate 0
}
|# Run up to mob, attack, taunt, kick and run back
/attack on
/if n $char(ability,taunt)>0 /doability taunt
/if n $char(ability,kick)>0 /doability kick
/delay 1s
/attack off
/call AfterAttack
|# If we had to suspend vengence... re-activate it here
/if n $TempVar==1 /varset Retaliate 1
}
}
|# The help command, lists what the bot can do.
/if "$arg(1,"$p2")"=="Help" {
/tell Master Attack [TargetID], Pull [TargetID], Taunt [TargetID], Guard [here] or [me] or [x y], Report, Back, Stop, Sit, Stand, Follow, are my commands master!
}
|# This command reports hp information and IF it ever works... buffs too.
/if "$arg(1,"$p2")"=="Report" {
/tell Master HP: $char(hp,pct)% $char(hp,cur) / $char(hp,max)
|/if n $Debug==1 /echo Buffs: $if(n,"$char(buff,$if(n,"$char(buff,$if(n,"$char(buff,$if(n,"$char(buff,$if(n,"$char(buff,$if(n,"$char(buff,$if(n,"$char(buff,$if(n,"$char(buff,$if(n,"$char(buff,$if(n,"$char(buff,f,1)"!="NULL",,"1 - $char(buff,1)") $if(n,"$char(buff,2)"!="NULL",,", 2 - $char(buff,2)") $if(n,"$char(buff,3)"!="NULL",," 3 - $char(buff,3)") $if(n,"$char(buff,4)"!="NULL",," 4 - $char(buff,4)") $if(n,"$char(buff,5)"!="NULL",," 5 - $char(buff,5)") $if(n,"$char(buff,6)"!="NULL",," 6 - $char(buff,6)") $if(n,"$char(buff,7)"!="NULL",," 7 - $char(buff,7)") $if(n,"$char(buff,8)"!="NULL",," 8 - $char(buff,8)") $if(n,"$char(buff,9)"!="NULL",," 9 - $char(buff,9)") $if(n,"$char(buff,10)"!="NULL",," 10 - $char(buff,10)") $if(n,"$char(buff,11)"!="NULL",," 11 - $char(buff,11)") $if(n,"$char(buff,12)"!="NULL",," 12 - $char(buff,12)") $if(n,"$char(buff,13)"!="NULL",," 13 - $char(buff,13)") $if(n,"$char(buff,14)"!="NULL",," 14 - $char(buff,14)") $if(n,"$char(buff,15)"!="NULL",," 15 - $char(buff,15)")
/tell Master Buffs $if(n,"$char(buff,1)"!="NULL",,"1 - $char(buff,1)") $if(n,"$char(buff,2)"!="NULL",," 2 - $char(buff,2)") $if(n,"$char(buff,3)"!="NULL",," 3 - $char(buff,3)")
|$if(n,"$char(buff,4)"!="NULL",," 4 - $char(buff,4)") $if(n,"$char(buff,5)"!="NULL",," 5 - $char(buff,5)") $if(n,"$char(buff,6)"!="NULL",," 6 - $char(buff,6)") $if(n,"$char(buff,7)"!="NULL",," 7 - $char(buff,7)") $if(n,"$char(buff,8)"!="NULL",," 8 - $char(buff,8)") $if(n,"$char(buff,9)"!="NULL",," 9 - $char(buff,9)") $if(n,"$char(buff,10)"!="NULL",," 10 - $char(buff,10)") $if(n,"$char(buff,11)"!="NULL",," 11 - $char(buff,11)") $if(n,"$char(buff,12)"!="NULL",," 12 - $char(buff,12)") $if(n,"$char(buff,13)"!="NULL",," 13 - $char(buff,13)") $if(n,"$char(buff,14)"!="NULL",," 14 - $char(buff,14)") $if(n,"$char(buff,15)"!="NULL",," 15 - $char(buff,15)")
}
|# The attack command, uses $Target(ID)
/if "$arg(1,"$p2")"=="Attack" {
/sit off
/press Backward
/target id $arg(2,"$p2")
|# Some checks to make sure what we are about to attack is what we were TOLD to attack
/if n $target(id)==$arg(2,"$p2") /if "$target(type)"!="PC" {
/tell Master Attacking: $target(level) $target(name,clean) master!
/varset OkToFight 1
/call Attack "$arg(2,"$p2")"
/call AfterAttack
} else {
/tell Master That is not a valid target, master!
}
/varset BreakLoop 1
}
/if "$arg(1,"$p2")"=="Farm" {
/tell Master attempting to harvest the hell out of $arg(2,"$p2"), master!
/varset OkToFight 1
/sit off
/press Backward
:KeepFarming
/attack off
/doevents
/target npc $arg(2,"$p2")
/delay 5
/if n $BreakLoop!=1 /if $target()==TRUE /if $target(level)<=50 {
/tell Master Attacking a level $target(level) $target(name) from $target(distance) away, master!
/call Attack $target(id)
/attack off
/delay 5
/if n $BreakLoop!=1 /goto :KeepFarming
}
/tell Master There are no more $arg(2,"$p2") to harvest the hell out of, master!
/call AfterAttack
/varset BreakLoop 1
}
|# The sit command, turns off retaliation and sits
/if "$arg(1,"$p2")"=="Sit" {
/if n $Retaliate==1 {
/varset Retaliate 0
/varset TempVar 1
}
/tell Master Sitting down master!
/press Backward
|# Because for some reason, sony is stupid...
/sit off
/sit on
/varset BreakLoop 1
}
|# If retaliation was turned on, and sit was used... turns retaliation back on and stands up
/if $arg(1,"$p2")==Stand {
/if n $TempVar==1 /varset Retaliate 1
/tell Master Standing up master!
/sit off
/varset BreakLoop 1
}
|# Takes Y and X parameters and sends bot to them
/if "$arg(1,"$p2")"=="Goto" {
/sit off
/if n $arg(2,"$p2")!=NULL /if n $arg(3,"$p2")!=NULL /if $X!=31337 /if $Y!=31337 /call GotoLoc $arg(3,"$p2") $arg(2,"$p2")
/varset BreakLoop 1
}
|# Tells bot to follow master, turns retaliation off
/if "$arg(1,"$p2")"=="Follow" {
/varset X 31337
/varset Y 31337
/varset Retaliate 0
/sit off
/target id $MastID
/tell Master Following $target(name) master!
/if n $Debug==1 /echo Following $target(name) from $target(distance) away.
|# Face target and give it a moment to happen
/face nopredict id $MastID
/delay 8
|# No reason to use anything fancy if we are close enough to /follow
/if n $target(distance)>150 /call GotoBody $MastID
/follow
/varset BreakLoop 1
}
|# Turns taunting on/off OR sends bot to a mob to taunt... you know, in case
|# you are not the MT and shouldn't get agro.
/if $arg(1,"$p2")==Taunt {
/if "$arg(2,"$p2")"=="On" {
/tell Master Taunting on master!
/varset DoTaunt 1
} else /if "$arg(2,"$p2")"=="Off" {
/tell Master Taunting off master!
/varset DoTaunt 0
} else /if "$arg(2,"$p2")"=="Smart" {
/tell Master Smart taunting activated master!
/varset DoTaunt 2
} else /if "$arg(2,"$p2")"=="Dumb" {
/tell Master Smart taunting deactivated master!
/varset DoTaunt 1
} else {
/target id $arg(2,"$p2")
/if n $target(id)==$arg(2,"$p2") {
|# We don't want to start beating on something we are just supposed to taunt
/varset Retaliate 0
/tell Master Taunting $target(name,clean) until you tell me to stop master!
/press Backward
/call Taunt $target(id)
/varset BreakLoop 1
}
}
}
|# Guard command takes "here" "me" or "Y" "X" locs and guards them (retaliation on)
/if "$arg(1,"$p2")"=="Guard" {
|# We definatly want to fight and protect ourselves in "gaurd" mode
/varset Retaliate 1
/varset OkToFight 1
/if "$arg(2,"$p2")"=="Here" {
|# Stop follow, record loc and heading
/press Backward
/varset X $char(x)
/varset Y $char(y)
/varset GuardHeading $char(heading)
/tell Master Guarding $Y, $X facing $GuardHeading master!
} else /if "$arg(2,"$p2")"=="Me" {
|# Set to those elite cords and follow mastuh
/varset X 31337
/varset Y 31337
/sit off
/target id $MastID
/if n $Debug==1 /echo Following $target(name) from $target(distance) away
/tell Master Guarding $target(name) master!
/face nopredict id $MastID
/delay 8
/if n $target(distance)>150 /call GotoBody $MastID
/follow
} else /if n $arg(3,"$p2")!=NULL /if n $arg(4,"$p2")!=NULL {
|# Use provided chords and current heading to setup guard here...
|# I hope no one uses this :)
/varset Y $arg(3,"$p2")
/varset X $arg(4,"$p2")
/varset GuardHeading $char(heading)
/tell Master Guarding $Y, $X facing $GuardHeading master!
}
}
|# Recalls the bot immediatly to master or its guard loc
/if "$arg(1,"$p2")"=="Back" {
/tell Master Coming back master!
/attack off
/varset Retaliate 0
/varset OkToFight 0
/call AfterAttack
/varset BreakLoop 1
}
|# Attempts to stop the bot from doing what ever the hell it is doing
/if "$arg(1,"$p2")"=="Stop" {
/tell Master Stopping what I am doing master!
/attack off
/target clear
/press Backward
/varset Retaliate 0
/varset BreakLoop 1
/varset OkToFight 0
}
|# If all else fails, we can always exit the script
/if "$arg(1,"$p2")"=="Exit" {
/tell Master Stopping it all master!
/attack off
/target clear
/press Forward
/press Backward
/varset BreakLoop 1
/endmacro
}
|# Resets the Owner's ID which is used extensively (and can be broken if pet finishes zoning before owner)
/if "$arg(1,"$p2")"=="Reset" {
/call SetMastID
}
} else /if "$p1"!="Master" /tell Master I have have recieved a private tell from $lasttell master!
/return
|# This event is called by the phrase "YOU for". We then check to see if it also contains the phrase
|# "points of damage." and just to double check we look at the OkToFight variable and then double check that
|# it was not in any "say" or "tell". If the target is NOT an NPC, we clear our target.
|# After that, we check to make sure eq is not in combat, the target IS an NPC AND we are in retaliation mode
Sub Event_GettingHit
/if "$p0"~~"points of damage." /if n $OkToFight==1 /if "$p0"!~"say" /if "$p0"!~"tell" {
/if $target()==TRUE /if "$target(type)"!="NPC" /target clear
/if $target()==TRUE /if $combat==FALSE /if $target(type)=="NPC" /if n $Retaliate==1 {
/if n $Debug==1 /echo I am being attacked by $target(name,clean)!
/tell Master I am being attacked by $target(name,clean), attacking in 2 seconds master!
/delay 2s
/press Backward
/call Attack $target(id)
}
}
/return
|# Triggered by zoning, we reset our variables and get ready to do it all again.
Sub Event_Zoning
/if n $Debug==1 /echo Zone detected, resetting everything
/press Forward
/press Backward
/attack off
/varset X 31337
/varset Y 31337
/varset BreakLoop 0
/varset TargetID 0
/varset TargetName 0
/varset OkToFight 1
/varset ToldAboutGM 0
/call SetMastID
/call DoStance $DefaultStance
/return
|# This should help us to keep from attacking enraged mobs (eating rage)
Sub Event_Enrage
/if "$p0"~~"botname" /return
/if "$p0"~~"$target(name,clean)" {
/attack off
/delay 5
/varset MobEnraged 1
/if n $Debug==1 /echo ENRAGE DETECTED, attack off!
}
/return
|# This should let us attack a mob AFTER it is done raging
Sub Event_UnEnrage
/if "$p0"~~"$target(name,clean)" {
/if n $Debug==1 /echo ENRAGE over, attack on!
/varset MobEnraged 0
/attack on
/delay 5
}
/return
|# This should stop us from fighting if we break mez.
Sub Event_BrokeMez
/if "$p0"~~"Botname" {
/attack off
/varset OkToFight 0
/varset BreakLoop 1
/if n $Debug==1 /echo BROKE MEZ DETECTED, attack off!
}
/return
|# Watching for invite message, we join.
Sub Event_Invited
/if n $Debug==1 /echo Invite recieved, joining group in 2 seconds
/delay 20
/invite
/return
Sub Event_MobCasting
/if "$p0"~~"$target(name,clean)" {
/if n $char(ability,slam)>0 /doability slam
/if n $char(ability,kick)>0 /doability kick
}
/return
Sub Event_MobGating
/if "$p0"~~"$target(name,clean)" {
/g %t trying to gate
/if n $char(ability,slam)>0 /doability slam
/if n $char(ability,kick)>0 /doability kick
}
/return
Sub Event_MobGated
/if "$p0"!~"say" /if "$p0"!~"group" /if "$p0"!~"out of character" /if "$p0"!~"shout" /if "$p0"!~"guild" /if "$p0"~~"$target(name,clean)" {
/tell Master Mob Gated, stopping attack.
/varset BreakLoop 1
/varset OkToFight 0
}
/return
|# This is used to take care of how we behave at script start and after zoning
Sub DoStance
/target id $MastID
/if n $p0==2 /if $target()==TRUE {
/varset X 31337
/varset Y 31337
/varset Retaliate 0
/sit off
/tell Master Following $target(name) master!
/if $Debug==1 /echo Following $target(name) from $target(distance) away.
/face nopredict id $MastID
/delay 5
/if $target(distance)>=150 /call GotoBody $MastID
/follow
/return
}
/if n $p0==3 /if $target()==TRUE {
/varset X 31337
/varset Y 31337
/varset Retaliate 1
/sit off
/target id $MastID
/tell Master Guarding $target(name) master!
/if n $Debug==1 /echo Guarding $target(name) from $target(distance) away
/face nopredict id $MastID
/if $target(distance)>=150 /call GotoBody $MastID
/follow
/return
}
/if n $p0==4 (
/press Backward
/varset X $char(x)
/varset Y $char(y)
/varset GuardHeading $char(heading)
/varset Retaliate 1
/tell Master Guarding $Y, $X facing $GuardHeading master!
/return
} else {
/tell Master Just standing here master!
/varset X 31337
/varset Y 31337
/varset Retaliate 0
}
/return
|# This will reset the ID of the owner, or fail if they are not in the zone
Sub SetMastID
/target pc Master
/if $target()==TRUE {
/varset MastID $target(id)
/tell Master ID has been set to $MastID master!
/if n $Debug==1 /echo Owner = Master , $MastID
} else {
/tell Master Error, ID has not be set master!
/if n $Debug==1 /echo Owner ID NOT SET!
}
/delay 1 s
/return
|# Checks to see if we may have bumped into something that is stopping us
sub CheckObstacle
|# Record our current position, wait a moment and then check if its the same
/varset MyXLOC $char(x)
/varset MyYLOC $char(y)
/delay 2
/if n $MyXLOC==$char(x) /if n $MyYLOC==$char(y) /call Obstacle
/return
|# Uses strafe and randomness to try and get around things
sub Obstacle
/if n $Debug==1 /echo We hit an obstacle, trying to get around it.
/sendkey up Forward
/sendkey down Backward
/delay 2
/sendkey up Backward
/sendkey down ctrl
/if n $rand(99)>50 {
/sendkey down right
} else {
/sendkey down left
}
/delay 3
/sendkey up right
/sendkey up left
/sendkey up ctrl
/sendkey down Forward
/return
| Takes X Y loc and goes there
Sub GotoLoc
/sit off
/if n $X==31337 /return
/if n $Y==31337 /return
:KeepGoingLoc
/if n $BreakLoop==1 /return
/call CheckObstacle
/doevents Chat
/doevents Zoning
/delay 0
/if n $distance($p0,$p1)>=25 {
/face loc $p0,$p1
/sendkey down Forward
/if n $BreakLoop!=1 /goto :KeepGoingLoc
}
/if n $distance($p0,$p1)<25 {
/sendkey up Forward
/return
}
/sendkey up Forward
/return
| Takes ID of body to goto and goes there
Sub GotoBody
/sit off
/target id $p0
:KeepGoingBody
/doevents Chat
/doevents Zoning
/delay 0
/if n $BreakLoop==1 /return
/if n $target(distance)>=25 {
/face nopredict fast id $target(id)
/sendkey down Forward
}
/if n $target(distance)<25 {
/sendkey up Forward
/return
}
/call CheckObstacle
/if n $BreakLoop!=1 /goto :KeepGoingBody
/return
| Takes ID of what to taunt, goes there and taunts it until told to stop
Sub Taunt
/target id $p0
|# We don't want to go off and attack merchants or PCs
/if $target(class)=="Merchant" /return
/if $target(type)=="PC" /return
/if $target(distance)>40 /call GotoBody $p0
:KeepGoingTaunt
/doevents Chat
/doevents Zoning
/call StickToTarget
/if n $char(ability,taunt)>0 /doability taunt
/if n $BreakLoop!=1 /goto :KeepGoingTaunt
/return
|# Chooses what to do depending on guard settings and does it
Sub AfterAttack
/if n $X==31337 /if n $Y==31337 {
/tell Master Returning to you master!
/target id $MastID
/face nopredict id $MastID
/delay 8
/if $target(distance)>=150 /call GotoBody $MastID
/follow
} else /if n $X!=31337 /if n $Y!=31337 {
/tell Master Returning to $Y, $X master!
/call GotoLoc $Y $X
/face heading $GuardHeading
}
/return
|# Fairly obvious, goes and attacks the $target(id) its given
Sub Attack
/target id $p0
/if "$target(class)"=="Merchant" /return
/if "$target(type)"=="PC" /return
/if n $target(distance)>35 /call GotoBody $p0
|# Prep some variables for use
/varset MobGates 0
/varset MobEnraged 0
/varset MobCasts 0
/attack on
/if n $StopOnMezBreak==1 /doevents BrokeMez
/if $OkToFight==0 {
/attack off
/return
}
/if n $SmartKB==1 {
/if "$target(class)"=="Cleric" {
/varset MobGates 1
/varset MobCasts 1
} else /if "$target(class)"=="Enchanter" {
/varset MobGates 1
/varset MobCasts 1
} else /if "$target(class)"=="Necromancer" {
/varset MobGates 1
/varset MobCasts 1
} else /if "$target(class)"=="Wizard" {
/varset MobGates 1
/varset MobCasts 1
} else /if "$target(class)"=="Druid" {
/varset MobGates 1
/varset MobCasts 1
} else /if "$target(class)"=="Shaman" {
/varset MobGates 1
/varset MobCasts 1
} else /if "$target(class)"=="Magician" {
/varset MobGates 1
/varset MobCasts 1
} else /if "$target(class)"=="Shadow Knight" {
/varset MobCasts 1
} else /if "$target(class)"=="Paladin" {
/varset MobCasts 1
} else /if "$target(class)"=="Ranger" {
/varset MobCasts 1
}
}
/if n $target(level)>61 /if n $target(level)<64 /if n $UseDisc==1 /disc evasive
/if n $target(level)>64 /if n $UseDisc==1 /disc defensive
:AttackLoop
/if n $StopOnMezBreak==1 /doevents BrokeMez
/doevents Chat
/doevents Zoning
/doevents Enrage
/doevents UnEnrage
/doevents MobGating
/doevents MobGated
/doevents MobCasting
| Stops attacking if mob is dead, raged, mezed or for some other reason we need to break loop
/if n $target(id)!=$p0 {
|# most likely dead target
/attack off
/press Backward
/return
}
/if n $OkToFight==0 {
|# Something happened and we shouldn't fight
/attack off
/press Backward
/return
}
/if n $BreakLoop==1 {
|# Something happened and we need to break the loop and do something else
/attack off
/press Backward
/return
}
/call StickToTarget
/if n $DoTaunt>=1 {
/if n $char(ability,disarm)>0 /doability disarm
/if n $char(ability,begging)>0 {
/attack off
/doability Begging
/attack on
}
}
/if n $DoTaunt==2 {
/varcalc MobShouldFace $char(heading)+180
/varcalc MobShouldFace $MobShouldFace%360
/if $target(heading)<=$calc($MobShouldFace+10) /if $target(heading)>=$calc($MobShouldFace-10) {
|/doability taunt
} else {
/if n $char(ability,taunt)>0 /doability taunt
}
} else /if $DoTaunt==1 {
/if n $char(ability,taunt)>0 /doability taunt
}
/if n $MobEnraged==0 /if n $MobGates!=1 /if n $MobCasts!=1 {
/if n $char(ability,slam)>0 /doability slam
/if n $char(ability,kick)>0 /doability kick
}
/if n $BreakLoop!=1 /goto :AttackLoop
/return
|# Meant to be called inside a loop, it should use big changes to get close to target then
|# Use smaller changes once fairly close.
Sub StickToTarget
/if $target()==FALSE /return
/face fast nopredict
/if n $target(speed)<=0.20 /if $target(distance)<20 {
/if n $target(distance)>8 /press Forward
/if n $target(distance)<5 /press Backward
} else {
/if n $target(distance)>18 /sendkey down Forward
/if n $target(distance)<14 /sendkey up Forward
}
/return



