Jump to content

Recommended Posts

I was looking for a plugin or a code snippet that would alternate tagets. I found MultiPull plugin which is great but it's pretty limited. It will pull a number of targets but then still tunnel vision the last one it pulled

I play a warlock and even though I wrote my script in a way that each new dot will make the voidwalker attack that target (to hold aggro), sometimes with multipull what happens is that I will cast the dot, but before voidwalker reaches the target to taunt it MultiPull pulls another target so the voidwalker switches targets before it can taunt the first one which results in the second mob being tanked by voidwalker and the first target attacking me. The other annoying thing is that once I pull multiple mobs, once the dots are off from the first target, they are not applied again until the last target which is tunneled is dead.

My idea is this, let's keep MultiPull as is, but let's come up with another code that would:

  • scan debuffs on mobs which are in combat with me or with voidwalker
    • if any expire switch target and reapply
  • if any of the mobs that are in combat with me or my voidwalker are focusing me, make the voidwalker switch to that target.

 

Dear mr @Droidz is that even possible?

Link to comment
Share on other sites

If you have some pseudo code, it's very easily done.
Assuming this isn't vanilla, we're going to use focus to avoid having to switch targets at all.
I'll keep the code as simple as possible and assume that you will NOT pull extra targets, rather just focus on those attacking you already.

 

WoWUnit corruptionTarget = ObjectManager.GetUnitAttackPlayer()
            .Where(o => 
                   o.IsAlive 
                   && o.IsValid 
            	   && !o.HaveBuff("Corruption")
                  ).OrderBy(o => o.Guid)
  .FirstOrDefault();

var oldFocus = ObjectManager.Me.FocusGuid;
ObjectManager.Me.FocusGuid = corruptionTarget.Guid;
SpellManager.CastSpellByNameOn("Corruption", "focus");
ObjectManager.Me.FocusGuid = oldFocus;

 

Link to comment
Share on other sites

unfortunately, we are in fact in vanilla formus :)

EDIT: if we were in non-vanilla-wow where would I put the code in? I use the grinder and a fight class. With my limited understanding it looks the fight class doesn't handle targeting.

Link to comment
Share on other sites

Then this should work:

WoWUnit corruptionTarget = ObjectManager.GetUnitAttackPlayer()
            .Where(o => 
                   o.IsAlive 
                   && o.IsValid 
            	   && !o.HaveBuff("Corruption")
                  ).OrderBy(o => o.Guid)
  .FirstOrDefault();

Interact.InteractGameObject(corruptionTarget.GetBaseAddress);
SpellManager.CastSpellByNameLUA("Corruption);

 

Link to comment
Share on other sites

I edited my previous post:

33 minutes ago, Seminko said:

EDIT: if we were in non-vanilla-wow where would I put the code in? I use the grinder and a fight class. With my limited understanding it looks the fight class doesn't handle targeting.

Also, quite often it happens that I will pull mobs in the middle of the fight unintentionally. I'm thinking with warlocks dots I would like to pull mobs in the middle of the fight in fact if a mob spawns or gets in a certain range.

Link to comment
Share on other sites

1 minute ago, Seminko said:

I edited my previous post:

Also, quite often it happens that I will pull mobs in the middle of the fight unintentionally. I'm thinking with warlocks dots I would like to pull mobs in the middle of the fight in fact if a mob spawns or gets in a certain range.

The code handles that - if something attacks you, it will get dotted. And these are all workaround for targeting. You do not actually get a choice over what the bot targets (no true way to override it).

So it has to be done within a fightclass or a plugin. That's where this code would go.

Link to comment
Share on other sites

5 minutes ago, Matenia said:

You do not actually get a choice over what the bot targets (no true way to override it).

So you would just temporarily switch targets to apply the dots?

I'm a Csharp noob but from what I gathered the script you posted just checks for a mob that is attacking you, assigns it the corruption target variable and checks whether it is valid, it is alive and whether it has corruption or not. Now I need something like a For loop to loop through all targets attacking me based on the 'GetUnitAttackPlayer().Count()' right?

Are mobs that are attacking the voidwalker considered GetUnitAttackPlayer?

Link to comment
Share on other sites

No, it already loops through all targets, checks which don't have corruption and selects that target as your new corruption target (because it does not have corruption).

You then tell the bot to select that target before casting corruption on your current target.

Link to comment
Share on other sites

8 minutes ago, Matenia said:

No, it already loops through all targets, checks which don't have corruption and selects that target as your new corruption target (because it does not have corruption).

You then tell the bot to select that target before casting corruption on your current target.

Interesting, so '.Where(o => ' is a loop expression?

Once the servers are up again I will fiddle with it and get back to you.

Link to comment
Share on other sites

Where is a filter function that takes a lambda expression to filter for, which it does lazily (so only once FirstOrDefault() is being called - which returns ONE entry, matching your criteria).

Link to comment
Share on other sites

Oh snap, now you confused me :-D First of all a lambda expression? What is this, half life? :-D

It loops through all the targets but it returns only ONE entry... hmm... let's consider this scenario, there are three mobs attacking me and none of them have corruption, the script will find the first mob as missing Corruption and cast it on him but that's it. It would have found the first, in other words - ONE, mob that matches that criteria and be done with it. But the other two will still be missing corruption? Or am I mistaken?

This is great, this is how I learn things when I can chat with skilled ppl like you! Appreciate that!

Link to comment
Share on other sites

Yep, that's what it would do.
Of course, you'd be calling that function in an endless loop and it would keep corruption up on all targets, as soon as it expires.

You can easily modify that to do any other dot.

Link to comment
Share on other sites

Brilliant! I have also found this code:

internal void MultiTargetRotation()
    {
        var unitsAffectingMyCombat = ObjectManager.GetUnitAttackPlayer();

        if (unitsAffectingMyCombat.Count <= 0)
            return;

        var unitsAttackMe = unitsAffectingMyCombat.Where(u => u != null && u.IsValid && u.IsTargetingMe).ToList();

        if (unitsAttackMe.Count > 1)
        {
            var unitToAttack = unitsAttackMe.FirstOrDefault(u => u != null && u.IsValid && !u.IsMyPetTarget);
            if (unitToAttack != null && unitToAttack.IsValid && unitToAttack.IsAlive)
            {
                if (!unitToAttack.IsMyTarget)
                    Interact.InteractGameObject(unitToAttack.GetBaseAddress, !ObjectManager.Me.GetMove);
                if (unitToAttack.IsMyTarget)
                    Lua.LuaDoString("PetAttack();");
                Logging.Write("PET ATTACKING: " + unitToAttack);
            }
        }
        //IF ALL THE MOBS ARE ATTACKING THE PET FOCUS THE LOWER HP ONE
        else
        {
            var unitsAttackPet = unitsAffectingMyCombat.Where(u => u != null && u.IsValid && u.IsTargetingMyPet).ToList();
            var lowerHpUnit = unitsAttackPet.OrderBy(unit => unit.HealthPercent).FirstOrDefault();
            if (lowerHpUnit != null && lowerHpUnit.IsValid && lowerHpUnit.IsAlive && !lowerHpUnit.IsMyPetTarget)
            {
                if (!lowerHpUnit.IsMyTarget)
                    Interact.InteractGameObject(lowerHpUnit.GetBaseAddress, !ObjectManager.Me.GetMove);
                if (lowerHpUnit.IsMyTarget)
                    Lua.LuaDoString("PetAttack();");
                Logging.Write("PET ATTACKING LOWER HP: " + lowerHpUnit);
            }
        }
    }

 

Also, since you know your coding, say I would like to summon voidwalker or create healthstone, how do I make the bot stop searching for targets and just stay still until it is summoned? I use IsSpellUsable to check if I have enough mana and if I do, sometimes the bot wants to summon the voidwalker but it's trying to do it while running. It seems once it finds its target it moves to the defined range, stops AND THEN summons the voidwalker.

Link to comment
Share on other sites

List<WoWUnit> units = new List<WoWUnit>();

// Short version
IEnumerable<WoWUnit> sortedUnits = units.Where(u => u.Health < 10);

// Long version
List<WoWUnit> sortedUnits = new List<WoWUnit>();
foreach(WoWUnit unit in units)
{
   // Validate
   if(unit.Healt < 10)
   {
      // Add unit
      sortedUnits.Add(unit);
   }
}

Hope it explains it a bit. At the end the compiler won't do something else.

 

Link to comment
Share on other sites

5 minutes ago, iMod said:
List<WoWUnit> units = new List<WoWUnit>();

// Short version
IEnumerable<WoWUnit> sortedUnits = units.Where(u => u.Health < 10);

// Long version
List<WoWUnit> sortedUnits = new List<WoWUnit>();
foreach(WoWUnit unit in units)
{
   // Validate
   if(unit.Healt < 10)
   {
      // Add unit
      sortedUnits.Add(unit);
   }
}

Hope it explains it a bit. At the end the compiler won't do something else.

 

Hi iMod, what does it do exactly? It seems it puts all mobs with HP lower than 10 into a list or an array?

Link to comment
Share on other sites

9 minutes ago, Seminko said:

Hi iMod, what does it do exactly? It seems it puts all mobs with HP lower than 10 into a list or an array?

Yes i just tried to demonstrate what the expression does in the background. The first one is with expression and the other one without.

Link to comment
Share on other sites

Still not able to test since the servers are down.

I still need to figure out the Voidwalker summon / Healthstone creation situation. As I described above:

1 hour ago, Seminko said:

Also, since you know your coding, say I would like to summon voidwalker or create healthstone, how do I make the bot stop searching for targets and just stay still until it is summoned? I use IsSpellUsable to check if I have enough mana and if I do, sometimes the bot wants to summon the voidwalker but it's trying to do it while running. It seems once it finds its target it moves to the defined range, stops AND THEN summons the voidwalker.

I checked the How to create a fight class from Droidz and he has this in his PetManager class:

public override void Run()
        {
            if (!ObjectManager.Pet.IsValid)
            {
                _callPet.Launch(true);
                Thread.Sleep(Usefuls.Latency + 1000);
            }
            if (!ObjectManager.Pet.IsValid || ObjectManager.Pet.IsDead)
                _revivePet.Launch(true);
 
            _petTimer = new Timer(1000 * 2);
        }

I see override, does this actually overrieds the default bot behavior?

 

To be honest I don't know how I would incorporate it into my script. I'm putting together multiple scripts from multiple sources. Here is my potato script and how I handle the combat:

private void GetFightingState()
        {
			if ((ObjectManager.Pet.IsValid && !ObjectManager.Pet.IsDead) && ObjectManager.Pet.HealthPercent < 7)
			{	
				fightState = fightingStateEnum.LowPetHealth;
				return;
			}
			else if (ObjectManager.Me.HealthPercent < 25 && (_timer == null || _timer.IsReady) && (ItemsManager.GetItemCountByIdLUA(5512) >= 1 || ItemsManager.GetItemCountByIdLUA(19004) >= 1 || ItemsManager.GetItemCountByIdLUA(19005) >= 1))
			{	
				fightState = fightingStateEnum.LowPlayerHealth;
				return;
			}
			else if (DrainSoul.IsSpellUsable && ObjectManager.Target.HealthPercent < 35)
			{
				fightState = fightingStateEnum.TargetLowHealth;
				return;
			}
			else if (LifeTap.IsSpellUsable && ObjectManager.Me.ManaPercentage < 17 && ObjectManager.Me.HealthPercent >= 25  && !ObjectManager.Target.HaveBuff("Drain Soul"))
			{
				fightState = fightingStateEnum.LowPlayerMana;
				return;
			}
			else if (Corruption.IsSpellUsable && !ObjectManager.Target.HaveBuff("Corruption")  && !ObjectManager.Target.HaveBuff("Drain Soul"))
			{
				fightState = fightingStateEnum.CorruptionNeed;
				return;
			}
			else if (CurseOfAgony.IsSpellUsable && !ObjectManager.Target.HaveBuff("Curse of Agony") && !ObjectManager.Target.HaveBuff("Drain Soul"))
			{
				fightState = fightingStateEnum.CoANeed;
				return;
			}
			else if (Fear.IsSpellUsable && ObjectManager.GetWoWUnitHostile().Count(u => u.GetDistance <= 5 && u.IsAttackable) >= 2  && !ObjectManager.Target.BuffCastedByAll("Fear").Contains(ObjectManager.Me.Guid)  && !ObjectManager.Target.HaveBuff("Drain Soul"))
			{
				fightState = fightingStateEnum.TargetClose;
				return;
			}
			else if (ShadowBolt.IsSpellUsable)
			{	
				fightState = fightingStateEnum.SpamShadowBolt;
				return;
			}
			else
			{
				if (EquippedItems.GetEquippedItem(WoWInventorySlot.Ranged) != null && !Lua.LuaDoString<bool>("return IsAutoRepeatAction(" + (SpellManager.GetSpellSlotId(SpellListManager.SpellIdByName("Shoot")) + 1) + ")") && ObjectManager.Me.ManaPercentage < 17 && ObjectManager.Me.HealthPercent < 25)
				{
					if (Shoot.KnownSpell)
						SpellManager.CastSpellByNameLUA("Shoot");
					return;
				}
			}
        }

public void Start()
    {
        
        Logging.Write("Seminko's Warlock Loaded");
        while (iMageLaunched)
        {
            if (!Products.InPause)
                {
                    GetFightingState();
                    if (!ObjectManager.Me.IsDeadMe)
                    {
                        GetFightingState();
                        if (!ObjectManager.Me.IsMounted && BuffRotation() == false && !ObjectManager.Me.InCombat)
						{
                            BuffRotation();
                        }
                        if (Fight.InFight && ObjectManager.Me.Target > 0)
                        {
                            GetFightingState();
                            CombatRotation();
                        }
                    }
                }
            Thread.Sleep(10);
        }
        Logging.Write("Warlock is now stopped.");
    }

public bool BuffRotation()
    {
		if (!ObjectManager.Me.InCombat)
			SummonPet();
			BuffArmor();
			TapForManaOoc();
			ShardManagement();
			CreateHealthstone();

        if (BuffArmor() == true && TapForManaOoc() == true && SummonPet() == true && ShardManagement() == true && CreateHealthstone() == true)
				return true;
			else
                return false;
    }

 

Link to comment
Share on other sites

1 hour ago, Seminko said:

Also, since you know your coding, say I would like to summon voidwalker or create healthstone, how do I make the bot stop searching for targets and just stay still until it is summoned? I use IsSpellUsable to check if I have enough mana and if I do, sometimes the bot wants to summon the voidwalker but it's trying to do it while running. It seems once it finds its target it moves to the defined range, stops AND THEN summons the voidwalker.

public static bool CastSpell(RotationSpell spell, WoWUnit unit, bool force)
    {
        // targetfinder function already checks that they are in LoS
        if (unit != null &&
            spell.IsKnown() &&
            spell.CanCast() &&
            unit.IsValid &&
            !unit.IsDead)
        {

            if (wManager.wManagerSetting.CurrentSetting.IgnoreFightGoundMount && ObjectManager.Me.IsMounted)
                return false;

            Lua.LuaDoString("if IsMounted() then Dismount() end");

            if (ObjectManager.Me.GetMove && spell.Spell.CastTime > 0)
                MovementManager.StopMoveTo(false, 500);

            if (ObjectManager.Me.IsCast && !force)
                return false;

            if (force)
                Lua.LuaDoString("SpellStopCasting();");

            if (AreaSpells.Contains(spell.Spell.Name))
            {
                /*spell.Launch(true, true, false);
                Thread.Sleep(Usefuls.Latency + 50);
                ClickOnTerrain.Pulse(unit.Position);*/
                SpellManager.CastSpellByNameOn(spell.FullName(), GetLuaId(unit));
                //SpellManager.CastSpellByIDAndPosition(spell.Spell.Id, unit.Position);
                ClickOnTerrain.Pulse(unit.Position);
            }
            else
            {
                if (unit.Guid != ObjectManager.Me.Guid)
                {
                    MovementManager.Face(unit);
                }
                SpellManager.CastSpellByNameOn(spell.FullName(), GetLuaId(unit));
                //Interact.InteractObject also works and can be used to target another unit
            }
            return true;
        }
        return false;
    }

This is the function I use to cast spells and make sure my bot stops walking, if required.
Here, spell.IsKnown() and spell.CanCast() are shorthand functions on my spell class to make sure that the spell is not on cooldown and IsSpellUsable is true.
AreaSpells is just a list of strings containing spell names like Blizzard, Rain of Fire and other targeting AoE spells.

Then when deciding whether to use buffs (or like combat spells on an enemy), I just check as follows:

if(Fight.InFight || ObjectManager.Me.InCombat)
{
  //Rotation here, for example CastSpell("Corruption", ObjectManager.Target)
}else
{
  //use buffs
}

 

Link to comment
Share on other sites

4 minutes ago, Matenia said:

This is the function I use to cast spells and make sure my bot stops walking, if required.
Here, spell.IsKnown() and spell.CanCast() are shorthand functions on my spell class to make sure that the spell is not on cooldown and IsSpellUsable is true.
AreaSpells is just a list of strings containing spell names like Blizzard, Rain of Fire and other targeting AoE spells.

Thank you!!!

Link to comment
Share on other sites

I tried using StopMoveTo before casting my spell but does not have any effect. As I was saying, once the bot is in combat mode and stops to prepare for fight then it creates the HS but otherwise my log shows it tried creating it but didn't stop.

public bool CreateHealthstone()
        {
            if (ItemsManager.GetItemCountByIdLUA(5512) == 0 && ItemsManager.GetItemCountByIdLUA(19004) == 0 && ItemsManager.GetItemCountByIdLUA(19005) == 0 && !ObjectManager.Me.InCombat)
            {
				MovementManager.StopMoveTo(false, 500);
				Logging.WriteDebug("Creating Healthstone");
				SpellManager.CastSpellByNameLUA("Create Healthstone (Minor)()");
				Thread.Sleep(Usefuls.Latency + 3500);
				return false;
            }
            return true;
        }

 

Link to comment
Share on other sites

14 minutes ago, Seminko said:

I tried using StopMoveTo before casting my spell but does not have any effect. As I was saying, once the bot is in combat mode and stops to prepare for fight then it creates the HS but otherwise my log shows it tried creating it but didn't stop.

public bool CreateHealthstone()
        {
            if (ItemsManager.GetItemCountByIdLUA(5512) == 0 && ItemsManager.GetItemCountByIdLUA(19004) == 0 && ItemsManager.GetItemCountByIdLUA(19005) == 0 && !ObjectManager.Me.InCombat)
            {
				MovementManager.StopMoveTo(false, 500);
				Logging.WriteDebug("Creating Healthstone");
				SpellManager.CastSpellByNameLUA("Create Healthstone (Minor)()");
				Thread.Sleep(Usefuls.Latency + 3500);
				return false;
            }
            return true;
        }

 

Give MovementManager.StopMove() a try and double check your return value, false if he was casting looks kinda strange.

Link to comment
Share on other sites

Will do.

Also, still struggling with MultiTargeting... :( I update code i posted above and now it should do one of the following things:

  • If a mob is attacking me, and is not my target, switch to that mob and tell pet to attack it
  • If a mob is attacking me, and is my target, tell pet to attack it
  • If no mob is attacking me, check whether they have Corruption and CoA, if they don't apply it

However what happens is that the bot switches the targes but doesn't cast anything... It looks like what Matenia said that you cannot tell the bot what target to choose, so it switches targets, seems like it cannot cast the spell and immediatelly switches back. Ideas?

internal void MultiTargetRotation()
    {
        var unitsAffectingMyCombat = ObjectManager.GetUnitAttackPlayer();

        if (unitsAffectingMyCombat.Count <= 0)
            return;

        var unitsAttackMe = unitsAffectingMyCombat.Where(u => u != null && u.IsValid && u.IsTargetingMe).ToList();

        if (unitsAttackMe.Count >= 1)
        {
            var unitToAttack = unitsAttackMe.FirstOrDefault(u => u != null && u.IsValid && !u.IsMyPetTarget);
            if (unitToAttack != null && unitToAttack.IsValid && unitToAttack.IsAlive)
            {
                if (!unitToAttack.IsMyTarget)
                    Interact.InteractGameObject(unitToAttack.GetBaseAddress, !ObjectManager.Me.GetMove);
					Lua.LuaDoString("PetAttack();");
                if (unitToAttack.IsMyTarget)
                    Lua.LuaDoString("PetAttack();");
                Logging.Write("PET ATTACKING: " + unitToAttack);
            }
        }
		else
		{
			var unitsAttackPet = unitsAffectingMyCombat.Where(u => u != null && u.IsValid && u.IsTargetingMyPet && (!u.HaveBuff("Corruption") || !u.HaveBuff("Curse of Agony"))).FirstOrDefault();
            if (unitsAttackPet != null && unitsAttackPet.IsValid && unitsAttackPet.IsAlive && !unitsAttackPet.IsMyPetTarget)
            {
                if (!unitsAttackPet.IsMyTarget)
				{
					if (!unitsAttackPet.HaveBuff("Corruption") && Corruption.IsSpellUsable)
					{
						Interact.InteractGameObject(unitsAttackPet.GetBaseAddress, !ObjectManager.Me.GetMove);
						SpellManager.CastSpellByNameLUA("Corruption");
					}
					if (!unitsAttackPet.HaveBuff("Curse of Agony") && CurseOfAgony.IsSpellUsable)
					{
						Interact.InteractGameObject(unitsAttackPet.GetBaseAddress, !ObjectManager.Me.GetMove);
						SpellManager.CastSpellByNameLUA("Curse of Agony");
					}
				}
                if (unitsAttackPet.IsMyTarget)
				{	
					if (!unitsAttackPet.HaveBuff("Corruption") && Corruption.IsSpellUsable)
					{
						SpellManager.CastSpellByNameLUA("Corruption");
					}
					if (!unitsAttackPet.HaveBuff("Curse of Agony") && CurseOfAgony.IsSpellUsable)
					{
						SpellManager.CastSpellByNameLUA("Curse of Agony");
					}
                    Lua.LuaDoString("PetAttack();");
				}
            }
		}
    }

 

Link to comment
Share on other sites

Abuse the focus as target. Set your focus target by your self and cast the spell at it.

 

        /// <summary>
        /// Sets the target as focus target and executes the given method
        /// </summary>
        /// <param name="action">The method we want to execute</param>
        public static void SetAsFocusTarget(WoWUnit target, Action action)
        {
            if (ObjectManager.Me.FocusGuid != target.Guid)
            {
                // Hold old target
                ulong oldFocusTarget = ObjectManager.Me.FocusGuid;

                // Set focus target
                ObjectManager.Me.FocusGuid = target.Guid;

                // Call action
                action.Invoke();

                // Set old focus
                ObjectManager.Me.FocusGuid = oldFocusTarget;
            }
            else
            {
                // Call action
                action.Invoke();
            }
        }
            // Dummy unit
            WoWUnit unit = new WoWUnit(1);
            SetAsFocusTarget(unit, () => new Spell("SpellName").Launch(true, true, false, "focus"));

 

Edited by iMod
Link to comment
Share on other sites

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
 Share

×
×
  • Create New...