Jump to content

Recommended Posts

Right, so based on my previous experience with moving after frostnova I now know tha for something like this I will need FightEvents.OnFightLoop.

The idea is simple, however with my limited knowledge of CSharp I was not able to make this work reliably and/or as smooth as I would like to.

The scripting language I'm familiar with is AutoIt and if I was using that I would grab the attacking units, put them into an array, polymorph the second, make the script remember which mob index I polymorphed and go back to any other index. Or grab all the mobs attacking me into an array, polymorph any of them really, probably the one that I have targetted to make it simple, and then do a for loop to loop through them all and check for unit.HaveBuff("Polymorph"), find the first that doesn't have it and attack.

I have tried several versions but I always hit a brick wall due to my CSharp ignorance.

Here's my total pseudo code (don't laugh too hard, or do :-D ) that works but only somewhat. It correctly casts poly, switches target but unfortunately once the target is dead the bot doesn't start fighting with the polymorphed mob. Despite being in combat it considers itself not fighting and tries to move on. The worst scenario is when I have 'Pause if player nearby' selected, once I kill the non-poly mob and player is nearby, it stops, sits there and takes the punishment from the recently unpolymorphed mob.

  Reveal hidden contents

There must be a clean way to do this.

You don't need to use onfightloop. This could be an if in your rotation.

Once again, I can't test right now but I don't see why the below couldn't do the trick (there are probably cleaner ways to do it):

	List<WoWUnit> attackers = ObjectManager.GetUnitAttackPlayer();
        if (attackers.Count > 1)
        {
            WoWUnit mainTarget = attackers.Where(u => u.HealthPercent == attackers.Min(x => x.HealthPercent)).FirstOrDefault();
            WoWUnit polyTarget = attackers.Where(u => u.HealthPercent == attackers.Max(x => x.HealthPercent)).FirstOrDefault();     
            if (!polyTarget.HaveBuff("Polymorph") && polyTarget != mainTarget)
            {
                Interact.InteractGameObject(polyTarget.GetBaseAddress);
                SpellManager.CastSpellByNameLUA("Polymorph");
                Thread.Sleep(500);
                Interact.InteractGameObject(mainTarget.GetBaseAddress);
            }       
        }

~edit: you'd probably want to add some more conditions to make sure polymorph is known etc.

That will most likely result in the bot just throwing around random targeting. You absolutely NEED to do this during on the OnFightLoop and cancel all other events.
As for polymorphs not being valid targets - it's because they don't target you. That's why the bot doesn't know it's being attacked. You need to actively start a fight with them again (build this into your fightclass).
I had the same problem in TBC. 

To avoid the bot trying to polymorph another target when pulling more mobs, you can sort them by Guid + HP + Level + Entry, that should result in always the same target being selected.

 

  On 11/2/2017 at 1:16 PM, Matenia said:

That will most likely result in the bot just throwing around random targeting. You absolutely NEED to do this during on the OnFightLoop and cancel all other events.

Expand  

That's true

  On 11/2/2017 at 1:16 PM, Matenia said:

That will most likely result in the bot just throwing around random targeting. 

Expand  

Can you explain to me why that would be? We have a defined poly target and a main target? The only issue I could think of is that the polytarget could change because there could be multiple mobs at 100% hp. You could get around that though with another condition

Well the way I understand it is that if you don't use OnFightLoop and you call InteractGameObject and it instantly switches back to the original target, the one bot decided to target.

I can polymorph a mob but it will keep it targetted until it dies despite InteractGameObject switching to a different target.

So if the bot targets MOB1 and you InteractGameObject with MOB2 and cast Poly, it might work. But if the bot targets MOB1 and you poly MOB1, it will keep switching between MOB2 and MOB1.

I guess it could work if polytarget was NOT my original target.

  On 11/2/2017 at 1:16 PM, Matenia said:

You absolutely NEED to do this during on the OnFightLoop and cancel all other events.

Expand  

How do I cancel all other events?

I tried cancelable.Cancel = true within my OnFightLoop and I'm not 100% convinced it cancelled my main fight loop.

God damn, I'm totally lost :-D

EDIT: the thing is, if we do this (WoWUnit mainTarget = attackers.Where(u => u.HealthPercent == attackers.Min(x => x.HealthPercent)).FirstOrDefault();) inside an OnFightLoop it will "forget" the poly target, won't it? Because it will get redefined everytime it loops...

  On 11/2/2017 at 2:18 PM, Seminko said:

Well the way I understand it is that if you don't use OnFightLoop and you call InteractGameObject and it instantly switches back to the original target, the one bot decided to target.

I can polymorph a mob but it will keep it targetted until it dies despite InteractGameObject switching to a different target.

So if the bot targets MOB1 and you InteractGameObject with MOB2 and cast Poly, it might work. But if the bot targets MOB1 and you poly MOB1, it will keep switching between MOB2 and MOB1.

I guess it could work if polytarget was NOT my original target.

Expand  

Pretty much this. Plus, since the bot runs on another thread, sometimes it switches your target back BEFORE your poly cast even starts. Then you end up polying 2 targets back and forth and looking like a retard. Basically why Jasabi could never get polymorph to work correctly, I believe.

cancelable.Cancel = true is correct. However, I recommend NOT breaking the OnFightLoop event handler UNTIL your target has been successfully polymorphed. You can solve this with a while loop (Thread.Sleep inside) until poly is on another target.

  On 11/2/2017 at 3:25 PM, Matenia said:

cancelable.Cancel = true is correct. However, I recommend NOT breaking the OnFightLoop event handler UNTIL your target has been successfully polymorphed. You can solve this with a while loop (Thread.Sleep inside) until poly is on another target.

Expand  

Just so I understand... From my testing today I found out that if I have OnFightLoop it combines my BAU rotation with the OnFightLoop rotation. It doesn't really seem it superseeds the BAU rotation. So if I go cancelable.Cancel = true; what will it cancel? The OnFightLoop rotation or everything else except the OnFightLoop rotation?

Can Cancel be used from within the OnFightLoop?

Sorry, I don't follow. My understanding is the OnFightLoop "loop" is acting like a while loop everytime I'm in combat, doing its thing continuously.

Let's say, if I have the code below and the first argument would be true, cancelable.Cancel would be set to true, what would happen? It would skip the second if argument in the OnFightLoop and start right from the start?

FightEvents.OnFightLoop += (unit, cancelable) => {
	if (ObjectManager.Target.GetDistance <= 8 && (!ObjectManager.Target.HaveBuff("Frost Nova") || !ObjectManager.Target.HaveBuff("Frostbite")) && (_timerFrostNova == null || _timerFrostNova.IsReady) && ObjectManager.Target.HealthPercent >= 20)
	{
		Move.StrafeRight(Move.MoveAction.PressKey, 1250);
		cancelable.Cancel = true;
	}
	
	if (ObjectManager.Target.GetDistance <= 10 && (!ObjectManager.Target.HaveBuff("Frost Nova") || !ObjectManager.Target.HaveBuff("Frostbite")) && (_timerFrostNova == null || _timerFrostNova.IsReady) && ObjectManager.Target.HealthPercent >= 20)
	{
		Move.StrafeLeft(Move.MoveAction.PressKey, 1250);
	}
};

If that is the case can I disable OnFightLoop? I'm looking at the += and thinking if I did -= it would somehow remove things from the OnFightLoop? If so, how?

 

Btw guys, this is great, this is how I like to learn, not sitting in books, that doesn't work for me at all. I have to dive right in and figure things out on real life examples. ;) Thanks for being so helpful!

  On 11/2/2017 at 5:11 PM, Seminko said:

Btw guys, this is great, this is how I like to learn, not sitting in books, that doesn't work for me at all. I have to dive right in and figure things out on real life examples. ;) Thanks for being so helpful!

Expand  

100% agree :happy:

You are actually subscribing to an event (hence the term event handler).
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/events/how-to-subscribe-to-and-unsubscribe-from-events

So your entire code ALWAYS gets executed - but whatever follows this event (the original fighting code by wRobot) can be stopped by setting cancelable.Cancel to true.

  On 11/2/2017 at 5:54 PM, Matenia said:

You are actually subscribing to an event (hence the term event handler).
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/events/how-to-subscribe-to-and-unsubscribe-from-events

So your entire code ALWAYS gets executed - but whatever follows this event (the original fighting code by wRobot) can be stopped by setting cancelable.Cancel to true.

Expand  

So both the OnFightLoop and my FightClass code will get executed, the only thing we are cancelling is wrobot's "default built in" fighting code / behavior? That's strange, kind of. If that is so, what would happen if I did:

FightEvents.OnFightLoop += (unit, cancelable) => {
	cancelable.Cancel = true;
};

Well, time to experiment...

Absolutely noob question.

Inside the OnFightLoop I have WoWUnit currentTarget = etc.etc. What the heck do I need to do to be able to use it in an IF statement outside of the OnFightLoop?

I want to test using it in my main rotation "if polyTarget.IsValid" (now gives an error) and if that is true I want to do "Interact.InteractGameObject(polyTarget.GetBaseAddress);" which also gives an error, saying it doesn't exist in the current context.

Do I need to define it at the start? What type do I define it as?

You need to define the variable outside of the scope of the event handler (onfightloop eventhandler) and then assign it inside the event handler. 
I'm not sure why you need that to achieve it?

So I made it work. I basically used a bool inside the OnFightLoop and set it to true when there are more than 1 mob attacking me. While true my BAU combat rotation won't trigger... once the Poly is applied, the bool is set to false and normal combat continues.

To wake the sheep just CastSpellByNameLUA.

  • 1 year later...
List<WoWUnit> attackers = ObjectManager.GetUnitAttackPlayer();

        FightEvents.OnFightLoop += (unit, cancelable) =>
        {
            if (attackers.Count > 1 && Polymorph.KnownSpell && Polymorph.IsSpellUsable && ObjectManager.Target.GetDistance <= 25 && presence.KnownSpell && presence.IsSpellUsable)
            {
                WoWUnit mainTarget = attackers.Where(u => u.HealthPercent == attackers.Min(x => x.HealthPercent)).FirstOrDefault();
                WoWUnit polyTarget = attackers.Where(u => u.HealthPercent == attackers.Max(x => x.HealthPercent)).FirstOrDefault();
                if (!polyTarget.HaveBuff("Polymorph") && polyTarget != mainTarget)
                {
                    SpellManager.CastSpellByNameOn("Polymorph", polyTarget.Name);
                    Usefuls.WaitIsCasting();
                    return;
                }
            }
        };

(non tested)

  • 10 months later...

Hello, for any1 who needs, I have implemented working polymorph offtarget with attacking poly after mainTarget is dead. Its quite reliable unsless there are 2 polyTargets - 2 mobs with same name and level pulled after mainTarget. If you guys could make a workaround, please share, but I will deffinitelly try to overcome it too (mby just run from them is a solution).

        List<WoWUnit> attackers = ObjectManager.GetUnitAttackPlayer();
        if (attackers.Count >= 2 && PolyMorph.KnownSpell)
        {
            FightEvents.OnFightLoop += (unit, cancelable) =>
            {
                WoWUnit mainTarget = attackers.Where(u => u.HealthPercent == attackers.Min(x => x.HealthPercent)).FirstOrDefault();
                WoWUnit polyTarget = attackers.Where(u => u.HealthPercent == attackers.Max(x => x.HealthPercent)).FirstOrDefault();
                if (!polyTarget.HaveBuff("Polymorph") && polyTarget != mainTarget && !ObjectManager.Me.IsDeadMe && !mainTarget.IsDead && !polyTarget.IsDead)
                {
                    Interact.InteractGameObject(polyTarget.GetBaseAddress);
                    SpellManager.CastSpellByNameLUA("Polymorph");
                    Usefuls.WaitIsCasting();
                    Interact.InteractGameObject(mainTarget.GetBaseAddress);
                }
                else if (mainTarget.IsDead && !polyTarget.IsDead && !ObjectManager.Me.IsDeadMe)
                {
                    Interact.InteractGameObject(polyTarget.GetBaseAddress);
                    SpellManager.CastSpellByIdLUA(116);
                    Thread.Sleep(500);
                }
            };
            return;
        }

 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...