diff --git a/README.md b/README.md index 644984e..b8288df 100644 --- a/README.md +++ b/README.md @@ -8,48 +8,75 @@ ![image](https://github.com/pepopo978/Cursive/assets/149287158/801511af-29c7-4baf-b1ac-5e8c52f0f846) - -Cursive combines ShaguScan unit scanning with curse tracking similar to DotTimer and the ability to automatically curse targets similar to Decursive. +Cursive combines ShaguScan unit scanning with curse tracking similar to DotTimer and the ability to automatically curse +targets similar to Decursive. ### Recommended setup -Move the Cursive label to the desired position on the screen. You can turn on 'Show Frame Background' in the settings to help with this. Once you have it where you want it, turn off 'Show Frame Background' and turn on 'Allow clickthrough' - so that it doesn't block your clicks when it's not displaying mobs. + +Move the Cursive label to the desired position on the screen. You can turn on 'Show Frame Background' in the settings to +help with this. Once you have it where you want it, turn off 'Show Frame Background' and turn on 'Allow clickthrough' +so that it doesn't block your clicks when it's not displaying mobs. ## Commands + `/cursive` for commands, minimap icon to edit options. ### Curse + `/cursive curse ||`: Casts spell if not already on target/guid -EXAMPLE: `/cursive curse Corruption|target` will attempt to cast Corruption on your target if it's not already on them and they aren't cc'ed. +EXAMPLE: `/cursive curse Corruption|target` will attempt to cast Corruption on your target if it's not already on them +and they aren't cc'ed. ### Multicurse -`/cursive multicurse ||`: Picks target based on priority and casts spell if not already on target and they aren't cc'ed. -EXAMPLE: `/cursive multicurse Corruption|HIGHEST_HP` will attempt to cast Corruption picking the target with the highest HP that doesn't already have it and will warn you if it does nothing. +`/cursive multicurse ||`: Picks target based on priority and +casts spell if not already on target and they aren't cc'ed. + +EXAMPLE: `/cursive multicurse Corruption|HIGHEST_HP` will attempt to cast Corruption picking the target with the highest +HP that doesn't already have it and will warn you if it does nothing. + ## Priority Options -- HIGHEST_HP - Target highest HP enemy without a curse first. -- RAID_MARK - Target largest raid mark enemy without a curse first. Raid mark priority is as follows: - - Skull = 8 (1st priority) - - Cross = 7 - - Square = 6 - - Moon = 5 - - Triangle = 4 - - Circle = 3 - - Star = 2 - - Diamond = 1 (8th priority) - - No mark = 0 -- HIGHEST_HP_RAID_MARK - Target highest HP enemy with a raid (use raid mark priorities for identical hp), then highest HP enemy without a mark. +- HIGHEST_HP - Target highest HP enemy without a curse first. +- RAID_MARK - Target largest raid mark enemy without a curse first. Priority is as follows: + - Skull = 8 (1st priority) + - Cross = 7 + - Square = 6 + - Moon = 5 + - Triangle = 4 + - Circle = 3 + - Star = 2 + - Diamond = 1 (8th priority) + - No mark = 0 +- RAID_MARK_SQUARE - Target largest raid mark but ignore Skull and Cross. Priority is as follows: + - Square = 6 (1st priority) + - Moon = 5 + - Triangle = 4 + - Circle = 3 + - Star = 2 + - Diamond = 1 + - No mark = 0 + - Cross = -1 + - Skull = -2 (9th priority) +- INVERSE_RAID_MARK - Target lowest raid mark enemy without a curse first. (reverse of RAID_MARK) + +- HIGHEST_HP_RAID_MARK - Target highest HP enemy with a raid (use raid mark priorities for identical hp), then highest + HP enemy without a mark. +- HIGHEST_HP_RAID_MARK_SQUARE - Same as HIGHEST_HP_RAID_MARK but with RAID_MARK_SQUARE priority for marked enemies. +- HIGHEST_HP_INVERSE_RAID_MARK - Same as HIGHEST_HP_RAID_MARK but with INVERSE_RAID_MARK priority for marked enemies. ## Command Options + All commands can take the following options separated by commas: + - `warnings` : "Display text warnings when a curse fails to cast.", - `resistsound` : "Play a sound when a curse is resisted.", - `expiringsound` : "Play a sound when a curse is about to expire.", -- `allowooc` : "Allow out of combat targets to be multicursed. Would only consider using this solo to avoid potentially griefing raids/dungeons by pulling unintended mobs.", +- `allowooc` : "Allow out of combat targets to be multicursed. Would only consider using this solo to avoid potentially + griefing raids/dungeons by pulling unintended mobs.", - `minhp=` : "Minimum HP for a target to be considered.", -- `refreshtime=` : "Time threshold at which to allow refreshing a curse. Default is 0 seconds.", +- `refreshtime=` : "Time threshold at which to allow refreshing a curse. Default is 0 seconds.", EXAMPLE: `/cursive multicurse Corruption|HIGHEST_HP|warnings,resistsound,expiringsound,minhp=10000,refreshtime=2` @@ -58,6 +85,7 @@ EXAMPLE: `/cursive multicurse Corruption|HIGHEST_HP|warnings,resistsound,expirin All commands will prioritize targets within 28 yards of you first to have a better chance of being in range. All commands will ignore targets with the following CCs on them: + - Sleep - Entangling Roots - Shackle Undead @@ -69,4 +97,5 @@ All commands will ignore targets with the following CCs on them: - Freezing Trap - Banish -Multicurse will only ever target enemies that are already in combat (except if you target a mob directly first) to prevent pulling things you didn't intend like marked patrols. +Multicurse will only ever target enemies that are already in combat (except if you target a mob directly first) to +prevent pulling things you didn't intend like marked patrols. diff --git a/commands.lua b/commands.lua index 1d8fa5d..c67309e 100644 --- a/commands.lua +++ b/commands.lua @@ -16,10 +16,22 @@ local commands = { ["multicurse"] = "/cursive multicurse ||>: Picks target based on priority and casts spell if not already on target", } +local PRIORITY_HIGHEST_HP = "HIGHEST_HP" +local PRIORITY_RAID_MARK = "RAID_MARK" +local PRIORITY_RAID_MARK_SQUARE = "RAID_MARK_SQUARE" +local PRIORITY_INVERSE_RAID_MARK = "INVERSE_RAID_MARK" +local PRIORITY_HIGHEST_HP_RAID_MARK = "HIGHEST_HP_RAID_MARK" +local PRIORITY_HIGHEST_HP_RAID_MARK_SQUARE = "HIGHEST_HP_RAID_MARK_SQUARE" +local PRIORITY_HIGHEST_HP_INVERSE_RAID_MARK = "HIGHEST_HP_INVERSE_RAID_MARK" + local priorities = { - ["HIGHEST_HP"] = "Target with the highest HP.", - ["RAID_MARK"] = "Target with the highest raid mark.", - ["HIGHEST_HP_RAID_MARK"] = "Target with the highest HP and raid mark.", + [PRIORITY_HIGHEST_HP] = "Target with the highest HP.", + [PRIORITY_RAID_MARK] = "Target with the highest raid mark.", + [PRIORITY_RAID_MARK_SQUARE] = "Target with the highest raid mark with Cross set to -1 and Skull set to -2 (Square highest prio at 6).", + [PRIORITY_INVERSE_RAID_MARK] = "Target with the lowest raid mark.", + [PRIORITY_HIGHEST_HP_RAID_MARK] = "Target with the highest HP and raid mark.", + [PRIORITY_HIGHEST_HP_RAID_MARK_SQUARE] = "Same as HIGHEST_HP_RAID_MARK but with RAID_MARK_SQUARE mark prio.", + [PRIORITY_HIGHEST_HP_INVERSE_RAID_MARK] = "Same as HIGHEST_HP_RAID_MARK but with INVERSE_RAID_MARK mark prio." } local curseNoTarget = "|cffffcc00Cursive:|cffffaaaa Couldn't find a target to curse." @@ -91,6 +103,10 @@ local crowdControlledSpellIds = { [9852] = { name = "Entangling Roots", rank = 5, duration = 24 }, [9853] = { name = "Entangling Roots", rank = 6, duration = 27 }, + [2637] = { name = "Hibernate", rank = 1, duration = 20 }, + [18657] = { name = "Hibernate", rank = 2, duration = 30 }, + [18658] = { name = "Hibernate", rank = 3, duration = 40 }, + [1425] = { name = "Shackle Undead", rank = 1, duration = 30 }, [9486] = { name = "Shackle Undead", rank = 2, duration = 40 }, [10956] = { name = "Shackle Undead", rank = 3, duration = 50 }, @@ -160,10 +176,22 @@ local function isMobCrowdControlled(guid) return false end +local function GetSquarePrioRaidTargetIndex(guid) + local index = GetRaidTargetIndex(guid) + if index == 7 then + return 0 -- cross becomes 0 + elseif index == 8 then + return -1 -- skull becomes -1 + elseif index == 0 then + return -2 -- nomark becomes -2 + end + return index or -2 +end + local function pickTarget(selectedPriority, spellNameNoRank, checkRange, options) -- Curse the target that best matches the selected priority - local highestPrimaryValue = -1 - local highestSecondaryValue = -1 + local highestPrimaryValue = -10 + local highestSecondaryValue = -10 local targetedGuid = nil local minHp = options["minhp"] @@ -187,19 +215,37 @@ local function pickTarget(selectedPriority, spellNameNoRank, checkRange, options if not Cursive.curses:HasCurse(spellNameNoRank, guid, refreshTime) and not isMobCrowdControlled(guid) then local mobHp = UnitHealth(guid) if not minHp or mobHp >= minHp then - local primaryValue + local primaryValue = -1 local secondaryValue = -1 - if selectedPriority == "HIGHEST_HP" then - primaryValue = UnitHealth(guid) - elseif selectedPriority == "RAID_MARK" then + if selectedPriority == PRIORITY_HIGHEST_HP then + primaryValue = UnitHealth(guid) or 0 + elseif selectedPriority == PRIORITY_RAID_MARK then primaryValue = GetRaidTargetIndex(guid) or 0 - elseif selectedPriority == "HIGHEST_HP_RAID_MARK" then + elseif selectedPriority == PRIORITY_RAID_MARK_SQUARE then + primaryValue = GetSquarePrioRaidTargetIndex(guid) + elseif selectedPriority == PRIORITY_INVERSE_RAID_MARK then + primaryValue = -1 * (GetRaidTargetIndex(guid) or 9) + elseif selectedPriority == PRIORITY_HIGHEST_HP_RAID_MARK then secondaryValue = GetRaidTargetIndex(guid) or 0 if secondaryValue > 0 and not seenRaidMark then - highestPrimaryValue = -1 -- reset highestPriorityValue if this is the first raid mark we've seen + highestPrimaryValue = -10 -- reset highestPriorityValue if this is the first raid mark we've seen seenRaidMark = true end - primaryValue = UnitHealth(guid) + primaryValue = UnitHealth(guid) or 0 + elseif selectedPriority == PRIORITY_HIGHEST_HP_RAID_MARK_SQUARE then + secondaryValue = GetSquarePrioRaidTargetIndex(guid) + if secondaryValue > -2 and not seenRaidMark then + highestPrimaryValue = -10 -- reset highestPriorityValue if this is the first raid mark we've seen + seenRaidMark = true + end + primaryValue = UnitHealth(guid) or 0 + elseif selectedPriority == PRIORITY_HIGHEST_HP_INVERSE_RAID_MARK then + secondaryValue = -1 * (GetRaidTargetIndex(guid) or 9) + if secondaryValue > -9 and not seenRaidMark then + highestPrimaryValue = -10 -- reset highestPriorityValue if this is the first raid mark we've seen + seenRaidMark = true + end + primaryValue = UnitHealth(guid) or 0 end if primaryValue > highestPrimaryValue then @@ -276,7 +322,7 @@ function Cursive:Multicurse(spellName, priority, options) return end - local selectedPriority = priority or "HIGHEST_HP" + local selectedPriority = priority or PRIORITY_HIGHEST_HP -- remove (Rank x) from spellName if it exists local spellNameNoRank = string.gsub(spellName, "%(.+%)", "") diff --git a/ui.lua b/ui.lua index c305f20..994618e 100644 --- a/ui.lua +++ b/ui.lua @@ -330,6 +330,7 @@ local function DisplayGuid(guid, row, col) local curse = barFrame["curse" .. curseNumber] if remaining >= 0 then curse:SetTexture(Cursive.curses.trackedCurseIds[curseData.spellID].texture) + -- curse:SetTexCoord(.078, .92, .079, .937) rounded icons curse.timer:SetText(remaining) curse.timer:Show() curse:Show()