• You've discovered RedGuides, an EverQuest multi-boxing and scripting community 🧙‍♀️⚙️. We want you to play several EQ characters at once, come join us and say hello! 👋

  • A TLP without truebox has thawed (Very Vanilla ready)
    Frostreaver

Problem - Code auto-targets my pet, dont know why!

Joined
Mar 20, 2024
RedCents
1,051¢
This one is a head scratcher and I cant figure it out: as I am in the midst of combat, my 6-box characters randomly switch their target from the mob I am fighting to their respective pets. It happens randomly and without any clear pattern.

I have combed through the code and I only use the /target command in 2 functions:

1) When I instruct my pets to stick to whichever mob in the Xtarget window has the lowest PctHPs before moving to the next target. This function only affects pets, not characters.

2) When I instruct my characters to nuke whichever mob in the Xtarget window has the lowest PctHPs as soon as it drops below 50% health.

That is it, nowhere else in the code I use the /target or /assist commands, and nowhere in the code I ever instruct a character to /target his own pet.

Have you ever experienced your characters auto-targeting their pets out of the blue? Any insights as of what might be causing it?

For reference, here I attach the full code:

Lua:
local mq = require('mq')
math.randomseed(os.clock())

--- Definition variables
local MainAssist = "My_Main_Character"
local DA1 = "Quivering Veil of Xarn"
local DA2 = "Harmshield"
local FD = "Feign Death"
local LifetapNuke = "Spirit Tap"
local LifetapDoT = "Vampiric Curse"
local MyRune = "Steelskin"
local PetHeal = "Renew Bones"
local PetRune = "Protection of Calliav"
local PetFocusSpell = "Augment Death"
local ShieldingSpell = "Greater Shielding"
local LeechSpell = "Call of Bones"
local AttackNuke = "Tobas' Acid Blast"
local AttackDoT = "Chilling Embrace"

--- Cache variables
local CurrentLowestMobPctHPsCache = 0 --- This is just a default to declare the variable
local CurrentPetTargetNameCache = "abc" --- This is just a default to declare the variable
local CurrentPetTargetCleanNameCache = "abc" --- This is just a default to declare the variable
local CurrentLowestMobIDCache = 0 --- This is just a default to declare the variable

--- Fixed threshold variables
local HPthreshold_Defense = 100
local HPthreshold_LifetapDoT = 80
local HPthreshold_LifetapNuke = 60
local HPthreshold_AttackDoT1 = 90 --- dont cast any attack spells if mob has more HPs than this
local HPthreshold_AttackDoT2 = 50 --- dont cast attack DoTs if mob has less HPs than this. Below this point, cast only Nukes. If equal to Attack Dot 1, it means we prefer to cast nukes only
local LowOnManaThreshold = 20
local MidManaThreshold = 50
local MeditatingThreshold = 80
local PetHPthreshold = 70
local Aggrothreshold_Defcon1 = 90
local Aggrothreshold_Defcon2 = 60
local HPthreshold_Leech = 40

--- Operational functions
local function removebuff(spell)
    mq.cmdf('/removebuff "%s"', spell)
    mq.delay(100)
end
local function assist(MainAssist)
    mq.cmd('/assist ', MainAssist)
    mq.delay(100)
end
local function TargetSpawn(TargetMob)
    local TargetMobName = mq.TLO.Spawn(TargetMob)()
    mq.cmd('/target ', TargetMobName)
    mq.delay(100)
end
local function stopcast()
    mq.cmdf('/stopcast')
    mq.delay(100)
end
local function stopmoving()
    mq.cmdf('/afollow off')
    mq.delay(100)
end
local function use_aa(aa)
    mq.cmdf('/alt activate "%s"', aa.ID())
    mq.delay(100)
end
local function stand()
    mq.cmdf('/stand')
    mq.delay(100)
end
local function cast(spell)
    if not LowOnMana and not Feigning and not Invulnerable and not Moving and not Casting and not Invisible then
        stand()
        mq.cmdf('/cast "%s"', spell)
        mq.delay(100)
    end
end
local function castsemipriority(spell)
    if not Feigning and not Invulnerable and not Moving and not Casting and not Invisible then
        stand()
        mq.cmdf('/cast "%s"', spell)
        mq.delay(100)
    end
end
local function castpriority(spell)
    if not Feigning and not Invulnerable then
        stopmoving()
        stopcast()
        stand()
        mq.cmdf('/cast "%s"', spell)
        mq.delay(100)
    end
end

--- Condition functions
local function condition()

    --- Operational variables
    local Meditating = mq.TLO.Window('SpellBookWnd').Open
    local StopMeditating = mq.TLO.Window('SpellBookWnd').DoClose
    local Class = mq.TLO.Me.Class.ShortName()
    local PctHPs = mq.TLO.Me.PctHPs()
    local PctMana = mq.TLO.Me.PctMana()
    local Casting = false
        if mq.TLO.Me.Casting.ID() ~= nil then
            Casting = true
        end
    local Invisible = mq.TLO.Me.Invis()
    local Feigning = mq.TLO.Me.Feigning()
    local Moving = mq.TLO.Me.Moving()
    local SpellReady = mq.TLO.Me.SpellReady
    local CombatMobs = mq.TLO.Me.XTarget()
    local CombatSlots = mq.TLO.Me.XTargetSlots()
    local Aggro = mq.TLO.Me.PctAggro()
    local Sitting = mq.TLO.Me.Sitting()
    local Invulnerable = false
       if mq.TLO.Me.Invulnerable() ~= nil then
            Invulnerable = true
        end
    local LowOnMana = false
        if PctMana < LowOnManaThreshold then
            LowOnMana = true
        end
    local AboveMidMana = true
        if PctMana < MidManaThreshold then
            AboveMidMana = false
        end  
    local MustMeditate = false
        if PctMana < MeditatingThreshold then
            MustMeditate = true
        end    

    --- Lets declare some group-related variables and give them some default values.  
    local NumberOfGroupMembers = mq.TLO.Group.Members()
    local CurrentLowestPet = mq.TLO.Group.Member(0).Pet.PctHPs()
    local CurrentLowestPetIndex = 0
    local OwnerOfCurrentLowestPet = MainAssist

    --- Since CombatMobs is buggy, we gotta confirm that we're indeed in Combat mode
    local CombatMode = 0 --- This is just a default to declare the variable
    if CombatMobs > 0 then
        for i = 1, CombatSlots do
            local MobsID = mq.TLO.Me.XTarget(i).ID() or 0 -- safety net: incase of a nil, make it 0
            if MobsID > 0 and mq.TLO.Me.XTarget(i).Type.NotEqual(CORPSE)() and mq.TLO.Me.XTarget(i).PctHPs() > 0  then -- safety net: make sure mob(i) is actually alive
                CombatMode = 1
            end
        end
    end
   
    --- Define local functions that will be called upon later

    --- Set of defensive actions if we're under attack
    local function EvasiveActions()
        if PctHPs < HPthreshold_Defense and not Feigning and not Invulnerable and not Invisible then
            if mq.TLO.Me.CleanName() ~= MainAssist then --- Remove the MainAssist from Defensive Actions because I am playing him manually. Defensive Actions are only meant to be for passive characters.
                mq.cmd('/g ***** UNDER ATTACK! *****')
                --- HarmShield
                if mq.TLO.Me.SpellReady(DA2)() then
                    mq.cmd('/g Casting -> ', DA2)
                    castpriority(DA2)
                --- Feign Death  
                elseif not mq.TLO.Me.SpellReady(DA2)() and mq.TLO.Me.SpellReady(FD)() then
                    mq.cmd('/g Casting -> ', FD)
                    castpriority(FD)
                end
            end
        end
        mq.delay(100)
    end

    --- Pet switch targets to the lowest mob in the xTarget window
    local function TargetLowestHP()
        ---Lets pick the mob in the xTarget window with lowest HP, so pets stick to it before moving to the next mob.
        local CurrentLowestMobName = "abc" --- This is just a default to declare the variable
        local CurrentLowestMobCleanName = "abc" --- This is just a default to declare the variable
        local CurrentLowestMobPctHPs = 100 --- This is just a default to declare the variable. It NUST be a global variable because we want to use it outside of this function.
        local CurrentLowestMobIndex = 1 --- This is just a default to declare the variable
        local CurrentPetTargetName = mq.TLO.Me.Pet.Target.Name() --- It NUST be a global variable because we want to use it outside of this function.
        local CurrentLowestMobID = 0 --- This is just a default to declare the variable. It NUST be a global variable because we want to use it outside of this function.
        local CurrentPetTargetID = 0 --- This is just a default to declare the variable.
        --- Lets find out the mob in Xtarget with lowest HPs
        for i = 1, CombatSlots do
            local MobsID = mq.TLO.Me.XTarget(i).ID() or 0 -- safety net: incase of a nil, make it 0
            if MobsID > 0 and mq.TLO.Me.XTarget(i).Type.NotEqual(CORPSE)() and mq.TLO.Me.XTarget(i).PctHPs() > 0  then -- safety net: make sure mob(i) is actually alive
                if mq.TLO.Me.XTarget(i).PctHPs() < CurrentLowestMobPctHPs then
                    CurrentLowestMobIndex = i
                    --- These variables below need to be inside the IF so they update with the current info as per the latest FOR loop
                    CurrentLowestMobPctHPs = mq.TLO.Me.XTarget(CurrentLowestMobIndex).PctHPs()
                    CurrentLowestMobName = mq.TLO.Me.XTarget(CurrentLowestMobIndex).Name()
                    CurrentLowestMobID = mq.TLO.Me.XTarget(CurrentLowestMobIndex).ID()
                    CurrentLowestMobCleanName = mq.TLO.Me.XTarget(CurrentLowestMobIndex).CleanName()
                    --- Store the values from these function variables into their respective caches so we can use them outside of this function
                    CurrentLowestMobPctHPsCache = CurrentLowestMobPctHPs
                    CurrentLowestMobNameCache = CurrentLowestMobName
                    CurrentLowestMobIDCache = CurrentLowestMobID
                    CurrentLowestMobCleanNameCache = CurrentLowestMobCleanName
                end
            end
        end
        --- Now that we know which of the mobs in XTarget with lowest HP, lets switch targets to that one.
        CurrentPetTargetID = mq.TLO.Me.Pet.Target.ID()
        if mq.TLO.Me.Pet.ID() ~= 0 and CurrentPetTargetID ~= CurrentLowestMobID then
            mq.TLO.Me.Pet.DoTarget(CurrentLowestMobID)
            mq.cmd('/pet back off')
            mq.delay(50)
            mq.cmd('/pet attack ', CurrentLowestMobID)
        end
    end

    local function RuneMyself()
        if not LowOnMana and not Feigning and not Invulnerable and not Moving and not Casting and not Invisible then
            if mq.TLO.Me.Buff(MyRune)() ~= nil or mq.TLO.Me.Buff("Group Pact of the Wolf")() ~= nil or mq.TLO.Me.Buff("Rune of Rikkukin")() ~= nil or mq.TLO.Me.Buff("Group Spirit of the Black Wolf")() ~= nil then
                --- do nothing, I am already runed
            elseif mq.TLO.Me.SpellReady(MyRune)() then  
                mq.cmd('/g Casting -> ', MyRune)
                cast(MyRune)
            elseif not mq.TLO.Me.Gem(MyRune)() and mq.TLO.Me.Pet.ID() ~= 0 and mq.TLO.Me.Pet.Buff(PetFocus)() == nil then
                if mq.TLO.Me.Gem(PetFocus)() then
                    mq.cmdf('/memorize "%s" 5', MyRune)
                    mq.delay(1000)
                elseif not mq.TLO.Me.Gem(PetFocus)() then --- If you dont have neither PetFocus nor MyRune memorized and both need to be cast, memorize MyRune in slot 3 (instead of the usual 4) to avoid conflicts. That way each will be memorized in a different Spell Gem only for this time, they will be cast, and the script can move forward organically from there.
                    mq.cmdf('/memorize "%s" 5', MyRune)
                    mq.delay(1000)
                end
            end
        end
    end

    local function Shielding()
        if not LowOnMana and not Feigning and not Invulnerable and not Moving and not Casting and not Invisible then
            if mq.TLO.Me.Buff(ShieldingSpell)() ~= nil or mq.TLO.Me.Buff("Group Spirit of the Black Wolf")() ~= nil or mq.TLO.Me.Buff("Talisman of Wunshi")() ~= nil then --- Add whatever 3rd party buff blocks your buff
                --- do nothing, I am already shielded
            elseif mq.TLO.Me.SpellReady(ShieldingSpell)() then  
                mq.cmd('/g Casting -> ', ShieldingSpell)
                cast(ShieldingSpell)
            elseif not mq.TLO.Me.Gem(ShieldingSpell)() then
                if mq.TLO.Me.Gem(PetFocus)() or mq.TLO.Me.Gem(MyRune)() then
                    mq.cmdf('/memorize "%s" 5', ShieldingSpell)
                    mq.delay(1000)
                else --- If you dont have neither PetFocus nor MyRune memorized and both need to be cast, memorize MyRune in slot 3 (instead of the usual 4) to avoid conflicts. That way each will be memorized in a different Spell Gem only for this time, they will be cast, and the script can move forward organically from there.
                    mq.cmdf('/memorize "%s" 5', ShieldingSpell)
                    mq.delay(1000)
                end
            end
        end
    end

    local function Leech()
        --- If I am leeching but full mana, lets remove Leech
        if not MustMeditate and mq.TLO.Me.Buff(LeechSpell)() ~= nil then --- I dont need to leech anymore
            removebuff(LeechSpell)
        --- If I am leeching but low on health, lets remove Leech  
        elseif PctHPs < HPthreshold_Leech and mq.TLO.Me.Buff(LeechSpell)() ~= nil then --- Running low on HP, lets remove leech
            removebuff(LeechSpell)
        --- If we are not low on HP and we are not almost full mana, lets leech.  
        elseif PctHPs >= HPthreshold_Leech and MustMeditate and not Feigning and not Invulnerable and not Moving and not Casting and not Invisible then
            if mq.TLO.Me.Buff(LeechSpell)() ~= nil or mq.TLO.Me.Buff("Clarity")() ~= nil then --- Add whatever 3rd party buff blocks your buff
                --- do nothing, I am already leeching
            elseif mq.TLO.Me.Buff(LeechSpell)() == nil and mq.TLO.Me.SpellReady(LeechSpell)() then  
                mq.cmd('/g Casting -> ', LeechSpell)
                castsemipriority(LeechSpell)
            elseif not mq.TLO.Me.Gem(LeechSpell)() then
                if mq.TLO.Me.Gem(PetFocus)() or mq.TLO.Me.Gem(MyRune)() then
                    mq.cmdf('/memorize "%s" 5', LeechSpell)
                    mq.delay(1000)
                else --- If you dont have neither PetFocus nor MyRune memorized and both need to be cast, memorize the spell in a different Gem to avoid conflicts. That way each will be memorized in a different Spell Gem only for this time, they will be cast, and the script can move forward organically from there.
                    mq.cmdf('/memorize "%s" 5', LeechSpell)
                    mq.delay(1000)
                end
            end  
        end
    end

    local function FocusPet()
        if mq.TLO.Me.Pet.ID() ~= 0 and not LowOnMana and not Feigning and not Invulnerable and not Moving and not Casting and not Invisible then
            if mq.TLO.Me.Pet.Buff(PetFocusSpell)() ~= nil or mq.TLO.Me.Pet.Buff("Speed of the Brood")() ~= nil or mq.TLO.Me.Pet.Buff("Incapacitate")() ~= nil then
                --- do nothing, the pet is already focused
            elseif mq.TLO.Me.Pet.Buff(PetFocusSpell)() == nil and mq.TLO.Me.SpellReady(PetFocusSpell)() then  
                mq.cmd('/g Casting -> ', PetFocusSpell)
                cast(PetFocusSpell)
            elseif not mq.TLO.Me.Gem(PetFocusSpell)() then
                mq.cmdf('/memorize "%s" 5', PetFocusSpell)
                mq.delay(1000)
            end
        end
    end

    local function Meditate()
        --- Meditate if Mana is below a certain threshold. Since it is very unfortable to move around with this Meditation function running, I will turn it off for the MainAssist
        if MustMeditate and not Meditating() and not Sitting and not Feigning and not Invulnerable and not Moving and not Casting and not mq.TLO.Me.CleanName() == MainAssist then
            mq.cmd('/sit')
        end
    end
   

    --- DEFCON declaration:
    ----- Defcon 1 is emergency situation.
    ----- Defcon 2 is dont do anything that can gain aggro.
    ----- Defcon 3 is you may take actions.
    ----- Defcon 4 means we are not in combat.

    --- Firstly, lets see if the character is agro with ANY of the mobs in the Xtarget window and, if so, we can define the Defcon score depending on the Aggro level.
    local defcon = 4
    if CombatMode == 1 then
        for i = 1, CombatSlots do
            if mq.TLO.Me.XTarget(i).PctAggro() >= Aggrothreshold_Defcon1 then
                defcon = 1
            elseif mq.TLO.Me.XTarget(i).PctAggro() < Aggrothreshold_Defcon1 and mq.TLO.Me.XTarget(i).PctAggro() >= Aggrothreshold_Defcon2 and defcon >= 2 then --- The "defcon >= 2" is so if Defcon was already at level 1 for ANY mob in the loop, any subsequence mob with a lower aggro does not dilute the previous higher Defcon score.
                defcon = 2
            elseif mq.TLO.Me.XTarget(i).PctAggro() < Aggrothreshold_Defcon2 and defcon >= 3 then --- The "defcon >= 3"... read above
                defcon = 3
            end
        end
    else
        defcon = 4
    end

    --- Now that we know the Defcon number, we can start playing defensive, pet healing, lifetaps, etc.

    --- Defcon == 1, initiate evasive action
    if Class == 'NEC' and defcon == 1 then
       
        --- Initiate evasive actions
        EvasiveActions()


    --- Defcon == 2, dont do anything so you dont gain aggro.
    elseif Class == 'NEC' and defcon == 2 then
        --- dont do a thing yoursel


    elseif Class == 'NEC' and defcon == 3 then    

        --- Lifetaps. Lets heal ourselves before healing pets.
        if mq.TLO.Me.CleanName() ~= MainAssist then --- Only supportive characters will lifetap
            if not LowOnMana and not Feigning and not Invulnerable and not Casting and not Invisible and not Moving then
                --- Lets cast some lifetaps only if we drop below certain health thresholds.
                if CurrentLowestMobPctHPsCache < HPthreshold_AttackDoT1 then --- Lets wait for the mob to drop a bit in HPs before we cast to avoid aggro
                    if PctHPs < HPthreshold_LifetapDoT and PctHPs > HPthreshold_LifetapNuke and mq.TLO.Me.Buff(LifetapDoT)() == nil then
                        if mq.TLO.Me.SpellReady(LifetapDoT)() then
                            mq.cmd('/g Casting -> ', LifetapDoT)
                            TargetSpawn(CurrentLowestMobIDCache)
                            cast(LifetapDoT)
                            mq.delay(1000)
                        elseif not mq.TLO.Me.Gem(LifetapDoT)() then
                            mq.cmdf('/memorize "%s" 1', LifetapDoT)
                        end
                    elseif PctHPs <= HPthreshold_LifetapNuke then
                        if mq.TLO.Me.SpellReady(LifetapNuke)() then
                            mq.cmd('/g Casting -> ', LifetapNuke)
                            TargetSpawn(CurrentLowestMobIDCache)
                            cast(LifetapNuke)
                            mq.delay(1000)
                        elseif not mq.TLO.Me.Gem(LifetapNuke)() then
                            mq.cmdf('/memorize "%s" 2', LifetapDoT)
                        end
                    end
                end
            end
        end

        --- Pet Heals
        if mq.TLO.Me.CleanName() ~= MainAssist then --- Only supportive characters will heal pets
            if not LowOnMana and not Feigning and not Invulnerable and not Casting and not Invisible and not Moving then
                --- Just as precaution, lets only heal pet if we ourselves are healed up. Otherwise, as per above, the Lifetaps should take priority.
                if PctHPs >= HPthreshold_LifetapDoT then
                    --- Firstly, lets determine the pet with the lowest health percentage and his owner.
                    local CurrentLowestPetPctHPs = 100 --- This is just a default to declare the variable
                    for i=0,NumberOfGroupMembers do
                        if mq.TLO.Group.Member(i).ID() and mq.TLO.Group.Member(i).Type.NotEqual(CORPSE)() and mq.TLO.Group.Member(i).Pet.ID() ~= 0 then
                            if mq.TLO.Group.Member(i).Pet.PctHPs() <= PetHPthreshold then
                                if mq.TLO.Group.Member(i).Pet.PctHPs() < CurrentLowestPetPctHPs then
                                    CurrentLowestPetPctHPs = mq.TLO.Group.Member(i).Pet.PctHPs()
                                    CurrentLowestPetIndex = i
                                end  
                            end
                        end
                        CurrentLowestPet = mq.TLO.Group.Member(CurrentLowestPetIndex).Pet.CleanName()
                        OwnerOfCurrentLowestPet = mq.TLO.Group.Member(CurrentLowestPetIndex).CleanName()
                    end

                    --- Now that we know the pet with the lowest health percentage, lets either Rune it or Heal it when it drops under the health threshold.
                    if mq.TLO.Group.Member(CurrentLowestPetIndex).ID() and mq.TLO.Group.Member(CurrentLowestPetIndex).Type.NotEqual(CORPSE)() and mq.TLO.Group.Member(CurrentLowestPetIndex).Pet.ID() ~= 0 and mq.TLO.Group.Member(CurrentLowestPetIndex).Pet.PctHPs() <= PetHPthreshold then
                        --- If it is my pet, I will prioritize Runes over Heals. That being said, I will make sure they are always memorized and ready.
                        mq.cmd('/target ', CurrentLowestPet)
                        mq.delay(50)
                        if CurrentLowestPet == mq.TLO.Me.Pet.CleanName() then
                            if mq.TLO.Me.SpellReady(PetRune)() then
                                mq.cmd('/g Casting -> ', PetRune)
                                cast(PetRune)
                            elseif not mq.TLO.Me.Gem(PetRune)() then
                                mq.cmdf('/memorize "%s" 4', PetRune)
                            elseif mq.TLO.Me.Gem(PetRune)() and not mq.TLO.Me.SpellReady(PetRune)() and mq.TLO.Me.SpellReady(PetHeal)() then
                                mq.cmd('/g Casting -> ', PetHeal)
                                cast(PetHeal)
                            elseif not mq.TLO.Me.Gem(PetHeal)() then
                                mq.cmdf('/memorize "%s" 3', PetHeal)
                            end  
                        else
                            if mq.TLO.Me.Gem(PetHeal)() and mq.TLO.Me.SpellReady(PetHeal)() then
                                mq.cmd('/g Casting -> ', PetHeal)
                                cast(PetHeal)
                            elseif not mq.TLO.Me.Gem(PetHeal)() then
                                mq.cmdf('/memorize "%s" 3', PetHeal)
                            end
                        end
                        mq.delay(1000)
                    end
                end
            end
        end

        --- Attack spells (DoTs and Nukes).

        --- Lets pick a random Group Member to cast the spell. We dont need to over-burn mana having all characters DoTing and Nuking at the same time. One at a time is enough.
        local RandomIndex = mq.TLO.Math.Rand(1, 6)() --- There are 5 supportive characters.
        local RandomMember = mq.TLO.Group.Member(RandomIndex-1).CleanName()  --- This gives me the name of the character
        if mq.TLO.Me.CleanName() ~= MainAssist then --- Only supporting characters will cast attack spells
            if mq.TLO.Me.CleanName() == RandomMember then --- We want to pace down the attack casting to 20% (since there are 5 supportive characters), so on average only 1 out 5 supportive characters will attack. It's not perfect, but it's the best approximation I got.
                if AboveMidMana and not Feigning and not Invulnerable and not Casting and not Invisible and not Moving then
                    --- If mob is high on health (but never full due to aggro), cast AttackDoT
                    if CurrentLowestMobPctHPsCache < HPthreshold_AttackDoT1 and CurrentLowestMobPctHPsCache >= HPthreshold_AttackDoT2 and mq.TLO.Spawn(CurrentLowestMobID).MyBuff(AttackDoT)() == nil then
                        if mq.TLO.Me.SpellReady(AttackDoT)() then
                            mq.cmd('/g Casting -> ', AttackDoT)
                            TargetSpawn(CurrentLowestMobIDCache)
                            cast(AttackDoT)
                            mq.delay(5000)
                        elseif not mq.TLO.Me.Gem(AttackDoT)() then
                            mq.cmdf('/memorize "%s" 5', AttackDoT)
                        end
                    --- But if the mob is not high on health, cast AttackNuke
                    elseif CurrentLowestMobPctHPsCache < HPthreshold_AttackDoT2 then
                        if mq.TLO.Me.SpellReady(AttackNuke)() then
                            mq.cmd('/g Casting -> ', AttackNuke)
                            TargetSpawn(CurrentLowestMobIDCache)
                            cast(AttackNuke)
                            mq.delay(5000)
                        elseif not mq.TLO.Me.Gem(AttackNuke)() then
                            mq.cmdf('/memorize "%s" 5', AttackNuke)
                        end
                    end
                end
            end
        end


    --- Defcon == 4. Rebuff, rutine checks, etc.
    elseif Class == 'NEC' and defcon == 4 then
       
        --- Always keep yourself buffed
        Shielding()

    end
   
    --- Actions to perform always when in combat...
    if defcon == 1 or defcon == 2 or defcon == 3 then

        --- Make sure that pets are always locked into the mob with the lowest HPs
        TargetLowestHP()

    end

    --- Actions to perform always except in moments of sheer emergency mode (Defcon 1)...
    if defcon == 2 or defcon == 3 or defcon == 4 then
       
        --- Keep mana flowing
        Leech()
        --- Focus your pet
        FocusPet()
        --- Keep yourself runed
        RuneMyself()

    end

    --- Actions to perform only in moments of low aggro...
    if defcon == 3 or defcon == 4 then
   
        --- Sit down and meditate
        Meditate()

    end

    --- Actions to perform always, no matter the DEFCON score...
    if defcon == 1 or defcon == 2 or defcon == 3 or defcon == 4 then
       
        --- enter code here

    end


end

--- Action functions
local function action()
end

--- Return functions
return {condfunc=condition, actionfunc=action}
 
Last edited by a moderator:
assuming behavior isn't happening due to outside forces (conflicting automation, cat sitting on keyboard etc) without seeing code - the overwhelming answer is going to be "you have an error somewhere in your code"
 
assuming behavior isn't happening due to outside forces (conflicting automation, cat sitting on keyboard etc) without seeing code - the overwhelming answer is going to be "you have an error somewhere in your code"

Fair comment. I have attached the full code to my original post.
 
You have at least one more target where you instruct your characters to target the pet with lowest hps.

Line 384: mq.cmd('/target ', CurrentLowestPet)

I don't know if that's really where the issue is, but you may want to look closer at how that works.

It's also possible that your pets are getting on xtar through charms or something and you're picking them in your TargetLowestHP() function.
 
Difficult to diagnose just by browsing the code.

If I was trying to diagnose it myself - i would just add some more diagnostic/logging code to your routines. If that doesnt work -you havent added enough diagnostic code.

Sort of like that old adage - if you cant fix it with Duct Tape - you're not using enough Duct Tape.


Are you sure you dont have something else running that might be doing it? ie pet gets hit with a debuff and other routine tries to cure it?
 
Alright, after a LOT of debugging, I have identified the function that causes my character to randomly switch target from whatever I am targeting to my actual pet. I have confirmed that if I take this function out of the code, the random target switching doesnt happen anymore:

Code:
local function TargetLowestHP()
            ---Explanation: This function finds the mob in the xTarget window with lowest HP, so pets stick to it before moving to the next mob.

            ---Lets declare the variables needed for this function
            local CurrentLowestMobPctHPs = 100 --- This is just a default to declare the variable.
            local CurrentLowestMobIndex = 1 --- This is just a default to declare the variable
            local CurrentLowestMobID = 0 --- This is just a default to declare the variable.
            local CurrentPetTargetID = 0 --- This is just a default to declare the variable.

            --- Lets find out the mob in Xtarget with lowest HPs
            for i = 1, CombatSlots do
                local MobsID = mq.TLO.Me.XTarget(i).ID() or 0 -- safety net: incase of a nil, make it 0
                if MobsID > 0 and mq.TLO.Me.XTarget(i).Type.NotEqual(CORPSE)() and mq.TLO.Me.XTarget(i).PctHPs() > 0  then -- safety net: make sure mob(i) is actually alive
                    if mq.TLO.Me.XTarget(i).PctHPs() < CurrentLowestMobPctHPs then
                        CurrentLowestMobIndex = i
                        CurrentLowestMobID = mq.TLO.Me.XTarget(CurrentLowestMobIndex).ID()
                    end
                end
            end

            --- Now that we know which is the mob in XTarget with the lowest HP, lets have pet switch target to that one.
            CurrentPetTargetID = mq.TLO.Me.Pet.Target.ID()
            if mq.TLO.Me.Pet.ID() ~= 0 and CurrentPetTargetID ~= CurrentLowestMobID then
                mq.TLO.Me.Pet.DoTarget(CurrentLowestMobID)
                mq.cmd('/pet back off')
                mq.delay(50)
                mq.cmd('/pet attack ', CurrentLowestMobID)
            end

end

The funny thing is that in that function, all the instructions relate to my pet (not me) re-targetting to what ever mob in the XTarget window has the lowest PctHPs. So, if all the instructions relate to mq.TLO.Me.Pet , why does it affect me?

By the way, I have confirmed that at no point the pet gets charmed. None of the mobs I fight charm at all.
 
For anyone interested or future reference, the culprit of the issue was the line mq.TLO.Me.Pet.DoTarget(CurrentLowestMobID) . It was meant to instruct my pet to target CurrentLowestMobID , but it was messing with my own targetting.

I removed that line and used an alternative approach, and now it works beautifully.
 
Problem - Code auto-targets my pet, dont know why!

Users who are viewing this thread

Back
Top
Cart