Moderator: MacroQuest Developers

Code: Select all
|--------------------------------------------------------------
| XPBEAST.MAC
| Author : Tuna
| UPDATED: 2004 Mar 17
| PURPOSE: Automate XP and Alt XP gain in any zone
|
| LONGEST RUN TIME: 6 days, 4 hours nonstop
|
| Bugs: 1: If someone buffs you with something which overwrites
| one of your own, you will go OOM trying to put your
| buff back on you. Might incorporate the "buff timer"
| logic I use in TPC macro to fix this.
| 2: Movement does not look perfect. Someone watching
| could detect it is a bot (assuming they watched for
| a while).
| 3: Player keeps up buffs even when someone is near.
| Ideally, beastlord should do *nothing* when a player
| is near.
| 4: You will announce to the chat channel of choice
| an XP gain twice per kill.
| 5: This script is VERY processor heavy. You have
| been warned! A 1400mhz machine will drop to about
| 3 frames per second while running this.
|
| Todo: * Randomize the run spot
| * Make a more natural "/face"
| * Make a more natural run-to.
| * Pull from multiple camps
| * Get someone to paypal me for this shit
|--------------------------------------------------------------
#turbo
#include occutils.mac
#chat say
| Change this to wherever you XP
#define ZONE_TO_XP_IN "Fungus Grove"
| You will also need to search for @@STARTINGLOCS and change
| those values.
| Minimum amount of mana you must have before starting a fight
#define manaMin_toAggro 80
| If bot is not sneaky, he'll pull even when people are near.
| You probably want a sneaky bot, so leave this set to 1.
#define BOT_IS_SNEAKY 0
| Secret phrase for inter-bot chat
#define CONST_SECRETPHRASE "sup :)"
| Change this to a private channel name.
#define CHANNEL_ANNOUNCE "fraglerok"
| If REQUIRE_PET is 0, you will not summon pets and if the script
| is started without one, you will pull and kill without one.
#define REQUIRE_PET 1
| If nonzero, and you are alone in a group, this will /quit
| immediately.
#define REQUIRE_DUO_PARTNER 1
| If this is set to 1, you will summon food and drink approx once
| per every 2 fights. Otherwise you will never summon food and
| drink. I'd like to make this "smarter" by summoning a stack
| of food in response to "You are low on food" but I'm a bit
| lazy about this fix.
#define SUMMON_ORGANICS_AS_NEEDED 0
| Self-explanatory handling of adds:
#define KILL_ANYTHING_THIS_CLOSE_TO_ALLIES 35
| Name of mob killing. Will not pull anything except this.
| Make sure you change this. :-p
#define MOB_KILLING "a small mushroom"
| If you are grouped with a necro, you will send "Medding"
| to the group every so many seconds if you are low on mana.
| This way he can fulfill his destiny as a necromancer and twitch you.
#define timeBetween_manaAnnounce 18s
| Max distance to pull. I have an extended range item.
#define dist_maxPull 220
| Spell to pull with. This is only cast once.
| I use a shitty low level nuke because I only have a shitty
| low level extended range 2 item. And I'm cheap.
#define sn_Pull "Malosini"
| Spell to nuke target with. Right now the bst does not
| need to nuke any, so this goes unused.
#define sn_Nuke "Sun Vortex"
| Spell to slow target with.
| If you are level 65 and have Revenge you'll change this.
#define sn_Slow ""
| Spell to heal players with.
#define sn_HealPC ""
| Spell to DoT mobs with.
#define sn_DoT ""
| Primary pet heal. Should be the largest, slowest heal you have.
#define sn_PetHeal "Planar Renewal"
| Secondary pet heal. Should take less mana than primary.
| Alternatively, you could put a player heal here but it
| may drain you of mana. :p
#define sn_PetHeal2 "Planar Renewal"
| Pet proc spell. Also make sure you change the event triggers
| in this macro to a matching value.
#define sn_PetProc "Flameshield of Ro"
| Pet haste spell.
#define sn_PetHaste "Burnout V"
| Pet summon spell. Put your highest level warder here.
#define sn_PetSummon "Ward of Xegony"
| Regen buff name.
#define sn_Regen ""
| ===================================================================
| EVENTS
| These events will force subroutines to be called (triggered)
| when they enter your logfile.
|
| VERY IMPORTANT BUG:
| If you have HitsMode set to "number only" for "Me getting hit"
| then this script will break. Macroquest only sees "119" when
| a mob hits you for 119 in that case. It needs to see "hits YOU for"
| instead of just the number.
|
|
| ALSO: Make sure you read over the events. If you change your slow
| to the level 65 one, make sure you also update the SlowWoreOff
| event trigger text, etc.
| ===================================================================
|#event HitsGroupmate ""
|#event RegenRequest ""
|#event PetRegenWoreOff "Your pet's Flameshield of Ro spell has worn off"
#event SlowWoreOff "Your Malosini spell has worn off"
#event GainXP "You gain experience"
#event GainXPParty "You gain party experience"
#event PetIsTaunting "Taunting attacker, Master"
#event concheck " scowls at you"
|#event TargetSlowed ""
#event ImDead "You have been slain by"
#event INuked "staggers as the spirits of frost slam against"
#event YouHaveSlain "You have slain"
|#event PetHasSlain "has been slain by $pet(name)"
|#event PetNuking "$pet(name) begins to cast a spell"
#event WizTellsReady ""
#event ptDS "Your pet's Flameshield of Ro spell has worn off.
#event ptHaste "Your pet's Burnout V spell has worn off."
| You may want to add other HitsMe events for slashing, piercing,
| etc.
#event HitsMe "bashes YOU for"
#event HitsMe "kicks YOU for"
#event HitsMe "hits YOU for"
| =====================================================================
| end events. Begin MAIN routine
| =====================================================================
Sub Main
/echo ============================================
/echo XPBEAST v1.66 : 17 Mar 2004
/echo *Requires* level 62 BeastLord
/echo Also REQUIRES: /pet hold
/echo You *will very likely* die without this AA.
/echo This macro also assumes (but does not require)
/echo your beastlord has PARAGON and SPIRIT FRENZY.
/echo ============================================
/call SetupGlobals
/call OUGlobals
/call AnotherSwapSpot 7
/call AnotherSwapSpot 8
| /call AnotherFriendlyPlayer
| /call AnotherFriendlyPlayer Yourotherbuddy
| /call AnotherFriendlyPlayer Someguywhoalwaysxpsnearyou
| /call AnotherFriendlyPlayer Acultfollower
| /call AnotherFriendlyPlayer SycophantNumberTwo
/call AlsoNeedBuff "Shield of Maelin"
| /call AlsoNeedBuff "Regrowth"
| /call AlsoNeedBuff "Infusion of Spirit"
/call AlsoNeedBuff "Xegony's Phantasmal Guard"
| /call AlsoNeedBuff "Talisman of Jasinth"
| /call AlsoNeedBuff "Spiritual Vigor"
| /call AlsoNeedBuff "Celerity"
| /call AlsoNeedBuff "Stamina"
| --------
| Clear out any sticky keys from other macros or players
| --------
/keypress CLEAR_TARGET
/keypress CLEAR_TARGET
/keypress CLEAR_TARGET
| /press alt
| /press shift
| /press ctrl
| --------
| Run to start location
| --------
/call InitSounds
/call PlaySound "init"
/call RunHomeIfNeeded
| --------
| I feel this loop is faily self-explanatory. If you have questions
| about the function names or the bot states, just poke through
| this macro. All functions are documented.
|
| If they are not in this macro, check the include file(s)
| --------
:Loop
| /call NoisyDebug
/call StopMovingIfMoving
/call DuoHealer
/call HateListChecker
/if "@botState"=="KILL" {
/call StateChecker
/call GetTarget
/call RefreshSpells
/call PetCleric
/call BattlePercents
/call CombatRangeHandler
}
/if "@botState"=="LOOT" {
/call LootCorpses
}
/if "@botState"=="WAIT" {
/call RunHomeIfNeeded
| /call ParagonWhenNeeded
| /call SitStand
/call PetSummoner
/call StateChecker
/call BotWait
/call RefreshSpells
/call PetCleric
| /call QuenchOrganics
}
/doevents
/goto :Loop
/return
Sub LootCorpses
/if n @t_LootTimerWindow<=0 {
/varset botState "WAIT"
/return
}
/keypress CLEAR_TARGET
/target npc corpse "MOB_KILLING" radius 50
/if "$target()"=="TRUE" {
/if n $target(distance)<50 {
/call AutoRunToLoc $target(x) $target(y) "STOPATDEST" "CAREFUL"
/call SimpleLootAll
}
}
/return
Sub CombatRangeHandler
/declare dist3d local
/if "$char(casting)"=="TRUE" /return
/if "$target()"=="FALSE" {
/call CombatDone
/return
}
/if @isGettingHit==0 {
/call CombatDone
/return
}
/if @bstassist==1 {
| /gsay assist
| /delay 4s
| /gsay slow
| /varset bstassist 0
}
/if "$spawn(@isFighting,type)"!="NPC" {
/call CombatDone
/return
}
/if n $target(id)==$char(pet) /return
/if n $target(id)==$char(id) /return
/if n $group(1)>0 {
/if n $target(id)==$group(1) /return
}
/stand
/face fast
| /doability "Slam"
/varset dist3d $distance($target(y),$target(x),$target(z))
/if n @dist3d>=@FastRange /call Fastmove
/if n @dist3d>@RangeMax {
/keypress FORWARD hold
}
/keypress FORWARD
/if n @dist3d<@RangeMin {
/keypress BACK hold
}
/keypress BACK
/face fast
/return
sub CombatDone
/call StopMovingIfMoving
/return
Sub Fastmove
/declare dist3d local
/varset MyXLOC $char(x)
/varset MyYLOC $char(y)
/if "$target()"=="FALSE" {
/keypress FORWARD
/if "$combat"=="TRUE" {
/attack off
/return
}
}
/if "$spawn(@isFighting,type)"!="NPC" {
/call CombatDone
/return
}
/stand
/face fast
/varset dist3d $distance($target(y),$target(x),$target(z))
/if n @dist3d>@FastRange {
/keypress FORWARD hold
}
/if n @dist3d<=@FastRange {
/keypress FORWARD
/return
}
/return
Sub SitStand
/if n @isFighting==0 {
/if n $char(hp,pct)<90 {
/if n $char(mana,pct)<90 {
/if "$char(state)"=="STAND" /sit
}
}
} else {
/if "$char(state)"=="SIT" /stand
}
/return
Sub HateListChecker
/declare a local
/if n @hateList_count>0 {
/for a 1 to @hateList_count
/if n @hateList(@a)>0 {
/if "$spawn(@hateList(@a))"=="FALSE" {
/echo Removing missing spawn # @hateList(@a) from hatelist
/varset hateList(@a) 0
} else {
/if "$spawn(@hateList(@a),state)"=="DEAD" {
/echo Oh. It's a corpse. Lolz.
/varset hateList(@a) 0
} else {
/if n @isFighting!=@hateList(@a) {
/echo Yes - it's around and $spawn(@hateList(@a),distance) away. KILL IT!
/target ID @hateList(@a)
/call OfficiallyAggro
}
}
}
}
/next a
}
/return
Sub SetupGlobals
/declare t_LoopDelay_CheckForNewSpawns timer
/declare t_LootTimerWindow timer
/declare t_SpiritFrenzy timer
/varset t_SpiritFrenzy 0
/declare t_DelayAfterFindingNearbyPC timer
/varset t_DelayAfterFindingNearbyPC 0
/declare FriendlyPlayers array
/declare ID_TARGET_NEXT global
/declare ID_DUO global
/declare fAAXPStarted global
/declare QuitASAP global
/declare isGettingHit global
/declare tempCount global
/declare alertSound global
/declare isFighting global
/declare needsSlow global
/declare needsNuke global
/declare needsDoT global
/declare petHasAggro global
/declare petNeedsRegen global
/declare wizNeedsRegen global
/declare idTemp global
/declare idPetEating global
/declare doingBattlePercents global
/declare botState global
/declare xpStart global
/declare totalKills global
/declare deadTarget global
/declare nukesThisFight global
/declare maxNukesPerFight global
/declare buffFound global
/declare mobDist_petAttack global
/declare bstassist global
/declare t_ParagonTimer timer
/declare petDS global
/declare petHaste global
/varset petDS 0
/varset petHaste 0
/varset t_ParagonTimer 0
/declare t_CommandLag timer
| -------------- Buff tracking -------------------
| -------------- AutoRunning -------------------
/declare iLastSpot global
/declare iMaxLocs global
/declare arX array
/declare arY array
| @@STARTINGLOCS
| Spot 0 is normal pull spot
/varset arX(0) 63.87
/varset arY(0) 53.37
| Spot 1 is another safe spot
/varset arX(1) 73
/varset arY(1) 107
| Spot 2 is another safe spot...etc.
/varset iLastSpot 0
/varset iMaxLocs 1
| Combat movement vars
/declare ObstCount global
/declare MyXLOC global
/declare MyYLOC global
/declare RangeMax global
/declare RangeMin global
/declare FastRange global
/varset RangeMax 40
/varset RangeMin 30
/varset FastRange 40
| -------------- /AutoRunning -------------------
/varset QuitASAP 0
| -------------- Target Picking -------------------
/declare Pull_NpcCount global
/declare RadiusFromSpawnCenter global
/declare MobList array
/declare hateList_count global
/declare hateList array
/varset hateList_count 0
| -------------- </Target Picking> -------------------
| ------ Group mana notifications -----------
/declare t_AnnounceMana timer
/varset t_LootTimerWindow 0
/varset t_LoopDelay_CheckForNewSpawns 0
/varset isGettingHit 0
/varset buffFound 0
/varset doingBattlePercents 1
/varset xpStart $int($char(exp))
/varset isFighting 0
/varset alertSound 0
/varset deadTarget 0
/varset needsSlow 0
/varset needsDoT 0
/varset needsNuke 0
/varset maxNukesPerFight 1
/varset idPetEating 0
/varset petHasAggro 0
/varset petNeedsRegen 0
/varset wizNeedsRegen 0
/varset botState "WAIT"
/varset totalKills 0
/varset mobDist_petAttack 110
/varset bstassist 0
/varset fAAXPStarted $char(aa,exp)
| /keypress alt
| /keypress shift
| /keypress ctrl
/keypress CLEAR_TARGET
/if n $group(1)!=0 {
/echo DUO partner seems to be $target(name,clean), id $target(id)
/varset ID_DUO $group(1)
} else {
/echo We seem to be solo. No one in group.
/varset ID_DUO 0
}
/return
| If getting hit, runs around.
Sub ChickenWithHeadCutOff
/if n @isGettingHit==0 /return
/varcalc iLastSpot @iLastSpot+1
| Don't go to spot #0, that is starting spot.
/if n @iLastSpot>@iMaxLocs /varset iLastSpot 1
/varset isGettingHit 0
/stand
/call AutoRunToLoc @arX(@iLastSpot) @arY(@iLastSpot) "STOPATDEST" "CAREFUL"
/face id $target(id)
/keypress CENTERVIEW
/return
Sub StateChecker
/if n @QuitASAP!=0 {
/chat #CHANNEL_ANNOUNCE Need to go for a little bit.
| /quit
}
/call AlertIfLowHP
/if "$zone"!="ZONE_TO_XP_IN" {
/chat #CHANNEL_ANNOUNCE Huh... not in ZONE_TO_XP_IN
/varset QuitASAP 1
/delay 5
| /quit
}
/if "$gm"=="TRUE" {
/chat #CHANNEL_ANNOUNCE Oh nos! Black helicopters!
/varset QuitASAP 1
/delay 20s
| /quit
}
/if n $group(1)==0 {
/if n REQUIRE_DUO_PARTNER!=0 {
/chat #CHANNEL_ANNOUNCE Duo... duo... Bueller... Bueller...
/varset QuitASAP 1
/delay 5
| /quit
}
}
/if n @t_AnnounceMana<=0 {
/varset t_AnnounceMana timeBetween_manaAnnounce
/if n $char(mana,pct)<90 {
/if n $group(1)>0 {
/if "$spawn($group(1),class)"=="Necromancer" {
/gsay Medding
} else {
/if "$spawn($group(2),class)"=="Necromancer" /gsay Medding
}
}
}
}
/if n @deadTarget!=0 /call TargetIsDead
| ----------------------------------
| Pet has not aggro'd anything and we are not fighting.
| Once here, you're basically safely medding up.
| ----------------------------------
/if n @petHasAggro==0 {
/if n @isFighting==0 {
/if n $char(mana,pct)<manaMin_toAggro {
/varset botState "WAIT"
/return
}
/if n $char(hp,pct)<90 {
/varset botState "WAIT"
/return
}
/if "$target()"=="TRUE" {
/if "$target(type)"=="NPC" {
/if "$target(state)"=="DEAD" {
/call TargetIsDead
/return
}
}
}
}
}
/if n @petHasAggro==1 {
/if "@botState"!="KILL" {
/echo Pet has aggro? setting botState to kill
/varset botState "KILL"
/return
}
}
/if n @isFighting!=0 {
/if "@botState"!="KILL" {
/echo Fighting id @isFighting -- setting botState to kill
/varset botState "KILL"
/return
}
}
/if "@botState"!="KILL" {
/if n $char(mana,pct)<manaMin_toAggro /return
/if n $char(hp,pct)<90 /return
/if n REQUIRE_PET!=0 {
/if n $char(pet)>0 {
/if n $spawn($char(pet),hp,pct)<75 {
/echo Fullmana, fullhp - but pet still hurt
/call SureCast "sn_PetHeal2"
/return
}
}
}
/echo Fullmana, fullhp - setting botstate to kill
/varset botState "KILL"
}
/return
Sub BotWait
/if "$char(state)"=="STAND" {
/if n $char(hp,pct)<90 /sit
}
/if "$char(state)"=="STAND" {
/if n $char(mana,pct)<90 /sit
}
| ------------ Heal ---------------
| /if n $char(hp,pct)<90 {
| /if n $char(mana,pct)>20 {
| /press esc
| /press f1
| /call SureCast "sn_HealPC"
| }
| }
/return
Sub BattlePercents
/if n @doingBattlePercents==0 /return
/if n @isFighting<=0 /return
/if n $target(hp,pct)<80 {
/if n @t_SpiritFrenzy<=0 {
| /alt activate 127
/varset t_SpiritFrenzy 12m
}
}
/call TargetByID @isFighting
/if "$target()"=="FALSE" /return
/if n $target(hp,pct)<7 {
/return
}
/if n @needsDoT!=0 {
/call TargetByID @needsDoT
/varset needsDoT 0
| /call SureCast "sn_DoT"
}
/if n $target(hp,pct)<70 {
/if n @nukesThisFight<@maxNukesPerFight {
/varset needsNuke 1
/return
}
}
/return
Sub PetSummoner
| If you don't require a pet, and don't have a pet, return early.
/if n REQUIRE_PET==0 {
/if n $char(pet)==0 /return
}
| However, if you're here it means you do require a pet.
/if n $char(pet)==0 {
/echo No pet, and we require one. Pulling it up.
/call SureCast "sn_PetSummon"
}
/return
Sub PetCleric
| If you don't require a pet, and don't have a pet, return early.
/if n REQUIRE_PET==0 {
/if n $char(pet)==0 /return
}
| Save old target ID
/if $target(id)>0 {
/varset idTemp $target(id)
} else {
/varset idTemp 0
}
| Stay within 90 units of pet
/call MoveToPetHealDistance
| If pet needs healed
/if n $spawn($char(pet),hp,pct)<55 {
/varset doingBattlePercents 0
/call SureCast "sn_PetHeal"
} else {
/varset doingBattlePercents 1
}
/if n @isFighting==0 {
/if n $spawn($char(pet),hp,pct)<75 {
/call SureCast "sn_PetHeal2"
}
}
/if n @idTemp>0 {
/if n $target(id)!=@idTemp {
/echo Just healed pet now returning to prev target, @idTemp ($spawn(@idTemp,name,clean))
/call TargetByID @idTemp
}
}
/return
Sub RefreshSpells
| ----- Combat spells -----
/if n @isFighting>0 {
/if n @needsSlow>0 {
| /call TargetByID @needsSlow
| /if n $target(hp,pct)<98 /call SureCast "sn_Slow"
}
/if n @needsNuke!=0 {
/if n $target(hp,pct)<70 {
/varadd nukesThisFight 1
/call SureCast "sn_Nuke"
/varset needsNuke 0
}
}
} else {
/call RefreshBuffList_Downtime
}
/return
Sub GetTarget
/declare l0 local
/if n @isFighting>0 {
/if n $target(id)!=@isFighting {
/call TargetByID @isFighting
/echo target: We weren't on @isFighting but it is what we're fighting so, like, fuqit.
}
/return
}
/if n @petHasAggro==1 {
/if "$target()"=="FALSE" {
/echo You have no target but your pet has aggro. Way to go, Vanderhar.
/call AssistPet
} else {
/echo Pet has aggro, I have a target. Not picking new target.
}
/return
}
| --- If low mana, low hp, duo partner is low hp, pet has low hp... abort!
/if n $char(hp,pct)<100 /return
/if n $char(mana,pct)<manaMin_toAggro /return
/if n REQUIRE_PET!=0 {
/if n $char(pet)!=0 {
/if $spawn(char(pet),hp,pct)<100 /return
}
}
| Don't pull if partner is hurt
/if n $group(1)>0 {
/keypress CLEAR_TARGET
/if n $spawn(@ID_DUO,hp,pct)<25 {
/echo $spawn(@ID_DUO,name,clean) is pretty hurt - not pulling.
/return
}
}
| Don't pull if someone is near
/if n BOT_IS_SNEAKY!=0 {
/if n @t_DelayAfterFindingNearbyPC>0 {
/return
}
/if n $group(1)>0 {
/keypress CLEAR_TARGET
/target PC radius 300 notid @ID_DUO
/if "$target()"=="TRUE" {
/call IsPlayerFriendly $target(name)
/if n $return==0 {
/varset t_DelayAfterFindingNearbyPC 18s
/echo Stranger, $target(name,clean), is within 300 units.. not pulling mobs.
/return
}
}
} else {
/keypress CLEAR_TARGET
/target PC radius 300
/if "$target()"=="TRUE" {
/call IsPlayerFriendly $target(name)
/if n $return==0 {
/varset t_DelayAfterFindingNearbyPC 18s
/echo $target(name,clean) is within 300 units.. not pulling mobs.
/return
} else {
/echo $target(name,clean) is within 300 units.. but friendly. Hi.
}
}
}
}
/keypress CLEAR_TARGET
| -------- Any NPC killable -----------
/call RunHomeIfNeeded
| Return early if loop still being delayed.
| This is one way I am trying to combat the
| hellish processor hogging MQ does if your
| script is too intense.
/if n @t_LoopDelay_CheckForNewSpawns>0 /return
/varset t_LoopDelay_CheckForNewSpawns 5
/call PickMobToPull
/if n @ID_TARGET_NEXT==0 /return
/if "$spawn(@ID_TARGET_NEXT,type)"!="NPC" /return
/call TargetByID @ID_TARGET_NEXT
/echo Okay. PickMobToPull has us targetting $target(name), $target(id)
/stand
/face
/if "$target()"=="TRUE" {
| Make sure the new target:
| 1) is not me
| 2) is not the pet
| 3) is not a dead thing
/if n $target(id)==$char(pet) {
/echo Oh cool. You targetted your pet to kill. WTG.
/return
}
/if n $target(id)==$char(id) {
/echo Oh cool. You targetted yourself to kill. WTG.
/return
}
/if "$target(state)"=="DEAD" {
/echo Oh cool. You targetted a corpse to attack. WTG.
/return
}
/call OfficiallyAggro
}
/return
Sub CheckForBuff
/varset buffFound 0
/for tempCount 1 to 15
/if "$char(buff,@tempCount)"~~"@Param0" {
/varset buffFound 1
/return
}
/next l0
/return
| ------------------------------------------
| QuenchOrganics
| Summons one food and one drink, placing them
| in your autoinventory.
| ------------------------------------------
Sub QuenchOrganics
/if n SUMMON_ORGANICS_AS_NEEDED==0 /return
/if n $char(mana,pct)<100 /return
/autoinventory
/delay 10
/call SureCast "Summon Drink"
/autoinventory
/delay 10
/call SureCast "Summon Food"
/autoinventory
/return
| -------------------------------------------------
| Cycles through the buffs and places them on
| you and your partner (if you have one)
| Will also refresh pet buffs and any special buffs
| such as wizard-regen. There was a time I never
| placed regen on myself, only on wizard.
| -------------------------------------------------
Sub RefreshBuffList_Downtime
/declare l0 local
/declare l1 local
/declare c local
/if n @wizNeedsRegen!=0 {
/if n $group(1)>0 {
/call TargetByID $group(1)
| /call SureCast "sn_Regen"
/varset wizNeedsRegen 0
}
}
/if n @petDS!=0 {
/target id $char(pet)
/call SureCast "sn_PetProc"
/varset petDS 0
| /g sn Yekan's Quickening
| /g sn Spirit of Vermin
}
/if n @petHaste!=0 {
/call SureCast "sn_PetHaste"
/varset petHaste 0
}
| /if n $char(buff,"Spiritual Light")<=0 {
| /g snt Spiritual Light on Karieanne
| }
| /if n $pet(buff,"Deftness")<=0 {
| /call TargetByID $char(pet)
| /call SureCast "Deftness"
| }
| Sometimes I duo with a cleric. Eh. I don't buff him.
/if "$spawn($group(1),class)"!="Cleric" {
| Also don't buff any partner below level 46.
/if n $spawn($group(1),level)>=65 {
/call DUO_CastAllNeededBuffs
} else {
/call CastAllNeededBuffs
}
} else {
/call CastAllNeededBuffs
}
/return
| ----------------------------------------------------------------------
| ParagonWhenNeeded
| If Mana is less than 80, this will use the Paragon ability and reset its
| script timer to 15 minutes.
| ----------------------------------------------------------------------
Sub ParagonWhenNeeded
| /if n $char(mana,pct)>=80 /return
| /if n @t_ParagonTimer>0 /return
| /if "$char(state)"=="SIT" /stand
| /alt activate 128
| /delay 7s
| /varset t_ParagonTimer 15m
/return
| ----------------------------------------------------------------------
| OfficiallyAggro()
| PURPOSE: Plays "Pop!" noise and marks a target for killing.
| Casts the pull spell (whatever sn_Pull is defined as) and if
| this bot is grouped with anyone, sends a /tell to the groupmate
| with secretphrase and incoming target ID.
| ----------------------------------------------------------------------
Sub OfficiallyAggro
/echo NEW KILL TARGET: $target(name) id $target(id) level $target(level)
/call AddHate $target(id)
/varset isFighting $target(id)
| /varset needsSlow $target(id)
| /varset needsDoT $target(id)
/call PlaySound "spawn"
/call SureCast "sn_Pull"
/if "$return"=="CANNOTSEE" {
/call RemoveHate $target(id)
/echo I can't see $target(name,clean).. uh... resetting
/varset petHasAggro 0
/varset isFighting 0
/varset deadTarget 0
/varset nukesThisFight 0
/varset botState "WAIT"
/return
}
/pet hold
/if n $group(1)>0 {
/gsay Incoming $target(name,clean)
|/tell $spawn(@ID_DUO,name,clean) CONST_SECRETPHRASE 0000$target(id)
}
/return
| ---------------------------------------------------------------------
| TargetIsDead
| PURPOSE: Updates killing statistics and puts bot in a WAIT state
|
| TRIGGER: Called in response to a "slain" death message. This will
| also be called when players die.
| ---------------------------------------------------------------------
Sub TargetIsDead
/keypress CLEAR_TARGET
/keypress CLEAR_TARGET
/keypress CLEAR_TARGET
/varset petHasAggro 0
/varset isFighting 0
/varset deadTarget 0
/varset nukesThisFight 0
/varset bstassist 0
/varset botState "WAIT"
/return
| ----------------------------------------------
| PURPOSE: If you are not near the home base,
| this macro will stand and run there.
| If you *are* near home base, the macro returns
| early.
| ----------------------------------------------
Sub RunHomeIfNeeded
/if n $distance(@arY(0),@arX(0))<=10 /return
/stand
/call AutoRunToLoc @arX(0) @arY(0) "STOPATDEST" "CAREFUL"
/face heading 143
/keypress CLEAR_TARGET
/keypress CENTERVIEW
/return
| ----------------------------------------------
| This is called when a target you are slowing
| is near enough to melee range for your EQ client
| to see the trigger text. IE "loses its fighting edge"
| or whatever. Once triggered, it zeros the
| "needsSlow" variable.
| Eventually this macro will keep an array of all
| targets who need slowed, but for now this assumes
| you are fighting one thing at a time.
| ----------------------------------------------
Sub Event_TargetSlowed
/varset needsSlow 0
/return
| ----------------------------------------------------------------------
| Assists pet and if the pet is targeting something other than
| itself, it is aggro'd.
| I've had a lot of trouble with this function and it seems very,
| very buggy. /assist in EQ is worrisome and unreliable.
| So what I've done is added "AddRadiusToHate" for the pet. If the
| pet is within 35 units (or whatever 'KILL_ANYTHING_THIS_CLOSE_TO_ALLIES'
| is set to) of any mobs, those mobs are added to the hatelist.
| ----------------------------------------------------------------------
Sub AssistPet
| Target the pet and assist it
/call TargetByID $char(pet)
/echo Targetting pet to assist it
/call AddRadiusToHate KILL_ANYTHING_THIS_CLOSE_TO_ALLIES $target(x) $target(y)
/assist
| Wait for shitty EQ /assist code to catch up
/delay 15
/echo Pet seems to be attacking $target(name) (id $target(id))
| If the thing the pet is attacking is alive
/if n $target(id)!=$char(pet) {
| @@FIX: Sometimes there are living mobs named "Soandso the Undying Corpse"
| or "a muddy corpse" or "a shambling corpse". This needs better
| checking. @@TODO probably something like /if "$target(state)"!="DEAD"
/if "$target(name)"!~"corpse" {
/if n $target(hp,pct)>0 {
/echo Assisting pet on $target(name,clean)
/varset petHasAggro 1
/varset isFighting $target(id)
/return
} else {
/keypress CLEAR_TARGET
}
}
}
| Else the stupid shit IS attacking a corpse
/varset isFighting 0
/varset petHasAggro 0
/return
| -----------------------------
| Unused right now except for space saver.
| In future may put Eliza code back in here.
| -----------------------------
Sub Event_Chat
/echo You got a @Param0 from @Param1: @Param2
/return
| -----------------------------
| Called in response to your nuke landing.
| -----------------------------
Sub Event_INuked
/varset needsNuke 0
/return
| -----------------------------
| Another placeholder. Eventually will
| be used in occutils for landmine, pulling
| and other checks. For instance if a
| target goes from scowling to indifferent
| yet you are not invis and are not feigned
| you can bet it is charmed
| -----------------------------
Sub Event_ConCheck
/echo He be scowling I guess
/return
| -----------------------------
| Cases where my targets die.
| -----------------------------
|Sub Event_PetHasSlain
| /call TargetIsDead
|/return
Sub Event_YouHaveSlain
/call TargetIsDead
/return
| -----------------------------
| GainXP and GainXPParty should do the exact same thing.
| I don't want to push another function call
| on the stack (though how much processing time does
| that really take in MQ anyway?)
| -----------------------------
Sub Event_GainXP
/declare aaXPGained local
/varcalc aaXPGained $char(aa,exp)-@fAAXPStarted
/echo @totalKills kills. XP: $char(exp) -- AAXP: $char(aa,exp)% and $char(aa,points) unspent.
/chat #CHANNEL_ANNOUNCE @totalKills, $char(exp), $char(aa,exp), $char(aa,points)
/varset t_LootTimerWindow 5s
/varset t_CommandLag 5s
/varadd totalKills 1
/varset deadTarget 1
/varset petHasAggro 0
/varset isGettingHit 0
/varset botState "LOOT"
/varset bstassist 0
/call RemoveDeadSpawnsFromHateList
/return
Sub Event_GainXPParty
/declare aaXPGained local
/varcalc aaXPGained $char(aa,exp)-@fAAXPStarted
/echo @totalKills kills. XP: $char(exp) -- AAXP: $char(aa,exp)% and $char(aa,points) unspent.
/chat #CHANNEL_ANNOUNCE @totalKills, $char(exp), $char(aa,exp), $char(aa,points)
/varset t_LootTimerWindow 5s
/varset t_CommandLag 5s
/varadd totalKills 1
/varset deadTarget 1
/varset petHasAggro 0
/varset isGettingHit 0
/varset botState "LOOT"
/varset bstassist 0
/call RemoveDeadSpawnsFromHateList
/return
| -----------------------------
| Called every time you see "Taunting attacker, Master"
| Normally this is ignored, but if you are in a wait
| or loot state it could indicate 1 of 4 things:
| 1) This script is a piece of shit
| 2) Someone trained you
| 3) You pulled adds because you picked a shitty place to XP
| 4) All the above
| -----------------------------
Sub Event_PetIsTaunting
| ---
| Who cares if pet is taunting if we already have a target?
/if n @petHasAggro!=0 /return
/if "@botState"=="KILL" /return
| ---
| Always wait a couple seconds after "you gain experience!!"
| before acknowledging a pettaunt. For some reason commands
| seem a bit laggy in MQ2. Pets last taunt msg could have been
| 5 to 20 seconds ago and this event still fires after xp gain.
/if n @t_CommandLag>0 /return
/varset botState "KILL"
/varset petHasAggro 1
/keypress CLEAR_TARGET
/call AssistPet
/if "$target(name,clean)"=="MOB_KILLING" {
/call OfficiallyAggro
} else {
/echo I can't figure out what the fuck $target(name) is. Ignoring.
}
/return
| -----------------------------------------------------
| See Event_PetIsTaunting for description of what PetNuking
| does also.
| -----------------------------------------------------
|Sub Event_PetNuking
| | Oh nos - our pet is aggro'd while we were medding.
| /if "@botState"!="KILL" {
| /echo Oh boy - pet is aggro'd on something.
| /call AssistPet
| /if "$target(name,clean)"=="MOB_KILLING" {
| /call OfficiallyAggro
| } else {
| /echo I can't figure out what the fuck $target(name) is. Ignoring.
| }
| /return
| }
|/return
| --------------------------------------------------------
Sub Event_ptDS
/varset petDS 1
/return
Sub Event_ptHaste
/varset petHaste 1
/return
| -----------------------------------------------------
| Event_ImDead is called when you are slain.
| You'll see this from time to time. Shit happens.
| Overall I've gone from level 60 with 3aa to level 62
| with 63aa so I can safely say the script is worth
| a death here and there.
| -----------------------------------------------------
Sub Event_ImDead
/varset QuitASAP 1
/return
| -----------------------------------------------------
| NoisyDebug
| Dumps stuff into mq2chatwnd
| -----------------------------------------------------
Sub NoisyDebug
/echo @botState : fight @isFighting Slow[@needsSlow] Pet: Aggro @petHasAggro tSpawn @t_LoopDelay_CheckForNewSpawns tLoot @t_LootTimerWindow tFrenzy @t_SpiritFrenzy
/return
| -----------------------------------------------
| Readies the MP3 player for playing.
| @@TODO add "downtime ambience" and maybe "battle ambience"
| so you know what state the bot is in without having
| to look at the screen.
| -----------------------------------------------
sub InitSounds
| /mp3 clear
| /mp3 add c:\mp3\eqbots\pop.wav
| /mp3 add c:\mp3\eqbots\init.wav
| /mp3 add c:\mp3\eqbots\battle.mp3
/return
| -----------------------------------------------
| Plays a song from the in-game mp3 player.
| -----------------------------------------------
sub PlaySound
/if @Param0=="spawn" {
/mp3 play 1
/delay 2
/mp3 stop
} else /if @Param0=="tell" {
| /mp3 play 2
| /delay 2s
| /mp3 stop
} else /if @Param0=="init" {
/mp3 play 2
/delay 1s
/mp3 stop
} else /if @Param0=="alert" {
/mp3 play 3
}
/return
| ---------------------------------------
| AlertIfLowHP
|
| Under the right conditions:
| 1) Plays a loud, obnoxious MP3
| 2) Moves to your groupmate and begs for an evac
| 3) Turns off loud music
| ---------------------------------------
sub AlertIfLowHP
/if n $char(mana,pct)<15 {
/if n $char(hp,pct)<30 {
/if n $group(1)>0 {
/gsay hot shit - evac!
/target id $group(1)
/call MoveToTarget
}
}
}
/if n $char(hp,pct)<30 {
/if n @alertSound==0 {
| /call PlaySound "alert"
/varset alertSound 1
}
}
/if n $char(hp,pct)>=90 {
/if n @alertSound==1 {
| /mp3 stop
/varset alertSound 0
}
}
/return
| ---------------------------------------
| QueryWizardForReady
| Queries duo partner for readiness.
| Currently unused.
| ---------------------------------------
sub QueryWizardForReady
| If timer has expired, as wiz again
/if n @t_wizReady<=0 {
/tell $spawn($group(1),name) are you ready?
/varset t_wizReady 10
}
/return
| ---------------------------------------
| Heals your partner if needed.
| Returns to previous target if you had one.
| ---------------------------------------
sub DuoHealer
/if n $group(1)==0 /return
/declare prevTarget local
/if "$target()"=="TRUE" {
/varset prevTarget $target(id)
} else {
/varset prevTarget 0
}
/if n $group(1)>0 {
| /if n $spawn($group(1),hp,pct)<60 {
| /echo Healing injured player
| /call TargetByID $group(1)
| /call SureCast "sn_HealPC"
| /if n @prevTarget!=0 /call TargetByID @prevTarget
| }
}
/return
| ------------------------------------------------
| Summons a horse, if you have one and it is in
| your ammo slot.
| @@NOTE: Make the fuck sure you don't own
| a DROGMOR and have "Summon Horse" listed in
| your bufflist. Instead change that buff to
| read "Summon Drogmor"
| ------------------------------------------------
sub SummonHorse
/stand
/cast item "$equip(ammo,name)"
/delay 45
/return
| ------------------------------------------------
| This event is called when your slow wears off.
| Note that if you have the bst epic or have
| someone helpful nearby slowing mobs for you
| then you will go OOM trying to re-slow your
| target.
|
| You can probably fix this by putting a "time
| until needs reslowed" timer in the code.
| ------------------------------------------------
sub Event_SlowWoreOff
/varset needsSlow @isFighting
/return
| ------------------------------------------------
| If you regen your pet (why bother?) this will
| tell the bufflist refresher to put regen
| on your pet again. This is called when
| your pets regen wears off.
| ------------------------------------------------
sub Event_PetRegenWoreOff
/varset petNeedsRegen 1
/return
| ------------------------------------------------
| If you get an "ow" tell from your partner
| then this function is called.
| Yes, it's insecure but it works for now.
| Note that if you anger me irl and haven't read
| this comment I'll probably exploit this to your
| utter dismay.
| ------------------------------------------------
sub Event_HitsGroupmate
/if n $group(1)!=0 {
/call AddRadiusToHate KILL_ANYTHING_THIS_CLOSE_TO_ALLIES $spawn($group(1),x) $spawn($group(1),y)
}
/if n $spawn($group(1),pet)!=0 {
/call AddRadiusToHate KILL_ANYTHING_THIS_CLOSE_TO_ALLIES $spawn($spawn($group(1),pet),x) $spawn($spawn($group(1),pet),y)
}
/return
| ------------------------------------------------
| Called *every* time a mob hits you.
| This is a big pig of a function to have occur
| so often.
| ------------------------------------------------
sub Event_HitsMe
/varset isGettingHit 1
| /varset bstassist 1
/if "$combat"=="FALSE" {
/call AddRadiusToHate 35 $char(x) $char(y)
/attack off
/pet attack
}
/return
| ------------------------------------------------
| Your parter sends you a regen request and this
| function is triggered. You will regen him
| when time and mana permits.
| ------------------------------------------------
sub Event_RegenRequest
/varset wizNeedsRegen 1
/return
| --------------------------------------------------------------------
| Radius-from-center pulling code
| This picks a mob sitting so-many units from a loc you designate.
| This is pretty solid code.
| --------------------------------------------------------------------
Sub PickMobToPull
/declare a local
/varset RadiusFromSpawnCenter 400
/varset ID_TARGET_NEXT 0
/call Populate_MobList
/if n @Pull_NpcCount>0 {
/for a 1 to @Pull_NpcCount
/echo Checking $spawn(@MobList(@a),x) x $spawn(@MobList(@a),y) y
/if "$spawn(@MobList(@a),name,clean)"=="MOB_KILLING" {
/if n $spawn(@MobList(@a),distance)<dist_maxPull {
/echo finalTarget is @MobList(@a) now ($spawn(@MobList(@a),name,clean))
/varset ID_TARGET_NEXT @MobList(@a)
/call TargetByID @ID_TARGET_NEXT
/return
} else {
/echo $spawn(@MobList(@a),name) too far to pull ($spawn(@MobList(@a),distance))
}
}
/delay 5
/next a
/echo None found - sorry.
}
/return
| --------------------------------------------------
| Subroutine of PickMobToPull
| This does the meat of finding a mob to pull.
| @@FIX add zradius check
| @@FIX move the hardcoded locs up to the top.
| @@FIX add anti-killsteal code
| --------------------------------------------------
Sub Populate_MobList
/declare npcid local
/declare firstnpcid local
/declare lastnpcid local
/varset npcid 0
/varset firstnpcid 0
/varset lastnpcid 0
/varset Pull_NpcCount 0
| Note that 666,777 is the loc of the CENTER of the circle from which
| you want to PULL MOBS. You'll need to adjust this depending on your
| zone and camp.
/varset npcid $searchspawn(npc,loc:-30:30,radius:@RadiusFromSpawnCenter)
:Loop
/if n @npcid==@firstnpcid {
/return
} else {
/if n @Pull_NpcCount==0 /varset firstnpcid @npcid
/varset lastnpcid @npcid
/varset npcid $searchspawn(npc,loc:-30:30,id:@lastnpcid,radius:@RadiusFromSpawnCenter,next)
/if "$spawn(@lastnpcid,name,clean)"=="MOB_KILLING" {
/echo Adding $spawn(@lastnpcid,name,clean) (@lastnpcid) to MobList
/if n @lastnpcid!=0 /varadd Pull_NpcCount 1
/if n @lastnpcid!=0 /varset MobList(@Pull_NpcCount) @lastnpcid
}
}
/goto :Loop
/return
| end xpbeast.mac
Code: Select all
| ----------------------------------------------------------------------
| occutils.mac
| AUTHORS: Tuna
|
| PURPOSE: Useful routines which I put in a lot of scripts.
| This one isn't as well commented as the other scripts.
| Enjoy!
|
| http://www.vigormortis.net
|
| I took the corpse looting code from someone in the forums. Also
| took but heavily modified the autorun code.
|
| UPDATED: 2004 Mar 17
| ----------------------------------------------------------------------
#define CONST_SECRETPHRASE "j3jf39jaljp"
#event SecretCommands "j3jf39jaljp""
| Let's stay within this many units of the pet.
#define gPetHealRange 85
#event SeatedCaster "You must be standing"
#event CastFizzle "Your spell fizzles!"
#event CastBegin "You begin casting"
#event SpellNotOnPC "That spell can not affect this target PC"
#event CannotSeeTarget "You cannot see your target"
#event TooFar "Your target is out of range, get closer!"
#event NoTargetHuh "You must first select a target for this spell!"
#event TooDistracted "You are too distracted to cast a spell now!"
#event HandsFull "You can't hold the book open with your hands full."
#event concheckNOTKOS " regards you amiably"
#event concheckNOTKOS " regards you indifferently -- "
#event concheckNOTKOS " glowers at you dubiously -- "
#event concheckKOS " glares at you threateningly -- "
#event concheckKOS " scowls at you, ready to attack -- "
sub Event_concheckKOS
/varset gLastConsiderVal "KOS"
/return
sub Event_concheckNOTKOS
/varset gLastConsiderVal "NOTKOS"
/return
sub Event_HandsFull
/chat #elarvus $cursor(name) huh...
/autoinventory
/return
| ==================================================
| MemIfNeeed
| Usage:
| /call MemIfNeeded "Super SpellName" [slot number]
|
| /call MemIfNeeded "Root"
| /call MemIfNeeded "Complete Heal"
| ==================================================
Sub AnotherSwapSpot
/varcalc SwapSlotCount @SwapSlotCount+1
/varset ar_SwapSlot(@SwapSlotCount) @Param0
/echo Swap slot choice #@SwapSlotCount is gem #@ar_SwapSlot(@SwapSlotCount)
/if n @SwapLastUsed<1 /varset SwapLastUsed 1
/return
Sub AnotherFriendlyPlayer
/varcalc FriendlyPlayerSlotCount @FriendlyPlayerSlotCount+1
/varset ar_FriendlyPlayerSlot(@FriendlyPlayerSlotCount) @Param0
/echo FriendlyPlayer #@FriendlyPlayerSlotCount is #@ar_FriendlyPlayerSlot(@FriendlyPlayerSlotCount)
/return
Sub IsPlayerFriendly
/declare c local
/for c 1 to @FriendlyPlayerSlotCount
/if "@ar_FriendlyPlayerSlot(@c)"=="@Param0" {
/return 1
}
/next c
/return 0
Sub MemIfNeeded
/declare c local
/if n @SwapSlotCount<=0 {
/echo You need to "/call AnotherSwapSpot 1" and replace 1 with a swap gem slot.
/return
}
/for c 1 to 8
/if "$char(gem,@c)"=="@Param0" {
| /echo Don't need to mem $char(gem,@c)
/goto :MIN_NoMem
}
/next c
/echo Memming @Param0 in gem @ar_SwapSlot(@SwapLastUsed)
/mem @ar_SwapSlot(@SwapLastUsed) "@Param0"
/varcalc SwapLastUsed @SwapLastUsed+1
/if n @SwapLastUsed>@SwapSlotCount /varset SwapLastUsed 1
/delay 6s
:MIN_NoMem
/return
Sub SureCastNoWait
/declare postCast local
/echo SureCast(@Param0)
/call MemIfNeeded "@Param0"
| --------------------------------------
/if "$char(state)"=="SIT" /stand
/varset castState "TRYING"
/cast "@Param0"
:CastLoop
/delay 4
/if "@castState"=="SUCCESS" /goto :DoneCasting
/if "@castState"=="NOHOLD" /goto :DoneCasting
/cast "@Param0"
/doevents
/goto :CastLoop
:DoneCasting
/varset postCast $int($calc($spell("@Param0",casttime)*10+10))
/return
| ==================================================
| SureCast
| The amazing action-blocking function which will
| not let the rest of your routines run until, by
| god, some outcome occurs from your spellcasting.
|
| Usage:
|
| /call SureCast "spellname"
| If the spell is not memmed, it will mem the spell in
| the swap slot.
| ==================================================
Sub SureCast
/declare postCast local
/declare t_CastTimeout local
/echo SureCast @Param0
/if "$char(ismoving)"=="TRUE" {
/echo You're moving and you want me to cast?
/keypress FORWARD
}
/if "$defined(Param0)"=="FALSE" {
| /echo @Param0 is $defined(Param0)
/return
}
/if "@Param0"=="NULL" {
/return
}
/if n $spell("@Param0",level)>$char(level) {
/echo Eh... @Param0 is $spell("@Param0",level) .. I can't mem it.
/return
}
/if n $spell("@Param0",level)<1 {
/echo Eh... @Param0 is $spell("@Param0",level) .. I can't mem it.
/return
}
/if "$target()"=="TRUE" {
/varset SureCast_target $target(id)
} else {
/varset SureCast_target 0
}
| --------------------------------------
/if "$char(state)"=="SIT" /stand
/varset castState "TRYING"
/varset t_CastTimeout 20s
:CastLoop
/call MemIfNeeded "@Param0"
/delay 2
| ---
| First: If something fucks up and you cannot
| complete the spell for whatever reason,
| give up after so many seconds and just go on
| with your life.
| ---
/if n @t_CastTimeout<=0 /goto :DoneCasting
/if "@castState"=="SUCCESS" /goto :DoneCasting
/if "@castState"=="TOOFAR" /goto :DoneCasting
/if "@castState"=="NOHOLD" /goto :DoneCasting
/if "@castState"=="CANNOTSEE" /goto :DoneCasting
/if "@castState"=="NOTARGET" /goto :DoneCasting
/cast "@Param0"
/doevents
/goto :CastLoop
:DoneCasting
/varset SureCast_target 0
/varset postCast $int($calc($spell("@Param0",casttime)*10+10))
/delay @postCast
/return "@castState"
Sub Event_SeatedCaster
/stand
/return
Sub Event_TooFar
/varset castState "TOOFAR"
/return
Sub Event_CastFizzle
/varset castState "ERROR"
/return
sub Event_SpellNotOnPC
/varset castState "NOHOLD"
/return
Sub Event_NotTakeHold
/varset castState "NOHOLD"
/return
Sub Event_CannotSeeTarget
/varset castState "CANNOTSEE"
/return
Sub Event_CastBegin
| Good enough for now
| Will have to fix later to deal with not taking hold, resists, etc
/varset castState "SUCCESS"
/return
Sub Event_TooDistracted
/keypress CLEAR_TARGET
/return
| --------------------
| Event for:
| "You must first select a target for this spell!
| --------------------
Sub Event_NoTargetHuh
/echo No target, huh? Last target of a spell was @SureCast_target
/if n @SureCast_target!=0 {
/if n $spawn(@SureCast_target)>0 {
/echo Retargeting $spawn(@SureCast_target,name,clean) ...
/call TargetByID @SureCast_target
} else {
/varset castState "NOTARGET"
}
}
/return
| ===================================================================
| Autorun( stopornot, changeWhenStuck )
|
| Sort-of blocking function.
| /doevents happens while autorunning
| Will return if stuck
|
| AutoRunToLoc X Y "STOPATDEST" "CARELESS"
| AutoRunToLoc X Y "NOSTOP" "CAREFUL"
| ===================================================================
sub AutoRunToLoc
/declare l1 local
/declare l2 local
/declare distLastCheck local
/declare gThreshold local
/declare doStopRunningWhenDone local
/declare isCareful local
/varset gThreshold 14
/varset l2 @Param0
/varset l1 @Param1
/varset doStopRunningWhenDone @Param2
/varset isCareful @Param3
/if n $distance(@l1,@l2)<@gThreshold /return
/varset t_StuckTimeout 2s
/face loc @l1, @l2
/if "$char(state)"!="STAND" /stand
/call AutoRun 1
/echo Running to @l2 X, @l1 Y ( @doStopRunningWhenDone, @isCareful )
/echo $distance(@l1,@l2)
/varset distLastCheck $distance(@l1,@l2)
:MainLoop2
/delay 1
/face loc @l1, @l2
/doevents
| Update loc every 3 seconds
/call isRooted
/if n $return==0 {
/if n @t_StuckTimeout<=0 {
/varset t_StuckTimeout 3s
| -----------------
| If we appear stuck, return. Calling procedure
| should pick a new spot and re-call.
| Only do this if "careful" mode, though.
| When in careless mode, just pick a random dir and
| run there for a sec or two.
| Careful = meant for running through dungeons and specific paths
| Careless = meant for running through Dawnshroud and other
| wide places where you might just be stuck on a rock, but in
| general you don't care if you aggro extra mobs.
| -----------------
/if n $distance(@l1,@l2)==@distLastCheck {
/if n @gPausingForAggro==0 {
/if "@isCareful"=="CAREFUL" {
/echo Appear to be stuck... facing random heading and returning!
/face heading $rand(360)
/return
} else {
/echo Appear to be stuck... being careful and just waiting.
| @@TODO : Put the MineField Navigator code in here ^_^
}
}
}
/varset distLastCheck $distance(@l1,@l2)
}
} else {
/echo I'm rooted... not bothering with safe/careful checking
}
| End mainLoop
/if n $distance(@l1,@l2)>@gThreshold /goto :MainLoop2
/if "@doStopRunningWhenDone"=="STOPATDEST" {
/call AutoRun 0
/echo Destination reached - stopping
} else {
/echo Destination reached - not stopping
}
/return
sub MoveToPetHealDistance
| Return early (don't even face or target it) if pet in range
/if n $spawn($char(pet),distance)<gPetHealRange /return
/face loc $spawn($char(pet),y),$spawn($char(pet),x)
/echo Running to pet .. he's $spawn($char(pet),distance) away
/call AutoRun 1
:MoveToPetLoop
/face loc $spawn($char(pet),y),$spawn($char(pet),x)
/if n $spawn($char(pet),distance)>gPetHealRange /goto :MoveToPetLoop
/call AutoRun 0
/echo Pet is in heal range again
/return
sub MoveToTarget
| Return early (don't even face it) if pet in range
/if n $target(distance)<40 /return
/face
/echo Running to $target(name,clean)...
/call AutoRun 1
:MoveToTargetLoop
/face
/if n $target(distance)>40 /goto :MoveToTargetLoop
/call AutoRun 0
/echo I'm near $target(name,clean) now
/return
Sub AutoRun
/if n @Param0==1 {
/if n $char(speed)<=0 {
/keypress FORWARD hold
}
/return
}
/if n @Param0==0 {
/if n $char(speed)>0 {
/keypress FORWARD
}
/return
}
/return
Sub CheckForBuff
/declare l local
/for l 1 to 15
| Return if this buff is on
/if "$char(buff,@l)"=="@Param0" /return 1
/next l
/return 0
| Expects mob ID as parameter
| Values gLastConsiderVal will be set to:
| "KOS"
| "NOTKOS"
| "PENDING"
| "NONE"
Sub DoConsider
/declare idTemp local
/if n $target(id)>0 {
/varset idTemp $target(id)
} else {
/varset idTemp 0
}
/varset gLastConsiderVal "PENDING"
/call TargetByID @Param0
/consider
/delay 15
/doevents concheckKOS
/doevents concheckNOTKOS
/if n @idTemp>0 /call TargetByID @idTemp
/return
Sub OUGlobals
/declare gLastConsiderVal global
/declare gPausingForAggro global
/declare t_StuckTimeout timer
/declare SureCast_target global
/declare castState global
/declare ar_SwapSlot array
/declare SwapSlotCount global
/declare SwapLastUsed global
/declare ar_FriendlyPlayerSlot array
/declare FriendlyPlayerSlotCount global
/declare BuffList array
/declare BuffCount global
/varset gPausingForAggro 0
/varset SureCast_target 0
/varset BuffCount 0
/varset SwapSlotCount 0
/varset SwapLastUsed 0
/varset FriendlyPlayerSlotCount 0
/varset gLastConsiderVal "amiable"
/call InitHateList
/return
Sub TargetByID
/if n @Param0==0 {
/keypress CLEAR_TARGET
/return
}
/if n $target(id)==@Param0 /return
| /echo TargetByID(@Param0) -- $spawn(@Param0,name,clean) $spawn(@Param0,distance) away
/target id @Param0
/return
Sub AlsoNeedBuff
/varcalc BuffCount $int(@BuffCount+1)
/varset BuffList(@BuffCount) "@Param0"
/echo BuffList(@BuffCount) is @Param0
/return
Sub CastAllNeededBuffs
/declare l0 local
/declare l1 local
/for l0 1 to @BuffCount
| /echo Checking if you have #@l0: @BuffList(@l0) ...
/for l1 1 to 15
| Skip if this buff is on
/if "$char(buff,@l1)"~~"@BuffList(@l0)" {
/goto :RBD_DontNeedIt
}
/next l1
| -------------- Special Cases ---------------
/if "@BuffList(@l0)"~~"Summon Horse" {
/call SummonHorse
} else {
| /echo @BuffList(@l0) is a normal buff. Targetting self.
/call TargetByID $char(id)
}
| -----------------------------
/if "@BuffList(@l0)"!~"Summon Horse" {
/call SureCast "@BuffList(@l0)"
}
:RBD_DontNeedIt
/next l0
/return
| -------------------------------------------
| This is like the occutils CastAllNeededBuffs
| The difference is, this function also casts
| each buff on your duo partner.
| -------------------------------------------
Sub DUO_CastAllNeededBuffs
/declare l0 local
/declare l1 local
/for l0 1 to @BuffCount
| /echo Checking if you have #@l0: @BuffList(@l0) ...
/for l1 1 to 15
| Skip if this buff is on
/if "$char(buff,@l1)"~~"@BuffList(@l0)" {
/goto :DRBD_DontNeedIt
}
/next l1
| -------------- Special Cases ---------------
/if "@BuffList(@l0)"~~"Summon Horse" {
/call SummonHorse
} else {
| /echo @BuffList(@l0) is a normal buff. Targetting self.
/call TargetByID $char(id)
/call SureCast "@BuffList(@l0)"
/if n $group(1)>0 {
| @@TODO Find out $spell("Name",xxxxx) to determine if
| spell is self-only, group, or what.
| Otherwise you'll blow all your mana casting group spells
| once per member of the group.
/if "@BuffList(@l0)"!="Alacrity" {
/if "@BuffList(@l0)"!="Talisman of Jasinth" {
/if "@BuffList(@l0)"!="Spiritual Purity" {
/if "@BuffList(@l0)"!="Spiritual Dominion" {
/if "@BuffList(@l0)"!="Shield of the Arcane" {
/if "@BuffList(@l0)"!="Force Shield" {
/if "@BuffList(@l0)"!="Instrument of Nife" {
/call TargetByID $group(1)
/call SureCast "@BuffList(@l0)"
}}}}}}}
}
}
:DRBD_DontNeedIt
/next l0
/return
| --------------------------------------------------
| AddRadiustoHate(radius,x,y)
| --------------------------------------------------
Sub AddRadiusToHate
/declare npcid local
/declare firstnpcid local
/declare lastnpcid local
/declare radiusSearch local
/varset npcid 0
/varset firstnpcid 0
/varset lastnpcid 0
/varset radiusSearch @Param0
/varset npcid $searchspawn(npc,loc:@Param1:@Param2,radius:@radiusSearch)
:AddRadiusLoop
/delay 1
/if n @npcid==@firstnpcid {
/return
} else {
/varset lastnpcid @npcid
/varset npcid $searchspawn(npc,loc:@Param1:@Param2,id:@lastnpcid,radius:@radiusSearch,next)
/if n @lastnpcid!=0 {
/call AddHate @lastnpcid
}
}
/goto :AddRadiusLoop
/return
| Param0: (required) ID of mob to hate
| Param1: (optional) How much to hate it:
| 0 ignore this mob for now, but leave it on hateList
| 1 do *not* attack if this mob is not KOS
| 2 attack this mob as soon as you can
| >2 vals higher than 2 indicate a higher hate value.
| Every time your pet gets a "hate 00398493 more" it will
| add 1 to the hate for that mob.
|
Sub AddHate
/declare newSlot local
/declare a local
/declare newamt local
/varset newSlot 0
/echo addhate(@Param0, @Param1)
/if n @hateList_count>0 {
/for a 1 to @hateList_count
/if n @hateList(@a)==0 {
/if n @newSlot==0 /varset newSlot @a
}
/if n @hateList(@a)==@Param0 {
/if n @Param1>0 {
/varcalc newamt @hateListRating(@a)+@Param1
/varset hateListRating(@a) @newamt
/echo Increasing hate for $spawn(@Param0,name,clean) to @hateListRating(@a)
} else {
/echo $spawn(@Param0,name,clean) ID @Param0 already on list in spot @a
}
/return 0
}
/next a
}
/if n @newSlot==0 {
/varcalc hateList_count @hateList_count+1
/varset newSlot @hateList_count
}
/varset a $int(@newSlot)
/echo hateList(@a) = ID @Param0, $spawn(@Param0,name,clean), $spawn(@Param0,distance) away moving at $spawn(@Param0,speed)
/varset hateList(@a) @Param0
/if n @Param1>0 {
/varset hateListRating(@a) @Param1
/echo Setting initial hate rating for $spawn(@Param0,name,clean) to @hateListRating(@a)
}
/return 1
/return
Sub RemoveHate
/declare a local
/if n @hateList_count>0 {
/for a 1 to @hateList_count
/if n @hateList(@a)==@Param0 {
/echo Removing @Param0 from hatelist
/varset hateList(@a) 0
/varset hateListRating(@a) 0
/return
}
/next a
}
/return
Sub InitHateList
/declare hateList_count global
/declare hateList array
/declare hateListRating array
/declare a local
/for a 1 to 72
/varset hateList(@a) 0
/varset hateListRating(@a) 0
/next a
/varset hateList_count 0
/return
Sub RemoveDeadSpawnsFromHateList
/declare a local
/if n @hateList_count>0 {
/for a 1 to @hateList_count
/if "$spawn(@hateList(@a))"=="FALSE" {
/echo Removing missing spawn # @hateList(@a) from hatelist
/varset hateList(@a) 0
/varset hateListRating(@a) 0
} else {
/if "$spawn(@hateList(@a),state)"=="DEAD" {
/echo Removing dead spawn from #@a in hateList
/varset hateList(@a) 0
/varset hateListRating(@a) 0
} else {
/if n @isFighting!=@hateList(@a) {
/echo hateList(@a) = $spawn(@hateList(@a),name,clean), $spawn(@hateList(@a),distance) units away. Inc!
/call TargetByID @hateList(@a)
/if n $char(pet)>0 /pet attack
/call OfficiallyAggro
}
}
}
/next a
}
/return
sub SimpleLootAll
/declare LootSlot local
/varset LootSlot 0
/lootn never
/loot
/delay 2s
|**
:lootloop
/if n @LootSlot>=9 /goto :doneloot
/click left corpse @LootSlot
/delay 1s
/if "$cursor()"!="TRUE" /goto :doneloot
:lootChecker
/autoinventory
/delay 1s
/varadd LootSlot 1
/goto :lootloop
:doneloot
**|
/echo /click left corpse is still broken - using hardcoded numbers
/click right 34 192
/delay 5
/click right 80 190
/delay 5
/click right 42 234
/delay 5
/click right 76 238
/delay 5
/click right 22 276
/delay 5
/click right 86 278
/delay 5
/click right 50 324
/delay 5
/lootn always
/keypress CLOSE_TOP_WINDOW
/keypress CLOSE_TOP_WINDOW
/keypress CLOSE_TOP_WINDOW
/delay 1s
/return
| -------------------------------------------------------------------
| RecastBuff
| PARAMETERS:
| Param0: Should be some name like "Haste", "Crack" or "Regen"
| Param1: Player name to rebuff
|
| If you call this function with "Haste" as a parameter,
| It will assume @sn_Haste and @t_Haste exist. It expects
| @sn_Haste to name a valid spell your character can cast,
| and it expects @t_Haste to be a valid, global timer.
| -------------------------------------------------------------------
sub RecastBuff
/declare c local
/declare timerVal local
/declare spellName local
/varset spellName "@sn_@Param0"
/varset timerVal @t_@Param0
| /echo Recasting buff for @Param0 ... currently @spellName
| /echo Timer variable ( t_@Param0 ) has val @timerVal
/if n @timerVal<=0 {
/target PC "@Param1"
/call SureCast "@spellName"
/varcalc c $spell("@spellName",duration)*CHAR_BUFF_EXTENSION
/varcalc c @c*10
/varset t_@Param0 $int(@c)
| Now recalc jus