autobuff module (was: buffbot)

Post your completed (working) macros here. Only for macros using MQ2Data syntax!

Moderator: MacroQuest Developers

User avatar
gimp
a grimling bloodguard
a grimling bloodguard
Posts: 584
Joined: Fri Oct 29, 2004 9:28 am
Location: internet

autobuff module (was: buffbot)

Post by gimp » Tue Feb 08, 2005 6:25 am

Here's a dynamic script for auto-buffing. If not told otherwise, it defaults to only accept buff requests from your guildies. It can also be configured to buff ppl of e certain guild (if your bot happens to be unguilded). You can also optionally add a "whitelist" of non-guilded friends in the [PlayerName_AllowedPlayers] section in the ini-file.
The text parsing contains some simple tricks to decipher common buff-beggage but may require tweaking, buffnames and addverbations seem to differ slightly from server to server.
The ini-file contain info for common druid buffs, just rip it out and replace with whatever class you're playing.
While running this module i suggest you have at least the most commonly requested buff memorized at all times, or it'll have to memorize the buff, cast spell & restore old spell gem.

In your script:

Code: Select all

#include spell_routines.inc

#define NOT_FOUND			0
#define INI_FILE			yourinifile.ini
#include gimp_buffrequests.inc
Basic useage: /tell buffbot ss plz

|changes:
| * made into include
| * changed INI format to allow one ini file for multiple characters
| * put name of guild to buff in ini instead
| * auto disabled for melee classes
| * restores old spell if it was changed
| * predefined default spell slot: DEFAULT_SPELL_SLOT
| * ignores requests containing the , letter since they mess up the ini functions
| * uses a free spell gem for the spell if available
| * handles buff requests from group members

|Note: If BuffGuild is undefined in INI_FILE under ${Me.Name} section, ${Me.Guild} will be used

Code: Select all

| gimp_buffrequests.inc

#Event HandleBuffRequest "#1# tells you, '#2#'"
#Event HandleBuffRequest "#1# tells the group, '#2#'"

|If no spell slots are free, it will default to using this slot for buffing (old spell will be restored when done)
#Define DEFAULT_SPELL_SLOT		5

|Handle incomming command
Sub Event_HandleBuffRequest(FullText, Player, Text)

	/if (!${gimp_buffrequests_loaded}) {
		/declare gimp_buffrequests_loaded			int		outer	1
		/declare gimp_buffrequests_activated		int		outer	1
		/declare gimp_buffrequests_AllowedGuild		string	outer
		
		/if ( ${Me.Class.Name.Equal["Bard"]} || ${Me.Class.Name.Equal["Berserker"]} || ${Me.Class.Name.Equal["Monk"]} || ${Me.Class.Name.Equal["Rogue"]} || ${Me.Class.Name.Equal["Warrior"]} ) {
			/echo gimp_buffrequests.inc disabled for melee classes
			/varset gimp_buffrequests_activated 0
			/return
		}

		/declare str string local
		/varset str 	${Ini[INI_FILE, ${Me.Name}, BuffGuild,]}

		/if (${str.NotEqual[NULL]}) {
			/varset gimp_buffrequests_AllowedGuild ${str}
		} else {
			/varset gimp_buffrequests_AllowedGuild ${Me.Guild}
		}

		/echo gimp_buffrequests.inc initialized
		/echo * Accepting <${gimp_buffrequests_AllowedGuild}> members
	}
	
	/if (!${gimp_buffrequests_activated}) {
		/return
	}

	/declare CheckStr			string	local
	/declare AllowedBuff		int		local	NOT_FOUND
	/declare RequestedBuff		string	local
	/declare i					int local 0
	/declare OldSpell			string	local
	/declare SpellSlot			int local

	|Is player in zone?
	/if (!${Spawn[${Player}].ID}) {
		|/echo # Debug: ${Player} not in zone said: ${Text}
		/return
	}

	/if (${Spawn[${Player}].GM}) {
		/beep
		/echo # GM ${Player} told me: ${Text}
	}

	/if (${Spawn[${Player}].Type.NotEqual["PC"]}) {
		|/echo # Debug: Ignoring non-player ${Player} (${Spawn[${Player}].Type})
		/return
	}
	
	|Checking if player is in specified guild, or in white-list
	/if (${Spawn[${Player}].Guild.NotEqual[${gimp_buffrequests_AllowedGuild}]}) {

		/varset AllowedBuff ${Ini[INI_FILE, ${Me.Name}_AllowedPlayers, ${Player}, NOT_FOUND]}

		/echo allowedbuff: ${AllowedBuff}
		/if (${AllowedBuff} == NOT_FOUND) {
			/echo # Debug: Ignoring request '${Text}' from ${Player}
			/return
		}
		/echo # Debug: ${Player} is whitelisted (${AllowedBuff})
	}

	|Is player in line of sight?
	/if (!${Spawn[${Player}].LineOfSight}) {
		|/echo # Debug: ${Player} asked for buff but is not in LoS
		/return
	}

	/varset RequestedBuff ${Text}
	/if (${RequestedBuff.Right[50].Equal["Sorry, I am A.F.K. (Away From Keyboard) right now."]})	/varset RequestedBuff ${RequestedBuff.Left[-50]}
	
	/if (${RequestedBuff.Left[12].Equal["can i get a "]})	/varset RequestedBuff ${RequestedBuff.Right[-12]}
	/if (${RequestedBuff.Left[10].Equal["can i get "]})		/varset RequestedBuff ${RequestedBuff.Right[-10]}
	/if (${RequestedBuff.Left[ 8].Equal["can you "]})		/varset RequestedBuff ${RequestedBuff.Right[-8]}

	/if (${RequestedBuff.Right[3].Equal[" =)"]})			/varset RequestedBuff ${RequestedBuff.Left[-3]}
	/if (${RequestedBuff.Right[3].Equal[" :)"]})			/varset RequestedBuff ${RequestedBuff.Left[-3]}
	/if (${RequestedBuff.Right[2].Equal[" )"]})				/varset RequestedBuff ${RequestedBuff.Left[-2]}
	/if (${RequestedBuff.Right[1].Equal["?"]})				/varset RequestedBuff ${RequestedBuff.Left[-1]}
	/if (${RequestedBuff.Right[1].Equal["!"]})				/varset RequestedBuff ${RequestedBuff.Left[-1]}

	/if (${RequestedBuff.Right[4].Equal[" hun"]})			/varset RequestedBuff ${RequestedBuff.Left[-4]}
	/if (${RequestedBuff.Right[4].Equal[" wmp"]})			/varset RequestedBuff ${RequestedBuff.Left[-4]}
	/if (${RequestedBuff.Right[4].Equal[" thx"]})			/varset RequestedBuff ${RequestedBuff.Left[-4]}

	/if (${RequestedBuff.Right[13].Equal[" when you can"]})	/varset RequestedBuff ${RequestedBuff.Left[-13]}
	/if (${RequestedBuff.Right[3].Equal[" me"]})			/varset RequestedBuff ${RequestedBuff.Left[-3]}
	/if (${RequestedBuff.Right[3].Equal[" ty"]})			/varset RequestedBuff ${RequestedBuff.Left[-3]}
	/if (${RequestedBuff.Right[4].Equal[" plz"]})			/varset RequestedBuff ${RequestedBuff.Left[-4]}
	/if (${RequestedBuff.Right[4].Equal[" pls"]})			/varset RequestedBuff ${RequestedBuff.Left[-4]}
	/if (${RequestedBuff.Right[7].Equal[" please"]})		/varset RequestedBuff ${RequestedBuff.Left[-7]}
	/if (${RequestedBuff.Right[7].Equal[" thanks"]})		/varset RequestedBuff ${RequestedBuff.Left[-7]}
	
	/if (${RequestedBuff.Length} < 1) {
		|/echo # Debug: too short text
		/return
	}
	
	/if (${RequestedBuff.Length} > 25) {
		/echo # Debug: too long text
		/return
	}

	|Ignore strings containing , since they mess up ini read functions
	/if (${RequestedBuff.Find[,]}) {
		/echo # Debug: ignoring requests containing ,
		/return
	}

	|Process request
	/varset CheckStr ${Ini[INI_FILE, ${Me.Name}_RecognizedBuffs, ${RequestedBuff}, NOT_FOUND]}

	/if (${String[${CheckStr}].Equal[NOT_FOUND]}) {

		/echo # Debug: buffreq parsed to: ${RequestedBuff}
		|/docommand /tell ${Player} unknown buff
		/return

	} else {

		|Is player in range? ${Spell[name].Range} just works if spell already is memmed
		/if (${Spawn[${Player}].Distance} > 100) {
			/echo # Debug: ${Player} asked for buff but is oor (${Spawn[${Player}].Distance})
			/return
		}

		/echo # Buffing ${Player} with '${CheckStr}' (${Text})
		|/docommand /tell ${Player} inc ${CheckStr}

		|If spell is not memorized in any spell gem slot, find first free slot, else put in DEFAULT_SPELL_SLOT
		/if (!${Me.Gem["${CheckStr}"]}) {

			|Fixme: do i have 9th slot AA?
			/for i 1 to 9
				/if (!${Me.Gem[${i}].ID}) {
					/varset SpellSlot ${i}
				}
			/next i
			
			|Find first free spell slot, if none is free, fall back to DEFAULT_SPELL_SLOT
			/if (!${SpellSlot}) {
				/echo falling back to default slot since they full
				/varset SpellSlot DEFAULT_SPELL_SLOT
			}

			/varset OldSpell ${Me.Gem[${SpellSlot}]}
			/echo debug: oldspell: ${OldSpell}
			/memspell ${SpellSlot} "${CheckStr}"
		}

		/target pc ${Player}
		
		:loop
		/if (!${Me.SpellReady[${CheckStr}]}) {
			/goto :loop
			/delay 5
		}

		/call Cast "${CheckStr}"
		/echo # Debug: Done buffing ${Player}

		|Restore old spell gem
		/if (${String[${OldSpell}].NotEqual[NULL]}) {
			/delay 2s
			/echo # Debug: Restoring old spell: ${OldSpell} in slot ${SpellSlot}
			/memspell ${SpellSlot} "${OldSpell}"
		}
	}

/return
buffbot.ini:

Code: Select all

[PlayerName]
BuffGuild=Guild name (optional entry, falling back to your own guild name if not specified)

[PlayerName_AllowedPlayers]
MyFirstFriend=1
MySecondFriend=1

[PlayerName_RecognizedBuffs]
po9=Steeloak Skin
pot9=Steeloak Skin
9=Steeloak Skin
nine=Steeloak Skin
pot10=Steeloak Skin
steeloak=Steeloak Skin
steelowk=Steeloak Skin
steeloak skin=Steeloak Skin
ss=Steeloak Skin
skin=Steeloak Skin
steel=Steeloak Skin
oak=Steeloak Skin

soe=Spirit of Eagle
eagle=Spirit of Eagle
spirit of eagle=Spirit of Eagle
spirit of eagles=Spirit of Eagle
foe=Flight of Eagles
flight of eagle=Flight of Eagles
flight of eagles=Flight of Eagles

pos=Protection of Seasons
season=Protection of Seasons
seasons=Protection of Seasons

str=Nature's Might
natures might=Nature's Might

eb=Everlasting Breath
ds=Nettle Shield
regen=Oaken Vigor
sow=Spirit of Wolf
spirit of wolf=Spirit of Wolf
Last edited by gimp on Thu Mar 31, 2005 10:53 am, edited 4 times in total.

Arune
a hill giant
a hill giant
Posts: 216
Joined: Sat Jul 03, 2004 1:51 pm

Post by Arune » Tue Feb 08, 2005 12:30 pm

This would be better off as an .inc or a plugin. Nice work, will test it out tonight when I get a chance.

dedpoet
a hill giant
a hill giant
Posts: 247
Joined: Sat Aug 14, 2004 12:22 pm

Post by dedpoet » Tue Feb 08, 2005 4:06 pm

If there were a plugin version of this, the clouds would part, the sun would shine down upon it, and a choir of harp-playing angels would descend to sing to its greatness.

Ok, that may be a bit much, but I can't wait to shamanize this and give it a test. Now I just have to figure out all the ways people ask for Wunshi's. Someone asked me for "sooshi" last night.

dedpoet
a hill giant
a hill giant
Posts: 247
Joined: Sat Aug 14, 2004 12:22 pm

Post by dedpoet » Thu Feb 10, 2005 9:52 am

Great macro! I shamanized this and played around with it last night. It did a good job, catching just under 60% of my bot's buff requests. Not perfect, but greatly reduced my workload. Some people send you the craziest tells for buffs.

At any rate, here's my shaman INI. Tweak for your needs:

Code: Select all

[RecognizedBuffs]
wunshi=Wunshi's Focusing
wunshis=Wunshi's Focusing
wunshi's=Wunshi's Focusing
sushi=Wunshi's Focusing
focus=Wunshi's Focusing
fokus=Wunshi's Focusing
7=Wunshi's Focusing

sta=Spirit of Fortitude
stamina=Spirit of Fortitude
fort=Spirit of Fortitude
fortitude=Spirit of Fortitude
boar=Spirit of Fortitude

regen=Spirit of Perseverance

might=Spirit of Might
str=Spirit of Might
strength=Spirit of Might

sense=Spirit of Sense
sos=Spirit of Sense
agi=Spirit of Sense

inv=Invisibility
invis=Invisibility

fa=Ferine Avatar
avatar=Ferine Avatar

hot=Quiescence

heal=Yoppa's Mending

haste=Swift Like the Wind

tot=Talisman of the Tribunal

sow=Spirit of Bih`Li
billy=Spirit of Bih`Li
bihli=Spirit of Bih`Li

shrink=Shrink

shrinkall=Tiny Terror
I also modified the macro a little bit to keep me canni'd up. It's not nearly as aggresive as I do in my full-on bot macro but is nice for a buff whore or a bot who is just being dragged along. I'm going to add a few more things to my own version to suit how I use it, but without straying too much from the spirit of the original macro, here is my Main sub modified just a bit for your cannibalizing pleasure:

Code: Select all

sub Main

[color=#FF0000]   /declare SpellCanni outer "Pained Memory"
   /declare SpellHoT outer "Quiescence"
   /declare CanniGem outer gem3
   /declare HoTGem outer gem1[/color]

   /echo mini-buffbot 1.0 started

   /tgb on

   :MyMainLoop
   /doevents
[color=#FF0000]   /if (${Me.PctMana} < 70 && ${Me.CurrentHPs} > 2600 && ${Me.AltAbilityReady[47]}) {
      /target clear
      /delay 2
      /target myself
      /call cast ${SpellHoT} ${HoTGem} 5s
      /gsay Canni5
      /aa act Cannibalization
      /delay 3s
   }
   /if (${Me.PctMana} < 70 && ${Me.CurrentHPs} > 2600 && ${Me.SpellReady[${SpellCanni}]}) /call cast ${SpellCanni} ${CanniGem} 6s
   /delay 1s[/color]
   /goto :MyMainLoop

/return
The only other suggestion I have for actual second box characters, is that I tossed in some /beep commands on some of the debug areas. I have it beep when someone requests an unknown buff, is out of range, or sends a string that's too long.

User avatar
OnyxSys
a ghoul
a ghoul
Posts: 133
Joined: Sun Dec 21, 2003 9:58 pm
Contact:

Post by OnyxSys » Thu Feb 10, 2005 10:39 pm

any way to make this great little macro into a more sufficient macro for buffing in raids from other tells like "blah tells you, "need a regen please"" .. anyway to make it take out key words like "regen" and make it cast just that?
[img]http://web.infoave.net/~jpdixon/onyxsys.jpg[/img]

dedpoet
a hill giant
a hill giant
Posts: 247
Joined: Sat Aug 14, 2004 12:22 pm

Post by dedpoet » Fri Feb 11, 2005 8:56 am

Take a look at the code, that is exactly what it does. In the macro, the line:

Code: Select all

/if (${RequestedBuff.Left[10].Equal["can i get "]})      /varset RequestedBuff ${RequestedBuff.Right[-10]}
tells the bot that when someone says "can I get regen", to ignore the first 10 characters and parse the next word as their request. The line in the ini file:

Code: Select all

regen=Spirit of Perseverance
tells the bot that when someone asks for "regen", SoP should be cast. You can add as many ini entries as you want to, and can add any other lines like that you want. If you have guild memebers that ask for buffs in weird ways, a simple addition will allow for it:

Code: Select all

/if (${RequestedBuff.Left[59].Equal["the power of tunare demands that you shall bestow upon me "]})     /varset RequestedBuff ${RequestedBuff.Right[-59]}

For example, where 59 is the number of characters (including trailing space) before the buff request. As I said in my post above, it isn't flawless, but it catches more than half of my buff requests, which makes me happy.

User avatar
OnyxSys
a ghoul
a ghoul
Posts: 133
Joined: Sun Dec 21, 2003 9:58 pm
Contact:

Post by OnyxSys » Fri Feb 11, 2005 6:30 pm

Ok i thought that is what it meant.. but i didnt work when it was asked, ill fool around with it more and edit what needs to be done.. thanks
[img]http://web.infoave.net/~jpdixon/onyxsys.jpg[/img]

kkmonte
orc pawn
orc pawn
Posts: 23
Joined: Sat Dec 14, 2002 2:52 pm

question here.. haven't used mq2 in a long time...

Post by kkmonte » Wed Feb 16, 2005 12:49 pm

Well my plan is to set up my chanter as a kei whore bot and sit him in pok. And no i'm not gonna charge or anything or take donations, but since i'm not playing eq anymore, might as well share the crack...

Which lines do I have to remove to make it so anyone can use this? Instead of just my guild? Also is there a way to add some reporting or something? like echo a line of text or something into a seperate log file? (So you can see who is using it and how many times/ etc? )

One last thing, I wanna have it mgb every hour or so, and maybe say an ooc like "MGB KEI at main bank in 1 minute". or something like that. I couldn't find what doability mgb is for chanters though...

Thx

Arune
a hill giant
a hill giant
Posts: 216
Joined: Sat Jul 03, 2004 1:51 pm

Post by Arune » Wed Feb 16, 2005 2:00 pm

That just brings more attention to the users of MQ and makes SOE want to change things that much more. PoK bots are not a good idea.

zaradin
decaying skeleton
decaying skeleton
Posts: 4
Joined: Thu Oct 21, 2004 4:07 pm

Post by zaradin » Thu Feb 17, 2005 7:02 am

OnyxSys .. you could just rewrite this http://macroquest2.com/phpBB2/viewtopic.php?t=9679 .. super easy to rewrite (even a totally newb like me figured it out) and it looks for keywords.

User avatar
gimp
a grimling bloodguard
a grimling bloodguard
Posts: 584
Joined: Fri Oct 29, 2004 9:28 am
Location: internet

Post by gimp » Mon Mar 28, 2005 3:30 pm

to arune: thanks for the suggestion about making it into a include instead, i'll try get something whipped up the next few days & post here (would be useful in other scripts i use too)


to dedpoet: i can look into possibilities of making a plugin version but my c skills are rusty :p and thanks for your shaman version im very happy someone finds my crap useful :)


to kkmonte: to use mgb aa, use:

Code: Select all

/alt activate 35
see this post as a reference: http://eqforums.station.sony.com/eq/boa ... sage.id=41
also i think that would draw too much attention to auto mgb every hour, even tho it is a great initiative & idea

User avatar
OnyxSys
a ghoul
a ghoul
Posts: 133
Joined: Sun Dec 21, 2003 9:58 pm
Contact:

Post by OnyxSys » Mon Mar 28, 2005 3:46 pm

I use this macro every day and infact i have included it in all my main macros i use.. we have modifed this macro to actually come into play when you say "buffme" it will generate 5 - 7 buffs that are posted in the ini file and will buff those 5 - 7 buffs on the person that asked for it, so handy when someone dies and is just freshly rezed.. so and so sends you a tell, 'buffme'.. also seperated the ini file into classes..

Great foot work with this! Very useful..
[img]http://web.infoave.net/~jpdixon/onyxsys.jpg[/img]

User avatar
gimp
a grimling bloodguard
a grimling bloodguard
Posts: 584
Joined: Fri Oct 29, 2004 9:28 am
Location: internet

Post by gimp » Mon Mar 28, 2005 3:50 pm

wow thanks!
please post ur mods when u feel satisfied with them :)

mmatt_y2k
decaying skeleton
decaying skeleton
Posts: 9
Joined: Fri Dec 31, 2004 10:44 am

Post by mmatt_y2k » Mon Mar 28, 2005 5:55 pm

Great macro for raiding! OnyxSys I would also love to see your mods.

User avatar
OnyxSys
a ghoul
a ghoul
Posts: 133
Joined: Sun Dec 21, 2003 9:58 pm
Contact:

Post by OnyxSys » Mon Mar 28, 2005 11:33 pm

Ill post it up when its complete and to what i think is the way i want it, there are a few more features im working on with.. and its basically only when someone sends me a tell saying "give me wunshi, fort, agi, sense please"

well i would like it to pick those key words out of the one sentence.. keywords being (wunshi,fort,agi,sense) and then buff them as they sent the tell seperatly.. but im having issues getting that to work atm..

When complete will be working on making this a full plugin with features for pausing etc.. making the ini file store the guild name is another thing i would like to see which wouldnt be hard just havent gotten around to it..
[img]http://web.infoave.net/~jpdixon/onyxsys.jpg[/img]