Skip to content

Commit 1567a71

Browse files
committed
Another mass update
1 parent 5cb75c4 commit 1567a71

File tree

14 files changed

+835
-239
lines changed

14 files changed

+835
-239
lines changed

Rotations/Druid/Feral/FeralCuteOne.lua

Lines changed: 260 additions & 96 deletions
Large diffs are not rendered by default.

Rotations/Monk/Windwalker/WindwalkerCuteOne.lua

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ local function runRotation()
799799
spell = br.player.spell
800800
talent = br.player.talent
801801
-- General Locals
802-
var.haltProfile = (unit.inCombat() and var.profileStop) or unit.mounted() or ui.pause() or ui.mode.rotation == 2
802+
var.haltProfile = (unit.inCombat() and var.profileStop) or unit.mounted() or ui.pause() or ui.mode.rotation == 4
803803
-- Dynamic Units
804804
-- Units
805805
units.get(5)
@@ -819,8 +819,6 @@ local function runRotation()
819819
end
820820
end
821821

822-
-- ui.chatOverlay("AOE: "..tostring(ui.useAOE(8,3)).." - C: "..#enemies.yards8.. " - NC: "..#enemies.yards8nc)
823-
824822
---------------------
825823
--- Begin Profile ---
826824
---------------------

System/API/UI.lua

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,4 +273,16 @@ br.api.ui = function(self)
273273
return br.functions.misc:getOptionValue(thisOption, optionPage)
274274
end
275275
end
276+
277+
if ui.setToggle == nil then
278+
--- Sets a toggle to the specified value and updates the UI
279+
-- @function ui.setToggle
280+
-- @string toggleName - The name of the toggle to set
281+
-- @number toggleValue - The value to set the toggle to (1, 2, 3, etc.)
282+
-- @return nil
283+
ui.setToggle = function(toggleName, toggleValue)
284+
if toggleName == nil or toggleValue == nil then return end
285+
br.ui:ToggleToValue(toggleName, toggleValue)
286+
end
287+
end
276288
end

System/API/Units.lua

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,22 @@ br.api.units = function(self)
2525
units[dynString] = thisUnit
2626
return thisUnit -- Backwards compatability for old way
2727
end
28+
29+
--- Custom target weight function that profiles can override to add coefficient bonuses for dynamic targeting.
30+
-- This allows profiles to customize target prioritization beyond the default coefficient system.
31+
-- Return a number to add to the unit's coefficient (higher = more priority).
32+
-- @function units.customTargetWeight
33+
-- @param unit - The unit to calculate custom weight for
34+
-- @returns number - Additional coefficient to add (default 0)
35+
-- @usage
36+
-- -- Example: Feral druid prioritizing Rip refresh
37+
-- units.customTargetWeight = function(thisUnit)
38+
-- if debuff.rip.exists(thisUnit) and debuff.rip.remains(thisUnit) < 5 then
39+
-- return 80 -- High priority to refresh expiring Rip
40+
-- end
41+
-- return 0
42+
-- end
43+
units.customTargetWeight = function(unit)
44+
return 0 -- Default: no custom weight
45+
end
2846
end

System/Functions/Cast.lua

Lines changed: 147 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,11 @@ function cast:castSpell(Unit, SpellID, FacingCheck, MovementCheck, SpamAllowed,
323323
if noCast then
324324
return true
325325
else
326+
-- Store pre-cast state to verify cast success
327+
local gcdBefore = br.functions.spell:getSpellCD(61304) -- GCD spell
328+
local castingBefore = br._G.UnitCastingInfo("player") ~= nil
329+
local channelingBefore = br._G.UnitChannelInfo("player") ~= nil
330+
326331
br.timersTable[SpellID] = br._G.GetTime()
327332
-- currentTarget = UnitGUID(Unit) -- Not Used
328333
br.botCast = true -- Used by old Queue Cast
@@ -332,21 +337,43 @@ function cast:castSpell(Unit, SpellID, FacingCheck, MovementCheck, SpamAllowed,
332337
local X, Y, Z = br._G.ObjectPosition(Unit)
333338
br._G.ClickPosition(X, Y, Z)
334339
end
335-
--lastSpellCast = SpellID
336-
-- change main button icon
337-
--if br.functions.misc:getOptionCheck("Start/Stop BadRotations") then
338-
br.ui.toggles.mainButton:SetNormalTexture(select(3, br._G.GetSpellInfo(SpellID)))
339-
br.lastSpellCast = SpellID
340-
br.lastSpellTarget = br._G.UnitGUID(Unit)
341-
--end
342-
return true
340+
341+
-- Verify cast actually started
342+
local gcdAfter = br.functions.spell:getSpellCD(61304)
343+
local castingAfter = br._G.UnitCastingInfo("player") ~= nil
344+
local channelingAfter = br._G.UnitChannelInfo("player") ~= nil
345+
346+
-- Cast succeeded if: GCD triggered OR started casting OR started channeling
347+
local castSucceeded = (gcdAfter > gcdBefore) or
348+
(castingAfter and not castingBefore) or
349+
(channelingAfter and not channelingBefore)
350+
351+
if castSucceeded then
352+
--lastSpellCast = SpellID
353+
-- change main button icon
354+
--if br.functions.misc:getOptionCheck("Start/Stop BadRotations") then
355+
br.ui.toggles.mainButton:SetNormalTexture(select(3, br._G.GetSpellInfo(SpellID)))
356+
br.lastSpellCast = SpellID
357+
br.lastSpellTarget = br._G.UnitGUID(Unit)
358+
--end
359+
return true
360+
else
361+
-- Cast failed - reset timer to allow retry
362+
br.timersTable[SpellID] = nil
363+
return false
364+
end
343365
end
344366
end
345367
end
346368
elseif (FacingCheck == true or br.functions.unit:getFacing("player", Unit) == true) and (br.functions.unit:GetUnitIsUnit("player", Unit) or br.engines.enemiesEngine.units[Unit] ~= nil or br.functions.misc:getLineOfSight("player", Unit) == true) then
347369
if noCast then
348370
return true
349371
else
372+
-- Store pre-cast state to verify cast success
373+
local gcdBefore = br.functions.spell:getSpellCD(61304) -- GCD spell
374+
local castingBefore = br._G.UnitCastingInfo("player") ~= nil
375+
local channelingBefore = br._G.UnitChannelInfo("player") ~= nil
376+
350377
-- currentTarget = UnitGUID(Unit) -- Not Used
351378
br.botCast = true
352379
br.botSpell = SpellID
@@ -355,12 +382,28 @@ function cast:castSpell(Unit, SpellID, FacingCheck, MovementCheck, SpamAllowed,
355382
local X, Y, Z = br._G.ObjectPosition(Unit)
356383
br._G.ClickPosition(X, Y, Z)
357384
end
358-
--if br.functions.misc:getOptionCheck("Start/Stop BadRotations") then
359-
br.ui.toggles.mainButton:SetNormalTexture(select(3, br._G.GetSpellInfo(SpellID)))
360-
br.lastSpellCast = SpellID
361-
br.lastSpellTarget = br._G.UnitGUID(Unit)
362-
--end
363-
return true
385+
386+
-- Verify cast actually started
387+
local gcdAfter = br.functions.spell:getSpellCD(61304)
388+
local castingAfter = br._G.UnitCastingInfo("player") ~= nil
389+
local channelingAfter = br._G.UnitChannelInfo("player") ~= nil
390+
391+
-- Cast succeeded if: GCD triggered OR started casting OR started channeling
392+
local castSucceeded = (gcdAfter > gcdBefore) or
393+
(castingAfter and not castingBefore) or
394+
(channelingAfter and not channelingBefore)
395+
396+
if castSucceeded then
397+
--if br.functions.misc:getOptionCheck("Start/Stop BadRotations") then
398+
br.ui.toggles.mainButton:SetNormalTexture(select(3, br._G.GetSpellInfo(SpellID)))
399+
br.lastSpellCast = SpellID
400+
br.lastSpellTarget = br._G.UnitGUID(Unit)
401+
--end
402+
return true
403+
else
404+
-- Cast failed - don't set lastSpellCast
405+
return false
406+
end
364407
end
365408
end
366409
end
@@ -426,32 +469,75 @@ function cast:castSpellMacro(Unit, SpellID, FacingCheck, MovementCheck, SpamAllo
426469
if noCast then
427470
return true
428471
else
472+
-- Store pre-cast state to verify cast success
473+
local gcdBefore = br.functions.spell:getSpellCD(61304) -- GCD spell
474+
local castingBefore = br._G.UnitCastingInfo("player") ~= nil
475+
local channelingBefore = br._G.UnitChannelInfo("player") ~= nil
476+
429477
br.timersTable[SpellID] = br._G.GetTime()
430478
br.currentTarget = br._G.UnitGUID(Unit)
431479
br._G.RunMacroText("/cast [@" .. Unit .. "] " .. br._G.GetSpellInfo(SpellID))
432-
--lastSpellCast = SpellID
433-
-- change main button icon
434-
--if br.functions.misc:getOptionCheck("Start/Stop BadRotations") then
435-
br.ui.toggles.mainButton:SetNormalTexture(select(3, br._G.GetSpellInfo(SpellID)))
436-
br.lastSpellCast = SpellID
437-
br.lastSpellTarget = br._G.UnitGUID(Unit)
438-
--end
439-
return true
480+
481+
-- Verify cast actually started
482+
local gcdAfter = br.functions.spell:getSpellCD(61304)
483+
local castingAfter = br._G.UnitCastingInfo("player") ~= nil
484+
local channelingAfter = br._G.UnitChannelInfo("player") ~= nil
485+
486+
-- Cast succeeded if: GCD triggered OR started casting OR started channeling
487+
local castSucceeded = (gcdAfter > gcdBefore) or
488+
(castingAfter and not castingBefore) or
489+
(channelingAfter and not channelingBefore)
490+
491+
if castSucceeded then
492+
--lastSpellCast = SpellID
493+
-- change main button icon
494+
--if br.functions.misc:getOptionCheck("Start/Stop BadRotations") then
495+
br.ui.toggles.mainButton:SetNormalTexture(select(3, br._G.GetSpellInfo(SpellID)))
496+
br.lastSpellCast = SpellID
497+
br.lastSpellTarget = br._G.UnitGUID(Unit)
498+
--end
499+
return true
500+
else
501+
-- Cast failed - reset timer to allow retry
502+
br.timersTable[SpellID] = nil
503+
return false
504+
end
440505
end
441506
end
442507
end
443508
elseif (FacingCheck == true or br.functions.unit:getFacing("player", Unit) == true) and (br.functions.unit:GetUnitIsUnit("player", Unit) or br.functions.misc:getLineOfSight("player", Unit) == true) then
444509
if noCast then
445510
return true
446511
else
512+
-- Store pre-cast state to verify cast success
513+
local gcdBefore = br.functions.spell:getSpellCD(61304) -- GCD spell
514+
local castingBefore = br._G.UnitCastingInfo("player") ~= nil
515+
local channelingBefore = br._G.UnitChannelInfo("player") ~= nil
516+
447517
br.currentTarget = br._G.UnitGUID(Unit)
448518
br._G.RunMacroText("/cast [@" .. Unit .. "] " .. br._G.GetSpellInfo(SpellID))
449-
--if br.functions.misc:getOptionCheck("Start/Stop BadRotations") then
450-
br.ui.toggles.mainButton:SetNormalTexture(select(3, br._G.GetSpellInfo(SpellID)))
451-
br.lastSpellCast = SpellID
452-
br.lastSpellTarget = br._G.UnitGUID(Unit)
453-
--end
454-
return true
519+
520+
-- Verify cast actually started
521+
local gcdAfter = br.functions.spell:getSpellCD(61304)
522+
local castingAfter = br._G.UnitCastingInfo("player") ~= nil
523+
local channelingAfter = br._G.UnitChannelInfo("player") ~= nil
524+
525+
-- Cast succeeded if: GCD triggered OR started casting OR started channeling
526+
local castSucceeded = (gcdAfter > gcdBefore) or
527+
(castingAfter and not castingBefore) or
528+
(channelingAfter and not channelingBefore)
529+
530+
if castSucceeded then
531+
--if br.functions.misc:getOptionCheck("Start/Stop BadRotations") then
532+
br.ui.toggles.mainButton:SetNormalTexture(select(3, br._G.GetSpellInfo(SpellID)))
533+
br.lastSpellCast = SpellID
534+
br.lastSpellTarget = br._G.UnitGUID(Unit)
535+
--end
536+
return true
537+
else
538+
-- Cast failed - don't set lastSpellCast
539+
return false
540+
end
455541
end
456542
end -- End Spam Check
457543
end -- End CD/Distance Check
@@ -714,6 +800,13 @@ function cast:createCastFunction(thisUnit, castType, minUnits, effectRng, spellI
714800
if br._G.UnitHealth(thisUnit) > 0 or castType == "dead" then
715801
-- Debug Only
716802
if debug then return true end
803+
804+
-- Store pre-cast state to verify cast success
805+
local gcdBefore = br.functions.spell:getSpellCD(61304) -- GCD spell
806+
local spellCDBefore = br.functions.spell:getSpellCD(spellID) -- This spell's CD
807+
local castingBefore = br._G.UnitCastingInfo("player") ~= nil
808+
local channelingBefore = br._G.UnitChannelInfo("player") ~= nil
809+
717810
-- Cast Spell
718811
br.botCast = true -- Used by old Queue Cast
719812
br.botSpell = spellID -- Used by old Queue Cast
@@ -727,14 +820,32 @@ function cast:createCastFunction(thisUnit, castType, minUnits, effectRng, spellI
727820
local X, Y, Z = br._G.ObjectPosition(thisUnit)
728821
br._G.ClickPosition(X, Y, Z)
729822
end
730-
-- add to cast timer
731-
castTimers[spellID] = br._G.GetTime() + 1
732-
-- change main button icon
733-
br.ui.toggles.mainButton:SetNormalTexture(icon)
734-
-- Update Last Cast
735-
br.lastSpellCast = spellID
736-
br.lastSpellTarget = br._G.UnitGUID(thisUnit)
737-
return true
823+
824+
-- Verify cast actually started
825+
local gcdAfter = br.functions.spell:getSpellCD(61304)
826+
local spellCDAfter = br.functions.spell:getSpellCD(spellID)
827+
local castingAfter = br._G.UnitCastingInfo("player") ~= nil
828+
local channelingAfter = br._G.UnitChannelInfo("player") ~= nil
829+
830+
-- Cast succeeded if: GCD triggered OR spell CD triggered OR started casting OR started channeling
831+
local castSucceeded = (gcdAfter > gcdBefore) or
832+
(spellCDAfter > spellCDBefore) or
833+
(castingAfter and not castingBefore) or
834+
(channelingAfter and not channelingBefore)
835+
836+
if castSucceeded then
837+
-- add to cast timer
838+
castTimers[spellID] = br._G.GetTime() + 1
839+
-- change main button icon
840+
br.ui.toggles.mainButton:SetNormalTexture(icon)
841+
-- Update Last Cast
842+
br.lastSpellCast = spellID
843+
br.lastSpellTarget = br._G.UnitGUID(thisUnit)
844+
return true
845+
else
846+
-- Cast failed - don't update timers or last cast
847+
return false
848+
end
738849
end
739850
return false
740851
end

System/Functions/Misc.lua

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -607,14 +607,22 @@ function misc:enemyListCheck(Unit)
607607
notPet = not br.functions.unit:GetUnitIsUnit(Unit, "pet"),
608608
creatorCheck = (not createdByPlayer or isHostileQuestNPC),
609609
notWaterEle = br.functions.unit:GetObjectID(Unit) ~= 11492,
610-
los = br.functions.misc:getLineOfSight("player", Unit)
611610
}
612611

613-
local allPass = checks.exists and checks.notDead and checks.canAttack and checks.hasHealth
612+
-- Expensive LoS check only done if other checks pass (early exit optimization)
613+
local basicChecks = checks.exists and checks.notDead and checks.canAttack and checks.hasHealth
614614
and checks.inRange and checks.notCritter and checks.mcCheck and checks.notPet
615615
and checks.creatorCheck and checks.notWaterEle
616-
-- LoS check: allow units without LoS if they're in combat (actively fighting)
617-
and (checks.los or br._G.UnitAffectingCombat(Unit))
616+
617+
if not basicChecks then
618+
return false -- Early exit before expensive LoS check
619+
end
620+
621+
-- LoS check: allow units without LoS if they're in combat (actively fighting)
622+
-- Skip LoS check for close enemies (<15y) to reduce overhead
623+
local los = distance < 15 or br.functions.misc:getLineOfSight("player", Unit) or br._G.UnitAffectingCombat(Unit)
624+
625+
local allPass = basicChecks and los
618626
and ((Unit ~= 131824 and Unit ~= 131823 and Unit ~= 131825) or ((br.functions.aura:UnitBuffID(Unit, 260805)
619627
or br.functions.unit:GetUnitIsUnit(Unit, "target")) and (Unit == 131824 or Unit == 131823 or Unit == 131825)))
620628

@@ -639,7 +647,21 @@ function misc:isValidUnit(Unit)
639647
return false
640648
end
641649

650+
-- PRIORITY: Units in damaged table bypass all validation checks
651+
-- These are units actively in combat with our group (attacking or being attacked)
652+
-- The combatlog cleanup already ensures these units are valid (exists, alive, attackable)
653+
-- damaged table keys are pointers from GetObjectWithGUID()
654+
-- damaged table values are unitSetup objects where .unit is also the pointer
655+
if br.engines.enemiesEngine.damaged then
656+
local unitPointer = br._G.ObjectPointer(Unit)
657+
-- Direct pointer lookup - ObjectPointer() should match GetObjectWithGUID() for same unit
658+
if unitPointer and br.engines.enemiesEngine.damaged[unitPointer] ~= nil then
659+
return true
660+
end
661+
end
662+
642663
-- Calculate all conditions once
664+
local unitPointer = br._G.ObjectPointer(Unit)
643665
local hostileOnly = br.functions.misc:isChecked("Hostiles Only")
644666
local playerTarget = br.functions.unit:GetUnitIsUnit(Unit, "target")
645667
local reaction = br.functions.unit:GetUnitReaction(Unit, "player") or 10
@@ -657,7 +679,7 @@ function misc:isValidUnit(Unit)
657679

658680
-- Check if unit is tapped but we've damaged it
659681
local isTapped = br._G.UnitIsTapDenied(Unit)
660-
local hasDamagedTapped = isTapped and br.engines.enemiesEngine.damaged[br._G.ObjectPointer(Unit)] ~= nil
682+
local hasDamagedTapped = isTapped and br.engines.enemiesEngine.damaged[unitPointer] ~= nil
661683

662684
-- Check if unit actually passed enemyListCheck or is in units table
663685
-- If it's the player target but not in units table, verify it at least passes basic enemyListCheck

System/Loader/cCharacter.lua

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,6 @@ function cCharacter:new()
307307
--- Base Wrap ---
308308
-----------------
309309
local section_base = br.ui:createSection(br.ui.window.profile, "Base Options")
310-
br.ui:createCheckbox(section_base, "Cast Debug", "Shows information about how the bot is casting.")
311-
br.ui:createCheckbox(section_base, "Threat Debug", "Shows information about threat and threat changes.")
312310
br.ui:createCheckbox(section_base, "Ignore Combat", "Checking this will make BR think it is always in combat")
313311
br.ui:createCheckbox(section_base, "Mute Queue", "Mute messages from Smart Queue and Queue Casting")
314312
br.ui:createDropdown(section_base, "Pause Mode", br.ui.dropOptions.Toggle, 2,

0 commit comments

Comments
 (0)