Jump to content

reapler

Elite user
  • Posts

    288
  • Joined

  • Last visited

Posts posted by reapler

  1. 4 minutes ago, iMod said:

    EDIT: Nvm reapler still wrote that it is c# code :laugh:

    Yep, that's not a secret that i love c# ;)

    13 minutes ago, lonellywolf said:

    This didn't work..Sorry for the trouble my friend and I appreciate your help.

    I've tried on wotlk, it works flawless: Abolish Poison test.xml

    Dunno how it will work on tbc, but in the wow api i haven't found any considerable changes.

  2. Personally i wouldn't use a timer like this. It's better to bind a timer on "SPELL_CAST_SUCCESS" with events and add delay on it(the purpose was another).

    To your problem:

    Your "spell.Launch(stopMoving);" in the method is causing now a own loop, because the parameter "waitIsCast is set to true".

    This means while you are casting holylight, and you have no conditions to check your current cast, then the next call of "UseSpell()" will be executed.

    If it's called and the character is still casting holy light, it will wait til the current cast is finished. If it's finished the loop in ".Launch();" will break and execute another "SpellManager.CastSpellByNameLUA(this.NameInGame);"

    Maybe also add "!ObjectManager.Me.IsCast" otherwise if the character is still casting another unnecessary spell, you may need to add the mentioned timer or reduce tickspeed of your rotation.

    If you would like to add the timer, feel free to ask.

     

    Edit:

    solution would be "spell.Launch(stopMoving, false);" instead of the other launch call

  3. Hello, you can use the "ObjectManager" and filter it with linq.

    I guess it will be used often, so I've made a method for it:

        /// <summary>
        /// Get attacking units from another unit
        /// </summary>
        /// <param name="from">Take hostile units from this unit</param>
        /// <param name="maxRange">Take hostile units within this range</param>
        /// <returns></returns>
        public List<WoWUnit> AttackingUnits(WoWUnit from, float maxRange = 10)
        {
            return ObjectManager.GetWoWUnitHostile().Where(i =>
                from.Guid == i.TargetObject.Guid
                && from.Position.DistanceTo(i.Position) <= maxRange
            ).ToList();
        }

    and use it in another method:

                if (condition1
                    && ...
                    && AttackingUnits(ObjectManager.Me, 15).Count < 3
                    )
                {
                    //cast spell
                }

     

  4. @Apexx At your case i would use Thread.Sleep() since, you would need to block your rotation for a short time (but make sure that  the ability is really usable).

    If you would use:

                var t = Task.Run(async delegate
                {
                    await Task.Delay(1600);
    				//cast spell
                });

    It will be triggered more than one time if you have a reactive fightclass. So you would need then a boolean to check if any spells are going to be executed.

    But instead of building such a system, which has most likely the same effect like a sleep, just use a sleep instead.

    There are may scenarios which still need an active loop in fightclasses for example you have a status bar of all enemy players which updates with each loop(~100ms) so a sleep(long or short) would cause to delay also this update of the bar.

    So in my eyes Task.Run would be worth if you want explicit to run the thread without lockouts.

    In your case i wouldn't mind that, events like "EventsLuaWithArgs.OnEventsLuaWithArgs" are still working so you could theoretically interrupt the enemy cast even on a sleeping thread.

    As i mentioned it's not a big issue to use a sleep here for this short time = > droidz example

    At the end you can also do a check if it's still clever to cast this spell:

    For example you have an heal rotation and casting a heal on a 100% health target & bot doesn't interrupt that, because you aren't checking after the cast. With the events you can also check if someone is already casting a heal, on your heal target, so your rotation wouldn't try that.

     

    OR you can simply put the tickspeed lower at your fightclass:

            var timer = new Timer(1000);//tickspeed
            timer.ForceReady();
            while (_isLaunched)
            {
                try
                {
                    if (
    		Conditions.ProductIsStartedNotInPause
            	&& timer.IsReady
    		//&& condition3
    		)
                    {
                        //do something every 1 sec
                    }
                }
                catch (Exception e)
                {
                    Logging.WriteError(e.ToString());
                }
                Thread.Sleep(30);
            }

    You can also use other examples with a sleep instead of the timer (i don't think that it will change anything).

    You may also add some other conditions this one is just a template on initialize.

  5. 1 hour ago, Apexx said:

    I don't mind having it there, just not spamming every time is runs the check inside my class.

    
    internal void BuffRotation()
        {
            if (ObjectManager.Me.IsMounted)
                return;
    
    	// Check Stance 
        }
    
    if (GetActiveStance().Id != 71 && player.IsInGroup) 
    {
    	if (DefensiveStance.KnownSpell && DefensiveStance.IsSpellUsable && player.IsInGroup)
      	{
          		DefensiveStance.Launch();
          		return;
      	}
    }

     

    This snippet should not throw any logs except of "DefensiveStance.Launch();" (tried on plugin). So i guess it's some internal behavior from WRobot itself.

    I've also experienced similar situations with .xml fightclass' spamming log (was well configured), but so far i know you can't change this yourself.

  6. 2 hours ago, pookasmight said:

    Hey thanks a lot for helping me with this but it's still not working right. the bot senses a player and stealths but immediately breaks the stealth and goes back to fishing. When the stealth cool down runs out it pops stealth again to only break again with a fish cast. it'll just keep doing this over and over. 

    i belive i know what's wrong, but please attach a log first, since it worked on 3.3.5a.

    3 hours ago, Marsbar said:

    This is cool, but wouldn't it be better as a plugin rather than a fight class? Then again you'd hope no one would attack you and no mobs would be close enough to aggro anyway.

    Of course, initially i wanted to add more features but i don't have time yet.

  7. Hello, i've made a few methods for this purpose( @Droidz contributed some parts ):

        public List<string> GetStanceNames()
        {
            return Lua.LuaDoString<List<string>>(@"local r = {}
                                                for i=1,10 do 
    	                                            local _, n = GetShapeshiftFormInfo(i);
    	                                            if n then table.insert(r, tostring(n)); end
                                                end
                                                return unpack(r);") ?? new List<string>();
        }
        
        public List<Spell> GetStanceSpells()
        {
            List<Spell> sp = new List<Spell>();
            foreach (var s in Lua.LuaDoString<List<string>>(@"local r = {}
                                                for i=1,10 do 
    	                                            local _, n = GetShapeshiftFormInfo(i);
    	                                            if n then table.insert(r, tostring(n)); end
                                                end
                                                return unpack(r);") ?? new List<string>())
            {
                sp.Add(new Spell(s));
            }
            return sp;
        }
    
        public Spell GetActiveStance()
        {
            return new Spell(Lua.LuaDoString<List<string>>(@"local r = {}
                                                for i=1,10 do 
    	                                            local _, n, a = GetShapeshiftFormInfo(i);
    	                                            if a then table.insert(r, tostring(n)); end
                                                end
                                                return unpack(r);").FirstOrDefault() ?? "");
        }

    Usage:

                Logging.Write(GetActiveStance().Id.ToString());
                if (GetActiveStance().Id == 2458)//berserker stance
                {
                    //...
                }

     

  8. Hello, this snippet should work but Thread.Sleep will locking your rotation. I recommend to use "EventsLuaWithArgs.OnEventsLuaWithArgs" & "Task.Run" to also checking more enemies at the same time:

        private readonly Spell _shieldBash = new Spell("Shield Bash");
        private readonly Random _r = new Random();
    
        private void EventsLuaWithArgsOnOnEventsLuaWithArgs(LuaEventsId id, List<string> args)
        {
            if (id == LuaEventsId.COMBAT_LOG_EVENT_UNFILTERED && args[1] == "SPELL_CAST_START")
            {
                ulong guid;
                ulong.TryParse(args[2].Replace("x", string.Empty), System.Globalization.NumberStyles.HexNumber, null, out guid);
                var caster = (WoWUnit) ObjectManager.GetObjectByGuid(guid);
                if (
                    caster.Reaction < Reaction.Neutral && 
                    _shieldBash.KnownSpell
                    )
                {
                    Interrupt(_shieldBash, caster, _r.Next(150, ((int)caster.CastingSpell.CastTime-200)*1000));
                }
            }
        }
        
        private void Interrupt(Spell spell, WoWUnit caster, int interruptTime)
        {
            Task.Run(delegate
            {
                while (caster.CastingTimeLeft != 0  && Products.IsStarted)
                {
                    Logging.Write("CastingTimeLeft: "+caster.CastingTimeLeft +"ms\nInterrupt at: "+interruptTime+"ms");
                    if (caster.CastingTimeLeft > interruptTime
                        && caster.GetDistance < _shieldBash.MaxRange
                        && _shieldBash.IsSpellUsable
                        && SpellManager.GetSpellCooldownTimeLeft(_shieldBash.Id) == 0
                        && caster.CanInterruptCasting
                    )
                    {
                        Logging.Write("Interrupt with " + spell.Name);
                        //cast without targeting behavior
                        var tmp = ObjectManager.Me.FocusGuid;
                        ObjectManager.Me.FocusGuid = caster.Guid;
                        spell.Launch(false, false, false, "focus");
                        ObjectManager.Me.FocusGuid = tmp;
                    }
                    Thread.Sleep(300);
                }
            });
        }
    
        public void Initialize()
        {
            EventsLuaWithArgs.OnEventsLuaWithArgs += EventsLuaWithArgsOnOnEventsLuaWithArgs;
            //...
        }

    This is not fully tested, otherwise you can also play around with other parameters & at problems it's a good idea to use "Logging.Write();".

  9. @apexx Namespace System.Linq is not referenced. So you need to copy this on the top of your code:

    using System.Linq;

    Both .Where() & .Count() are included in Linq, that's the reason why .Count() couldn't work because it doesn't had an overload available.

    So in the end you can use this:

                if (ObjectManager.GetUnitAttackPlayer().Count(u => u.GetDistance <= 6) > 2)
                {
                }

    Or use other Linq methods.

  10. Hello, for this purpose you need a stopwatch and events:

    
        private readonly Stopwatch _combatTimer = new Stopwatch();
    
    
        public void Initialize()
        {
            EventsLua.AttachEventLua(LuaEventsId.PLAYER_REGEN_DISABLED, CombatStart);
            EventsLua.AttachEventLua(LuaEventsId.PLAYER_REGEN_ENABLED, CombatEnd);
        }
    
    
        private void CombatStart(object context)
        {
            _combatTimer.Restart();
        }
    
    
        private void CombatEnd(object context)
        {
            _combatTimer.Reset();
        }

    usage in a method for example:

            if (_combatTimer.ElapsedMilliseconds > 8000)
            {
                Logging.Write("In combat since 8 seconds");
            }

     

  11. @pookasmight the last part would take take too much effort on fightclass. But this should be fine: StealthOnNearbyPlayers+stopfishing.xml

    New part looks like this:

    //C# Fish block on Stealth
                if (wManager.Statistics.RunningTimeInSec() < 2)
                {
                    robotManager.Helpful.Logging.Write("Register OnFishingPulse");
                    wManager.Events.FishingEvents.OnFishingPulse += delegate(ulong node, CancelEventArgs cancelable)
                    {
                        if (ObjectManager.Me.HaveBuff("Stealth"))
                        {
                            cancelable.Cancel = true;
                        }
                    };
                    robotManager.Helpful.Logging.Write("Register OnFishLoop");
                    wManager.Events.FishingEvents.OnFishLoop += delegate(ulong node)
                    {
                        while (ObjectManager.Me.HaveBuff("Stealth") && !robotManager.Products.Products.InPause)
                        {
                            Thread.Sleep(50);
                        }
                    };
                    System.Threading.Thread.Sleep(2000);//to initialize event only once on startup
                }

     

  12. Hello @Ke1ka, i had also problems to getting a list from party, so i made a similar method to acquire a general list from objectmanager:

    If a hostile npc doesn't target the tank (not tested):

        public static List<WoWUnit> GetNoAggroUnits(float range)
        {
            WoWLocalPlayer me = ObjectManager.Me;
            List<WoWUnit> u = new List<WoWUnit>();
            Parallel.ForEach(ObjectManager.GetWoWUnitHostile(), delegate(WoWUnit unit)
            {
                if (unit.Target != me.Guid
                && unit.Target != 0
                && unit.InCombat
                && unit.IsAlive
                && unit.GetDistance < range
                && !TraceLine.TraceLineGo(unit.Position, me.Position)) //slow part
                {
                    u.Add(unit);
                }
            });
            return u.OrderBy(i => i.TargetObject.HealthPercent).ToList();//first object in the returned list will contain the target with the lowest health
        }

    You could also do something like this:

        public static List<WoWUnit> GetNoAggroUnitsExplicit(float range)
        {
            WoWLocalPlayer me = ObjectManager.Me;
            var u = new List<WoWUnit>();
            var p = ObjectManager.GetObjectWoWPlayer().Where(woWPlayer => woWPlayer.PlayerFaction == me.PlayerFaction && woWPlayer.IsAlive).Select(i => i.Guid);
            Parallel.ForEach(ObjectManager.GetWoWUnitHostile(), delegate (WoWUnit unit)
            {
                if (p.Contains(unit.Target)
                && unit.Target != 0
                && unit.InCombat
                && unit.IsAlive
                && unit.GetDistance < range
                && !TraceLine.TraceLineGo(unit.Position, me.Position)) //slow part
                {
                    u.Add(unit);
                }
            });
            return u.OrderBy(i => i.TargetObject.HealthPercent).ToList();
        }

    But i don't think that's necessary, except you would use a party / raid list as "p" (which didn't worked for me last time).

×
×
  • Create New...