Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 185 additions & 0 deletions CombatMode/Config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,186 @@ local AdvancedConfigOptions = {
}
}

---------------------------------------------------------------------------------------
-- HEALING RADIAL CONFIG --
---------------------------------------------------------------------------------------
local HealingRadialOptions = {
name = CM.METADATA["TITLE"],
handler = CM,
type = "group",
args = {
header = {
type = "header",
name = "|cff00FF7FHEALING RADIAL|r",
order = 1
},
description = {
type = "description",
name = "\nA radial menu for quickly targeting party members when healing. While |cffE52B50Mouse Look|r is active and you're in a party, hold a mouse button to display the radial, flick toward your target, and release to cast.\n\n",
fontSize = "medium",
order = 2
},
enabled = {
type = "toggle",
name = "Enable |cff00FF7FHealing Radial|r",
desc = "Shows a radial menu when using click-cast buttons while in a party. Party members are arranged by role with the tank at 12 o'clock.\n\n|cffffd700Default:|r |cffE52B50Off|r",
width = "full",
order = 3,
set = function(_, value)
CM.DB.global.healingRadial.enabled = value
-- Re-apply mouse button bindings (clears them if radial enabled, sets them if disabled)
CM.OverrideDefaultButtons()
if CM.HealingRadial and CM.HealingRadial.SetCaptureActive then
CM.HealingRadial.SetCaptureActive(value)
end
end,
get = function()
return CM.DB.global.healingRadial.enabled
end,
},
spacing1 = Spacing("full", 3.1),
visualGroup = {
type = "group",
name = "Visual Settings",
order = 4,
inline = true,
args = {
showHealthBars = {
type = "toggle",
name = "Show Health Bars",
desc = "Display health bars on each party member slice.",
width = 1.2,
order = 1,
set = function(_, value)
CM.DB.global.healingRadial.showHealthBars = value
end,
get = function()
return CM.DB.global.healingRadial.showHealthBars
end,
disabled = function()
return not CM.DB.global.healingRadial.enabled
end
},
showHealthPercent = {
type = "toggle",
name = "Show Health %",
desc = "Display health percentage on each slice.",
width = 1.2,
order = 2,
set = function(_, value)
CM.DB.global.healingRadial.showHealthPercent = value
end,
get = function()
return CM.DB.global.healingRadial.showHealthPercent
end,
disabled = function()
return not CM.DB.global.healingRadial.enabled
end
},
showPlayerNames = {
type = "toggle",
name = "Show Names",
desc = "Display player names on each slice.",
width = 1.2,
order = 3,
set = function(_, value)
CM.DB.global.healingRadial.showPlayerNames = value
end,
get = function()
return CM.DB.global.healingRadial.showPlayerNames
end,
disabled = function()
return not CM.DB.global.healingRadial.enabled
end
},
showRoleIcons = {
type = "toggle",
name = "Show Role Icons",
desc = "Display role icons (tank, healer, DPS) on each slice.",
width = 1.2,
order = 4,
set = function(_, value)
CM.DB.global.healingRadial.showRoleIcons = value
end,
get = function()
return CM.DB.global.healingRadial.showRoleIcons
end,
disabled = function()
return not CM.DB.global.healingRadial.enabled
end
},
spacing2 = Spacing("full", 4.1),
sliceRadius = {
type = "range",
name = "Radial Size",
desc = "Distance from center to each party member slice.\n\n|cffffd700Default:|r |cff00FF7F120|r",
min = 60,
max = 200,
step = 10,
width = 1.5,
order = 5,
set = function(_, value)
CM.DB.global.healingRadial.sliceRadius = value
end,
get = function()
return CM.DB.global.healingRadial.sliceRadius
end,
disabled = function()
return not CM.DB.global.healingRadial.enabled
end
},
sliceSize = {
type = "range",
name = "Slice Size",
desc = "Size of each party member slice.\n\n|cffffd700Default:|r |cff00FF7F80|r",
min = 50,
max = 120,
step = 10,
width = 1.5,
order = 6,
set = function(_, value)
CM.DB.global.healingRadial.sliceSize = value
end,
get = function()
return CM.DB.global.healingRadial.sliceSize
end,
disabled = function()
return not CM.DB.global.healingRadial.enabled
end
},
}
},
spacing3 = Spacing("full", 5),
layoutInfo = {
type = "group",
name = "|cffffd700Layout Information|r",
order = 6,
inline = true,
args = {
layoutNote = {
type = "description",
name = "|cff909090Party members are automatically positioned by role:|r\n\n|cffcfcfcf• |cff00d1ffTank|r at 12 o'clock (top)\n• |cff00ff00Healer|r at 7 o'clock (bottom-left)\n• |cffff6060DPS|r fill remaining positions\n\nYour character is included in the radial at your role's position.|r",
order = 1
}
}
},
spacing4 = Spacing("full", 7),
devnote = {
type = "group",
name = "|cffffd700Developer Note|r",
order = 8,
inline = true,
args = {
note = {
type = "description",
name = "|cff909090The Healing Radial uses the same spell assignments as |cffB47EDCClick Casting|r. Configure which spells are bound to each mouse button in the Click Casting tab.|r\n\n|cffFF5050Note:|r Party assignments can only be updated outside of combat due to WoW API restrictions.",
order = 1
}
}
}
}
}

---------------------------------------------------------------------------------------
-- SETTINGS CATEGORY TREE --
---------------------------------------------------------------------------------------
Expand All @@ -1069,6 +1249,11 @@ CM.Config.OptionCategories = {
name = "|cffB47EDC • Click Casting|r",
table = ClickCastingOptions
},
{
id = "CombatMode_HealingRadial",
name = "|cff00FF7F • Healing Radial|r",
table = HealingRadialOptions
},
{
id = "CombatMode_Advanced",
name = "|cffffffff • Advanced|r",
Expand Down
41 changes: 39 additions & 2 deletions CombatMode/Constants.lua
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,28 @@ CM.Constants.BLIZZARD_EVENTS = {
"PLAYER_MOUNT_DISPLAY_CHANGED", -- Toggling crosshair when mounting/dismounting
"PLAYER_REGEN_ENABLED" -- Resetting crosshair when leaving combat
},
-- Events for Healing Radial
HEALING_RADIAL_EVENTS = {
"GROUP_ROSTER_UPDATE", -- Party composition changed
},

}

---------------------------------------------------------------------------------------
-- HEALING RADIAL POSITIONS --
---------------------------------------------------------------------------------------
-- Slice positions for 5-man content (angles in degrees, 0 = right, 90 = up)
-- Each slice covers 72 degrees (360/5)
CM.Constants.HealingRadialSlices = {
[1] = { defaultRole = "TANK", angle = 90, label = "12 o'clock (top)" },
[2] = { defaultRole = "DAMAGER", angle = 162, label = "10 o'clock (upper-left)" },
[3] = { defaultRole = "HEALER", angle = 234, label = "7 o'clock (lower-left)" },
[4] = { defaultRole = "DAMAGER", angle = 306, label = "5 o'clock (lower-right)" },
[5] = { defaultRole = "DAMAGER", angle = 18, label = "2 o'clock (upper-right)" },
}

CM.Constants.HealingRadialSliceArc = 72 -- degrees per slice

---------------------------------------------------------------------------------------
-- ASSETS --
---------------------------------------------------------------------------------------
Expand Down Expand Up @@ -370,7 +389,8 @@ CM.Constants.FramesToCheck = {
"WantAds",
"SubscriptionInterstitialFrame",
"CinematicFrameCloseDialog",
"MovieFrame"
"MovieFrame",
"CombatModeHealingRadialFrame"
}

-- Default frames to check with a dynamic name: any frame containing a string defined here will be matched, e.g. "OPieRT" will match the frame "OPieRT-1234-5678"
Expand Down Expand Up @@ -642,7 +662,24 @@ CM.Constants.DatabaseDefaults = {
crosshairY = 50,
silenceAlerts = false,
debugMode = false,
bindings = DefaultBindings
bindings = DefaultBindings,
-- Healing Radial settings
healingRadial = {
enabled = false,
sliceRadius = 120,
sliceSize = 80,
showHealthBars = true,
showHealthPercent = true,
showPlayerNames = true,
showRoleIcons = true,
highlightColor = {1, 1, 0, 0.4},
backgroundColor = {0, 0, 0, 0.7},
healthyColor = {0, 0.8, 0, 1},
damagedColor = {1, 1, 0, 1},
criticalColor = {1, 0, 0, 1},
fadeInDuration = 0.08,
fadeOutDuration = 0.05,
}
},
char = {
useGlobalBindings = false,
Expand Down
38 changes: 37 additions & 1 deletion CombatMode/Core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -642,10 +642,15 @@ local function IsUnlockFrameVisible()
CursorUnlockFrameGroupVisible(CM.Constants.WildcardFramesToCheck) or isGenericPanelOpen
end

local function IsHealingRadialActive()
return CM.HealingRadial and CM.HealingRadial.IsActive and CM.HealingRadial.IsActive()
end

local function ShouldFreeLookBeOff()
local evaluate = IsCustomConditionTrue() or
(FreeLookOverride or SpellIsTargeting() or InCinematic() or IsInCinematicScene() or
IsUnlockFrameVisible() or IsVendorMountOut() or IsInPetBattle() or IsFeignDeathActive())
IsUnlockFrameVisible() or IsVendorMountOut() or IsInPetBattle() or IsFeignDeathActive() or
IsHealingRadialActive())
return evaluate
end

Expand Down Expand Up @@ -681,6 +686,11 @@ function CM.SetNewBinding(buttonSettings)
return
end

-- If healing radial is enabled, it manages its own bindings
if CM.DB.global.healingRadial and CM.DB.global.healingRadial.enabled then
return
end

local valueToUse
if buttonSettings.value == "MACRO" then
valueToUse = "MACRO " .. buttonSettings.macroName
Expand Down Expand Up @@ -753,6 +763,10 @@ local function LockFreeLook()
MouselookStart()
CenterCursor(true)
HandleFreeLookUIState(true, false)
-- Notify Healing Radial of mouselook state change
if CM.HealingRadial and CM.HealingRadial.OnMouselookChanged then
CM.HealingRadial.OnMouselookChanged(true)
end
CM.DebugPrint("Free Look Enabled")
end
end
Expand All @@ -767,6 +781,10 @@ local function UnlockFreeLook()
end

HandleFreeLookUIState(false, false)
-- Notify Healing Radial of mouselook state change
if CM.HealingRadial and CM.HealingRadial.OnMouselookChanged then
CM.HealingRadial.OnMouselookChanged(false)
end
CM.DebugPrint("Free Look Disabled")
end
end
Expand All @@ -781,6 +799,10 @@ local function UnlockFreeLookPermanent()
end

HandleFreeLookUIState(false, true)
-- Notify Healing Radial of mouselook state change
if CM.HealingRadial and CM.HealingRadial.OnMouselookChanged then
CM.HealingRadial.OnMouselookChanged(false)
end
CM.DebugPrint("Free Look Disabled (Permanent)")
end
end
Expand Down Expand Up @@ -856,10 +878,19 @@ local function HandleEventByCategory(category, event)
end,
FRIENDLY_TARGETING_EVENTS = function()
HandleFriendlyTargetingInCombat()
-- Also handle combat end for healing radial pending updates
if event == "PLAYER_REGEN_ENABLED" and CM.HealingRadial and CM.HealingRadial.OnCombatEnd then
CM.HealingRadial.OnCombatEnd()
end
end,
UNCATEGORIZED_EVENTS = function()
SetCrosshairAppearance(HideCrosshairWhileMounted() and "mounted" or "base")
end,
HEALING_RADIAL_EVENTS = function()
if CM.HealingRadial and CM.HealingRadial.OnGroupRosterUpdate then
CM.HealingRadial.OnGroupRosterUpdate()
end
end,

}

Expand Down Expand Up @@ -994,6 +1025,11 @@ function CM:OnEnable()
CreatePulse()
CreateTargetMacros()

-- Initialize Healing Radial module
if CM.HealingRadial and CM.HealingRadial.Initialize then
CM.HealingRadial.Initialize()
end

-- Registering Blizzard Events from Constants.lua
for _, events_to_register in pairs(CM.Constants.BLIZZARD_EVENTS) do
for _, event in ipairs(events_to_register) do
Expand Down
1 change: 1 addition & 0 deletions CombatMode/Embeds.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<!-- MODULES -->
<Script file="Core.lua"/>
<Script file="Constants.lua"/>
<Script file="HealingRadial.lua"/>
<Script file="Config.lua"/>
<!-- FRAME -->
<Frame name="CombatModeFrame" hidden="false" parent="UIParent" inherits="SecureHandlerStateTemplate">
Expand Down
Loading