• You've discovered RedGuides, an EverQuest multi-boxing and scripting community 🧙‍♀️⚙️. We want you to play several EQ characters at once, come join us and say hello! 👋

  • A TLP without truebox has thawed (Very Vanilla ready)
    Frostreaver

My first macro, need help debugging

Fenix8452

Member
Joined
Sep 2, 2006
RedCents
101¢
Ok, I've never written a macro before but wanted to give it a shot. I may have set my sights a little high, but I'm working on a pally macro that can pull and kill only undead mobs in the area.

Rich (BB code):
|pallyslay.mac
|Author: Fenix with modified code inspired heavily by Crystane and help editing by Alatyami
|(9-27-08)	First attempt at making a simple macro
|(9-29-08)  Reworked parts of the code that were not functioning with help.  Tweaked movements a bit, cleaned up some of the stick commands.
|(9-30-08)	Multiple pulls and add handling working, cleaned up code to remove unneeded parts.  Added better handling of combat condition and mana regen durations.
|(10-1-08)	Added support for stacking issues with spells, and improved the definition of spells needing to be cast.  Also added checks of targets health while pulling as to not attempt to pull an engaged mob.  Added ability to detect if a camp is being taken by others and ends the macro at the home location.
|This should set up a base camp where the macro was started, locate the nearest undead, pull to this home spot, and kill it while watching
|	my health and healing where needed and medding where needed.  It should also keep a set of self buffs as well as ward up at all times.

#turbo
#Event EXP				"You gain experience#*#"
#Event BuffFade			"#1# fades."
#Event MyDeath			"You have been slain by#*#"
#Event CantSee			"You cannot see your target."
#Event CantSee			"You can't hit them from here."

#Include Spell_Routines.inc
#Include Itemcast.inc

Sub Main

|DistanceToStick used to determine how close the pulled mob is before using /stick command
/declare DistanceToStick	int outer	50

|SelfHealPoint is the percentage of health to trigger self healing.
/declare SelfHealPoint		int outer	50
/declare UseHoTPotion		int outer	35

|Spells setup
/declare PullSpell	string outer	Challenge for Honor Rk. III
/declare QuickHeal	string outer	Burst of Morrow Rk. II
/declare HoT		string outer	Solemn Cleansing Rk. II
/declare Nuke		string outer	Benediction Rk. II
/declare Ward		string outer	Sustenance of Tunare

|Buff definition
/declare SpellBuffs[6]	string outer
	/varset SpellBuffs[1]		Brell's Earthen Aegis Rk. II
	/varset SpellBuffs[2]		Oathbound Protector Rk. II
	/varset SpellBuffs[3]		Armor of Inexorable Faith Rk. II
	/varset SpellBuffs[4]		Righteous Fury Rk. II
	/varset SpellBuffs[5]		Blessed Aura
	/varset SpellBuffs[6]		Remorse for the Fallen Rk. II

|Item/Potion definition
/declare HoTPot		string outer	Distillate of Celestial Healing XIII
/declare ClickHeal	string outer	Mantle of the Wyrmguard
/declare EpicClick	string outer	Flames of the Valiant

/declare ItemBuffs[5]	string outer
	/varset ItemBuffs[1]		Wristplates of the Fallen Saint
	/varset ItemBuffs[2]		Mask of Lament
	/varset ItemBuffs[3]		Distillate of Alacrity X
	/varset ItemBuffs[4]		Distillate of Clarity XIII
	/varset ItemBuffs[5]		Distillate of Spirituality XIII

|Setup base camp
/declare HomeX		int outer	${Me.X.Int}
/declare HomeY		int outer	${Me.Y.Int}

|Mob Counter
/declare TotalMobs	int outer	0
/declare BadPulls	int outer	0
/declare BadPullsTotal	int	outer	10
/declare TarID		int	outer	NULL

|Target info
/declare TargetLocX	int outer
/declare TargetLocY	int outer

/declare PctToMed			int outer	40
/declare MaxPullDistance	int outer	800
/declare Rebuffstate 		bool	outer 	FALSE
/declare StillInCombat		bool	outer	FALSE
/declare NeedManaRegen		bool	outer	FALSE

/call SpellSetup

:Start

/if (${Me.Type.Equal[Corpse]}) {
	/echo I was killed
	/delay 5s
	/doevents MyDeath
	/goto :Start
	}

/if (${GameState.Equal[CHARSELECT]}) /endmacro
/call WardUpKeep
/call CheckMana
:FindLoop
/call FindTarget
/if (!${Target.ID}) {
	/delay 10s
	/if (${BadPulls} > ${BadPullsTotal}) {
		/echo Another person taking camp, closing macro.
		/endmacro
	}
	/goto :FindLoop
}
/call Pulling
:miniloop
/if (${Target.Distance} > ${DistanceToStick}) {
	/delay 2s
	/goto :miniloop
}
/call Combat
/call CheckSpellBuffs
/call CheckItemBuffs
/doevents
/goto :Start
/return

Sub SpellSetup
/if (${Me.Gem[${QuickHeal}]}!=1) {
	/memspell 1 "${QuickHeal}"
	/delay 6s ${Me.Gem[${QuickHeal}]}==1
}
/if (${Me.Gem[${HoT}]}!=2) {
	/memspell 2 "${HoT}
	/delay 6s ${Me.Gem[${HoT}]}==2
}
/if (${Me.Gem[${Ward}]}!=3) {
	/memspell 3 "${Ward}"
	/delay 6s ${Me.Gem[${Ward}]}==3
}
/if (${Me.Gem[${Nuke}]}!=6) {
	/memspell 6 "${Nuke}"
	/delay 6s ${Me.Gem[${Nuke}]}==6
}
/if (${Me.Gem[${PullSpell}]}!=7) {
	/memspell 6 "${PullSpell}"
	/delay 6s ${Me.Gem[${PullSpell}]}==7
}
/return

|Casts ward until successful
Sub WardUpKeep
/if (${Me.Buff[${Ward}].Duration}>5) /return
/call Cast "${Ward}"
/return

|If my mana is below the set point and no mob is close to me, then sit.  Check every 10 seconds.
Sub CheckMana
/if (${SpawnCount[npc radius 50]} > 0) /return
/if (${NeedManaRegen}) {
	/sit
	/goto :Manaloop
}
/if (${Me.PctMana} > ${PctToMed}) /return
/varset NeedManaRegen TRUE
/sit
:Manaloop
/echo Medding, only at ${Me.PctMana} mana.
/delay 10s
/if ((${Me.PctMana}<80)&&(${SpawnCount[NPC radius 50]}<1)) /goto :Manaloop
/stand
/echo Done medding, resuming pulls.
/return

Sub CheckSpellBuffs
/if (!${Rebuffstate}) /return
/Echo Checking Buffs
/declare i int local 1
/for i 1 to ${SpellBuffs.Size}
	/if (!${Me.Buff[${SpellBuffs[${i}]}].ID} && !${Me.Song[${SpellBuffs[${i}]} Effect].ID && ${Spell[${Spellbuffs[${i}]}].Stacks}) {
		/target ${Me.Name}
		/echo Rebuffing ${SpellBuffs[${i}]}
		/call Cast "${SpellBuffs[${i}]}" gem5
	}
/next i
/return

Sub CheckItemBuffs
/if (!${Rebuffstate}) /return
/declare i int local 1
/for i 1 to ${ItemBuffs.Size}
	/if (!${Me.Buff[${FindItem[${ItemBuffs[${i}]}].Spell}].ID}) {
		/call ItemCaster "${ItemBuffs[${i}]}"
		/delay 2
	}
/next i
/varset Rebuffstate FALSE
/return

Sub FindTarget
/Echo Finding nearest undead target
/call Cast "Sense the Dead" gem5
/if (${Target.Distance}>${MaxPullDistance} || ${Target.PctHPs} < 98) {
	/target clear
	/varcalc BadPulls (${BadPulls} + 1)
}
/return

Sub Pulling
/if (!${Target.ID}) /return
/face fast
/if (${Target.Distance}<200) /goto :Castpull
:moveloop
/declare i int local 1
/for i 1 to 400
	/keypress forward hold
	/delay 1s (${Target.Distance} > 200 && ${Target.PctHPs} > 98)
	/keypress forward
	/face fast
	/if (${Target.Distance} < 200 && ${Target.PctHPs} > 98) /goto :Castpull
/next i
:Castpull
/delay 1s
/call Cast "${PullSpell}" gem7
/call ReturnHome
/return

Sub ReturnHome
/face fast nolook loc ${HomeY},${HomeX}
/declare j int local 1
/for j 1 to 400
	/keypress forward hold
	/delay 0.5s
	/keypress forward
	/face fast nolook loc ${HomeY},${HomeX}
	/if (${Math.Distance[${HomeY},${HomeX}]}<15) /goto :Athome
/next j
:Athome
/if (${Target.ID}) {
	/face fast
	/varset StillInCombat TRUE
}
/return

Sub Combat
/if (!${StillInCombat}) /return
/stick 12
/attack on
:CombatLoop
/if (${SpawnCount[PC ${Me.Name}]}<1) {
	/doevents ImDead
	/return
}
/call WardUpKeep
/doevents
/if (${StillInCombat}) {
	/if (${Me.SpellReady[${Nuke}]} && ${Select[${Target.Body},Undead]}==1 && ${Me.PctMana}>20) /call Cast "${Nuke}"
	/if (${Me.AbilityReady[Bash]}) /doability Bash
	/call Cast "Nightbane, Sword of the Valiant"
	/if (${Me.Song[${EpicClick}].ID}) /call Cast "${ClickHeal}" item 2s
	/if (${Me.PctHPs}<${SelfHealPoint}) {
		/varset TarID ${Target.ID}
		/target ${Me.Name}
		/delay 1s
		/call Cast "${QuickHeal}" ${Me.Gem[${QuickHeal}]} 5s
		/target id ${TarID}
	}
	/if (${Me.PctHPs}<${UseHoTPotion}) /call ItemCaster "${HoTPot}"
	/goto :CombatLoop
}
/call Combat
/return

Sub Event_EXP
/varcalc TotalMobs (${TotalMobs}+1)
/stick off
/varset StillInCombat FALSE
/delay 3s
/target npc
/delay 1s
/echo Checking nearest mob distance
/if (${Target.Distance}<${DistanceToStick}) {
	/varset StillInCombat TRUE
	/stick 12
	/attack on
}
/delay 1s
/return

Sub Event_MyDeath
/echo Death takes us all eventually
/echo Ending Macro
/endmacro
/return

Sub Event_BuffFade
/varset Rebuffstate TRUE
/return

Sub Event_CantSee
/stick off
/keypress back hold
/delay .5s
/keypress back
/face fast
/stick 12
/return

EDIT: Recent changes should now check the pull mobs health before running and trying agro something already engaged. This is still best used in a safe spot and away from other players, but I'm adding basic checks to make this a little more useful. Next will be GM checks and other player checks, as I'm more concerned with doing this as safely as possible rather than grind as fast as possible.

Changed the code for setting off the epic click, but its not yet tested. I'll continue to update here in case anyone else wants to use this little project of mine.
 
Last edited:
I'm going threw this line by line ... I like the way you are using arrays, good job.

Something that I always do when I am having issues with a mac is run what I can manually and see if it works.

By doing this you'd see that you have a spelling error:
Rich (BB code):
Line 208: |/if (${Me.AbilityReady[Bash]}) /doabilty Bash
New Line: |/if (${Me.AbilityReady[Bash]}) /doability Bash

Now as far as your item clicking:

Rich (BB code):
Line 209: |/if (${Me.SpellReady[${EpicClick}]) /call Cast "${EpicClick}"
Line 210: |/if (${Me.SpellReady[${ClickHeal}]) /call Cast "${ClickHeal}"

Reading the ItemCast.inc (new one for me, never used it before), the function that you want to call is "Sub ItemCaster(ItemToCast)". So you need to change the above to:

Rich (BB code):
Line 209: |/if (${Me.SpellReady[${EpicClick}]) /call ItemCaster "${EpicClick}"
Line 210: |/if (${Me.SpellReady[${ClickHeal}]) /call ItemCaster "${ClickHeal}"

Make these changes, then we can look at your targeting issue.

~Alatyami
 
Last edited:
I started looking at your targeting ... my main is a cleric so I've got the whole self healing down.

Before:
Rich (BB code):
/if (${Me.PctHPs}<${SelfHealPoint}) {
	/target myself
	/delay 1s
	/call Cast "${QuickHeal}" 5s
	/target id ${TarID}
}

Alatyami'fied:
Rich (BB code):
/if (${Me.PctHPs} < ${SelfHealPoint}) {
	/target ${Me.Name}
	/delay 1s
	/call Cast "${QuickHeal}" ${Me.Gem[${QuickHeal}]} 5s
	/target id ${TarID}
}

I usually don't put a limit on casting retries, so I went spell_routines.inc and the following syntax is available for Sub Cast:

Rich (BB code):
Sub Cast(spellName,spellType,giveUpValue,mySub,int ResistTotal)

The way that you had it, you were telling the function that the spellType was "5s". "${Me.Gem[${QuickHeal}]}" should return the spell gem for the given spell.

"/target id ${TarID}" This is a tricky one, because it is based on the assumption that you were already in combat and that target has not died yet.

Found another Cast vs. ItemCaster ...

Rich (BB code):
/if (${Me.PctHPs}<${UseHoTPotion}) /call Cast "${HoTPot}"

Rich (BB code):
/if (${Me.PctHPs}<${UseHoTPotion}) /call ItemCaster "${HoTPot}"


Hope this helps ....

~Alatyami
 
This helps a ton, thank you very much. I will make the changes and continue to debug after my raid.

and /slap forehead on the spelling mistake, I typed all of this out before ever trying any of it, because I was bored at work and had free time.
 
The self healing worked perfectly, I'm still having trouble with my item clicks though.

I get the error saying

unparsable in Calculation: '$'
pallyslay.mac@209 (Combat): /if (${Me.SpellReady[${EpicClick}]) /call ItemCaster "${EpicClick}"

and

Failed to parse /if condition '/if (${Me.SpellReady[Nightbance, Sword of the Valiant])', non-numeric encountered.

I get the same thing with the clicky should heals. Once those are commented out it seemed to go pretty well ish, but I've not had alot of time to test it.

EDIT:

Ok, I kinda sorta found out what the issue was. Just a dumb typing error in that I didn't close the brackets. However, now that I have that corrected, it still won't use the clicky items. I've not gotten his health down low enough to check the potion click, but since the others don't click...

I'm debating just relying on the exchange plugin to do some of this stuff. It's lazy, but it works. I also made some other tweaks to the code and its semi-working. I was amazed when I first saw it kill 2 undeads in a row and then continue to pull and kill more. I can see why this is addictive.
 
Last edited:
Don't give up yet!

Try this in the MQ2 window:
Rich (BB code):
/call ItemCaster "Nightbance, Sword of the Valiant"
 
can't call if I'm not within a macro, so I'll have to try it when I have a chance to be running this. My test spot is currently camped ><

Ok, itemcaster is definately working, the issue must be in the check to see if the item is ready to be used. So I could always use a timer of some kind, unless there is another way of checking to see if an item is ready to be used.
 
Last edited:
Good point!

There is a way to check the value, I just can't remember right now :D
 
Updated the code in the first post here, it now includes checks againt the target type so I'm not spamming an undead nuke on something that isn't undead. Also included a new event that should help if the mob gets on top of me and I can't hit.

I think I have a solution (although not perfect) for clicking the epic in my main slot, and then firing off the heal when its on so I always get the most heal out of it. Will be testing more when I get home from work.

I'm amazed that there isn't some way of spawnsearching for undead mobs. I really don't like using sense the dead for this, since the spell is goofy at best, but it works for now.
 
Line 103 Error, missing double quote:

Rich (BB code):
/call Cast "${Ward}
 
Awesome ... now it just needs to come with a free pally ...
 
Ok here you go ... I asked the MQ2 guys for a solution .... to determine if your item's clicky is ready or not

${FindItem[X].Timer}

So, what we are doing is checking to see if the item has a timer, if it does then the spell is not ready.


~Alatyami
 
Ok, I'll put that into use, thanks for the heads up. Right now I am simply having it call it every combat round. I didnt' do that at first because I thought it would be stuck there continueing to try until it succeeded. Apparently not.

So something like:
/if (!${FindItem["Nightbane, Sword of the Valiant"].Timer}) /call Cast "Nightbane, Sword of the Valiant" item

And I still need to convert a few more things over variable so it can be modified easily. Perhaps just have it set as ${EpicName} and then do an additional check like:
/if ((${EpicName}!=NULL) && (!${FindItem[${EpicName}].Timer})) /call Cast "${EpicName}" item
 
Don't forget the quotes ....

Rich (BB code):
/if ((${EpicName}!=NULL) && (!${FindItem["${EpicName}"].Timer})) /call Cast "${EpicName}" item

because of the comma in the name.

~Alatyami
 
It seems my subscription has dried up for the moment. So no clue if MQ2 is up and working yet. As soon as I can arrange to get this back, I wil continue to update this and make this more effective.

EDIT: back in action it seems. I have a new writeup for this, but I've not had a good chance to test it. As soon as I know its not broken, there will be an update on this.
 
Last edited:
So I had a complete and utter distaster crash of my PC less than a week ago. And with it went all my files and incompleted projects. Including my updated version of this macro with all the improvements I had put in.

/sigh.

So, I'm starting from whats posted here again, and I will have some updates soon, however my common designed spot for this in direwind has been camped to hell since the expansion, and I'm still grinding pretty hard to get to 85, so it'll probably be delayed a bit. I didn't forget about this, and I have another side project/macro I'm working on for something completely unrelated.
 
That sucks. I'm looking forward to seeing the final product.
 
My first macro, need help debugging

Users who are viewing this thread

Back
Top
Cart