Lockem 1 Posted November 18, 2017 Share Posted November 18, 2017 Having some problems with the below chunk of code... I'm trying to make a dot rotation that will tab between each target and apply my dots (This part works!). My problem is that no matter what I do it seems to want to double cast Immolate... I've tried adding a timer for it, !ObjectManager.Me.IsCast and various sleeps. I'm kind of a C# noob... so excuse any obvious mistakes. Thanks, Spoiler // Pull Rotation... internal void dotRotation() { IEnumerable<WoWUnit> unitsToDot = ObjectManager.GetObjectWoWUnit().Where(u => u.IsTargetingMeOrMyPet && (!u.HaveBuff("Corruption") || !u.HaveBuff("Curse of Agony") || !u.HaveBuff("Immolate"))); foreach (WoWUnit unit in unitsToDot) { if (ObjectManager.Me.Target != unit.Guid) { Interact.InteractGameObject(unit.GetBaseAddress); } if (!ObjectManager.Target.HaveBuff("Corruption")) { Corruption.Launch(); Thread.Sleep(Usefuls.Latency + 1200); return; } if (!ObjectManager.Target.HaveBuff("Curse of Agony")) { CurseofAgony.Launch(); Thread.Sleep(Usefuls.Latency + 1200); return; } if (!ObjectManager.Target.HaveBuff("Immolate") && !ObjectManager.Me.IsCast) { Immolate.Launch(); Thread.Sleep(Usefuls.Latency + 1200); return; } return; } // Rest of rotation once no dot targets are available... Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/ Share on other sites More sharing options...
Seminko 40 Posted November 18, 2017 Share Posted November 18, 2017 So it correctly loops through all targets, refreshes Corruption, CoA and Immolate, but once Immolate is applied it casts it again? Just out of curiosity, what does Immolate.Launch() do? Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35273 Share on other sites More sharing options...
Lockem 1 Posted November 18, 2017 Author Share Posted November 18, 2017 Yes, it loops through all targets attacking me or my pet, applies all 3 dots to each of them and then moves on with the rotation. The problem is it always double casts Immolate... like this: Corruption > CoA > Immolate x2 > Switch targets > Corruption > CoA > Immolate x2 > Rest of rotation. Immolate.Launch() is how I'm casting. Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35274 Share on other sites More sharing options...
Seminko 40 Posted November 19, 2017 Share Posted November 19, 2017 4 minutes ago, Lockem said: Immolate launch is how I'm casting. Right... Hmmm, that's strange. Since you're looping through all the targets and you're not using while but rather if for the spell cast I can't image how it can cast twice. Basically: Does it have Corruption no cast it Does it have CoA no cast it Does it have Immolate no cast it Loop for that specific mob ended, whether the immolate has been successfully cast or not Switching targets BTW, do you use OnFightLoop? Can you share where is dotRotation() being called from? The more code you post the better. Going to sleep, it's 1AM here :) Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35275 Share on other sites More sharing options...
Lockem 1 Posted November 19, 2017 Author Share Posted November 19, 2017 Quote Basically: Does it have Corruption no cast it Does it have CoA no cast it Does it have Immolate no cast it Loop for that specific mob ended, whether the immolate has been successfully cast or not Switching targets Not exactly... it will make sure it actually puts immolate up, It's just that it always double casts it even if its on the target. It seems like its looping through dotRotation() while casting the immolate and it thinks it still needs immolate. Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35279 Share on other sites More sharing options...
Seminko 40 Posted November 19, 2017 Share Posted November 19, 2017 I should have said: "whether the immolate has been successfully APPLIED or not". BTW, how does it make sure it actually puts immolate up? On vanilla where we do SpellManager.CastSpellByNameLUA("Immolate"); it doesn't actually check whether it has been applied. It starts casting Immolate but if I cancel the cast, that's it. I pressume that Spell.Launch(); acts the same way. This is a longshot but try using List instead of IEnumerable. List<WoWUnit> unitsToDot = ObjectManager.GetObjectWoWUnit().Where(u => u.IsTargetingMeOrMyPet && (!u.HaveBuff("Corruption") || !u.HaveBuff("Curse of Agony") || !u.HaveBuff("Immolate"))); Also, don't know how you FC is set up but I pressume you only want dotRotation() to be applied on the mobs you are already in fight with? EDIT: and again --> Can you share where is dotRotation() being called from and when? The more code you post the better. Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35300 Share on other sites More sharing options...
Lockem 1 Posted November 19, 2017 Author Share Posted November 19, 2017 UPDATE: I'm 95% sure this problem only occurs when the bot is fighting a single mob... I could fix it by doing a count and adding a separate single target dot rotation, but I'd rather not, and I'm curious as to why this is happening. For testing purposes I removed dotRotation() and just made the dots the only thing in my combat rotation. The problem still happens... It seriously seems like the bot is checking for immolate while immolate is being cast and so it "pre-casts" it. Things I've tried: tweaking latency in General Settings (I normally have 90ms) limiting my framerate to 64fps removing all sleeps adding sleeps adding a timer to immolate Where I'm calling CombatRotation() Spoiler internal void Rotation() { Logging.Write("[My fightclass] Is started."); while (_isLaunched) { try { if (Conditions.InGameAndConnectedAndAliveAndProductStartedNotInPause && !ObjectManager.Me.IsDeadMe) { if (Fight.InFight || Conditions.IsAttackedAndCannotIgnore) { MovementManager.Face(wManager.Wow.ObjectManager.ObjectManager.Target); PetAggro(); CombatRotation(); } else { if (ObjectManager.Target.Reaction != Reaction.Friendly && ObjectManager.Target.IsAttackable && ObjectManager.Target.GetDistance <= Range) { CombatRotation(); } PetManager(); BuffRotation(); Healthstone(); } } } catch (Exception e) { Logging.WriteError("[My fightclass] ERROR: " + e); } Thread.Sleep(100); } Logging.Write("[My fightclass] Is now stopped."); } My new mult-dot code (I wanted to be able to use .Count) - The Immolate double cast still exists. Spoiler internal void CombatRotation() { List<WoWUnit> unitsToDot = ObjectManager.GetObjectWoWUnit(); unitsToDot = unitsToDot.Where(u => u.IsAttackable && u.GetDistance <= Range && u.Reaction != Reaction.Friendly && u.HealthPercent >= 15 && (!u.HaveBuff("Corruption") || !u.HaveBuff("Curse of Agony") || !u.HaveBuff("Immolate"))) .OrderBy(u => u.Guid).ToList(); foreach (WoWUnit unit in unitsToDot) { if (ObjectManager.Me.Target != unit.Guid) { Interact.InteractGameObject(unit.GetBaseAddress); } if (!ObjectManager.Target.HaveBuff("Corruption")) { Corruption.Launch(); Thread.Sleep(Usefuls.Latency + 1200); return; } if (!ObjectManager.Target.HaveBuff("Curse of Agony")) { CurseofAgony.Launch(); Thread.Sleep(Usefuls.Latency + 1200); return; } if (!ObjectManager.Target.HaveBuff("Immolate") && !ObjectManager.Me.IsCast) { Immolate.Launch(true); Thread.Sleep(Usefuls.Latency + 1200); return; } return; } if (DrainSoul.KnownSpell && !ObjectManager.Target.HaveBuff("Drain Soul") && ItemsManager.GetItemCountByNameLUA("Soul Shard") < 5 && ObjectManager.Target.HealthPercent < 15) { DrainSoul.Launch(true); } if (DrainLife.KnownSpell && ObjectManager.Me.HealthPercent <= 60) { DrainLife.Launch(true); } } Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35349 Share on other sites More sharing options...
Seminko 40 Posted November 19, 2017 Share Posted November 19, 2017 Well first thing I would do I set up Logging.Write inside your methods so you know when Immolate is cast, under what conditions etc. Also, howbout, just for the sake of testing, you did: if (!ObjectManager.Target.HaveBuff("Immolate")) { Immolate.Launch(); while (!ObjectManager.Target.HaveBuff("Immolate")) { Thread.Sleep(50); } Thread.Sleep(Usefuls.Latency + 1200); return; } EDIT: since you updated the previous post I'm removing all the stuff that was below... Still am curious what happens if you use the above code Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35352 Share on other sites More sharing options...
Lockem 1 Posted November 19, 2017 Author Share Posted November 19, 2017 Quote if (!ObjectManager.Target.HaveBuff("Immolate")) { Immolate.Launch(); while (!ObjectManager.Target.HaveBuff("Immolate")) { Thread.Sleep(50); } Thread.Sleep(Usefuls.Latency + 1200); return; } This fixes the problem completely. Weird... thanks! Still curious why the problem occurred in the first place. Also, my target switching is a little 'jittery'... mind giving me an example of how OnFightLoop would work for target switching? Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35354 Share on other sites More sharing options...
Seminko 40 Posted November 20, 2017 Share Posted November 20, 2017 So we've gone full circle :). Basically, the way I understand it, there are FightEvents which handle targetting (and probably more) which you cannot influence or control from within your fightclass - UNLESS when actually using events - OnFightStart, OnFightLoop or OnFightEnd. So when we use OnFightLoop it will loop independently of your default combat roration. In the OnFightLoop I would only handle targetting and the rest in my combat rotation. It's up to you to come up with the logic. Here's what I think might work - not tested, since I don't have a Lock. This should provide you all of the building blocks to fine tune it to your liking. Spoiler public Spell Corruption = new Spell("Corruption"); public Spell CoA = new Spell("Curse of Agony"); public Spell Immolate = new Spell("Immolate"); public Spell DrainSoul = new Spell("Drain Soul"); public Spell DrainLife = new Spell("Drain Life"); public void Initialize() // When product started, initialize and launch Fightclass { _isLaunched = true; targetSwitcher(); // calling it here, once called it will register the OnFightLoop and will do that without calling it again (in combat obviously) Start(); } private void targetSwitcher() { FightEvents.OnFightLoop += (unit, cancelable) => { WoWUnit targetToSwitchTo = ObjectManager.GetUnitAttackPlayer().Where(u => u.IsValid && u.GetDistance <= Range && u.HealthPercent >= 15 && (!u.HaveBuff("Corruption") || !u.HaveBuff("Curse of Agony") || !u.HaveBuff("Immolate"))).OrderBy(ou => ou.HealthPercent).FirstOrDefault(); if (targetToSwitchTo.IsValid && ObjectManager.Target.HaveBuff("Corruption") && ObjectManager.Target.HaveBuff("Curse of Agony") && ObjectManager.Target.HaveBuff("Immolate")) // if the target you want to switch to is valid AND your CURRENT target has all of the three buffs, it will switch and stay on the target until it has all of the three buffs, etc etc { Interact.InteractGameObject(targetToSwitchTo.GetBaseAddress); } }; } private void combatRotation() { if (!ObjectManager.Target.HaveBuff("Corruption") && Corruption.IsSpellUsable) // important part that you were missing - IsSpellUsable { SpellManager.CastSpellByNameLUA("Corruption"); //or Launch, if CastSpellByNameLUA is not usable for TBC return; } else if (!ObjectManager.Target.HaveBuff("Curse of Agony") && CoA.IsSpellUsable) { SpellManager.CastSpellByNameLUA("Curse of Agony"); return; } else if (!ObjectManager.Target.HaveBuff("Immolate") && Immolate.IsSpellUsable) { SpellManager.CastSpellByNameLUA("Immolate"); return; } else if (DrainSoul.KnownSpell && !ObjectManager.Target.HaveBuff("Drain Soul") && ItemsManager.GetItemCountByNameLUA("Soul Shard") < 5 && ObjectManager.Target.HealthPercent < 15 && DrainSoul.IsSpellUsable) { SpellManager.CastSpellByNameLUA("Drain Soul"); return; } else if (DrainLife.KnownSpell && ObjectManager.Me.HealthPercent <= 60 && DrainLife.IsSpellUsable) { SpellManager.CastSpellByNameLUA("Drain Life"); return; } return; } private void Start() { while (_isLaunched) { if (Fight.InFight && ObjectManager.Me.Target > 0 && !Products.InPause && !ObjectManager.Me.IsDeadMe) { combatRotation(); } Thread.Sleep(50); } } Btw, you're posting in the retail version of the forums. There is a dedicated forum for TBC help and support. Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35388 Share on other sites More sharing options...
Matenia 629 Posted November 20, 2017 Share Posted November 20, 2017 OnFightLoop doesn't actually loop anything. It's a function that is contiously called (like maybe 10 times a second - probably one per new frame, so 60 times per second). You are registering an event handler that is called from within wRobot code, by another wRobot spawned thread. So think of it this way: //wRobot code calls fight stuff here List<EventHandler> OnFightLoopEventHandlers; Target(unit); //puts it in ObjectManager.Target, targets it ingame etc while(true){ Execute(combatRotation); //for XML fightclasses or something foreach(handler in OnFightLoopEventHandlers){ handler.call(unit, cancelable); } Thread.Sleep(50); } //more wRobot code here Of course this is pseudo code. But if you call Thread.Sleep and keep the thread locked in a while loop within one of the OnFightLoopEventHandlers, then obviously the bot can't call Target(unit) again (assuming my pseudo code is called again and again as well). So you're really just blocking default behavior of the bot through event handlers that aren't executed asynchronously. Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35390 Share on other sites More sharing options...
Seminko 40 Posted November 20, 2017 Share Posted November 20, 2017 So in layman's terms, it's looping :-P in profi terms, it's being called continuously... in a loop :-D Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35392 Share on other sites More sharing options...
Lockem 1 Posted November 20, 2017 Author Share Posted November 20, 2017 Thanks for your help guys! I'll put something together when I'm off work and let you know how it goes. Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35423 Share on other sites More sharing options...
Lockem 1 Posted November 20, 2017 Author Share Posted November 20, 2017 Just wanted to give you guys an update... @Seminko Using the OnFightLoop for targeting worked perfectly! As for immolate being double cast, it seems to be a pretty common problem with heals and some spells with a cast time... The best solution I could find was adding a timer + delay to Immolate. If you can think of a better way of doing this I would love to know. Again, thanks for all the help! Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35457 Share on other sites More sharing options...
Matenia 629 Posted November 21, 2017 Share Posted November 21, 2017 8 hours ago, Lockem said: Just wanted to give you guys an update... @Seminko Using the OnFightLoop for targeting worked perfectly! As for immolate being double cast, it seems to be a pretty common problem with heals and some spells with a cast time... The best solution I could find was adding a timer + delay to Immolate. If you can think of a better way of doing this I would love to know. Again, thanks for all the help! Thanks for the response. I just had the same issue on Vanilla recently. Even though I managed to target -> cast -> target last target within a split second, it would sometimes really mess up targeting and just go back and forth too many times. The way I solved it now is to add a boolean to an OnFightLoop handler that (just for the time I need to target -> target -> target) blocks the OnFightLoop wRobot runs. Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35463 Share on other sites More sharing options...
azharkhoir 0 Posted November 21, 2017 Share Posted November 21, 2017 ok gooodd Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35470 Share on other sites More sharing options...
Lockem 1 Posted November 22, 2017 Author Share Posted November 22, 2017 So after some more research / tweaking I'm about 99.9% sure I've fixed my double Immolate problem for good... private bool ImmoCast; // Immolate if (!GcdActive && Immolate.KnownSpell && Immolate.IsSpellUsable && Immolate.IsDistanceGood && !ObjectManager.Me.IsCast && !ObjectManager.Target.HaveBuff("Immolate")) { ImmoCast = true; if (ImmoCast == true) { Immolate.Launch(true, false); Thread.Sleep(SpellManager.GetSpellCooldownTimeLeft(61304)); <-- This seemed to be the key part to fixing it. I originally had a 3500ms sleep... ImmoCast = false; that obviously caused other problems, this sleep if for the remaining GCD. } } This post was a good read... specifically the comments by @reapler Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35526 Share on other sites More sharing options...
becorath 0 Posted November 28, 2017 Share Posted November 28, 2017 I'm not sure with current Wow, because I am just now getting into programming fight classes again, but I remember in the past that "flight times" for spells could be an issue as well as the fact that some spells aren't seen until they tick once. This was an old problem, so it may not be relevant anymore, but something to look at. Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-35891 Share on other sites More sharing options...
kergudu 2 Posted December 7, 2017 Share Posted December 7, 2017 instead of Thread.Sleep(...) try to use wManager.Wow.Helpers.Usefuls.WaitIsCasting() Sleep rotation for long time is not good, and with this function you alwais can break cast and start another spell. Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-36354 Share on other sites More sharing options...
kergudu 2 Posted December 10, 2017 Share Posted December 10, 2017 My variant (attacks only units in front of player +-90 degrees): public bool multiDot(string spell,int distance){ WoWUnit target = ObjectManager.GetWoWUnitHostile() .Where(o => o.IsAlive && o.IsValid && !o.HaveBuff(spell) && o.GetDistance <= distance) .OrderBy(o => o.Health) .FirstOrDefault(); WoWUnit oldFocus = ObjectManager.Target; if (target != null) { if (!MovementManager.IsFacing(ObjectManager.Me.Position, ObjectManager.Me.Rotation, target.Position, 1.6f)) return false; Interact.InteractGameObject(target.GetBaseAddress, true); SpellManager.CastSpellByNameOn(spell, "focus"); Usefuls.WaitIsCasting(); Interact.InteractGameObject(oldFocus.GetBaseAddress, true); return true; } return false; } Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-36458 Share on other sites More sharing options...
adultperson 3 Posted February 2, 2018 Share Posted February 2, 2018 Lokem what code did you end up with? Presumed you eventually manage to fix it. Link to comment https://wrobot.eu/forums/topic/7720-problems-with-mult-dots/#findComment-38814 Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now