Rotation framework design menu

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 15 of 21
  1. #1
    aeo's Avatar Contributor
    Reputation
    135
    Join Date
    Apr 2007
    Posts
    286
    Thanks G/R
    97/68
    Trade Feedback
    7 (100%)
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)

    Rotation framework design

    So not really a memory editing direct topic but more of a brainstorm/question. With the time between now and Legion I'd like to try and rewrite my rotation bot frame work. Currently I unlock LUA, register my own functions and have a custom addon deal with the rotation tick. Currently though its very basic. It just follows the following structure:

    Code:
    function PaladinTick()
    
    if(condition)
      CastSpell
    
    if(condition2)
      CastAnotherSpell
    
    end
    While this work its clearly very inefficient and not optimal. An example problem is say doing a rogue burst rotation you want to do deathfromabove->vanish->envenom. However, I also have a check to feint if I'm taking damage. If feint is used it messes up the energy, the rotation and produces unwanted behavior. How would one go about making a better framework? I've looked at something like probably engine and it has some nice features but I also feel that it is limited in ways as well.

    Just want to start a discussion see what others suggest/are using.

    Thanks,
    Ace

    Rotation framework design
  2. #2
    lolp1's Avatar Site Donator CoreCoins Purchaser
    Reputation
    190
    Join Date
    Feb 2013
    Posts
    210
    Thanks G/R
    43/77
    Trade Feedback
    3 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I currently use a set of interfaces for each task, after seeing a post here about it. For example my ICombat interface has several methods. One is a regular dps rotation, another kills the target as fast as possible. I fine tune all of these based on the class/spec of the toon they are used on.

  3. #3
    aeo's Avatar Contributor
    Reputation
    135
    Join Date
    Apr 2007
    Posts
    286
    Thanks G/R
    97/68
    Trade Feedback
    7 (100%)
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    But in that combat class how are you queueing abilities, just by a whatever condition has been met first priority? A fixed don't do B until A is complete type list?

  4. #4
    namreeb's Avatar Legendary

    Reputation
    668
    Join Date
    Sep 2008
    Posts
    1,029
    Thanks G/R
    8/222
    Trade Feedback
    0 (0%)
    Mentioned
    9 Post(s)
    Tagged
    0 Thread(s)
    I have thought about doing something like this a few times over the years. The main problem with it is that you don't immediately know the outcome of the actions you perform (by that I mean spell casts, etc.). The results of your actions will often, if not always, dictate your next action. That being said, you do not want to wait for the results. Therefore, the only solution I have come up with is to have some sort of queue of 'performed' actions that our code will monitor for the results and have some plan for how to handle each possible outcome. Something like:

    - Cast scorch
    - If resisted and 5x fire vulnerability is not present, cast scorch again

    - Cast fireball
    - If clearcasting procs, cast Arcane Missles

    - Cast polymorph
    - If resisted, frost nova and warn raid that target x has resisted polymorph

    Those are some basic examples. The kicker is that there would have to be some mechanism to prioritize these reactions relative to whatever 'regularly scheduled' action may be in progress when the result comes in (and thus when the outcome handler is triggered). In some cases, I imagine we may want to interrupt the current action to call the outcome handler. In other cases, perhaps not. And how do we perform that interruption in a generic way?

    Anyways, that is about the extent of my thought on it, except to say that lua unlockers have always been fairly aggressively targeted by Blizzard, I think. So be careful!

  5. #5
    lolp1's Avatar Site Donator CoreCoins Purchaser
    Reputation
    190
    Join Date
    Feb 2013
    Posts
    210
    Thanks G/R
    43/77
    Trade Feedback
    3 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by aeo View Post
    But in that combat class how are you queueing abilities, just by a whatever condition has been met first priority? A fixed don't do B until A is complete type list?
    Think of my set of interfaces not as an absolute, but as a set of "builder" interfaces in which are then implemented into one of a few "rotation" base-classes.and fine tuned for the task at hand. Kind of like this set up but for rotations - https://github.com/lolp1/ToolsSharp/...harp/Managment .

    As an example, I have a set of interface implementations for a Mage. I then have a manager for mage rotations that will choose the interfaces to use at any given time based on either circumstances it's been programmed to choose interfaces from, or a hard-set choice.

    For an idea of what I mean, I wrote a team bot to do some old raids that can be done with two people but not one. I then took my basic mage and paladin interfaces, and added on to them or modified them to handle team botting those raids. My manager ran the rotations like normal - but the logic contained inside the interfaces did all the real work.

  6. #6
    aeo's Avatar Contributor
    Reputation
    135
    Join Date
    Apr 2007
    Posts
    286
    Thanks G/R
    97/68
    Trade Feedback
    7 (100%)
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by namreeb View Post
    I have thought about doing something like this a few times over the years. The main problem with it is that you don't immediately know the outcome of the actions you perform (by that I mean spell casts, etc.). The results of your actions will often, if not always, dictate your next action. That being said, you do not want to wait for the results. Therefore, the only solution I have come up with is to have some sort of queue of 'performed' actions that our code will monitor for the results and have some plan for how to handle each possible outcome. Something like:

    - Cast scorch
    - If resisted and 5x fire vulnerability is not present, cast scorch again

    - Cast fireball
    - If clearcasting procs, cast Arcane Missles

    - Cast polymorph
    - If resisted, frost nova and warn raid that target x has resisted polymorph

    Those are some basic examples. The kicker is that there would have to be some mechanism to prioritize these reactions relative to whatever 'regularly scheduled' action may be in progress when the result comes in (and thus when the outcome handler is triggered). In some cases, I imagine we may want to interrupt the current action to call the outcome handler. In other cases, perhaps not. And how do we perform that interruption in a generic way?

    Anyways, that is about the extent of my thought on it, except to say that lua unlockers have always been fairly aggressively targeted by Blizzard, I think. So be careful!
    This is the problem I've ran into its usually fringe situations where my chain of actions become broken and resorting to the next action in the list is actually a big net loss of DPS or a very bad situation in a PVP environment.

    As for the LUA unlocking I think I'm as safe as I'm going to get. I just use HWBP, I hide them with ntdll level hooks. I'm debating upgrading that to SSDT hooks since my bot is private but I'm pretty sure that is such overkill its unreal and im 64 bit..

  7. #7
    lolp1's Avatar Site Donator CoreCoins Purchaser
    Reputation
    190
    Join Date
    Feb 2013
    Posts
    210
    Thanks G/R
    43/77
    Trade Feedback
    3 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by aeo View Post
    But in that combat class how are you queueing abilities, just by a whatever condition has been met first priority? A fixed don't do B until A is complete type list?
    Think of my set of interfaces not as an absolute, but as a set of "builder" interfaces in which are then implemented into one of a few "rotation" base-classes.and fine tuned for the task at hand. Kind of like this set up but for rotations - https://github.com/lolp1/ToolsSharp/...harp/Managment .

    As an example, I have a set of interface implementations for a Mage. I then have a manager for mage rotations that will choose the interfaces to use at any given time based on either circumstances it's been programmed to choose interfaces from, or a hard-set choice.

    For an idea of what I mean, I wrote a team bot to do some old raids that can be done with two people but not one. I then took my basic mage and paladin interfaces, and added on to them or modified them to handle team botting those raids. My manager ran the rotations like normal - but the logic contained inside the interfaces did all the real work.

  8. #8
    aeo's Avatar Contributor
    Reputation
    135
    Join Date
    Apr 2007
    Posts
    286
    Thanks G/R
    97/68
    Trade Feedback
    7 (100%)
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    I'm leaning towards a more robust extension of probably engine at this point. Try to allow its combat routines to be more complex with more extensive conditions. I think its a great base for the LUA side of the project.

  9. #9
    vitalic's Avatar Contributor CoreCoins Purchaser
    Reputation
    182
    Join Date
    Jun 2010
    Posts
    3,527
    Thanks G/R
    8/3
    Trade Feedback
    10 (100%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by aeo View Post
    An example problem is say doing a rogue burst rotation you want to do deathfromabove->vanish->envenom. However, I also have a check to feint if I'm taking damage. If feint is used it messes up the energy, the rotation and produces unwanted behavior.
    In a sequential rotation Feint has to have some knowledge about the current state (i.e. are we bursting or is the target low) under which the conditions for its use are restricted to ensure it doesn't interfere with the offensive rotation unless it really is a critical situation (in which case you just accept the unwanted behavior, but try your best to compensate for it). Not aware of any design pattern or framework that makes this hugely more manageable, but abstracting helps a lot. For example I have a class for each spell, and the logic each spell needs is contained within that class, e.g. Feint.IsOffensive to determine if it should be skipped for the current tick. Never used PE but I'm sure you can achieve the same kind of thing.

  10. #10
    aeo's Avatar Contributor
    Reputation
    135
    Join Date
    Apr 2007
    Posts
    286
    Thanks G/R
    97/68
    Trade Feedback
    7 (100%)
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Great insight. Clearly your way is working as you have one of the highest regarded pvp profiles for a pretty complex class. Thanks vitalic.

  11. #11
    Filint's Avatar Contributor Authenticator enabled
    Reputation
    167
    Join Date
    Mar 2014
    Posts
    97
    Thanks G/R
    23/56
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    *I wrote a really massive reply to this, which was beautiful. I managed to lose it when ownedcore decided that it was the perfect time to log me out, despite having checked the "never log me out" box. I'll write a shorter, less beautiful reply this time.*

    Originally Posted by aeo View Post
    This is the problem I've ran into its usually fringe situations where my chain of actions become broken and resorting to the next action in the list is actually a big net loss of DPS or a very bad situation in a PVP environment.
    I think the distinction between PvP and PvE is an important one - in PvE there are fewer corner cases or extreme situations and you can get away with having a more regimented, inflexible rotation. As you have suggested it is the unusual situations which can bring a rotation to its knees. I only have experience in PvE, where I have my own private bot that at the moment does arcane/frost mage routines.

    What I do is very similar to you - essentially a big list of conditionals. The important thing is to have the most important actions, for example ice block, at the top, and to start at the top of the list after every action. What I do in addition to this bunch of actions is something similar to what Vitalic alluded to - each rotation has a number of states that indicate various different things about the rotation. This can be anything from whether the last action succeeded, to something much more specialised, for example the current phase in the arcane mage rotation (whether burning or conserving mana). Depending on the state the entire rotation can change. It's a bit like a decision tree actually.

    I think this provides just enough flexibility to be able to pull off a decent rotation; my arcane mage typically manages around the 90th percentile according to warcraft logs and I'm sure if I spent more time that could be pushed a bit higher. This can of course be higher or lower depending on the individual fight. This system fits in fairly nicely with what Namreeb was saying, with one caveat - there's not really a way to generalise it. It is very specific to each rotation, and at this point if you want everything to be automatic when fighting a given boss fight it usually requires behaviour specific to that boss. It's a bit of extra effort to get this running perfectly, but it's worth it, in my opinion.

    I experimented at one point with using a heuristic tree search with a bit of machine learning to try and automatically optimise rotations during a fight. It didn't really work though, there wasn't enough time to gather enough sample data to make a meaningful change and I just ended up with useless extra calculations.

    On the subject of Probablyengine. It is basically an abstraction of what I just talked about. When it boils down to it, it is doing exactly the same thing, only with added syntactical sugar over standard lua. To me, the benefits aren't worth it - I can write and debug my raw lua in an IDE and get nice syntax highlighting etc. while I've not found this to be possible as easily as with Probablyengine. You also have to consider that Probablyengine adds to the execution time. I've not measured by how much, and it probably (heh) isn't too bad, but it's still worth considering. There's also the issue of safety - you're using a public addon which is clearly intended to perform ToS-breaking activities, and although there's only a tiny chance Blizzard will detect the addon, it is a chance nonetheless. Far better, in my opinion, to use another method with almost certainly no chance of detection.

    But, like I said, I'm really talking only about PvE here - PvP is a whole other story, and I would hate to even think about how much work needs to go into PvP rotations to consider every case.

    TLDR:
    Basically any rotation system is going to boil down to being an abstraction of a series of conditionals, with the most important actions at the top, and restarting at the top after every action. You can use states to extend this and make it more versatile.

    -----------
    Offtopic
    -----------

    Originally Posted by aeo View Post

    As for the LUA unlocking I think I'm as safe as I'm going to get. I just use HWBP, I hide them with ntdll level hooks. I'm debating upgrading that to SSDT hooks since my bot is private but I'm pretty sure that is such overkill its unreal and im 64 bit..
    Now, here again is something that we do very similarly. I happen to know that you and I use the same library for memory editing, and I assume that, like me, you're using the HWBP functionality provided there to unlock lua. Cool. I don't do any HWBP hiding though; I keep telling myself that I'm going to add that and then I forget, or get distracted :P
    I'd be interested to learn more about the SSDT hooks. I don't know much about the kernel, or drivers - everything I currently do is in usermode. I have an Operating Systems course at Uni next semester so hopefully I'll learn a bit more then. Just to clarify, and display my utter ignorance, you are using the SSDT hooks to hide the HWBP right? Not to actually unlock the lua. From what I can tell the SSDT points to kernel functions and so can't really be used to influence usermode functions... right?

    I think you're right that this is all overkill, but really, that's half the fun of it.

    Hmm, this turned into another essay. Sorry about that.

  12. #12
    Travelformed's Avatar Member Authenticator enabled
    Reputation
    10
    Join Date
    Jan 2008
    Posts
    13
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    first of all thanks for sharing folks;

    myself ive been experimenting for a while and found that lua with few custom registered function is most suitable for the task.
    i'm using an idea of action priority lists utilized by simcraft (and actually quite an amount of conditionals i take from there)
    see: Simulationcraft Results open any class's "Action Priority List"

    basically i have lua table starting with an action followed by conditions to check

    Code:
    local s = {} -- state
    ...
    Mco:runApl({
        {"C", "Buff Name1", function() return s.autoCD end},    
        {"G", "Buff Name2", function() return s.autoCD and (s.buffBL > 0 or s.buffFF > 0 or s.hpTargetPrc < 3) end}, 
        
        {"I", "Spell Name 1", function() return aoe > 0 end},
        {"J", "Spell Name 2", function() return s.buffFFcharges > 0 and s.buffFF == 0 and (s.cdBW < 1 or s.buffST > 0 ) end},
        {"K", "Spell Name 3", function() return s.focus > 30 and s.buffBW == 0 end},
        ....
        ....
    })
    
    function Mco:runApl(apl, canCastCheck)
        for _, entry in pairs(apl) do
            local id, spell, checkCallback, target, actionCallback, continue = unpack(entry)
            --print(id, spell, checkCallback, target, actionCallback, continue)
            local check = true
            if checkCallback then 
                check, checkTarget, checkSpell = checkCallback(spell, target)
                spell = checkSpell or spell
                target = checkTarget or target
            end
            if check then
                if actionCallback then
                    --print(id, "action", spell, target)
                    local result = actionCallback(spell, target)
                    if not continue then return result end
                else
                    if (Mco:canCast(spell, target) and Mco:canIntChan()) then
                        print(id, spell, target)
                        Mco:castSpellByName(spell, target)
                        if not continue then return true end
                    end
                end
            end
        end
        return false
    end
    Last edited by Travelformed; 11-19-2015 at 02:11 PM.

  13. #13
    lolp1's Avatar Site Donator CoreCoins Purchaser
    Reputation
    190
    Join Date
    Feb 2013
    Posts
    210
    Thanks G/R
    43/77
    Trade Feedback
    3 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think perhaps this is a case of over complication. Is there anything wrong with a simple interface solution I currently use? What does it not provide that you really need/is worth the effort?

    This is a very very crude example of how mine works. Currently it's undocumented and very sloppy, so I chose to simplify an example for clarity of the basic way it works.

    [C#] RotationExampleEnumsInterfaces.cs - Pastebin.com - RotationExampleEnumsInterfaces.cs
    [C#] ExampleBaseRotationClass.cs - Pastebin.com - SubRogueBaseRotationExample.cs

    Now - with this set up I can have a solid base rotation that handles basic attack rotations for my sub rogue. Stuff like standard dps rotation, Slice and dice/energy/bleeds/buffs/poisons etc tracking and management.

    So the next step is easy - extending the implementation to suit your needs. One example might be your base rotation was cool for random bgs and all, but now you want to 2-man bot some old raids with your sub rogue and a healer shaman. You can build off the base to do this.

    [C#] ExampleRotationExtensionExample.cs - Pastebin.com


    Keep in mind, I probably am not breaking any speed-records here nor dps records. I am however maintaining pretty solid stability, clarity, and consistency in my rotations all working from the same set of principles. The only solid rotation I've wrote so far using this style is for a warsong gulch battle ground bot that runs with 4 holy paladins that baby sit a max-possible dps frost dk that runs at the enemy flag carrier. The modified rotations simply added a little logic for the holy paladins to break the dk from CC at all cost, with their 8 freedoms, 8 dispels, 8 bops, 8 aura mastery's, 8 bubbles, 8 trinkets, etc. For added lols, I made them target hojs on any healer in range if the dk was connecting to the fc.

    Oh, and the dks logic simply just was to run at enemy FC and use the fastest kill target mode.

    EDIT: Oh, and I don't see the need for such an addon to handle the 'tick'. These two classes work fine for me --

    https://github.com/lolp1/MemorySharp...adedUpdater.cs
    https://github.com/lolp1/MemorySharp...imedUpdater.cs

    If even further precision is desired, this is a start to get the search engine and solution ideas going:
    http://stackoverflow.com/questions/6...ixed-step-loop
    Last edited by lolp1; 11-19-2015 at 03:35 PM.

  14. #14
    Filint's Avatar Contributor Authenticator enabled
    Reputation
    167
    Join Date
    Mar 2014
    Posts
    97
    Thanks G/R
    23/56
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's not so much that your solution has anything wrong with it (it's actually very cool!), but that we are essentially going about things in a completely different way. You've got C# code which is being injected or somehow otherwise executed. I've chosen instead to use C++ and inject a module that runs a rotation written in LUA and uses some custom registered functions as well as functions from the wow lua api. Both are completely valid methods which work well

  15. #15
    lolp1's Avatar Site Donator CoreCoins Purchaser
    Reputation
    190
    Join Date
    Feb 2013
    Posts
    210
    Thanks G/R
    43/77
    Trade Feedback
    3 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Filint View Post
    It's not so much that your solution has anything wrong with it (it's actually very cool!), but that we are essentially going about things in a completely different way. You've got C# code which is being injected or somehow otherwise executed. I've chosen instead to use C++ and inject a module that runs a rotation written in LUA and uses some custom registered functions as well as functions from the wow lua api. Both are completely valid methods which work well
    I don't think C# or C++ matters, both offer the OOP features needed to do it.

    It's worth noting that I use this set up in both my injected and external code, and both systems use 'FrameScriptExecuteBuffer' aka LuaDoString to run lua code to handle their logic. I simply use a set of 5 interfaces and a base abstract class of the implementations for that class rotation to manage them. This allows:

    1. Easy porting to other games where a rotation system is desired, both internally or externally.
    2. Easy porting between injected and external code, as it does not depend on the lua scripts as a core, but as part of the custom implementation.
    3. Very easy communication between interfaces in the base class.

    Example:

    Code:
    public class FrostMageRotation
    {
    public ICombat FrostMageCombat {get;} = new FrostMageCombat();
    public IBuffsDebuffs FrostMageBuffs {get;] = new FrostMageBuffs();
    // All core interfaces.
    
    
    public void RushKillCurrentTarget(TargetKillSpeed killSpeed = TargetKillSpeed.Fastest, TargetKillPriority priority = TargetKillPriority.Highest)
    {
           if(killSpeed == TargetKillSpeed.Fastest && TargetKillPriority priority == TargetKillPriority.Highest)
           {
    
           // Here you can tag all your non essential methods/operations/values with a NotEssenital attribute or something.
           // Such as for a rogue, recups, etc can be haulted.
            InternalInterfaces.ForEach(iRotation => iRotation.PauseAllNonEssentials()); 
    
           // Kill
            KillTarget(CurrentTarget, TargetKillSpeed.Fastest, TargetKillPriority.Highest);
    
            // Resume non essentials.
            InternalInterfaces.ForEach(iRotation => iRotation.ResumeAllNonEssentials()); 
    
          }
    
    }
    Last edited by lolp1; 11-20-2015 at 03:56 AM.

Page 1 of 2 12 LastLast

Similar Threads

  1. Looking for Addon Maker/Designer
    By The Ronin in forum World of Warcraft General
    Replies: 3
    Last Post: 12-24-2006, 10:45 PM
  2. Web Designing
    By Grelkamah in forum Community Chat
    Replies: 14
    Last Post: 11-23-2006, 07:50 AM
  3. Designer island?
    By krazy12766 in forum WoW ME Questions and Requests
    Replies: 2
    Last Post: 09-04-2006, 06:12 AM
  4. Designer island?
    By krazy12766 in forum World of Warcraft Model Editing
    Replies: 1
    Last Post: 09-03-2006, 10:08 PM
  5. A Design for a band
    By Tenche in forum Community Chat
    Replies: 14
    Last Post: 08-02-2006, 02:37 AM
All times are GMT -5. The time now is 01:23 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search