4 Commits

7 changed files with 157 additions and 30 deletions
+5 -1
View File
@@ -284,12 +284,16 @@ do
spellName = HealBot_ScanTooltipTextLeft1 and HealBot_ScanTooltipTextLeft1:GetText() spellName = HealBot_ScanTooltipTextLeft1 and HealBot_ScanTooltipTextLeft1:GetText()
end end
HealBot_CastFailed = false
orig(slot, checkCursor, onSelf) orig(slot, checkCursor, onSelf)
if autoSelfCast then if autoSelfCast then
SetCVar("autoSelfCast", autoSelfCast) SetCVar("autoSelfCast", autoSelfCast)
end end
if spellName and HealBot_AnnounceCast then if spellName and not HealBot_CastFailed then
HealBot_CastingSpell = spellName
HealBot_CastingTarget = mouseover
HealBot_Process_HealValue(spellName, mouseover)
HealBot_AnnounceCast(spellName, mouseover) HealBot_AnnounceCast(spellName, mouseover)
end end
end end
+1 -1
View File
@@ -1,6 +1,6 @@
## Interface: 11200 ## Interface: 11200
## Title: HealBotBlue ## Title: HealBotBlue
## Version: 1.4.0 ## Version: 1.4.1
## Author: Bluewhale ## Author: Bluewhale
## Notes: Adds panel with skinable bars for healing and decursive ## Notes: Adds panel with skinable bars for healing and decursive
## SavedVariables: HealBot_Config ## SavedVariables: HealBot_Config
+1
View File
@@ -70,6 +70,7 @@ function HealBot_OnEvent_AddonMsg(this, addon_id, inc_msg, dist_target, sender_i
local tmpTest, unitname, heal_val local tmpTest, unitname, heal_val
tmpTest, tmpTest, unitname, heal_val = string.find(inc_msg, ">> (%a+) <<=>> (.%d+) <<" ); tmpTest, tmpTest, unitname, heal_val = string.find(inc_msg, ">> (%a+) <<=>> (.%d+) <<" );
if heal_val then if heal_val then
if sender_id == UnitName("player") then return end
if not HealBot_HealsIn[unitname] then if not HealBot_HealsIn[unitname] then
HealBot_HealsIn[unitname] = 0; HealBot_HealsIn[unitname] = 0;
end end
+22 -10
View File
@@ -3,10 +3,10 @@
HealBot_View_DirtyUnits = {} HealBot_View_DirtyUnits = {}
local HealBot_Timer1, HealsIn_Timer = 0, 0; local HealBot_Timer1, HealsIn_Timer = 0, 0;
HealBot_LastModState = ""
function HealBot_OnLoad(this) function HealBot_OnLoad(this)
this:RegisterEvent("VARIABLES_LOADED"); this:RegisterEvent("VARIABLES_LOADED");
this:RegisterEvent("MODIFIER_STATE_CHANGED");
SLASH_HEALBOT1 = "/healbot"; SLASH_HEALBOT1 = "/healbot";
SLASH_HEALBOT2 = "/hb"; SLASH_HEALBOT2 = "/hb";
@@ -42,6 +42,20 @@ function HealBot_RegisterThis(this)
end end
function HealBot_OnUpdate(this, arg1) function HealBot_OnUpdate(this, arg1)
if HealBot_Action_TooltipUnit and HealBot_Tooltip:IsVisible() then
local currentModState = ""
if IsShiftKeyDown() then currentModState = currentModState .. "S" end
if IsControlKeyDown() then currentModState = currentModState .. "C" end
if IsAltKeyDown() then currentModState = currentModState .. "A" end
if HealBot_LastModState ~= currentModState then
HealBot_LastModState = currentModState
HealBot_Action_RefreshTooltip(HealBot_Action_TooltipUnit)
end
else
HealBot_LastModState = ""
end
if HealBot_TargetRestorePending then if HealBot_TargetRestorePending then
HealBot_TargetRestoreTimer = HealBot_TargetRestoreTimer + arg1; HealBot_TargetRestoreTimer = HealBot_TargetRestoreTimer + arg1;
if HealBot_TargetRestoreTimer >= 0.1 then if HealBot_TargetRestoreTimer >= 0.1 then
@@ -179,17 +193,12 @@ local HealBot_EventHandlers = {
["VARIABLES_LOADED"] = function(this) ["VARIABLES_LOADED"] = function(this)
HealBot_OnEvent_VariablesLoaded(this) HealBot_OnEvent_VariablesLoaded(this)
end, end,
["MODIFIER_STATE_CHANGED"] = function(this, arg1, arg2)
if HealBot_Action_TooltipUnit and HealBot_Tooltip:IsVisible() then
HealBot_Action_RefreshTooltip(HealBot_Action_TooltipUnit)
end
end,
-- Legacy pass-throughs -- Legacy pass-throughs
["CHAT_MSG_ADDON"] = function(this, arg1, arg2, arg3, arg4) HealBot_OnEvent_AddonMsg(this, arg1, arg2, arg3, arg4) end, ["CHAT_MSG_ADDON"] = function(this, arg1, arg2, arg3, arg4) HealBot_OnEvent_AddonMsg(this, arg1, arg2, arg3, arg4) end,
["SPELLCAST_START"] = function(this, arg1, arg2) HealBot_OnEvent_SpellcastStart(this, arg1, arg2) end, ["SPELLCAST_START"] = function(this, arg1, arg2) HealBot_OnEvent_SpellcastStart(this, arg1, arg2) end,
["SPELLCAST_STOP"] = function(this) HealBot_OnEvent_SpellcastStop(this) end, ["SPELLCAST_STOP"] = function(this) HealBot_OnEvent_SpellcastStop(this, "SPELLCAST_STOP") end,
["SPELLCAST_INTERRUPTED"] = function(this) HealBot_OnEvent_SpellcastStop(this) end, ["SPELLCAST_INTERRUPTED"] = function(this) HealBot_OnEvent_SpellcastStop(this, "SPELLCAST_INTERRUPTED") end,
["SPELLCAST_FAILED"] = function(this) HealBot_OnEvent_SpellcastStop(this) end, ["SPELLCAST_FAILED"] = function(this) HealBot_OnEvent_SpellcastStop(this, "SPELLCAST_FAILED") end,
["PLAYER_REGEN_DISABLED"] = function(this) HealBot_OnEvent_PlayerRegenDisabled(this) end, ["PLAYER_REGEN_DISABLED"] = function(this) HealBot_OnEvent_PlayerRegenDisabled(this) end,
["PLAYER_REGEN_ENABLED"] = function(this) HealBot_OnEvent_PlayerRegenEnabled(this) end, ["PLAYER_REGEN_ENABLED"] = function(this) HealBot_OnEvent_PlayerRegenEnabled(this) end,
["BAG_UPDATE_COOLDOWN"] = function(this, arg1) HealBot_OnEvent_BagUpdateCooldown(this, arg1) end, ["BAG_UPDATE_COOLDOWN"] = function(this, arg1) HealBot_OnEvent_BagUpdateCooldown(this, arg1) end,
@@ -464,8 +473,11 @@ function HealBot_OnEvent_SpellcastStart(this, spell, duration)
end end
end end
function HealBot_OnEvent_SpellcastStop(this) function HealBot_OnEvent_SpellcastStop(this, eventName)
HealBot_IsCasting = false; HealBot_IsCasting = false;
if eventName == "SPELLCAST_FAILED" then
HealBot_CastFailed = true;
end
HealBot_StopCasting(); HealBot_StopCasting();
HealBot_RecalcHeals(); HealBot_RecalcHeals();
if HealBot_IamRessing then if HealBot_IamRessing then
+120 -17
View File
@@ -127,10 +127,45 @@ function HealBot_AnnounceCast(spell, target)
end end
end end
function HealBot_Process_HealValue(spell, target)
if HealBot_Spells[spell] and HealBot_Spells[spell].CastTime > 1 then
HealBot_HealValue = HealBot_Spells[spell].HealsDur;
-- Apply dynamic Preservation bonus
if HEALBOT_REGROWTH and string.find(spell, HEALBOT_REGROWTH) then
local presRank = HealBot_GetTalentRank("Preservation")
if presRank > 0 then
local hasRejuv = false
for i=1,32 do
local buff = UnitBuff(target, i)
if not buff then break end
if string.find(buff, "Spell_Nature_Rejuvenation") then
hasRejuv = true
break
end
end
if hasRejuv then
local extHeal = HealBot_Spells[spell].HealsExt or 0
local bonus = extHeal * (presRank * 0.10)
HealBot_HealValue = HealBot_HealValue + math.floor(bonus)
end
end
end
local uname = UnitName(target)
if uname then
HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. uname .. " <<=>> " .. HealBot_HealValue .. " << ");
if not HealBot_HealsIn[uname] then
HealBot_HealsIn[uname] = 0;
end
HealBot_HealsIn[uname] = HealBot_HealsIn[uname] + HealBot_HealValue;
HealBot_RecalcHeals(HealBot_FindUnitID(uname));
end
end
end
function HealBot_StartCasting(spell, target, ttype) function HealBot_StartCasting(spell, target, ttype)
HealBot_CastFailed = false;
HealBot_CastSpellByName(spell); HealBot_CastSpellByName(spell);
HealBot_CastingSpell = spell;
HealBot_CastingTarget = target;
if ( SpellCanTargetUnit(target) ) then if ( SpellCanTargetUnit(target) ) then
SpellTargetUnit(target); SpellTargetUnit(target);
ttype = "fired"; ttype = "fired";
@@ -138,28 +173,36 @@ function HealBot_StartCasting(spell, target, ttype)
SpellTargetUnit(target); SpellTargetUnit(target);
SpellStopTargeting() SpellStopTargeting()
elseif ttype == "direct" then elseif ttype == "direct" then
if ( CheckInteractDistance(target, 4) ) then if ( UnitIsUnit(target, "player") or CheckInteractDistance(target, 4) ) then
ttype = "fired"; ttype = "fired";
end end
end end
HealBot_AnnounceCast(spell, target)
if ttype == "fired" and HealBot_Spells[spell] then if ttype == "fired" and HealBot_Spells[spell] then
if HealBot_Spells[spell].CastTime > 1 then if not HealBot_CastFailed then
HealBot_HealValue = HealBot_Spells[spell].HealsDur; HealBot_CastingSpell = spell;
HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. UnitName(target) .. " <<=>> " .. HealBot_HealValue .. " << "); HealBot_CastingTarget = target;
HealBot_Process_HealValue(spell, target);
HealBot_AnnounceCast(spell, target);
end end
end end
end end
function HealBot_StopCasting() function HealBot_StopCasting()
if HealBot_CastingTarget then if HealBot_CastingTarget then
if HealBot_HealsIn[UnitName(HealBot_CastingTarget)] then if HealBot_HealValue > 0 then
if HealBot_HealValue > 0 then local uname = UnitName(HealBot_CastingTarget)
HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. UnitName(HealBot_CastingTarget) .. " <<=>> " .. 0 - HealBot_HealValue .. " << "); if uname then
HealBot_HealValue = 0; HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. uname .. " <<=>> " .. 0 - HealBot_HealValue .. " << ");
if HealBot_HealsIn[uname] then
HealBot_HealsIn[uname] = HealBot_HealsIn[uname] - HealBot_HealValue;
if HealBot_HealsIn[uname] < 0 then
HealBot_HealsIn[uname] = 0;
end
HealBot_RecalcHeals(HealBot_FindUnitID(uname));
end
end end
HealBot_HealValue = 0;
end end
end end
HealBot_CastingSpell = nil; HealBot_CastingSpell = nil;
@@ -298,7 +341,46 @@ function HealBot_SetItemDefaults(spell)
end end
function HealBot_SetSpellDefaults(spell) function HealBot_SetSpellDefaults(spell)
HealBot_Spells[spell].HealsDur = math.floor((HealBot_Spells[spell].HealsCast + HealBot_Spells[spell].HealsExt) + HealBot_Spells[spell].RealHealing); local baseHeal = HealBot_Spells[spell].HealsCast or 0
local extHeal = HealBot_Spells[spell].HealsExt or 0
local realHeal = HealBot_Spells[spell].RealHealing or 0
local _, class = UnitClass("player")
if class == "DRUID" then
local giftRank = HealBot_GetTalentRank("Gift of Nature")
local genRank = HealBot_GetTalentRank("Genesis")
local mult = 1 + (giftRank * 0.02)
baseHeal = baseHeal * mult
extHeal = extHeal * mult
realHeal = realHeal * mult
if genRank > 0 then
extHeal = extHeal * (1 + (genRank * 0.05))
end
elseif class == "PRIEST" then
local spiritRank = HealBot_GetTalentRank("Spiritual Healing")
local mult = 1 + (spiritRank * 0.06)
baseHeal = baseHeal * mult
extHeal = extHeal * mult
realHeal = realHeal * mult
if HEALBOT_RENEW and string.find(spell, HEALBOT_RENEW) then
local renewRank = HealBot_GetTalentRank("Improved Renew")
extHeal = extHeal * (1 + (renewRank * 0.05))
end
elseif class == "PALADIN" then
local hlRank = HealBot_GetTalentRank("Healing Light")
if (HEALBOT_HOLY_LIGHT and string.find(spell, HEALBOT_HOLY_LIGHT)) or
(HEALBOT_FLASH_OF_LIGHT and string.find(spell, HEALBOT_FLASH_OF_LIGHT)) or
(HEALBOT_HOLY_SHOCK and string.find(spell, HEALBOT_HOLY_SHOCK)) then
local mult = 1 + (hlRank * 0.04)
baseHeal = baseHeal * mult
realHeal = realHeal * mult
end
end
HealBot_Spells[spell].HealsDur = math.floor(baseHeal + extHeal + realHeal);
end end
function HealBot_AddHeal(spell) function HealBot_AddHeal(spell)
@@ -433,17 +515,38 @@ function HealBot_RecalcSpells()
HealBot_RecalcParty(); HealBot_RecalcParty();
end end
function HealBot_GetTalentRank(talentName)
for t = 1, GetNumTalentTabs() do
for i = 1, GetNumTalents(t) do
local nameTalent, icon, tier, column, currRank, maxRank = GetTalentInfo(t, i);
if nameTalent == talentName then
return currRank;
end
end
end
return 0;
end
function HealBot_SpiBonus(spell) function HealBot_SpiBonus(spell)
local heals_modifer = 0; local heals_modifer = 0;
local base, stat, posBuff, negBuff = UnitStat("player", 5); local base, stat, posBuff, negBuff = UnitStat("player", 5);
nameTalent, icon, tier, column, currRank, maxRank = GetTalentInfo(2, 14); -- Spiritual guidance local currRank = HealBot_GetTalentRank("Spiritual Guidance")
spiGuideBonus = stat * 0.05; if currRank > 0 then
heals_modifer = heals_modifer + (currRank * spiGuideBonus); local spiGuideBonus = stat * 0.05;
heals_modifer = heals_modifer + (currRank * spiGuideBonus);
end
return heals_modifer; return heals_modifer;
end end
function HealBot_GetBonus() function HealBot_GetBonus()
local HealBonus = HealBot_BonusScanner:GetBonus(); local HealBonus = HealBot_BonusScanner:GetBonus() or 0;
if UnitClass("player") == "PALADIN" then
local ironRank = HealBot_GetTalentRank("Ironclad")
if ironRank > 0 then
local base, effectiveArmor = UnitArmor("player")
HealBonus = HealBonus + (effectiveArmor * (ironRank * 0.01))
end
end
return HealBonus; return HealBonus;
end end
+1 -1
View File
@@ -1,4 +1,4 @@
HEALBOT_VERSION = "1.4"; HEALBOT_VERSION = "1.4.1";
------------- -------------
-- ENGLISH -- -- ENGLISH --
+7
View File
@@ -37,6 +37,13 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
### Change Log ### Change Log
**v1.4.1**
* **Talent-based Healing Calculations:** Implemented dynamic spell healing calculations for Druid, Priest, and Paladin classes based on talents.
* **Modifier Key Polling:** Replaced MODIFIER_STATE_CHANGED event with polling in HealBot_OnUpdate to track modifier keys reliably.
* **Incoming Heals Fix:** Fixed a bug where incoming heals failed to broadcast or show on the UI due to synchronous GCD fails and `CheckInteractDistance` limitations in the 1.12 API.
* **Hovercast Incoming Heals:** Added full support for processing and displaying incoming heals when using action bar hovercasting.
* **Zero-latency Self-Heals:** Incoming heals for the local player now process instantly with zero latency and no network reliance, ensuring they function even when playing solo.
**v1.4** **v1.4**
* **Extra Frame support for pets and familiars added:** Togglable from healing tab - Extra frames option selected & pets selected from dropdown. * **Extra Frame support for pets and familiars added:** Togglable from healing tab - Extra frames option selected & pets selected from dropdown.
* **Customizable Health Text:** Added a new dropdown in the Healing Options tab that allows users to choose how health text is displayed on unit frames (`Name Only`, `Health Percentage`, `Real Health`, or `Health Deficit`). Includes a smart truncation algorithm to preserve critical health numbers even if the unit name is too long. * **Customizable Health Text:** Added a new dropdown in the Healing Options tab that allows users to choose how health text is displayed on unit frames (`Name Only`, `Health Percentage`, `Real Health`, or `Health Deficit`). Includes a smart truncation algorithm to preserve critical health numbers even if the unit name is too long.