What's new
  • Visit Rebornbuddy
  • Visit Panda Profiles
  • Visit LLamamMagic
  • Visit Resources
  • Visit Downloads
  • Visit Portal

[Plugin] Skill-Aware Player Mover

stealthy

Member
Joined
Jun 25, 2011
Messages
84
Reaction score
0
This is a movement skill-aware player mover, complete with dodging and kiting, forked from Alcor75's player mover plugin with his permission.
My goal is to start with his fairly complete base and clean-up, fix, and improve what he'd started. It is very much a work-in-progress and should not yet be considered stable.

Things that aren't yet fixed:
  • Backtracking caused by Exploration, LootItem, and OpenChest tasks conflicting
  • "Backtracking" caused by sudden changes in direction by any combat routine
  • Kiting operations will still occasionally lead you right into another pack of monsters
  • Combat routines will still occasionally lead you right into another pack of monsters in order to gain vision, while looking like it's kiting

Code & Tasks
Public Trello board: Skill-Aware Player Mover
Bitbucket Git repository: jeremy-sylvis / SkillAwarePlayerMover — Bitbucket

Credits:
Alcor75, for his work on the Alcor75PlayerMover plugin

Downloads:
See 2nd post.
 
Last edited:
Releases & Notes

0.0.1.5:
Improvements:
  • Remove unnecessary Coroutines.FinishCurrentAction calls in order to improve responsiveness
  • Code cleanup & removal of unnecessary / dead code
  • XMLDoc cleanup
  • Convert Dodge, Kite, & FleeStrongbox operations into their own yielding coroutines
  • Gate Tick() rates to 200ms in order to avoid excess work and FPS loss
Fixes:
  • Clear key states before attempting to use a movement skill
  • Use skill.CanUse() instead of skill.IsCastable

0.0.1.4 (internal-only):
Improvements:
  • Skill-based movement now uses shift-based casting
  • Remove some log spam

0.0.1.3 (2016-10-26):
Improvements:
  • Move all code to its own buildable project, separating classes along the way
Fixes:
  • Correct an old namespace from Gui.g.cs

0.0.1.1 (2016-10-25):
Fixes:
  • Fix generation and inclusion of Gui.baml

0.0.1.0 (2016-10-25):
Improvements:
  • Dodging and Kiting operations are a bit quicker to react
  • Dodging operations now consider monsters of Magic or higher rarity, since they can all hit pretty hard in Merciless
  • MoveTowards and pathfinding operations are responsive, even without predictive mode
  • Plugin & Movement CPU load is noticeably lower
  • Logging & Codebase are cleaner - it's easier for others to join in!
  • It will reserve at least one use of charge-based skills (e.g. Flame Dash) while exploring, so you can still use it quickly to Kite & Dodge
Fixes:
  • A few scenarios where Dodging & Strongbox operations would be slow to react if also using Kiting
  • At least one cause of the MoveTowards-related path backtracking
 

Attachments

Last edited:
Here's an example of the settings I'm using with my glass-cannon Witch.

tJsAebD.png
 
I'm completely new, and just started using this Buddy bot as of yesterday, but when I put this in my 3rd party folder EB crashes upon load.
Here is what I'm using in my 3rdaparty folder.
61DjraBi.png
 
Gyazo - 9aeab674626b88ee1f064c922275b590.png
Based on darkbluefirefly's original code, I believe it was said due to trackmoremobs/trackmobs(maprunner) and combat's cansee/movetowards logic.

Therefore a fix would be to expose settings inside said plugins/classes to disable certain logic if kitting is enabled. This was deemed too much of an issue with user base compatibility and was dropped. AFIK
 
Gyazo - 9aeab674626b88ee1f064c922275b590.png
Based on darkbluefirefly's original code, I believe it was said due to trackmoremobs/trackmobs(maprunner) and combat's cansee/movetowards logic.

Therefore a fix would be to expose settings inside said plugins/classes to disable certain logic if kitting is enabled. This was deemed too much of an issue with user base compatibility and was dropped. AFIK
Combat's can-see/move-toward logic is one of the big contributors, yes - but not the only one. It's less a problem with kiting and more a problem with more than one task or plugin having the ability to "direct" movement at what's more-or-less the same time.
 
I'm completely new, and just started using this Buddy bot as of yesterday, but when I put this in my 3rd party folder EB crashes upon load.
Here is what I'm using in my 3rdaparty folder.
61DjraBi.png
Is this missing something? This zip should exist in that directory.

Additionally, this isn't sufficient information for debugging purposes - could you PM me the relevant log, with exception information, from ExileBuddy\logs?
 
Sorry, I extracted it. I'm a moron. That is prob what went wrong. I'll do it the right way, and try again, if there is an error again I will PM you the log file. :)
 
Sorry, I extracted it. I'm a moron. That is prob what went wrong. I'll do it the right way, and try again, if there is an error again I will PM you the log file. :)
Perhaps not - I did find an issue in generation of Gui.baml; I've resolved that and uploaded a new version. Interestingly enough, I only ran into that issue specifically when loading it as a zip.
 
Yes, that's why you have to code the tasks on a return false/true logic, and you need to know when to let other tasks work, and when to let yours do the lifting. The Dodge I believe wasn't meant to be ran under lower FPS, as the time it takes to compute locations drastically increases, due to the fact that when you have a lower fps, the wait time is almost infinite.
 
Yes, that's why you have to code the tasks on a return false/true logic, and you need to know when to let other tasks work, and when to let yours do the lifting. The Dodge I believe wasn't meant to be ran under lower FPS, as the time it takes to compute locations drastically increases, due to the fact that when you have a lower fps, the wait time is almost infinite.
Yeah, but the return values only go so far.

I agree that Dodge and Kiting are both a bit FPS sensitive and, indeed, have a marked FPS impact... but it's much less so now.
Dodge in particular did a lot of heavy lifting (e.g. unnecessary IEnumerable LINQ queries, ToList()ing, unnecessary and unused caching, unoptimized order of short-circuit conditional checks, etc.) and is much easier on CPU load after a solid cleanup. But, Dodge's biggest problem in responsiveness was that the SurviveTask50 component of Alcor75PlayerMover, which was responsible for triggering Kiting and Dodging, had a few unnecessary early returns. The first thing it checks is whether or not we should have allowed Kiting in configuration and, if so, if we've waited long enough to attempt kiting again... if so, it'll do some work to determine if we need to kite and, if we don't, it will return early. It won't actually reset that timer I'd mentioned until it *does* need to kite something... so the dodge code won't ever actually execute unless a) kiting is disabled, or b) it determined we do need to kite something. Removing the unnecessary early returns was the only bugfix necessary, at least for that set of issues.

On the true/false returns and Coroutines...
Maybe you can explain this for me, I couldn't find much documentation on it - in a given task, returning true indicates "logic was executed to handle this type" but that doesn't indicate what happens as a result. Does returning "false" allow another task to proceed? Does returning "true" block other tasks until this one executes again?

For that matter, the async/await work with Coroutines - most of them are used synchronously from within a task, but there are a few... oddballs. Coroutine.Yield() is often used synchronously (e.g. await Coroutine.Yield()), so what's the actual outcome here? Suspending execution of the current task until... what, another task (all other tasks?) finishes executing?
 
Um, I haven't heavily checked alcor's player mover, but I do know where it stemmed from and have my own version, since Pushedx included defaultplayermover into the /HelpFolder.
For the tasks, yes. It executes in an ordered basis from ascending.
When you return true in the async logic, task manager "restarts" at the begining of the task list and propagates downwards, the propagation happens if the task returns false, the next ordered task executes. When a task returns true in the async logic, task manager starts the first task on the list. Therefore logic for returning true/false in the async is very sensitive on knowledge of each task that executes, so you can manipulate adding your tasks into the order, via Taskmanager.AddBefore, Taskmanager.AddAfter, and Taskmanager.AddAtFront. It's pretty straightforward. You can also disable tasks now and freeze them with pause I believe.
QuestPlugin was heavily dependent on task locations to do logic. QuestBot orders the task properly for a Questing Bot. Like Pushedx said, QuestPlugin was Frankenstein code to get something working, util someone with more time/better knowledge came along to make something proper, Hence Exy came to the fray.

Yes you can have a task always return true to block tasks under it on the task list from executing.

I don't have much on Yield, will have to wait for Pushedx to reply.


Edit - yes for kiting, any logic that requires CPU computation, on an ideal system without FPS limitations, one can get away with alcor's current code, on lower fps, especially below 30, you will start to see delays as it's calculating ,due to the FPS bottleneck, code can only execute on the frames it's allowed to run on, therefore lower fps = slower computation code I believe. I'm not 100% sure on this.
darkbluefirefly's origional logic for kitting was what Pushedx told him, basically move towards current area anchor, which worked fine until you are at the actual anchor, so you need more code to handle that. But most builds with kitting away from the mob, towards anchor is safer and easier, because there should not be any alive enemies in that "direction" due to you killing them already.

You have to also keep in mind each skill's kitting ability for instance;
Lightning warp, you get "cast based + movement speed" for faster cast = more instantaneous movement to that location regardless of terrain(somewhat). Therefore, if you are having any "wait" code to see if you are actually moved, or skill successfully casted, skill interrupted, etc. This is dependent on fps as well.

For whirling blade, you can only move X distance to the "kit to location", so let's say you have kiting logic to move to a "safe" location, a location without any "dangerous" enemies.
If you do a monster check, and the monster moves while you are whirling, your location will be off, and you might re-cast that skill to get to that location(if you cached the "kit to location", if you are doing it on the fly, it's a different story, and you need to mind the FPS).

I kinda lost my train of thought while trying to elaborate this edit. But you will see that each skill needs specific "needs" to make it work properly, and will consume a lot of trial/error.

Best of luck.
 
Last edited:
I just got home, I'll try loading it as a zip then, because before I extracted it into a folder and it returned the force close upon load. I'll check it here in a few minutes and let you know what happened :). Thanks!
 
I've just uploaded a new version, 0.0.1.3. It should fix the issue Whitak3r was running into regarding Gui.g.cs namespace mismatch.
 
Um, I haven't heavily checked alcor's player mover, but I do know where it stemmed from and have my own version, since Pushedx included defaultplayermover into the /HelpFolder.
For the tasks, yes. It executes in an ordered basis from ascending.
When you return true in the async logic, task manager "restarts" at the begining of the task list and propagates downwards, the propagation happens if the task returns false, the next ordered task executes. When a task returns true in the async logic, task manager starts the first task on the list. Therefore logic for returning true/false in the async is very sensitive on knowledge of each task that executes, so you can manipulate adding your tasks into the order, via Taskmanager.AddBefore, Taskmanager.AddAfter, and Taskmanager.AddAtFront. It's pretty straightforward. You can also disable tasks now and freeze them with pause I believe.
Okay, great - that makes much more sense, thank you.

I can see how that becomes a tricky issue to address. It'll be fun trying to find a less painful way to approach it.

Edit - yes for kiting, any logic that requires CPU computation, on an ideal system without FPS limitations, one can get away with alcor's current code, on lower fps, especially below 30, you will start to see delays as it's calculating ,due to the FPS bottleneck, code can only execute on the frames it's allowed to run on, therefore lower fps = slower computation code I believe. I'm not 100% sure on this.
If we're framelocking then yes, for sure... I'm just not sure if we're actually frame-locked. Most of the wait-based code I've seen would imply we're not. I do see the ability to acquire framelock in LokiPoe, though.

Lightning warp, you get "cast based + movement speed" for faster cast = more instantaneous movement to that location regardless of terrain(somewhat). Therefore, if you are having any "wait" code to see if you are actually moved, or skill successfully casted, skill interrupted, etc. This is dependent on fps as well.
Ohhhh, yes. I've encountered that. I'm primarily a Flame Dash user and am lucky it's an instant move. There's some specialty code for handling phase run and a few others - grabbing appropriate gems and testing those out is something I've got on my to-do list.

For whirling blade, you can only move X distance to the "kit to location", so let's say you have kiting logic to move to a "safe" location, a location without any "dangerous" enemies.
If you do a monster check, and the monster moves while you are whirling, your location will be off, and you might re-cast that skill to get to that location(if you cached the "kit to location", if you are doing it on the fly, it's a different story, and you need to mind the FPS).
I've actually seen similar going on between skill-based movement and the combat routine... The kiting logic will attempt to flee, the routine will attempt to close the distance and face-check a pack of monsters, the kiting logic will attempt to flee... rinse and repeat.
I'm planning on solving that one in OldRoutine before much longer - it's the only thing keeping my Witch and Scion out of maps.

I kinda lost my train of thought while trying to elaborate this edit. But you will see that each skill needs specific "needs" to make it work properly, and will consume a lot of trial/error.
Completely agreed. Many of them have at least some level of commonality (e.g. the instant movement skills, the move-over-time skills, the slow-cast then instant movement skills) and that should be enough to work with... in theory. I'm hoping to rely on users feedback for some of this testing.
 
Looks good. Thanks a lot for the release.

Not quite as fast as version 0.20
 
Last edited:
@stealthy,
Can't seem to quote on the forums for some reason. Gyazo - dd2e71b6dd694ea87cadfea9e5b16528.gif

But what I think you can do while moving with your dodge routine is, call Oldroutine's execute func and set the combat range to 0, remember to save combat range first.

Do it by getting an instance to
Code:
var oldroutine = RoutineManager.CurrentRoutine;
            if (oldroutine.Name == "OldRoutine")
            {
                var combatrange = (int)oldroutine.Execute("GetCombatRange");
                oldroutine.Execute("SetCombatRange", 0);
            }
Probably should global the combatrange, cause we'll probably use it a lot.
But, I think that should fix the Oldroutine trying to move towards the mob, since if combat range is 0, it skips combat.

Oh for trackmoremobs, also, you can disable the task while dodging, and re-enable it after dodging. That should fix it all, let me do it on my end. Do you have it up on Git yet?
 
@stealthy,
Can't seem to quote on the forums for some reason. Gyazo - dd2e71b6dd694ea87cadfea9e5b16528.gif

But what I think you can do while moving with your dodge routine is, call Oldroutine's execute func and set the combat range to 0, remember to save combat range first.

Do it by getting an instance to
Code:
var oldroutine = RoutineManager.CurrentRoutine;
            if (oldroutine.Name == "OldRoutine")
            {
                var combatrange = (int)oldroutine.Execute("GetCombatRange");
                oldroutine.Execute("SetCombatRange", 0);
            }
Probably should global the combatrange, cause we'll probably use it a lot.
But, I think that should fix the Oldroutine trying to move towards the mob, since if combat range is 0, it skips combat.

Oh for trackmoremobs, also, you can disable the task while dodging, and re-enable it after dodging. That should fix it all, let me do it on my end. Do you have it up on Git yet?

I had considered that - the remaining issue with moving back is more about kiting than dodging, specifically this chain of events:
1) SurviveTask50 detects a clusterfuck of monsters and starts kiting, getting out of line of sight of the monsters
2) After movement, OldRoutine can't see a monster and moves us back to line of sight... which usually consists of walking up face-to-face with said monsters
3) Rinse, repeat

It will be up on Git shortly.
 
@stealthy,
Can't seem to quote on the forums for some reason. Gyazo - dd2e71b6dd694ea87cadfea9e5b16528.gif

But what I think you can do while moving with your dodge routine is, call Oldroutine's execute func and set the combat range to 0, remember to save combat range first.

Do it by getting an instance to
Code:
var oldroutine = RoutineManager.CurrentRoutine;
            if (oldroutine.Name == "OldRoutine")
            {
                var combatrange = (int)oldroutine.Execute("GetCombatRange");
                oldroutine.Execute("SetCombatRange", 0);
            }
Probably should global the combatrange, cause we'll probably use it a lot.
But, I think that should fix the Oldroutine trying to move towards the mob, since if combat range is 0, it skips combat.

Oh for trackmoremobs, also, you can disable the task while dodging, and re-enable it after dodging. That should fix it all, let me do it on my end. Do you have it up on Git yet?
It's up as a private repository. Could you PM me the Bitbucket username or other email address you'd like to use?
 
Yeap, the thing is the current mob that Survivetask is depending on, isn't the same one as the _bestTarget that OldRoutine is moving towards.
I might to have a quick nap to think on this.

Edit

Hum, we can probably use the same list of mobs that OldRoutine sees, that requires OldRoutine to expose it through RegisterExposedSettings(), which we need Drew to add because we can't go around telling everyone to add it manually. I'll talk to Pushedx and see.
 
Last edited:
Back
Top