Findeh 34 Posted July 15, 2017 Share Posted July 15, 2017 Good day. Sorry in advance for my english, it's far not my native language. Searched forum for a while, but still can't find detailed information about handwriting FightClass. Maybe it's because i'm new here, or just because i'm dumb. I'd like to use C#, where can i get more detailed api for it? For example, i'd like to write some custom functions for a bot, like this: 1) Override Eat function inside the bot. I'd like to force him check an inventory and eat first available food from the list, that is hardcoded inside the FC. 2) While in combat, check inventory for an item, and if it's available, use it. For example, if bot hp <= 15% && bot got "Healing potion" then bot use "Healing potion" 3) Check target health (not percent, but a number of health that left) 4) Use some abilityes when bot goes to the vendor (for example use blink or sprint to speed that process) and then use this abilities when bot is going back to the profile. And maybe some others functions, depending on api. Is it even possible? Thank you for your answers and any advices. Link to comment Share on other sites More sharing options...
reapler 154 Posted July 15, 2017 Share Posted July 15, 2017 Welcome @Findeh to WRobot, you can find details & templates about fightclasses here. To get a detailed documentation, you can decompile WRobot's libraries here explained. 1 hour ago, Findeh said: 1) Override Eat function inside the bot. I'd like to force him check an inventory and eat first available food from the list, that is hardcoded inside the FC. For this task you could use "wManager.Events.FightEvents.OnFightEnd" 1 hour ago, Findeh said: 2) While in combat, check inventory for an item, and if it's available, use it. For example, if bot hp <= 15% && bot got "Healing potion" then bot use "Healing potion" A plugin already exists here 1 hour ago, Findeh said: 3) Check target health (not percent, but a number of health that left) "wManager.Wow.ObjectManager.ObjectManager.Me.TargetObject.Health" for futures requests you may search in your decompiler by looking for "health" for example 1 hour ago, Findeh said: 4) Use some abilityes when bot goes to the vendor (for example use blink or sprint to speed that process) and then use this abilities when bot is going back to the profile. Unfortunately no event exists. But you can check it on a loop: "wManager.Wow.Bot.States.ToTown.GoToTownInProgress" Findeh 1 Link to comment Share on other sites More sharing options...
Findeh 34 Posted July 16, 2017 Author Share Posted July 16, 2017 Thanks alot for your answer, it was really wery helpful. Seems like i did almost every function i need, but still few remain. Maybe again it's my stupidity. 1) I was not able to find how do i get spell rank (level). For example, i want to count how many damage spell will do, depending on it's rank. To know will it kill the target, or will it not. Am i able to get spell rank somehow, or make it work any other way maybe? 2) This will be a wery stupid one. I don't get, how some events works. I'm decompiling wManager with ILSpy. Going to wManager/wMnager.Events/ and can't understand the order they are triggering each other at. For example, if i got "internal void BuffRotation()" class inside my FC, will it use it only after the fight, or only during the fight, or maybe it will use it during patrol? 3) And this one even more stupider. About "wManager.Wow.Bot.States.ToTown.GoToTownInProgress" If i get it right, i am able to chek it? Like this for example? if (Me.States.ToTown.GoToTownInProgress && SpellName.IsSpellUsable) { SpellName.Launch(); return; } But bot will not use "SpellName" anyway because there is no such event where i can place it? Right? Thanks alot for any advices or hints. And once again, sorry for my english. Link to comment Share on other sites More sharing options...
reapler 154 Posted July 16, 2017 Share Posted July 16, 2017 1 hour ago, Findeh said: 1) I was not able to find how do i get spell rank (level). For example, i want to count how many damage spell will do, depending on it's rank. To know will it kill the target, or will it not. Am i able to get spell rank somehow, or make it work any other way maybe? Logging.Write(Lua.LuaDoString<string>("name, rank, icon, castTime, minRange, maxRange = GetSpellInfo(\"Shadow Word: Pain\")", "rank")); Can be used. But i guess you could also need "desc = GetSpellDescription(spellId)" but unfortunately for me it doesn't return any string to parse the damage values. 1 hour ago, Findeh said: 2) This will be a wery stupid one. I don't get, how some events works. I'm decompiling wManager with ILSpy. Going to wManager/wMnager.Events/ and can't understand the order they are triggering each other at. For example, if i got "internal void BuffRotation()" class inside my FC, will it use it only after the fight, or only during the fight, or maybe it will use it during patrol? Ok let's take FightEvents. I linked a fightclass which has "internal void BuffRotation()" on a loop. Once "public void Initialize()" is called from the interface(start bot), it will loop this method till you stop the bot. So that means the buffrotation aswell the other methods in your fightclass having no impact / affiliation on "FightEvents". The "FightEvents" or the other events in WRobot are triggered from the bot behavior itself (you can imagine like a guy reporting you what he's doing). So this "guy" tells you: I attack now this npc = "wManager.Events.FightEvents.OnFightStart" While fighting i also report whats going on every ~30ms = "wManager.Events.FightEvents.OnFightLoop" the fight is over = "wManager.Events.FightEvents.OnFightEnd" This is useful for plugins for example but if you are going to write a fightclass, you wouldn't really need it. If you want to write a plugin which uses an item or do other action after a fight end, you could subscribe it like this: wManager.Events.FightEvents.OnFightEnd += delegate { wManager.Wow.Helpers.SpellManager.CastSpellByIdLUA(8690); //cast hearthstone }; 1 hour ago, Findeh said: But bot will not use "SpellName" anyway because there is no such event where i can place it? Right? If you write an plugin you could use your snippet on a loop or by subscribing it to "wManager.Events.MovementEvents.OnMoveToPulse". But i guess you are writing a fightclass anyway, so you can put this snippet to buffrotation or directly to while loop: internal void BuffRotation() { if (ObjectManager.Me.IsMounted) return; //if not mounted cast sprint var spelltocast = new Spell("Sprint"); if (wManager.Wow.Bot.States.ToTown.GoToTownInProgress && spelltocast.IsSpellUsable) { spelltocast.Launch(); } } or directly in while loop: internal void Rotation() { Logging.Write("[My fightclass] Is started."); while (_isLaunched) { try { if (!Products.InPause) { if (!ObjectManager.Me.IsDeadMe) { BuffRotation(); var spelltocast = new Spell("Sprint"); if (wManager.Wow.Bot.States.ToTown.GoToTownInProgress && spelltocast.IsSpellUsable && !ObjectManager.Me.IsMounted) { spelltocast.Launch(); } if (Fight.InFight && ObjectManager.Me.Target > 0) { Pull(); CombatRotation(); } } } } catch (Exception e) { Logging.WriteError("[My fightclass] ERROR: " + e); } Thread.Sleep(10); // Pause 10 ms to reduce the CPU usage. } Logging.Write("[My fightclass] Is now stopped."); } So you can see in the end it doesn't really matter. It's just for a better structure & readability. Findeh 1 Link to comment Share on other sites More sharing options...
iMod 99 Posted July 16, 2017 Share Posted July 16, 2017 Some event samples #region Events // Listen to events EventsLuaWithArgs.OnEventsLuaWithArgs += delegate (LuaEventsId id, List<string> args) { #region PLAYER_REGEN_ENABLED if (id == LuaEventsId.PLAYER_REGEN_ENABLED) { Functions.InCombat = false; } if (id == LuaEventsId.PLAYER_REGEN_DISABLED) { Functions.InCombat = true; } #endregion #region MODIFIER_STATE_CHANGED if (id == LuaEventsId.MODIFIER_STATE_CHANGED && args.Count == 2) { // Possible values are LSHIFT, RSHIFT, LCTRL, RCTRL, LALT, and RALT string key = args[0]; // 1 means that the the key has been pressed. 0 means that the key has been released int state = int.Parse(args[1]); // AOE mode if (key == "LALT" && state == 0) { // Set status rotation.AoeMode = !rotation.AoeMode; // Write to chat string message = $"iRotation AoeModes: {(rotation.AoeMode ? "|cFF00FF00On.|r" : "|cFFFF0000Off.|r")}"; Lua.LuaDoString($"print(\"{message}\")"); } // Burst mode if (key == "LCTRL" && state == 0) { // Set status rotation.BurstMode = !rotation.BurstMode; // Write to chat string message = $"iRotation BurstMode: {(rotation.BurstMode ? "|cFF00FF00On.|r" : "|cFFFF0000Off.|r")}"; Lua.LuaDoString($"print(\"{message}\")"); } } #endregion }; #endregion Findeh 1 Link to comment Share on other sites More sharing options...
Findeh 34 Posted July 16, 2017 Author Share Posted July 16, 2017 You have convinced me. For items use, i'll better write a plugin separately from the Fight Class. Thank you. Seems like did evrithing except one thing, thank to your answers. Much appreciate it. Thing that i stuck at is Spell Rank. Seems like i'm just handicapped. What this string should return? 3 hours ago, reapler said: Logging.Write(Lua.LuaDoString<string>("name, rank, icon, castTime, minRange, maxRange = GetSpellInfo(\"Shadow Word: Pain\")", "rank")); If do understand it right, GetSpellInfo Will return SpellInfo object, that is, according to wManager/wManager.Wow.Class : public class SpellInfo { public uint ID; public string Name = ""; public string SubName = ""; public string Icon = ""; public int CastTime; public float MinRange; public float MaxRange; } Seems like i don't get it :( there is no spell rank field, anyway :( The goal is to calculate damage. I can make a table with all Spell damage numbers depending on it's rank. (Some damage are static in vanilla). Then all i need to get a current rank of the spell as an integer, then get a damage number for it from the table and compare that damage number with current health of the target. if (ObjectManager.Target.Health <= damage) we should use the spell. else we should not. This is a main thing i'm stuck at :( Can't solve it. I do need my rogue to know, should he use Eviscerate at 2 Combo Points and that will end the fight, or wait should it wait for 3 or for 4 and so on. As far as i see, most of rogue fight class that i am able to download, just use Eviscerate when reach some static combo point number (3 or 5) without any logic behind it. Link to comment Share on other sites More sharing options...
reapler 154 Posted July 16, 2017 Share Posted July 16, 2017 55 minutes ago, Findeh said: If do understand it right, GetSpellInfo Will return SpellInfo object, that is, according to wManager/wManager.Wow.Class : Yes, that's right but with my snippet you get a string from your spell with lua in this case: "Shadow Word: Pain". I made a simple method: public Spell Spell_(string name) => new Spell(name) { Icon = Lua.LuaDoString<string>( "name, rank, icon, castTime, minRange, maxRange = GetSpellInfo(\"" + name + "\")", "rank") }; This overrides "Icon" to spell's rank. I guess it's not added in vanilla, because it was forgotten as it was backported :) Usage: public void Initialize() { wManager.Wow.Class.Spell eviscerate = Spell_("Eviscerate"); robotManager.Helpful.Logging.Write("Get information of spell: " + eviscerate.Name); robotManager.Helpful.Logging.Write("Spell rank: "+eviscerate.Icon);//now field ".Icon" returns the rank if you use "public Spell Spell_(string name) => new Spell(name)" robotManager.Helpful.Logging.Write("Spell id: "+eviscerate.Id); } Findeh 1 Link to comment Share on other sites More sharing options...
Findeh 34 Posted July 17, 2017 Author Share Posted July 17, 2017 Thanks alot for your help and answers, but guess i'll give up soon. Can't make it work. Just getting a bunch of errors when i start it with this code. Additionally, trying to force it use some spells when there is 2 or more attackers around. Using constuction like this: // If we are under attack from 3 or more mobs use Adrenaline Rush if (ObjectManager.GetUnitAttackPlayer().Count(u => u.GetDistance <= 6) > 2) { if (AdrenalineRush.KnownSpell && AdrenalineRush.IsSpellUsable) { AdrenalineRush.Launch(); } } But then again, got an errors saying that .Count can't be used like that. Don't know why again, because there is no documentation. Addittionally my bots don't skin units, have tryed different min and max MS settings, 0-100, 30-50, 30-100, 300-500, even 100-1000, no result. No metter what FC am i using, mine one, or downloaded, my bots only autoattack and not using any spells. Again, i don't get why. Is it a trial version issue or what? If it's so, how am i able to understand will it do all i need him to do, or will it just move around botlike and autoattack till get banned in a hour, because it looks wery botish Link to comment Share on other sites More sharing options...
Findeh 34 Posted July 17, 2017 Author Share Posted July 17, 2017 I'm not familiar with c#, so maybe i just have to buy the Fight Class writing services, but then again, what should i do with the other bugs that i got. Link to comment Share on other sites More sharing options...
Apexx 60 Posted July 23, 2017 Share Posted July 23, 2017 It's funny, I was just trying to do something similar in C# wanting to use an ability if certain amount of hostiles was within my range, and I am getting the same error with .Count: Quote Non-invocable member 'System.Collections.Generic.List<wManager.Wow.ObjectManager.WoWUnit>.Count' cannot be used like a method. Link to comment Share on other sites More sharing options...
Matenia 625 Posted July 23, 2017 Share Posted July 23, 2017 Yeah, the error message is very clear. Count is a property, you cannot call it like a method (such as "Count(args...)"). if (ObjectManager.GetUnitAttackPlayer().Where(u => u.GetDistance <= 6).ToList().Count > 2) Should do the trick Apexx 1 Link to comment Share on other sites More sharing options...
Apexx 60 Posted July 25, 2017 Share Posted July 25, 2017 Thanks @Matenia for the assist with the count issue! I am going to try it out now. Error: 'System.Collections.Generic.List<wManager.Wow.ObjectManager.WoWUnit>' does not contain a definition for 'Where' and no extension method 'Where' accepting a first argument of type 'System.Collections.Generic.List<wManager.Wow.ObjectManager.WoWUnit>' could be found (are you missing a using directive or an assembly reference?) Link to comment Share on other sites More sharing options...
reapler 154 Posted July 25, 2017 Share Posted July 25, 2017 @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. Findeh 1 Link to comment Share on other sites More sharing options...
Matenia 625 Posted July 25, 2017 Share Posted July 25, 2017 25 minutes ago, reapler said: @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. Didn't know Linq hatd Count() - for some reason I had gotten compile errors before. iMod recently told me I could use .NET later than 4.0 too, maybe that's why I hadn't noticed it so far. Link to comment Share on other sites More sharing options...
Apexx 60 Posted July 25, 2017 Share Posted July 25, 2017 Thank you so much! Link to comment Share on other sites More sharing options...
iMod 99 Posted July 25, 2017 Share Posted July 25, 2017 If you compile your dll by your self you can use the lastest framework. If you just want to use the .cs file in the bot it won't work because the internal compiler just supports .NET 4.0 Link to comment Share on other sites More sharing options...
Apexx 60 Posted July 25, 2017 Share Posted July 25, 2017 I am using Visual Studio 2013 with .Net Framework 4.5 Before you guys supplied me with the Namespace System.Linq reference, I managed to get my rotation working using private int HostileUnitsInRange(int range) { var unitAttackPlayer = ObjectManager.GetUnitAttackPlayer(); if (unitAttackPlayer.Count <= 0) return 0; var hostileUnitsAttacking = unitAttackPlayer.FindAll(u => u != null && u.IsValid && u.IsTargetingMe && u.GetDistance <= range); return hostileUnitsAttacking.Count; } Link to comment Share on other sites More sharing options...
Findeh 34 Posted August 15, 2017 Author Share Posted August 15, 2017 Good day, guys. I'm tyrying to make a construction that checks is target can bleed or not. Have found the CreatureTypeTarget() function, that returns String, but not sure how should i compare strings in c#. Trying to use that construction, but it says something like: "wManager.Wow.ObjectManager.WowUnit.CreatureTypeTarget can not be used as a method". private bool TargetCanBleed() { return ( (object.Equals("Elemental", ObjectManager.Me.CreatureTypeTarget())) || (object.Equals("Mechanical", ObjectManager.Me.CreatureTypeTarget())) ); } How should i compare them right, to make function return bool result? Thank you in advance for any advices. Link to comment Share on other sites More sharing options...
reapler 154 Posted August 15, 2017 Share Posted August 15, 2017 @Findeh private bool CanBleed(WoWUnit unit) { return unit.CreatureTypeTarget != "Elemental" && unit.CreatureTypeTarget != "Mechanical"; } Usage: if (CanBleed(ObjectManager.Me.TargetObject)) { new Spell("Rend").Launch(); } Findeh 1 Link to comment Share on other sites More sharing options...
Findeh 34 Posted August 16, 2017 Author Share Posted August 16, 2017 @reapler thanks alot, going to test it right now. Link to comment Share on other sites More sharing options...
Findeh 34 Posted August 18, 2017 Author Share Posted August 18, 2017 Got a new problem now, at my rotation the is peace of code for Buff i have formed it as a void Buff() function and placed all buffs inside, no problems with that. Now i need to call this function with the criteria: "if not fighting" the problem is, if i place it inside the if (!ObjectManager.Me.IsDeadMe) without any criteria, like this: if (!ObjectManager.Me.IsDeadMe) { Buff(); if (Fight.InFight && ObjectManager.Me.Target > 0) { FightRotation(); } } then i'll buff during combat as well. if i place it with criteria like this: if (!ObjectManager.Me.IsDeadMe) { if (!Fight.InFight) { Buff(); } if (Fight.InFight && ObjectManager.Me.Target > 0) { FightRotation(); } } The weird things happens. For example, bot runs, decides to Buff(), goes inside that function, body-pulls the mob (just because continue to run his path, for example). Now he is in combat, but he does not live Buff() function, and don't continue to buff, even though his buffs are usable in combat. Guess it's because of !Fight.InFight criteria before Buff(). So he just autoattack the mob, don't do FightRotation() because he is not in the FightRotation() code block. If he kills the mob with his autoattack, he just continue to buff from the place where he stopt and then runs as normal, till the next situation like this. So i need to code a condition where Buff() will be priority number 1, but only if we not in combat. And if during the buff the combat started, we should quit the Buff() and start the FightnRotation() Is it even possible? Thank you in advance. Link to comment Share on other sites More sharing options...
Findeh 34 Posted August 18, 2017 Author Share Posted August 18, 2017 Okay, nwm, have fixed that with !ObjectManager.Me.InCombat So if some one interested: if (!ObjectManager.Me.IsDeadMe) { if (!ObjectManager.Me.InCombat) { Buff(); } if (Fight.InFight && ObjectManager.Me.Target > 0) { FightRotation(); } } This will work. You will stop do Buff(), quit this code section and will go to FightRotation if during the Buff() the combat was started. Link to comment Share on other sites More sharing options...
Findeh 34 Posted August 18, 2017 Author Share Posted August 18, 2017 Im sorry. I take my words back. Still not working. You still able to "stuck" inside the Buff() section during the combat. Link to comment Share on other sites More sharing options...
Findeh 34 Posted August 18, 2017 Author Share Posted August 18, 2017 Question is still open. Why is it happening? Why bot is not following the code in FC? Additional things 1) Any default (in build) function to cencel shapesifting? 2) How to crate Fairie Fire (Feral) spell? public Spell FaerieFire = new Spell("Faerie Fire (Feral)"); and public Spell FaerieFire = new Spell("Faerie Fire (Feral)()"); Not working for me. Link to comment Share on other sites More sharing options...
Apexx 60 Posted August 19, 2017 Share Posted August 19, 2017 Maybe check for your buffs at the end of a fight? wManager.Events.FightEvents.OnFightEnd += delegate { Buff(); }; Link to comment 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