GithubHelp home page GithubHelp logo

jnnshschl / ameisenbotx Goto Github PK

View Code? Open in Web Editor NEW
127.0 14.0 64.0 6.04 MB

A bot, aimed at full automatic gameplay

License: GNU General Public License v3.0

C# 100.00%
wow-bot woltk mmaps bot 335a automatic

ameisenbotx's People

Contributors

bia10 avatar brewingcoder avatar dependabot[bot] avatar finalcommit avatar geigerkind avatar ieecor avatar jamsbaer avatar jnnshschl avatar toadlump avatar vpoverennov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ameisenbotx's Issues

[FeatureRequest] DevTools

  • Add rolling log to DevTools

  • Filter WowObjects by type, create a tab for each object type
    basic implementation done in #93

  • Option to copy data
    basic implementation done in #93

[FeatureRequest] Better blacklist implementation

Blacklisting currently is a pain in ass. The IEnumerable type is immutable, therefore not suitable for rapid addition/deletion of items.

What do we actually want from a blacklist implementation?

  • Simply procedure to add or delete item from blacklist

Do we actually need Ordering?
Do we actually need Concurrency?

What about some kind of timed cache?

        public class Cache<TKey, TValue>
        {
            private readonly Dictionary<TKey, CacheItem<TValue>> _cache = new();

            public void Store(TKey key, TValue value, TimeSpan expiresAfter)
            {
                _cache[key] = new CacheItem<TValue>(value, expiresAfter);
            }

            public TValue Get(TKey key)
            {
                if (!_cache.ContainsKey(key))
                    return default;

                var cached = _cache[key];
                if (DateTimeOffset.Now - cached.Created < cached.ExpiresAfter) 
                    return cached.Value;

                _cache.Remove(key);
                return default;
            }

            public int Count() => _cache.Count;
        }

        private class CacheItem<T>
        {
            public T Value { get; }
            internal DateTimeOffset Created { get; } = DateTimeOffset.Now;
            internal TimeSpan ExpiresAfter { get; }

            public CacheItem(T value, TimeSpan expiresAfter)
            {
                Value = value;
                ExpiresAfter = expiresAfter;
            }
        }

[CodeQuality] (WIP)

I will write down issues here relating to code quality which i think could be done better or require an explanation.

  • Reduce branching/nesting where possible
    There are areas where unnecessary branching/nesting is introduced. Ultimately as complexity of the code grows so does the overhead introduced by these control flow features. If we assume a ideal Combat Class which manages from lvl 1 to top tier raids. Its likely in current style of code it would include thousands of control structures in case of need to handle every unique case that may happen during various states of execution. This would result in a lot of time spent traversing branches. A rewrite in well written behavioral trees approach would greatly reduce this overhead and make code much more readable.

  • Variable/parameters/args naming conventions
    Some variables/parameters/args conform neither to PascalCasing nor to camelCasing conventions.

  • For loops where foreach loop suffices
    Some for loops actually don't have any need for use of the index, the item of foreach loop suffices
    This is adressed in #114

  • Variables can be just var
    Depends on consensus i am fine with vars where the underlying type is obvious from context
    There are many places where variable type is apparent no need to speficy, like:

int totalSeconds = (int)totalTime.TotalSeconds;
  • Separate code and data constants
    It would be great to isolate various magic numbers, scripts, texts from code into data constants

  • Some namespaces are incorrect
    This is resolved in #111

  • Project structural problems
    Combat classes do not belong to engines, however moving them proper namespace would trigger instantiation of abstract classes and therefore compilation would fail.

  • Enforce line ending
    Matter of consensus indeed however according to theory by Markus Itkonen, Typography and readability
    the optimal size of a single line should be 40 to 90 characters wide, historicaly programmers have been biased since ancient times to magically decide the number to be 80, Its hard to read file compares when lines are too long.

  • No need to introduce nesting on control flow feature which is followed only by one statement
    This depends on consensus (IDE0011) but i vote for
    csharp_prefer_braces = when_multiline or multi-conditional or linq-foreachloop

if (true)
{
   Something();
}

just

if (true) Something();
  • Use simple 'using' statement
    again as above (IDE0063) i vote for
    csharp_prefer_simple_using_statement = true
using var a = b;
  • Low level features in high level code.
  • Usually it doesn't make sense to enumerate over single item, henceforth enums doesn't have a need to end with plural form. This is done in #112

[TODO] GrindEngine logic

This relates to PR #61

  • When returning to sell/repair nearest NPC being a vendor is selected not the profile defined one

  • fixed in PR #65

  • When walking to new node, bot doesn't care about walking into agro range of mobs

  • pve fixed in PR #67

  • Mouting/Unmounting logic

  • Mount

  • Unmount

  • added in PR #74

[Bug] Stability issues

So finally got my combat class working to leave it run for few hours grinding.

I have noticed that every several hour run of grind ended up in either client silently crashing or being frozen and unresponsive with bot reporting no exceptions.

This is a severe problem and will need more investigation.

Sometimes stuck running on the same spot

It wanted to approach an cactus in valley of strength but got stuck on one and just kept running without making progress.

In this case the bot should have an unstuck routine.

[Brainstorming] Client cache

AFAIK beside spellEntry from clients DB (DBC) it would be useful to parse the following wow client caches (WDB):

  • CreatureCache.wdb

  • GameObjectCache.wdb

  • ItemCache.wdb

  • QuestCache.wdb

[Bia10-CombatClass-Bugs] Todo list

  • Ranged classes wont move closer if enemy is not in LOS

  • Ranged classes will move closer upon first cast

  • Melee classes interacting with target end up with too quick animations being played, something wrong with Bot.Wow.InteractWithUnit(target.BaseAddress);

  • Warrior335a.VictoryRush requires tracking of time elapsed since last kill for proper timing

[FeatureRequest] more user friendly lua parsing/execution

Currently the way that Lua is parsed and executes is kind of confusing:

public void ClickOnTrainButton()
{
   LuaDoString("LoadAddOn\"Blizzard_TrainerUI\"f=ClassTrainerTrainButton;f.e=0;if f:GetScript\"OnUpdate\"then f:SetScript(\"OnUpdate\",nil)else f:SetScript(\"OnUpdate\",function(f,a)f.e=f.e+a;if f.e>.01 then f.e=0;f:Click()end end)end");
}
  • Annoyingly long lines, not suitable for diff comparison
  • Stripping of whitespace makes it hardly readable
  • Need to escape strings from Lua code

Why can't we have it like this?

public void ClickOnTrainButton()
{
	LuaDoString(@"
	LoadAddOn"Blizzard_TrainerUI"
	local trainButton = ClassTrainerTrainButton
	trainButton.e = 0

	if trainButton:GetScript"OnUpdate" then
	   trainButton:SetScript("OnUpdate", nil)
	else
	     trainButton:SetScript("OnUpdate", function(trainButton, e)
	     trainButton.e = trainButton.e + e
		 if trainButton.e > .01 then
		    trainButton.e = 0
	            trainButton:Click()
		 end
	     end)
	end")
}

[Bug] System.ComponentModel.Win32Exception

System.ComponentModel.Win32Exception
  HResult=0x80004005
  Message=The data area passed to a system call is too small.
  Source=WindowsBase
  StackTrace:
   at MS.Win32.UnsafeNativeMethods.GetWindowText(HandleRef hWnd, StringBuilder lpString, Int32 nMaxCount)
   at System.Windows.Automation.Peers.WindowAutomationPeer.GetNameCore()
   at System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree()
   at System.Windows.ContextLayoutManager.fireAutomationEvents()
   at System.Windows.ContextLayoutManager.UpdateLayout()
   at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
   at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
   at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
   at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run()
   at AmeisenBotX.App.Main()

[FeatureRequest] Proper implementation of SpellManager class

Currently spells are done via Lua hack workaround. A proper implementation of SpellManager will require a memory interfacing and local wow storage interfacing.

The current implementation is insufficient for all that has to be automated with regards to spells.

  • Most of the work with regard to parsing Spell.dbc is already done by SpellWork

  • Memory interface

  • ISpellManager interface

  • HasSpell()

  • CanCastSpell()

  • CanBuff()

  • CanDebuff()

  • CastSpellAtLocation()

  • StopCasting()

[Bug] gossip selection doesn't work as intended

Been experimenting with trainer gossip and here's something fishy i did not get to bottom of:

Once you have gossip frame open with trainer following scenarios unfold:

  1. Bot.Wow.SelectGossipOptionSimple(1);

which calls:

public void SelectGossipOptionSimple(int gossipId)
{
  LuaDoString($"SelectGossipOption({gossipId}))");
}

result: does nothing

  1. Bot.Wow.SelectGossipOption(1);

which calls:

public void SelectGossipOption(int gossipId)
{
  LuaDoString($"SelectGossipOption(max({gossipId}, GetNumGossipOptions()))");
}

result: unlearn talents frame opens

  1. Using dev-tools and calling LuaDoString with "SelectGossipOption(1)"

result: learn skills frame opens

So the question is how are the case 1 and 3 different? if they lead to such drastically different results.

[Bug] engine configuration behavior

  • Bot starts running not paused
  • To change engine config u have to select it
  • If engine is selected the last configuration is loaded giving no opportunity to change it
  • Stopping the bot and changing the engine config doesn't take effect upon starting the bot again.

So to change engine config you have to restart the bot entirely. Not very useful, helpful or friendly.

[FeatureRequest] Allow no combat class

Currently bot will throw exception if we enter ingame without combat class. This isn't very nice for two reasons.

  1. If user starts the bot for first time its very hard to pause the bot before jumping ingame on high-end rigs. Thus its not possible to stop the bot and select combat class without running into exception.

  2. Not all engines should require a combat class. Doing profession tasks while at secure location in town doesn't have much need for a combat class.

[Question] What kind of interfacing does this bot offers?

I have not red the entire source, but what i saw in few snippets this is mainly a Lua bot if i understand correctly?

What are the main obstacles that this cannot become a packet based or memory based bot?

As i understand it interfacing wow client follows a priority hierarchy.

Packet based -> Memory based -> Lua based

AFAIK the wow client has only thread for Lua, what happens if i want to run a Lua addon which is computation heavy (as in uses a lot of Lua thread time) and at the same time rely on the Lua calls for the bot?

Thanks for your time.

[QuestGrinding/Grinding] Add more data to profiles and expose them

Well i think it would be good idea to have data like Vendors/Trainer/Mailboxes localized in profiles rather then somewhere global, i am also open to discussion wherever FreeBagSlots or SellByItemQuality shouldn't also be included as sometimes i would want less free space sometimes more free space depending on profile not a global settings.

  • Add Vendors to profiles
  • Add Trainers to profiles, Vector3 Position, string Name, TrainerType Type
  • Add Mailboxes to profiles

initial implementation done in #94

[QuestGinding/Grinding] More filtering options for profiles

Things which are missing:

  • Blacklist/whitelist mobs

  • Blacklist/whitelist nodes

  • Define nodes by geometry/surface topology

  • Filter mobs by ID

  • Filter mobs by FactionID

  • Filter mobs by WoWCreatureType

  • Filter mobs by Min/Max Level

  • Filter mobs by RarityLevel

[Bug] BasicTargetSelectionLogic

I am starting to see that your mainly using the bot to test dungeons. That's not very wise as dungeons are much easier to bot then outside world.

protected bool IsValidUnit(IWowUnit wowUnit)
{
    return !wowUnit.IsDead
        && !wowUnit.IsNotAttackable
        && wowUnit.IsInCombat
        && !IsBlacklisted(wowUnit)
        && Bot.Db.GetReaction(wowUnit, Bot.Player) == WowUnitReaction.Hostile
        && wowUnit.DistanceTo(Bot.Player) < 80.0f;
}
!wowUnit.IsDead 

is actually not simple to decide as

 bool IsDead => (Health == 0 || UnitFlagsDynamic[(int)WowUnitDynamicFlags.Dead]) && !UnitFlags2[(int)WowUnit2Flags.FeignDeath];

there exist few units which are at Health == 0 && !UnitFlagsDynamic[(int)WowUnitDynamicFlags.Dead]

The 'Dead' flag doesn't ensure the unit is dead. It just ensures it has a gray name.

!IsBlacklisted(wowUnit)

Its a good question what kind of role a global blacklist would have, in most cases a local blacklist dependent upon profile is more optimal.

The global blacklist is only good for mobs which roam very big area. Of which there are only very few and mostly rare ones.

Bot.Db.GetReaction(wowUnit, Bot.Player) == WowUnitReaction.Hostile

Not very friendly, i do like to fight non-hostiles, filter critters if not used for skinning/leatherworking

wowUnit.DistanceTo(Bot.Player) < 80.0f;

Maybe be irrelevant on staircase/cliff, distance may be such that interaction radius overlaps and yet traversal cost is massive.

Please keep in mind:

DynamicFlags are only for visuals!

Well need to come up with much better mechanics of unit validation, more dynamic, more flexible.

[FeatureRequest] add new node to generic logic NeedToLearnNewSpells

The interaction with the trainer will be similar to merchant via Lua hacks :/

  • A very stupid solution that visits trainer every level up and assume having more cash then price of services

  • This is implemented in #88

Some more refined spell training

This should use the Lua API for trainer:
BuyTrainerService(), GetTrainerServiceInfo(), GetTrainerServiceCost()

  • LearnSpellByName()

  • LearnSpellById()

  • LearnAllSpells()

  • CanLearnNewSpells()

  • CanImproveSpellsRank()

This leads to question:
The question remains where are we gonna check for these data from? prolly hold it in external LiteDB or in json/xml/csv

[Pathfinding] Lack of environmental awareness

  • Well the world is composed of other objects then just navmesh. Things like doodads, structures will have to be ultimately resolved their bounding box acknowledged and checked if nav path goes thru such a bounding box. Currently the bot doesn't understand being blocked by a tree, cacti, fence etc..

  • What if the enemy is nearby but above or below us. In such a case some more refined path measurement like traversal cost would be more beneficial rather then measurement like Euclidian distance.

these are just 2 things i noticed but likely many cases of similar issues arise, ill have to write my combat class for now :]

in general the bot should be aware of other things then just navmesh with regard to pathing decisions.

[Bug] Some loots are skipped

For ranged classes the looting state passes faster then time needed to traverse to corpse, as such many loots are missed.

some problems

  • AmeisenBotX.Core claims following:

<HintPath>..\dep\AnTCP.Client.dll</HintPath>

However the only file present is AnTCP.Client.1.0.0.nupkg which i had to restore manually to be able to build.

  • I am getting some weird error, what this about?
    image

Some additional questions:

  • Is there somewhere a rolling log?
    I rly hate the silence that surrounds the bot, it should constantly scream what's going on.

[FeatureRequest] Debug overlays

It would be nice to have overlays for thing which are hard to debug from logs like positioning/facing/line of sight.

So what id love to see would be overlays for :

  • Circle to represent interaction sizes which often don't match model size.

  • Angles

  • Position

  • Rays to see if something is in line of sight or not

  • Bounding boxes

[Brainstorming] Stuckness compendium

This issue serves as repository for all issues relating to bot being stuck unable to proceed without human intervention.
All such issues should be described here.

The generic stuck problem template:

Evidence?

Happens during execution of a profile?
If so, When during execution of a profile stuck occurs?

Can stuckness be resolved by existing unstuck routine?
If NOT so, Can stuckness be resolved by alternative unstuck routine?

Is the stuckness related to pathing/traversing only?
If NOT so, What kind of activities contribute to getting stuck?

Problem description:

Client-sided workaround possible?
If so, What kind of client patch solves the problem?

Further notes:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.