From 9d9c8a7c7e8e0a4cf8c8fc6af560dc1e0034019c Mon Sep 17 00:00:00 2001 From: pepopo978 Date: Fri, 13 Dec 2024 17:14:58 -0800 Subject: [PATCH] add name filter option --- Localization.lua | 2 + README.md | 4 +- commands.lua | 136 ++++++++++++++++++++++++++++------------------- 3 files changed, 85 insertions(+), 57 deletions(-) diff --git a/Localization.lua b/Localization.lua index 53a049e..2b51859 100644 --- a/Localization.lua +++ b/Localization.lua @@ -10,6 +10,7 @@ L:RegisterTranslations("enUS", function() ["Play a sound when a curse is about to expire."] = true, ["Allow out of combat targets to be multicursed. Would only consider using this solo to avoid potentially griefing raids/dungeons by pulling unintended mobs."] = true, ["Minimum HP for a target to be considered. Example usage minhp=10000. "] = true, + ["Filter targets by name. Can be a partial match. If no match is found, the command will do nothing."] = true, ["Time threshold at which to allow refreshing a curse. Default is 0 seconds."] = true, ["Ignore the current target when choosing target for multicurse. Does not affect 'curse' command."] = true, ["/cursive curse ||>: Casts spell if not already on target/guid"] = true, @@ -158,6 +159,7 @@ L:RegisterTranslations("zhCN", function() ["Play a sound when a curse is about to expire."] = "当诅咒即将到期时播放声音.\n 详细使用说明及示例请查看readme文件", ["Allow out of combat targets to be multicursed. Would only consider using this solo to avoid potentially griefing raids/dungeons by pulling unintended mobs."] = "允许战斗外目标被多重诅咒。只有在单人游戏中才会考虑使用这个选项,以避免在副本中意外拉到怪物而造成困扰.", ["Minimum HP for a target to be considered. Example usage minhp=10000. "] = "目标考虑的最小生命值。例如:minhp=10000.", + ["Filter targets by name. Can be a partial match. If no match is found, the command will do nothing."] = "通过名称过滤目标。可以是部分匹配。如果没有找到匹配项,命令将不执行.", ["Time threshold at which to allow refreshing a curse. Default is 0 seconds."] = "允许刷新诅咒的时间阈值。默认是0秒.例如:refreshtime=2", ["Ignore the current target when choosing target for multicurse. Does not affect 'curse' command."] = "选择多重诅咒目标时忽略当前目标。不影响‘诅咒’命令。", ["/cursive curse ||>: Casts spell if not already on target/guid"] = "/cursive curse <法术名称>|<目标ID>|<选项列表,用半角逗号分隔>: 如果目标/ID身上没有此法术,目标ID可以是以下内容(mouseover), (player), (pet), (party)(%d), (partypet)(%d), (raid)(%d+), (raidpet)(%d+), (target), (targettarget)", diff --git a/README.md b/README.md index eacd319..2c0b7ca 100644 --- a/README.md +++ b/README.md @@ -78,14 +78,16 @@ All commands can take the following options separated by commas: - `ignoretarget` : "Ignore the current target when choosing target for multicurse. Does not affect 'curse' command.", - `minhp=` : "Minimum HP for a target to be considered.", - `refreshtime=` : "Time threshold at which to allow refreshing a curse. Default is 0 seconds.", +- `name=` : "Filter targets by name. Can be a partial match. If no match is found, the command will do nothing.", EXAMPLE: `/cursive multicurse Corruption|HIGHEST_HP|warnings,resistsound,expiringsound,minhp=10000,refreshtime=2` +EXAMPLE: `/cursive multicurse Curse of Recklessness|RAID_MARK|name=Touched Warrior,resistsound,expiringsound` ## Important info If you have my latest nampower, it will use the SpellInRange function from that to provide improved range checking. -All commands will prioritize targets within 28 yards of you first to have a better chance of being in range. +Otherwise, 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: diff --git a/commands.lua b/commands.lua index 78f26e4..fe1d473 100644 --- a/commands.lua +++ b/commands.lua @@ -11,6 +11,7 @@ local commandOptions = { minhp = L["Minimum HP for a target to be considered. Example usage minhp=10000. "], refreshtime = L["Time threshold at which to allow refreshing a curse. Default is 0 seconds."], ignoretarget = L["Ignore the current target when choosing target for multicurse. Does not affect 'curse' command."], + name = L["Filter targets by name. Can be a partial match. If no match is found, the command will do nothing."], } local commands = { @@ -54,6 +55,11 @@ local function parseOptions(optionsStr) if refreshTime then options["refreshtime"] = tonumber(refreshTime) end + elseif option == "name" then + local _, _, name = string.find(optionsStr, "name=([%w%s]+)") + if name then + options["name"] = name + end elseif string.find(optionsStr, option) then options[option] = true end @@ -247,64 +253,72 @@ local function pickTarget(selectedPriority, spellNameNoRank, checkRange, options if not options["ignoretarget"] or guid ~= currentTargetGuid then -- check if in combat already or player is actively targeting the mob if ignoreInFight or Cursive.filter.infight(guid) or guid == currentTargetGuid then - local passedRangeCheck = false - if IsSpellInRange then - -- use IsSpellInRange from nampower if available - local result = IsSpellInRange(spellNameNoRank, guid) - if result == -1 then - passedRangeCheck = checkRange == false or CheckInteractDistance(guid, 4) -- fallback to old range check - else -- 0 or 1 - passedRangeCheck = result == 1 - end - else - -- prioritize targets within 28 yards first to improve chances of being in range - passedRangeCheck = checkRange == false or CheckInteractDistance(guid, 4) + local passedNameCheck = true + if options["name"] then + local name = UnitName(guid) + passedNameCheck = string.find(name, options["name"]) end - if passedRangeCheck then - -- check if the target has the curse - 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 = -1 - local secondaryValue = -1 - if selectedPriority == PRIORITY_HIGHEST_HP then - primaryValue = UnitHealth(guid) or 0 - elseif selectedPriority == PRIORITY_RAID_MARK then - primaryValue = GetRaidTargetIndex(guid) or 0 - 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 = -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_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 - highestPrimaryValue = primaryValue - highestSecondaryValue = secondaryValue - targetedGuid = guid - elseif primaryValue == highestPrimaryValue and secondaryValue > highestSecondaryValue then - highestSecondaryValue = secondaryValue - targetedGuid = guid + if passedNameCheck then + local passedRangeCheck = false + if IsSpellInRange then + -- use IsSpellInRange from nampower if available + local result = IsSpellInRange(spellNameNoRank, guid) + if result == -1 then + passedRangeCheck = checkRange == false or CheckInteractDistance(guid, 4) -- fallback to old range check + else -- 0 or 1 + passedRangeCheck = result == 1 + end + else + -- prioritize targets within 28 yards first to improve chances of being in range + passedRangeCheck = checkRange == false or CheckInteractDistance(guid, 4) + end + if passedRangeCheck then + -- check if the target has the curse + 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 = -1 + local secondaryValue = -1 + if selectedPriority == PRIORITY_HIGHEST_HP then + primaryValue = UnitHealth(guid) or 0 + elseif selectedPriority == PRIORITY_RAID_MARK then + primaryValue = GetRaidTargetIndex(guid) or 0 + 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 = -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_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 + highestPrimaryValue = primaryValue + highestSecondaryValue = secondaryValue + targetedGuid = guid + elseif primaryValue == highestPrimaryValue and secondaryValue > highestSecondaryValue then + highestSecondaryValue = secondaryValue + targetedGuid = guid + end end end end @@ -349,6 +363,16 @@ function Cursive:Curse(spellName, targetedGuid, options) end end + if targetedGuid and options["name"] then + local name = UnitName(targetedGuid) + if not string.find(name, options["name"]) then + if options["warnings"] then + DEFAULT_CHAT_FRAME:AddMessage(curseNoTarget) + end + return + end + end + -- remove (Rank x) from spellName if it exists local spellNameNoRank = string.gsub(spellName, "%(.+%)", "")