-
Posts
288 -
Joined
-
Last visited
Content Type
Forums
Articles
Bug Tracker
Downloads
Store
Posts posted by reapler
-
-
So i've researched a bit, because i'm not .xml fan :)
This snippet can be pasted, if you add a new condtion on your spell with "C Sharp Code" in the right pane on the textbox "Value":
Lua.LuaDoString<bool>(@" for i=1,25 do local _, _, _, _, d = UnitDebuff('player',i); if d == 'Poison' then return true end end")
-
Hello, i guess you need this in .xml fightclass? If yes you may specify what it should return or in which context you need this.
-
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
-
So how your "new Spell("").Launch();" call look like in your "UseSpell"?
-
I think you need to provide me the header of your "UseSpell" method before i can give a well answer. it could be look like this:
public void UseSpell(bool stopMove, bool waitIsCast = true, bool ignoreIfCast = false)
-
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 }
-
7 hours ago, lonellywolf said:
It seems like no matter what I put in there, the plugin still do the same movements. It does not follow what I put in there. And when I open it back again, it has all that stuff written from the first time.
https://wrobot.eu/files/file/303-move-during-combat/?tab=comments#comment-4431
-
11 minutes ago, Apexx said:
Thanks! So guess something like the following will work alright?
Thread.Sleep(_r.Next(300, 650)); Revenge.Launch();
Yep
-
@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.
-
Hello @Apexx, so you would like to only delay the current cast or has it a special reason to do that?
Otherwise you can still use Thread.Sleep() if the fightclass shouldn't execute anything (for a small time / simple task it's ok i guess).
-
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.
-
-
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.
-
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 { //... }
-
45 minutes ago, pookasmight said:
I get an error that says [string "KJIRFYNIY.lua"]:1: attempt to call global "CancelUnitBuff' (a nil value). Any ideas?
Forgot that you are playing on vanilla, so "CancelUnitBuff" doesn't exist in the api.
I replaced it just with another cast: StealthOnNearbyPlayers+stopfishing.xml
-
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();".
-
@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.
-
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"); }
-
-
-
Hello, you might try
-
@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 }
-
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).
-
By the way did you alter the the attached xml in order to resolve the error? if yes please attach it here since i don't have a vanilla client & can't see occurring erros
[Solved] How to detect debuff Type ?
in WRobot for Wow The Burning Crusade - Help and support
Posted
Yep, that's not a secret that i love c# ;)
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.