Moderator: MacroQuest Developers
It does this because the mob warps far far away; it's not the problem of the macro itself.tac8357 wrote:Well after about 30 mins of good hunting it kinda goes wacko, it will circle the mob till it hits 18 percent then it seems to shoot off in a straight line to no where. No sure why it does that it works great for about 30 mins.
Code: Select all
| - chant.mac - By Raebis
|
| This mac is used mostly for big open zones with not a lot of
| big hills (cause hills cause pain - unless you have levitate)
|
| Features:------------------------------------------------------------------------
|
| * Automatically selects high light blue, dark blue, or white mob
| * Runs to mob before targeting it (Stealth! No cross-zone targeting!)
| * Aggro/Add Detection: Automatically targets and kites aggroed mobs (adds)
| * Ignores greens and low light blues unless they are aggroed (adds)
| * Caster Detection: Automatically will switch target to aggroed casting mobs
| * Compatible with level 49 and level 6 selos
|
| ---------------------------------------------------------------------------------
|
| usage: chant.mac <DOTs> <49selo> <radius> [<heal song>]
|
|
| Usage Examples:
| -Scenario 1: If you are using...
| ...DOTs in Gems 1, 2, 3, and 4
| ...Level 49 Selo in Gem 5
| ...Hymn of Restoration in Gem 6
| ...Radius of 55
| syntax: /mac chant 1234 5 55 6
|
| -Scenario 2: If you are using...
| ...DOTs in Gems 1 and 2
| ...Level 6 Selo in slot 3
| ...No Healsong
| ...Radius of 80
| syntax: /mac chant 123 0 80
|
|
| If <heal song> is defined then when health goes below @HealthMin (default is 70%)
| it will replace the first song in <DOTs> with <heal song> until health is above
| @HealthMax (default is 85%)
|
| If <selo> is 0 then the macro will not try to cast selos every 150 seconds
|
| [REV3 was] Tested in in burning woods (for 1 hours); east wastes (for 2 hours), PoM (for 30 mins)
|
| Warning: You WILL wander around the zone, thought in ew for an hour i pretty
| much stayed east of the kael zone and didn't wander too much
|
| REV4nt Dec 22 22:45
|
| Note: REV4nt has not been tested yet due to MQ2 updating
|
#event MissedNote "You miss a note, bringing your song to a close!"
#event NeedTarget "You must first select a target for this spell!"
#event Slow "you slow down"
#event Exp "You gain "
#event Tell "tells you"
#event Recovered "You haven't recovered yet..."
#event Died "You have entered"
#event Caster " begins to cast a spell."
#turbo
Sub Main(DOTs,Selos,CRadius,HealSong)
/zapvars
/if $defined(CRadius)==false {
/echo usage: chant.mac <DOTs> <49selo> <radius> [<heal song>]
/return
}
/declare CirR global
/declare Songs array
/declare nSongs global
/declare CurSong global
/declare PrevSong global
/declare Exper global
/declare AAExp global
/declare SongTimer timer
/declare SeloTimer timer
/declare SelosSong global
/declare HealSong global
/declare OrigSong global
/declare HealthMin global
/declare HealthMax global
/declare DBLevel global
/declare LBLevel global
/declare GettingTarget global
/declare TargetUpNext global
/declare EachSong local
/varset nSongs $strlen(@DOTs)
/for EachSong 1 to @nSongs
/varset Songs(@EachSong) $mid($calc(@EachSong-1),1,@DOTs)
/echo Song @EachSong: $char(gem,@Songs(@EachSong)
/next EachSong
/if n @Selos!=0 {
/varset SelosSong $calc(@nSongs+1)
/varset Songs(@SelosSong) @Selos
/echo Selo's: $char(gem,@Songs(@SelosSong))
} else {
/varset SelosSong 0
/echo Not using level 49 Selos.
}
/if $defined(HealSong)!=false {
/varset HealSong @HealSong
/echo Healsong: $char(gem,@HealSong)
} else {
/echo No HealSong. Please watch your health.
}
/varset CirR @CRadius
/echo Radius: @CRadius
/varset OrigSong @Songs(1)
/varset CurSong 1
/varset Exper $char(exp)
/varset AAExp $char(aa,exp)
/varset SongTimer 64
/varset SeloTimer 0
/varset LBLevel $calc($calc($char(level)*.66)+1)
/varset DBLevel $calc($calc($char(level)*.7)+1)
/varset HealthMin 70
/varset HealthMax 85
/varset TargetUpNext 0
:Loop
[color=darkred] /if n $target(hp,pct)<=15 /if n $target(distance)>2000 {
/cleanup
/echo Target warped, acquiring another
/call gettarget
} [/color]
/if n @TargetUpNext<=0 /if n $target(id)<=0 {
/call gettarget
}
/if n @TargetUpNext>0 /if n $target(id)>0 {
/echo User Selected Target or Aggroed while running
/varset TargetUpNext 0
}
/if n @SelosSong==0 /varset SeloTimer 10000
/if n @SeloTimer<=0 {
/varset CurSong @SelosSong
/varset SeloTimer 1500
/call Sing
}
/if n @SeloTimer<1460 /if n $char(speed)<=100 /if n $char(speed)>40 {
/echo Selos down for some reason... casting $char(gem,@Songs(5))
/varset CurSong @SelosSong
/varset SeloTimer 1500
/call Sing
}
/if $defined(HealSong)!=false /if n @SeloTimer<1460 {
/if n $calc($calc($char(hp,cur)/$char(hp,max))*100)<@HealthMin {
/if n @Songs(1)!=@HealSong {
/echo Healing On - Health: $char(hp,pct)% to @HealthMax%
/varset Songs(1) @HealSong
}
} else /if n $calc($calc($char(hp,cur)/$char(hp,max))*100)>@HealthMax {
/if n @Songs(1)!=@OrigSong {
/echo Healing Off
/varset Songs(1) @OrigSong
}
}
}
/if n @SelosSong!=0 {
/if n @SeloTimer<1460 /if n @SongTimer<=0 /call Sing
} else {
/if n @SongTimer<=0 /call Sing
}
/call circ
/doevents
/delay 0
/goto :Loop
/return
Sub Sing
/stopsong
/cast @Songs(@CurSong)
/varset PrevSong @CurSong
/varadd CurSong 1
/varset SongTimer 32
/doevents
/if n @CurSong>@nSongs /varset CurSong 1
/return
Sub circ
/declare CirX local
/declare CirY local
/if n @TargetUpNext>0 {
/varset CirX $spawn(@TargetUpNext,y)
/varset CirY $spawn(@TargetUpNext,x)
/if n $spawn(@TargetUpNext,distance)<=$calc(@CirR*1.2) {
/target id @TargetUpNext
/varset TargetUpNext 0
}
}
/if n $target(id)>0 {
/varset CirX $target(y)
/varset CirY $target(x)
}
/if n $distance(@CirX,@CirY)<$calc(@CirR/2) {
/face heading $calc($heading(@CirX,@CirY)+180)
} else {
/face heading $calc($heading(@CirX,@CirY)+$calc(90*$calc(@CirR/$distance(@CirX,@CirY))))
}
/return
Sub Event_MissedNote
/varset CurSong @PrevSong
/varset SongTimer 0
/doevents
/return
Sub Event_Recovered
/if n @CurSong!=$calc(@SelosSong-1) {
/varset CurSong @PrevSong
/varset SongTimer 0
} else {
/varset CurSong @SelosSong
/varset SeloTimer 1500
/call Sing
}
/doevents
/return
Sub Event_NeedTarget
/if n @TargetUpNext<=0 {
/call gettarget
}
/doevents
/return
Sub Event_Tell
/beep
/doevents
/return
Sub Event_Died
/delay 10
/sit
/delay 10
/camp desktop
/return
Sub Event_Exp
/varset AAExp $calc($char(aa,exp)-@AAExp)
/varset Exper $calc($char(exp)-@Exper)
/echo EXP: @Exper%:$char(exp)% - AAXP: @AAExp%:$char(aa,exp)% - $calc($running/60) minutes
/varset Exper $char(exp)
/varset AAExp $char(aa,exp)
/varset LBLevel $calc($calc($char(level)*.66)+1)
/varset DBLevel $calc($calc($char(level)*.7)+1)
/if n @TargetUpNext<=0 /if n $target(id)<=0 {
/call gettarget
}
/if n @SeloTimer<1460 {
/stopsong
/varset CurSong 1
}
/varset SongTimer 0
/doevents
/return
Sub gettarget
/declare SID1 local
/if n @GettingTarget==1 /goto :GotId
/varset GettingTarget 1
/varset SID1 $searchspawn(npc,radius:$calc(@CirR*1.2))
/if n @SID1>0 /if n $spawn(@SID1,level)>$calc(@LBLevel-3) /if n $spawn(@SID1,level)<=$char(level) /if n $spawn(@SID1,speed)>100 {
/target id @SID1
/echo Kiting aggro'd mob: $target(name,clean)
/goto :GotId
}
/varset SID1 $searchspawn(npc)
:NeedId
/if n $spawn(@SID1,level)>@DBLevel /if n $spawn(@SID1,level)<=$char(level) {
/varset TargetUpNext @SID1
/echo TargetUpNext: $spawn(@TargetUpNext,name,clean) Distance: $spawn(@TargetUpNext,distance)
/goto :GotId
} else {
/varset SID1 $searchspawn(npc,"id:@SID1","next")
}
/goto :NeedId
:GotId
/varset GettingTarget 0
/return
Sub Event_Caster(CastText)
/declare CastLen local
/declare CastPut local
/declare SID2 local
/varset CastLen $calc($strlen("CastText")-24)
/varset CastPut $left(@CastLen,"CastText")
/varset SID2 $id(@CastPut)
/if $spawn(@SID2,type)!=NPC /return
/if n $target(id)==@SID2 /return
/if n $spawn(@SID2,distance)<=$calc(@CirR*1.2) /if n $spawn(@SID2,level)>$calc(@LBLevel-3) /if n $spawn(@SID2,level)<=$char(level) /target id @SID2
/return
Yes i found a bug where healing doesn't work if you don't have level 49 selos. Will be fixed in the next rev (pm me if you want quick-fix)El wrote: 1. Healing just doesn't work. I got beat on regularly from agroed mobs, and it didn't kick in once.
This also when using level 6 selos, if you kill a mob the song list gets reset to zero and sow could wear off thenEl wrote:2. There seems to be a timing problem with level 6 selo's. After awhile (>5 minutes?), Selo's would just wear off. No missed notes, no stuns or anything. It would just wear off and not be recast before I was beat into a pulp.
I dunnoEl wrote:3. With the warnings about #turbo in other threads, is it necessary to have it on?
Make sure you have numlock/autorun on. Also it doesn't get a target until the target is within range (feature of the no cross zone targeting)El wrote:4. If you have no target when you start this macro, it stands in one place and shivers. Occasionally (maybe 3 times in 5 hours of testing?), I would lose my target, and then the mobs I had agroed would catch up and beat on me.
Yes, i'm going to be implementing better target verification as wellEl wrote:Once, I drank a sow potion while kiting, which targeted myself, and the macro then proceeded to dot me while trying to circle myself. Yay for stupidity. Need some way of retargeting your agroed mobs if the target shifts or is lost.
Holy crap... maybe laterEl wrote: 5. Asking for the moon, I know, but it would be way cool if the macro could switch instruments.
Thanks :)El wrote: Other than those minor items, this is a very good macro. I wish I could aoe kite my mobs as well as this does :-)
If I understand your thinking here. (pretty sure I doRaebis wrote:In testing right now is a sort of rubber anchor, which does exactly what you need... This anchor will target the mob closest to the original starting point instead of targeting the mob closest to u
I will look into the add issue as well.
Code: Select all
| Run your character to the center of your hunting area and provide a large enough radius so that you stay in a safe area.
| Then you set a variable with your starting loc.
/declare StartX global
/declare StartY global
/declare MobID global
/varset StartX $char(x)
/varset StartY $char(y)
| Then when you do your $searchspawn it should be giving you mobs that are closest to the loc:x:y that you were standing at when you started the script.
| Also note that you can specify level ranges. This should cut down alot of /if statements I saw in your code. This will exclude anything not in your range limits.
/varset MobID $searchspawn(npc,range:@minlvl:@maxlvl,loc:@StartX:@StartY,radius:@radiussize)