vanilla-wow-addons – Rev 1
?pathlinks?
--[[ BestBuff 1.7
Casts the best rank possible of various buffs on caster's target,
irregardless of caster or target level.
Configuration: /bestbuff
It will bring up a window to set options and define buffs.
Generally you will only need to do this once or very seldom.
There are now two ways to use BestBuff:
Old way: /script BestBuff(buff_name)
ie: /script BestBuff("Power Word: Fortitude")
New way: Go into /bestbuff config panel and check Enabled.
Any buff defined there on your action bars will automatically BestBuff.
This means if you have macros dedicated to casting BestBuff you can get
rid of them. Drag the spell from your spellbook to a hotkey and use it
there.
Self cast and spam which were previously turned on/off in the BestBuff()
function are now defined in the BestBuff settings. By default, buffs
have no notification and do not self cast.
To add/change/remove buffs, use the /bestbuff config panel. For more
permanent changes (in case you frequently lose SavedVariables.lua),
instructions are in the BestBuff_Defaults.lua.
To restore settings to default, use /bestbuff reset.
-- Gello
3/29/06 - 1.10 tooltip changes
7/24/05 - changed highest rank to highest rank user knows
4/11/05 - removed BestBuff from UISpecialFrames
4/1/05 - added UI config window, ability to auto-BestBuff from action bar,
saved buffs to SavedVariables.lua so users don't have to re-edit
for every update.
3/22/05 - updated toc to 1300
3/18/05 - fixed a small bug causing excess spam
3/17/05 - added switch to kill self cast, some cleanup and comments
2/8/05 - initial release
]]
BestBuff_Original_UseAction = nil; -- for hooking UseAction
--[[ Variables saved to SavedVariables.lua ]]
BB = {};
BB.Buffs = {};
BB.Enabled = 1;
BB.Population = 0;
BB.Selected = 0;
--[[ Original BestBuff() left mostly unchanged ]]
--[[ no squelch or self cast disable flags, they're in config options now ]]
function BestBuff(intended_buff)
local best_rank = 1;
local target_rank = 1;
local cast_rank = 1;
local which_buff = 0;
local x = 1;
local text = nil;
which_buff = nil;
-- intended_buff is the string passed to us by user, see if this is in the buffnames list
for x=1, table.getn(BB.Buffs), 1 do
if (BB.Buffs[x].Name == intended_buff) then
which_buff = x;
end
end
-- if it is in the list...
if which_buff then
-- see which is the player's best castable rank due to player's level
for x=1, table.getn(BB.Buffs[which_buff].Levels), 1 do
if (UnitLevel("player")>=tonumber(BB.Buffs[which_buff].Levels[x])) then
best_rank = x;
end
end
-- see which is the target's best rank due to target's level
if (UnitLevel("target")>0) then
for x=1, table.getn(BB.Buffs[which_buff].Levels), 1 do
if (UnitLevel("target")>=(tonumber(BB.Buffs[which_buff].Levels[x])-10)) then
target_rank = x;
end
end
else
target_rank = best_rank
end
-- if the target's best rank is greater than the caster's best rank,
-- (ie, target is much higher level) then the actual rank will be
-- the caster's best rank.
if best_rank < target_rank then
cast_rank = best_rank;
else
-- otherwise, choose the best rank for the target.
cast_rank = target_rank;
end
-- attempt the spell
BestBuff_CastSpellByName(intended_buff,"Rank "..cast_rank);
-- if spam is on and we have a friendly target, spam away
if BB.Buffs[which_buff].Notify==1 and UnitExists("target") then
text = "Casting "..intended_buff.."(Rank "..cast_rank..") on "..UnitName("target")..".";
end
-- If the spell didn't actually cast, and selfcasting not disabled, self cast it
if BB.Buffs[which_buff].SelfCast==1 and SpellIsTargeting() then
cast_rank = best_rank;
SpellTargetUnit("player");
if BB.Buffs[which_buff].Notify==1 then
text = "Casting "..intended_buff.."(Rank "..cast_rank..") on yourself.";
end
end
else
-- if we're here it means the user asked for a buff not in the buffnames list
text = "Unable to cast "..intended_buff..".";
end
-- if we gained a message to spam at some point, spam it
if text and DEFAULT_CHAT_FRAME then
DEFAULT_CHAT_FRAME:AddMessage(text);
end
end
--[[ BestBuff callback functions ]]
function BestBuff_OnLoad()
BestBuff_Original_UseAction = UseAction;
UseAction = BestBuff_New_UseAction;
this:RegisterEvent("VARIABLES_LOADED");
end
function BestBuff_OnEvent()
if event=="VARIABLES_LOADED" then
BestBuffFrame:Hide();
if BB.Population<1 then
BestBuff_PopulateBuffs()
end
if BB.Enabled then
BestBuffEnableCheckButton:SetChecked(1);
else
BestBuffEnableCheckButton:SetChecked(0);
end
SlashCmdList["BestBuffCOMMAND"] = BestBuff_SlashHandler;
SLASH_BestBuffCOMMAND1 = "/bestbuff";
end
end
function BestBuff_SlashHandler(arg1)
if string.find(arg1,"reset") then
BestBuff_PopulateBuffs();
end
BestBuff_Startup();
BestBuff_ClearEntry();
end
function BestBuff_New_UseAction(slot,arg2,onself)
local intended_buff;
local which_buff = nil;
local i;
if not BB.Enabled then
BestBuff_Original_UseAction(slot,arg2,onself);
else
BestBuffTooltip:SetOwner(UIParent,"ANCHOR_NONE")
BestBuffTooltip:SetAction(slot);
intended_buff = getglobal("BestBuffTooltipTextLeft1"):GetText();
for i=1,table.getn(BB.Buffs) do
if BB.Buffs[i].Name == intended_buff then
which_buff = intended_buff;
end
end
if which_buff then
BestBuff(intended_buff);
else
BestBuff_Original_UseAction(slot,arg2,onself);
end
end
end
--[[ Helper functions ]]
-- CastSpellByName() won't work from within UseAction, use CastSpell instead
function BestBuff_CastSpellByName(spell_name,spell_rank) --intended_buff,"Rank "..cast_rank);
local id;
local i = 1;
local done = nil;
local name;
local rank;
local id = nil;
local intended_rank;
_,_,intended_rank = string.find(spell_rank,"(%d+)")
while not done do
name,rank = GetSpellName(i,BOOKTYPE_SPELL);
if not name then
done = true;
else
if name==spell_name then
_,_,rank = string.find(rank,"(%d+)")
if tonumber(rank)<=tonumber(intended_rank) then
id = i;
end
end
end
i = i+1;
end
if id then
CastSpell(id,BOOKTYPE_SPELL);
end
end
-- restore or initialize Buff to defaults
function BestBuff_PopulateBuffs()
BestBuffEnableCheckButton:SetChecked(0);
BB = {};
BB.Buffs = {};
BB.Enabled = false;
BB.Selected = 0;
BB.Population = 1;
foreach(BBDefaultBuffs,BestBuff_AddDefaultBuffs);
BestBuff_SortBuffs();
end
function BestBuff_AddDefaultBuffs(arg1)
local i;
if arg1 then
BB.Buffs[BB.Population] = {};
BB.Buffs[BB.Population].Name = arg1;
BB.Buffs[BB.Population].Notify = BBDefault_Notify;
BB.Buffs[BB.Population].SelfCast = BBDefault_SelfCast;
BB.Buffs[BB.Population].Levels = {};
for i=1,table.getn(BBDefaultBuffs[arg1]) do
BB.Buffs[BB.Population].Levels[i] = BBDefaultBuffs[arg1][i];
end
end
BB.Population = BB.Population + 1;
end
-- always sort buffs alphabetically by .Name
function BestBuff_SortBuffs()
local temp_buff = {};
local changed = true;
if BB.Population>2 then
while changed do
changed = false;
for i=1,BB.Population-2 do
if BB.Buffs[i].Name > BB.Buffs[i+1].Name then
temp_buff = BB.Buffs[i];
BB.Buffs[i] = BB.Buffs[i+1];
BB.Buffs[i+1] = temp_buff;
changed = true;
end
end
end
end
end
function BestBuff_Debug()
local i;
local j;
local text;
DEFAULT_CHAT_FRAME:AddMessage("Population: "..BB.Population);
for i=1,table.getn(BB.Buffs) do
text = "Buff #"..i..": "..BB.Buffs[i].Name..": ";
for j=1,table.getn(BB.Buffs[i].Levels) do
text = text .. BB.Buffs[i].Levels[j] .. " ";
end
DEFAULT_CHAT_FRAME:AddMessage(text);
end
end
-- reset the lower "edit" area of the window
function BestBuff_ClearEntry()
BestBuffEditBox_OnEscapePressed();
BestBuff_SortBuffs()
BB.Selected = 0;
BestBuffEditNameBox:SetText("");
BestBuffEditLevelsBox:SetText("");
BestBuffNotifyCheckButton:SetChecked(0);
BestBuffSelfCastCheckButton:SetChecked(0);
BestBuffList_Update();
end
-- returns a string as levels separated by spaces
function BestBuff_LevelString(arg1)
local text = "";
if BB.Buffs[arg1].Levels then
for i=1,table.getn(BB.Buffs[arg1].Levels) do
if i>1 then
text = text .. " ";
end
text = text .. BB.Buffs[arg1].Levels[i];
end
end
return text;
end
function BestBuff_Startup()
BestBuffFrame:StopMovingOrSizing();
BestBuffFrame:Show();
end
--[[ Dialog control functions ]]
function BestBuff_OnMouseDown(arg1)
if arg1=="LeftButton" then
BestBuffFrame:StartMoving();
end
end
function BestBuff_OnMouseUp(arg1)
if arg1=="LeftButton" then
BestBuffFrame:StopMovingOrSizing();
end
end
function BestBuffCloseButton_OnClick()
BestBuff_ClearEntry();
BestBuffFrame:Hide();
end
function BestBuffNameButton_OnClick(arg1)
local index;
local item;
BestBuffEditBox_OnEscapePressed();
index = arg1 + FauxScrollFrame_GetOffset(BestBuffScrollFrame)
if index==BB.Selected then
index = BB.Population;
BB.Selected = 0;
end
if index < BB.Population then
BB.Selected = index;
BestBuffEditNameBox:SetText(BB.Buffs[index].Name);
BestBuffEditLevelsBox:SetText(BestBuff_LevelString(index));
BestBuffNotifyCheckButton:SetChecked(BB.Buffs[index].Notify);
BestBuffSelfCastCheckButton:SetChecked(BB.Buffs[index].SelfCast);
BestBuffList_Update();
else
BestBuff_ClearEntry();
end
end
function BestBuffEnableCheckButton_OnClick()
if BestBuffEnableCheckButton:GetChecked()==1 then
BB.Enabled = true;
else
BB.Enabled = false;
end
end
function BestBuffSelfCastCheckButton_OnClick()
if BB.Selected>0 then
BB.Buffs[BB.Selected].SelfCast = BestBuffSelfCastCheckButton:GetChecked();
end
end
function BestBuffNotifyCheckButton_OnClick()
if BB.Selected>0 then
BB.Buffs[BB.Selected].Notify = BestBuffNotifyCheckButton:GetChecked();
end
end
function BestBuffAddButton_OnClick()
local i;
local j;
local text;
local err_msg = "";
text = BestBuffEditNameBox:GetText();
for i=1,BB.Population-1 do
if text=="" or BB.Buffs[i].Name==text then
err_msg = "Can't add this buff.\nNew buffs must have a unique name.";
end
end
if err_msg~="" then
message(err_msg);
else
BB.Buffs[BB.Population] = {};
BB.Buffs[BB.Population].Name = BestBuffEditNameBox:GetText();
text = BestBuffEditLevelsBox:GetText();
-- populate .Levels with numbers in text
BB.Buffs[BB.Population].Levels = {};
j = 1;
for i in string.gfind(text,"(%d+)") do
BB.Buffs[BB.Population].Levels[j] = i;
j = j+1;
end
if j==1 then
BB.Buffs[BB.Population].Levels[1] = 1;
end
BB.Buffs[BB.Population].Notify = BestBuffNotifyCheckButton:GetChecked();
BB.Buffs[BB.Population].SelfCast = BestBuffSelfCastCheckButton:GetChecked();
table.setn(BB.Buffs,BB.Population);
BB.Population = BB.Population + 1;
BestBuff_ClearEntry();
end
end
function BestBuffChangeButton_OnClick()
local item;
local i;
local j;
local text;
if BB.Selected>0 then
BB.Buffs[BB.Selected].Name = BestBuffEditNameBox:GetText();
text = BestBuffEditLevelsBox:GetText();
-- populate .Levels with numbers in text
BB.Buffs[BB.Selected].Levels = {};
j = 1;
for i in string.gfind(text,"(%d+)") do
BB.Buffs[BB.Selected].Levels[j] = i;
j = j+1;
end
if j==1 then
BB.Buffs[BB.Selected].Levels[1] = 1;
end
BB.Buffs[BB.Selected].Notify = BestBuffNotifyCheckButton:GetChecked();
BB.Buffs[BB.Selected].SelfCast = BestBuffSelfCastCheckButton:GetChecked();
BestBuff_ClearEntry();
end
end
function BestBuffDeleteButton_OnClick()
if BB.Selected>0 then
table.remove(BB.Buffs,BB.Selected);
BB.Population = BB.Population - 1;
BB.Selected = 0;
BestBuff_ClearEntry();
end
end
function BestBuffEditBox_OnEscapePressed()
BestBuffEditNameBox:ClearFocus();
BestBuffEditLevelsBox:ClearFocus();
if BB.Selected>0 then
BestBuffEditNameBox:SetText(BB.Buffs[BB.Selected].Name);
BestBuffEditLevelsBox:SetText(BestBuff_LevelString(BB.Selected));
end
end
function BestBuffList_Update()
local index;
local i;
local itemText;
local itemButton;
FauxScrollFrame_Update(BestBuffScrollFrame, BB.Population-1, 8, 8);
for i=1,8 do
index = i + FauxScrollFrame_GetOffset(BestBuffScrollFrame);
itemButton = getglobal("BestBuffName"..i);
itemText = getglobal("BestBuffName"..i.."_Text");
if (index<BB.Population) then
itemText:SetText(BB.Buffs[index].Name);
itemText:Show();
if index==BB.Selected then
itemButton:LockHighlight();
else
itemButton:UnlockHighlight();
end
else
itemText:Hide();
itemButton:UnlockHighlight();
end
end
end
--[[ BestBuff Tooltip/OnEnter functions ]]
function BestBuff_Tooltip(arg1,arg2)
GameTooltip_SetDefaultAnchor(GameTooltip,this);
GameTooltip:SetText(arg1);
GameTooltip:AddLine(arg2, .75, .75, .75, 1);
GameTooltip:Show();
end
function BestBuffEnableCheckButton_OnEnter()
BestBuff_Tooltip("Enable Auto BestBuff","Checking this will allow BestBuff to alter the ranks of buffs cast directly from an action bar. This will not affect the /script BestBuff() macro command at all.\n\nThe buffs below will still be used for /script BestBuff().");
end
function BestBuffSelfCastCheckButton_OnEnter()
BestBuff_Tooltip("Self cast this buff","Checking this will cause this buff to cast on you if it cannot cast on the current target.");
end
function BestBuffNotifyCheckButton_OnEnter()
BestBuff_Tooltip("Notify on casting this buff","Checking this will send a notification of the spell, rank and target to your main chat window when you cast this buff.");
end
function BestBuffAddButton_OnEnter()
BestBuff_Tooltip("Add this buff","Click here to add this buff to the potential buffs list.");
end
function BestBuffChangeButton_OnEnter()
BestBuff_Tooltip("Change this buff", "Click here to change the selected buff to the values entered above.");
end
function BestBuffDeleteButton_OnEnter()
BestBuff_Tooltip("Delete this buff", "Click here to delete the selected buff from the potential buffs list.");
end
function BestBuffEditNameBox_OnEnter()
BestBuff_Tooltip("Buff name", "This field is the exact cast-sensitive name of the buff as used by WoW. ie, Power Word: Fortitude");
end
function BestBuffEditLevelsBox_OnEnter()
BestBuff_Tooltip("Buff levels", "This field is a list of the levels each rank of a buff is learned, separated by spaces. Each number corresponds to a rank.\n\nie, 1 12 24 means:\n(Rank 1) is learned at level 1\n(Rank 2) is learned at level 12\n(Rank 3) is learned at level 24");
end
function HighestRank(spellname)
local rank = 0;
local foundspell,foundrank="";
local i=1;
while foundspell do
foundspell, foundrank = GetSpellName(i,BOOKTYPE_SPELL);
i = i + 1;
_,_,foundrank=string.find(tostring(foundrank),"Rank (%d+)");
foundrank = tonumber(foundrank);
if foundspell==spellname and foundrank and foundrank>rank then
rank = foundrank;
end
end
return rank;
end