Rotations



  • Is anyone working/testing rotations using the framework in minibot?


  • Manager

    BadRotations have already adapted their scripts by simply adding the EWT API converter. But note that you need to rename the addon and the .toc file to keep your account safe (refer to this topic for more info).

    You can also build your own combat rotations and scripts using Minibot's native API



  • Does anyone ahs a rotation script for minibot that they can share . I just want to see how its build up.


  • Manager

    @exstazi What kind of script are you looking for?



  • think he's looking for a rotation say for warlock affliction that he can look at to get an idea of how it works am i right @exstazi ?



  • @Stickybun any rotation that works with minibot. i just want to know how its done so i can learn from it.


  • Manager

    I don't think we have any "native" Minibot open source rotations available, but you can look at BadRotations code that was adapted to Minibot via the Converter file

    Just use any open source LUA script and then look at the Minibot API to make it work here.



  • I will post mine when I get home (about 40hrs from now). I am working on a team of 5 doing instances together, so have prot paladin, disc priest, moonkin, ele shammy and fire mage.

    They are all low level, but doing optimal dps rotations for their classes. I'm struggling a bit with movement, particularly evading boss mechanics, and my code is a hodge-podge of minibot API, wow API and minibot studio code, so be warned in probably not doing everything optimally, but at least it will give you an idea how to script lua to do rotations, that part was actually pretty easy. I just used the icy veins priority list for that level and modified them sightly to fit the stateless, functional coding style.


  • Manager

    thank you @MrCeeJ
    the Rotation part is indeed not too hard, all you need to do is create an object manager function and then call the rotation sequence in your OnUpdate frame.
    if you just want it to use spells and kill mobs, follow your common sense knowledge of the class. if you want a higher quality optimized pve rotation you may follow either Icy Veins guide or SimCraft
    unfortunately, there is no one mighty source of a pvp rotation priority list with tricks but you can use different forums and guides, including same Icy Veins



  • lol i dont get why there is no basic rotations for folks to modify and expand on and share @titan surely they would be a great selling point



  • @MrCeeJ said in Rotations:

    I will post mine when I get home (about 40hrs from now). I am working on a team of 5 doing instances together, so have prot paladin, disc priest, moonkin, ele shammy and fire mage.

    They are all low level, but doing optimal dps rotations for their classes. I'm struggling a bit with movement, particularly evading boss mechanics, and my code is a hodge-podge of minibot API, wow API and minibot studio code, so be warned in probably not doing everything optimally, but at least it will give you an idea how to script lua to do rotations, that part was actually pretty easy. I just used the icy veins priority list for that level and modified them sightly to fit the stateless, functional coding style.

    Nice thats what im looking for πŸ˜› something to learn from. πŸ™‚



  • You can also check our official relogger example to build a rotation. Though it is not for combat, but conceptually it is the same and the code is rather simplistic.



  • So here is the current state of my code, it is clearly work in progress, and there are a few rough edges / unimplemented work. I figured it was better to get something online for you now, I can tidy it up and comment it and then repost it later when I get a sec (just got back home today).

    I use a very simple minibot studio project to manage the dungeon pathing, all 5 accounts use the same project, and same lua script (hence the switching on class type). The studio setup is just 5 paths joined in sequence, with PvE and Looting turned on at the top level, and the below lua file imported as a custom script. There is a little trick to change the min_melee distance for Scragmaw to stop the tank ending up in lava, and I think I will need to do something for loot range too as they all jump in the lava after killing it, but other than that they clear the instance without intervention.

    As I mentioned earlier, there is a mix of engine code, and API code (both bot and wow), sometimes things don't seem to work in one, and I try another way and it does. I'm not suggesting anyone follow what I'm doing, but this is where I have got to by hacking bits together and reading the documentation. I think if I used more studio code I could do things more easily, particularly the multiplayer, actions and buffs/ food. At the moment I'm doing it all in the prepare code and probably didn't need to. I am also struggling a bit with non-path movement, say spreading out on a boss or not standing in fire (been playing wow since beta and the irony of this is not escaping me). I have also not looked into functions or storing any state, both of which could be hepful in solving my problems, but I wanted to get the hang of the various frameworks first.

    Any questions feel free to ask, I don't follow the forum here but do check it fairly frequently.

    return {
        -- Define rotation
        rotations = {
            combat = function(env, is_pulling)
                local _, global_cd_duration, _, _ = GetSpellCooldown("61304")
                local main_tank = "" -- tank name ;)
                local UnitClassName = env:evaluate_condition_variable("myself.class") --  UnitClass("player")
                local enemeies = env:evaluate_condition_variable("npcs.all.is_attacking_me")
                local min_dot_hp = 10
                --env:evaluate_condition_variable("npcs.attackable.range_10")>=2  -- more than 2 targets in 10 yards
    
                -- NOTE: Off gcd abilities won't be used until the next free gcd, but they won't trigger gcd so the next ability will happen at the same time
                if (global_cd_duration == 0) then
                    -- ** PALADIN ** --
                    if UnitClassName == "PALADIN" then
                        local current_health = UnitHealth("player")
                        local max_health = UnitHealthMax("player")
                        local _, hoj_cd = GetSpellCooldown("Hammer of Justice")
                        local life = current_health / max_health
                        -- A fix for no target spam
                        if (UnitExists("target") == false) then
                            RunMacroText("/targetenemy [noexists][dead]")
                        end
                        -- cleanse
                        --RunMacroText("/cast Cleanse Toxins")
    
                        -- defensives
                        if (hoj_cd == 0 and life < 0.4) then
                            RunMacroText("/cast Hammer of Justice")
                        else
                            -- tank rotation
                            local _, avengers_shield_cd = GetSpellCooldown("Avenger's Shield")
                            local _, hammer_of_the_rightrous_cd = GetSpellCooldown("Hammer of the Righteous")
                            local _, judgment_cd = GetSpellCooldown("Judgment")
                            local _, crusader_strike_cd = GetSpellCooldown("Crusader Strike")
                            local _, consecration_cd = GetSpellCooldown("Consecration")
                            local has_consecration = env:evaluate_condition_variable("myself.buff.Consecration")
                            local shield_charges, shield_max_harges, shield_cooldown_start, shield_cooldown_duration, _ = GetSpellCharges("Shield of the Righteous")
                            local has_shield = env:evaluate_condition_variable("myself.buff.132403") -- 132403 for dmg reduction effect
    
                            -- Use shield if we have taken damage and don't have it up
                            if (life < 1 and has_shield == -1 and shield_charges > 0 and env:evaluate_condition_variable("npcs.attackable.range_8") >= 1) then
                                RunMacroText("/cast Shield of the Righteous")
                            elseif (avengers_shield_cd == 0) then
                                RunMacroText("/cast Avenger's Shield")
                            elseif (has_consecration == -1 and consecration_cd == 0 and env:evaluate_condition_variable("npcs.attackable.range_8") >= 1) then
                                RunMacroText("/cast Consecration")
                            elseif (hammer_of_the_rightrous_cd == 0) then
                                RunMacroText("/cast Hammer of the Righteous")
                            elseif (judgment_cd == 0) then
                                RunMacroText("/cast Judgment")
                            elseif (crusader_strike_cd == 0) then
                                RunMacroText("/cast Crusader Strike")
                            elseif (consecration_cd == 0 and env:evaluate_condition_variable("npcs.attackable.range_8") >= 1) then
                                RunMacroText("/cast Consecration")
                            elseif (hoj_cd == 0) then
                                RunMacroText("/cast Hammer of Justice")
                            end
                        end
                    end
                    -- ** PRIEST ** --
                    if UnitClassName == "PRIEST" then
                        local emergency_health = 50
                        local ok_health = 75
                        local good_health = 80
                        local party_size = 1
                        RunMacroText("/assist " .. main_tank)
                        -- Do Healing
                        local healing = false
                        local current_health = UnitHealth("player")
                        local max_health = UnitHealthMax("player")
                        local life = tonumber(current_health) / tonumber(max_health)
                        local hp = env:evaluate_condition_variable("myself.health")
                        local has_weakened_soul = env:evaluate_condition_variable("myself.debuff.6788")
                        local start, penance_cd_duration, enabled, modRate = GetSpellCooldown("Penance")
    
                        -- Heal yourself
                        if (hp < emergency_health and has_weakened_soul == -1) then
                            healing = true
                            RunMacroText("/cast Power Word: Shield")
                        elseif (hp < good_health) then
                            healing = true
                            RunMacroText("/cast Flash Heal")
                        else
                            -- Heal the party
                            local party_members = GetHomePartyInfo()
                            if (party_members ~= nil) then
                                -- emergency healing
                                for i, player_name in ipairs(party_members) do
                                    local target_hp = env:evaluate_condition_variable("unit." .. player_name .. ".health")
                                    -- print(i, player_name, target_hp, "Checking for healing already done? :", healing)
                                    if (healing == false) then
                                        local has_weakened_soul = env:evaluate_condition_variable("unit." .. player_name .. ".debuff.6788")
                                        if (target_hp > 0 and target_hp < emergency_health and has_weakened_soul == -1) then
                                            -- print(i, player_name, target_hp, "Receiving shield")
                                            healing = true
                                            RunMacroText("/cast [target=" .. player_name .. "] Power Word: Shield")
                                        elseif (target_hp > 0 and target_hp < emergency_health and penance_cd_duration == 0) then
                                            -- print(i, player_name, target_hp, "Receiving Penance")
                                            healing = true
                                            RunMacroText("/cast [target=" .. player_name .. "] Penance")
                                        elseif (target_hp > 0 and target_hp < emergency_health) then
                                            healing = true
                                            RunMacroText("/cast [target=" .. player_name .. "] Flash Heal")
                                        -- print(i, player_name, target_hp, "Receiving Flash Heal")
                                        end
                                    end
                                end
                                -- top everyone else off
                                for i, player_name in ipairs(party_members) do
                                    local target_hp = env:evaluate_condition_variable("unit." .. player_name .. ".health")
                                    -- print(i, player_name, target_hp, "Checking for healing already done? :", healing)
                                    if (healing == false) then
                                        local has_weakened_soul = env:evaluate_condition_variable("unit." .. player_name .. ".debuff.6788")
                                        if (target_hp > 0 and target_hp < good_health and penance_cd_duration == 0) then
                                            -- print(i, player_name, target_hp, "Receiving Penance")
                                            healing = true
                                            RunMacroText("/cast [target=" .. player_name .. "] Penance")
                                        elseif (target_hp > 0 and target_hp < good_health and has_weakened_soul == -1 and player_name == main_tank) then
                                            -- print(i, player_name, target_hp, "Receiving shield")
                                            healing = true
                                            RunMacroText("/cast [target=" .. player_name .. "] Power Word: Shield")
                                        elseif (target_hp > 0 and target_hp < ok_health) then
                                            healing = true
                                            RunMacroText("/cast [target=" .. player_name .. "] Flash Heal")
                                        -- print(i, player_name, target_hp, "Receiving Flash Heal")
                                        end
                                    end
                                end
                            end
                        end
                        -- Do Damage
                        if (healing == false) then
                            if (UnitExists("target")) then -- check LOS and Move?
                                local has_swpain = env:evaluate_condition_variable("unit.target.debuff.589") -- TODO: Check all in combat targets
                                local target_health = env:evaluate_condition_variable("unit.target.health")
                                local _, schism_cd_duration, _, _ = GetSpellCooldown("Schism")
    
                                -- print("target health: " .. target_health)
                                if (target_health > min_dot_hp and has_swpain == -1) then
                                    -- print(target_health, " greater than ", min_dot_hp, " casting SW:P")
                                    RunMacroText("/cast Shadow Word: Pain")
                                elseif (schism_cd_duration == 0) then
                                    RunMacroText("/cast Schism")
                                elseif (penance_cd_duration == 0) then
                                    RunMacroText("/cast Penance") -- ID 47540
                                else
                                    RunMacroText("/cast Smite")
                                end
                            else
                                RunMacroText("/assist " .. main_tank)
                            end
                        end
                    end
                    -- ** DRUID ** --
                    if UnitClassName == "DRUID" then
                        local lunar_power = UnitPower("player", 8)
                        if (UnitExists("target")) then
                            --Get buff Ids
                            -- for i = 1, 40 do
                            --     local name, _, count, type, duration, etime, source, isStealable, _, spellID = UnitBuff("player", i)
                            --     if name then
                            --          Winds of Wisdom, Fortitude, Attonement, Bezerking, PWS
                            --         if (spellID ~= 326419 and spellID ~= 21562 and spellID ~= 194384 and spellID ~= 26297) then
                            --             print("Name :", name, " id :", spellID, " duration :", duration, "has heating up :", has_heating_up, " has hot streak :", has_hotstreak)
                            --         end
                            --     end
                            -- end
    
                            local target_hp = env:evaluate_condition_variable("unit.target.health")
                            local has_moonfire = env:evaluate_condition_variable("unit.target.debuff.Moonfire")
                            local knows_sunfire = IsSpellKnown(93402, false) --  not 164815
                            local has_sunfire = env:evaluate_condition_variable("unit.target.debuff.164815")
                            local _, berserking_cd_duration, _, _ = GetSpellCooldown("Berserking")
                            local has_solar_emp = env:evaluate_condition_variable("myself.buff.164545") -- solar
                            local has_lunar_emp = env:evaluate_condition_variable("myself.buff.164547") -- lunar
    
                            if (berserking_cd_duration == 0) then
                                RunMacroText("/cast Berserking")
                            elseif (target_hp > min_dot_hp and has_moonfire == -1) then
                                RunMacroText("/cast Moonfire")
                            elseif (knows_sunfire == true and target_hp > min_dot_hp and has_sunfire == -1) then
                                RunMacroText("/cast Sunfire")
                            elseif (has_solar_emp ~= -1) then -- will recast as buff isn't removed until spell lands
                                RunMacroText("/cast Solar Wrath")
                            elseif (lunar_power >= 40) then
                                RunMacroText("/cast Starsurge")
                            elseif (has_lunar_emp ~= -1) then -- will recast as buff isn't removed until spell lands
                                RunMacroText("/cast Lunar Strike")
                            else
                                RunMacroText("/cast Solar Wrath")
                            end
                        else
                            RunMacroText("/assist " .. main_tank)
                        end
                    end
                    -- ** MAGE ** --
                    if UnitClassName == "FROSTMAGE" then
                        if (UnitExists("target")) then
                            local target_is_frozen = nil --UnitAura("target", "Frozen")
                            -- local tank_name = "ceejpaladin-Doomhammer"
                            -- RunMacroText("/assist " .. tank_name)
    
                            local _, berserking_cd_duration, _, _ = GetSpellCooldown("Berserking")
                            if (berserking_cd_duration == 0) then
                                RunMacroText("/cast Berserking")
                            elseif (target_is_frozen ~= nil) then
                                RunMacroText("/cast Ice Lance")
                            else
                                RunMacroText("/cast Frostbolt")
                            end
                        else
                            RunMacroText("/assist " .. main_tank)
                        end
                    end
                    if UnitClassName == "MAGE" then
                        if (UnitExists("target")) then
                            local has_hotstreak = env:evaluate_condition_variable("myself.buff.48108") --195283  48108
                            local has_heating_up = env:evaluate_condition_variable("myself.buff.48107") -- Check for Heating Up when lvl 18
                            local _, fireblast_cd_duration, _, _ = GetSpellCooldown("Fire Blast")
                            local _, berserking_cd_duration, _, _ = GetSpellCooldown("Berserking")
    
                            if (berserking_cd_duration == 0) then
                                RunMacroText("/cast Berserking")
                            elseif (has_hotstreak > 0) then
                                RunMacroText("/cast Pyroblast")
                            elseif (fireblast_cd_duration == 0 and has_heating_up > 0) then
                                RunMacroText("/cast Fire Blast")
                            else
                                RunMacroText("/cast Fireball")
                            end
                        else
                            RunMacroText("/assist " .. main_tank)
                        end
                    end
                    -- ** SHAMAN ** --
                    if UnitClassName == "SHAMAN" then
                        if (UnitExists("target")) then
                            local target_hp = env:evaluate_condition_variable("unit.target.health")
                            local _, flame_shock_cd_duration, _, _ = GetSpellCooldown("188389")
                            local has_flame_shock = env:evaluate_condition_variable("unit.target.debuff.188389")
                            local maelstrom = UnitPower("player", 11)
                            local lb_charges, maxCharges, lb_cooldownStart, lb_cooldownDuration, lb_chargeModRate = GetSpellCharges("Lava Burst")
                            local _, berserking_cd_duration, _, _ = GetSpellCooldown("Berserking")
                            if (berserking_cd_duration == 0) then
                                RunMacroText("/cast Berserking")
                            elseif (target_hp > min_dot_hp and has_flame_shock == -1 and flame_shock_cd_duration == 0) then
                                RunMacroText("/cast Flame Shock")
                            elseif (maelstrom ~= nil and maelstrom >= 90) then
                                RunMacroText("/cast Earth Shock")
                            elseif (IsSpellKnown(51505, false) and lb_charges > 0 and lb_cooldownDuration == 0) then --"Lava Burst"
                                RunMacroText("/cast Lava Burst")
                            else
                                RunMacroText("/cast Lightning Bolt")
                            end
                        else
                            RunMacroText("/assist " .. main_tank)
                        end
                    end
                end
            end,
            prepare = function(env)
                local in_combat = env:evaluate_condition_variable("myself.is_in_combat") -- UnitAffectingCombat("player")
                local needs_more_time = false
                local healer_name = "" -- healer name :)
                if (in_combat) then
                    needs_more_time = false
                else
                    local healer_mana = UnitPower(healer_name, 0)
                    local healer_max_mana = UnitPowerMax(healer_name, 0)
                    -- print("Healer Mana :", healer_mana, "/", healer_max_mana)
                    local healer_mp = 100 * healer_mana / healer_max_mana
                    if (healer_mp < 90) then
                        needs_more_time = true
                    end
                    local UnitClassName = env:evaluate_condition_variable("myself.class") --  UnitClass("player")
                    if UnitClassName == "PRIEST" then
                        -- ** PRIEST ** --
                        -- local mp = env:evaluate_condition_variable("myself.mana")
                        local mana = UnitPower("player", 0)
                        local max_mana = UnitPowerMax("player", 0)
                        local mp = 100 * mana / max_mana
    
                        -- local is_drinking = env:evaluate_condition_variable("myself.buff.159") -- Refreshing Srping Water?
                        local has_fortitude = env:evaluate_condition_variable("myself.buff.21562") 
    
                        if (mp < 90) then
                            needs_more_time = true
                            -- Drink
                            local is_drinking = env:evaluate_condition_variable("myself.buff.43518") -- 43518 Conjured Mana Pie
                            if (is_drinking == -1) then
                                RunMacroText("/use Conjured Mana Pie")
                            end
                            print("Priest needs more mana :", mp, "is drinking :", is_drinking)
                        elseif (has_fortitude == -1) then
                            needs_more_time = true
                            RunMacroText("/cast Power Word: Fortitude")
                        end
                        local hp = env:evaluate_condition_variable("myself.health")
                        if (hp < 90) then
                            needs_more_time = true
                            RunMacroText("/cast [@Player]Flash Heal")
                        end                    
                    elseif UnitClassName == "PALADIN" then
                        -- ** PALADIN ** --
                        local hp = env:evaluate_condition_variable("myself.health")
                        if (hp < 90) then
                            needs_more_time = true
                            RunMacroText("/cast [@Player]Flash Of Light")
                        end
                    elseif UnitClassName == "MAGE" then
                        -- ** MAGE ** --
                        RunMacroText("/cast [nopet][@pet, dead] Summon Water Elemental")
                    elseif UnitClassName == "DRUID" then
                        -- ** DRUID ** --
                        local hp = env:evaluate_condition_variable("myself.health")
                        if (hp < 90) then
                            needs_more_time = true
                            RunMacroText("/cast [@Player]Regrowth")
                        else
                            RunMacroText("/cast [noform:4] Moonkin Form")
                        end
                    elseif UnitClassName == "SHAMAN" then
                        -- ** SHAMAN ** --
                        local hp = env:evaluate_condition_variable("myself.health")
                        if (hp < 90) then
                            needs_more_time = true
                            RunMacroText("/cast [@Player]Healing Surge")
                        end
                    end
                end
                -- called to check and run the preparation roation, such as summoning and buffing
                -- return true if preparations are still ongoing
                return needs_more_time
            end
        }
    }
    
    '''


  • @MrCeeJ

    Firstly thanks for your sharing. It helps a lot of users here.

    A small tip for you is you can replace "evaluate_condition_variable" with "evaluate_variable" as a shorter alias.

    And for your "random movements", you can utilize move action in global actions, while the positions are calculated in any way you want.



  • Thanks Pierre, I was thinking of the move action, I just wasn't sure how to add it into /on top of the waypoints. I'll make a separate post about it once I've solved my other problems and have a cleaner code base to share.



  • @MrCeeJ Wow thank you for this project. I think sharing would be nice here so we can get the code right also. Like Pierre that gave you tips. Thank you again mate



  • @exstazi No problem, I'm just doing this project for fun (It has been a dream of mine for a long long time, and it is great to finally have a platform to do it on. Yesterday I added the full pathing for Wailing Caverns, once I have the last few niggles ironed out and my rotations improved (dispelling, multi-target dots, no duplicate casts) I'll post the whole project and people can download it and try it out (if they have 5 characters of the correct classes, obviously).

    I'm happy to share the code and answer questions, as you say it is how we get better.



  • @MrCeeJ said in Rotations:

    @exstazi No problem, I'm just doing this project for fun (It has been a dream of mine for a long long time, and it is great to finally have a platform to do it on. Yesterday I added the full pathing for Wailing Caverns, once I have the last few niggles ironed out and my rotations improved (dispelling, multi-target dots, no duplicate casts) I'll post the whole project and people can download it and try it out (if they have 5 characters of the correct classes, obviously).

    I'm happy to share the code and answer questions, as you say it is how we get better.

    great attitude not really a multi boxer one char is enough at a time thx lol so would be very interested in your future projects



  • This post is deleted!




  • great stuff for people to learn from



  • Hi MrCeeJ,

    Very neat script πŸ™‚ thank you for helping us. I have a question.

    The player is attacking the 1st target and there is a 2nd target near by using range on the player at the same time, is there a way for the player to move towards the 2nd target to start attack after killing the first target .

    Currently the player stays at the 1st dead target trying to attack the 2nd target.

    If there is any confusion, please let me know.

    Regards,
    G



  • Do you know how to get these numbers on skills?
    alt text



  • Oh the number of casts to trigger an eclipse? I have been handling it differently.

    If I leave an eclipse, I just cast two more of the same spell:

    if (UnitExists("target")) then
                                -- Check for renewal
                                local my_hp = env:evaluate_variable("myself.health")
                                local _, renewal_cd, _, _ = GetSpellCooldown("Renewal")
                                local renewal_hp = 70
    
                                local target_hp = env:evaluate_variable("unit.target.health")
                                local moonfire_duration = env:evaluate_variable("unit.target.debuff.Moonfire")
                                local sunfire_duration = env:evaluate_variable("unit.target.debuff.Sunfire")
                                local _, berserking_cd, _, _ = GetSpellCooldown("Berserking")
                                local _, alignment_cd, _, _ = GetSpellCooldown("Celestial Alignment") --39
                                local _, incarnation_cd, _, _ = GetSpellCooldown("Incarnation: Chosen of Elune")
                                local _, beam_cd, _, _ = GetSpellCooldown("Solar Beam")
                                local solar_emp_duration = env:evaluate_variable("myself.buff.164545") -- solar
                                local lunar_empduration = env:evaluate_variable("myself.buff.164547") -- lunar
                                local astral_power = UnitPower("player", 8)
    
                                previous_eclipse = env:evaluate_variable("get_previous_eclipse")
                                local lunar_eclipse_duration = env:evaluate_variable("myself.buff.Eclipse (Lunar)")
                                local solar_eclipse_duration = env:evaluate_variable("myself.buff.Eclipse (Solar)")
                                local eclipse_charges = env:evaluate_variable("get_eclipse_charges")
                                if (debug) then
                                    print(".. counting enemies")
                                end
                                local enemy_count = get_aoe_count()
                                debug_msg(false, "Enemy aoe count : " .. enemy_count)
    
                                if (my_hp < renewal_hp and renewal_cd == 0) then
                                    check_cast("/cast Renewal")
                                elseif (beam_cd == 0) then
                                    check_cast("Solar Beam")
                                elseif (target_hp > min_dot_hp and sunfire_duration < 1 and eclipse_charges == 0) then
                                    check_cast("Sunfire")
                                elseif (target_hp > min_dot_hp and moonfire_duration < 1 and eclipse_charges == 0) then
                                    check_cast("Moonfire")
                                elseif (alignment_cd == 0) then
                                    check_cast("Celestial Alignment")
                                elseif (berserking_cd == 0) then
                                    check_cast("Berserking")
                                elseif (incarnation_cd == 0) then
                                    check_cast("Incarnation: Chosen of Elune")
                                elseif (solar_emp_duration > 0 and eclipse_charges == 0) then -- will recast as buff isn't removed until spell lands
                                    check_cast("Wrath")
                                elseif (lunar_empduration > 0 and eclipse_charges == 0) then -- will recast as buff isn't removed until spell lands
                                    check_cast("Lunar Strike")
                                elseif (lunar_eclipse_duration > 0) then
                                    previous_eclipse = "Lunar"
                                    if (astral_power >= 30 and lunar_eclipse_duration > 6) then
                                        check_cast("Starsurge")
                                    else
                                        check_cast("Starfire")
                                    end
                                elseif (solar_eclipse_duration > 0) then
                                    previous_eclipse = "Solar"
                                    if (astral_power >= 30 and solar_eclipse_duration > 6) then
                                        check_cast("Starsurge")
                                    else
                                        check_cast("Wrath")
                                    end
                                elseif (previous_eclipse == "Solar") then
                                    if (eclipse_charges < 2) then
                                        eclipse_charges = eclipse_charges + 1
                                        check_cast("Wrath")
                                    else
                                        eclipse_charges = 0
                                        check_cast("Starfire")
                                    end
                                elseif (previous_eclipse == "Lunar") then
                                    if (eclipse_charges < 2) then
                                        eclipse_charges = eclipse_charges + 1
                                        check_cast("Starfire")
                                    else
                                        eclipse_charges = 0
                                        check_cast("Wrath")
                                    end
                                end
                            else
                                RunMacroText("/assist " .. main_tank)
                            end
    

    The check_cast function is just a wrapper around casting the spell, doesn't do anything meaningful here. The eclipse_charges is the tracker I use to trigger an eclipse, and then reset it when it gets to two. There is one feature missing, if you reload after a (solar?) eclipse it will think you have just had a lunar one (my default) so will mess up a bit, but two Starfalls fix it.



  • I found a WOW API that gets gets the number of charges

    local Charges, _, _, _, _ = GetSpellCharges("Wrath")
    if (Charges >= 1) then
         RunMacroText("/cast Wrath")
    

    but it somehow doesn't work, when I add it I get an error.
    alt text


  • Manager

    This API will return nil if the spell you give it doesn't have charges (I don't think Wrath has charges?). And then you try to compare a number with nil, which results in LUA error.



  • Well, what is it then?
    alt text
    How do I get these numbers on Wrath and Starfire if they are not charges?



  • @Titan said in Rotations:

    This API will return nil if the spell you give it doesn't have charges (I don't think Wrath has charges?). And then you try to compare a number with nil, which results in LUA error.

    Yo mate πŸ™‚ I did write aabout a bug that i found but never got any response from any dev.


  • Manager

    Simply use GetSpellCount() wow API



  • @Titan said in Rotations:

    Simply use GetSpellCount() wow API

    Isnt GetSpellCharges(spellId or "spellName") active anymore ?

    [https://wow.gamepedia.com/API_GetActionCharges](link url)



  • @exstazi said in Rotations:

    GetSpellCharges

    As I understand it, WoW does not consider this as charges, and therefore we cannot get the number of casts to the Π•clipse via GetSpellCharges().



  • They are not actually spell charges, the API works fine for spells that do have charges:

                                    local radiance_charges, _, _, radiance_cd_duration, _ = GetSpellCharges("Power Word: Radiance")
    

    I expect there wil be a function in the API to get it, but I don't know what it is. Possibly a new function or reusing an old one but I couldn't find it with a breif look, it would be useful for my Balance code too.



  • @MrCeeJ said in Rotations:

    They are not actually spell charges, the API works fine for spells that do have charges:

                                    local radiance_charges, _, _, radiance_cd_duration, _ = GetSpellCharges("Power Word: Radiance")
    

    I expect there wil be a function in the API to get it, but I don't know what it is. Possibly a new function or reusing an old one but I couldn't find it with a breif look, it would be useful for my Balance code too.

    This is an old script i found online. Maybe something you can read out of it. My lua scripting is bad πŸ™‚

    local start, duration, enable = GetSpellCooldown(self.spellID)
    local charges, maxCharges, chargeStart, chargeDuration = GetSpellCharges(self.spellID)
    
        if event == 'SPELL_UPDATE_CHARGES' then
            if maxCharges ~= nil and maxCharges > 1 then
                self.Icon.Count:SetText(charges)
            else
                self.Icon.Count:SetText('')
            end
        end
    
        if charges and maxCharges and maxCharges > 1 and charges < maxCharges then
            StartChargeCooldown(self.Icon, chargeStart, chargeDuration)
        else
            ClearChargeCooldown(self.Icon)
        end
    


  • It is using the exact same API call I posted above: GetSpellCharges, and just sets an icon depending if you have maxed out and/or have at least one. No help I'm afraid.



  • Is it possible to add pulling to rotations? I farm points with hyperspawn, and often new mobs appear, but rotation, first finishes off the mob in the tareget and only then switches to the next one. I want it to cast a sunfire on it when a new mob appears, and then continue her normal rotation.


  • Manager

    @Titan said in Rotations:

    Simply use GetSpellCount() wow API

    people I gave you the solution above, why do you keep debating