[Plugin] Recruit-A-Friend Recruit-A-Friend *placeholder* This plugin will allow for at minimum two bots running for questing, granting levels, summoning, and ideally party mounting. Initially, this will support only two bots linked to each other. Release Status - Alpha: Framework has been written, and plugin starts/stops without error. DOWNLOAD INSTRUCTIONS SVN Location Code: https://subversion.assembla.com/svn/recruitafriend/trunk Download and install the latest version of TortoiseSVN for your operating system Create a new folder named RecruitAFriend in your HonorBuddy/Plugins directory. Right click the new folder you just created, and select SVN Checkout.... If you have the above SVN URL in your clipboard, it will be automatically filled in, if not, then copy/paste the SVN Location above into the box under URL Repository. Make sure Fully Recursive, and HEAD Revision are selected, then click [ OK ] Launch WoW, and sign in. Launch HonorBuddy In HonorBuddy - Click Plugins, and put a checkmark beside RecruitAFriend. If you do not see this option, click on the Recompile.. button at the bottom of the Plugins window, and then you should be able to. Launch another session of WoW and sign in, and do the same for HonorBuddy. Make sure that each HonorBuddy session is set to QuestBuddy, and have the same quest profiles loaded. Click start on each session of HonorBuddy and enjoy the Recruit-A-Friend bonus experience on Quest turn ins. ** Current team members are listed below ** C# CORE WRAPPER Code: using Microsoft.VisualBasic; using System; using System.Collections; using System.Collections.Generic; using System.Windows.Forms; using System.Data; using System.Diagnostics; using System.Linq; using Styx; using Styx.Common; using Styx.Plugins; using Styx.WoWInternals; using Styx.WoWInternals.WoWObjects; namespace RecruitAFriend { enum EnumLootThreshold { Uncommon =1, Rare = 2, Epic = 3 } enum EnumLootMethod { Group, FreeForAll, Master, NeedBeforeGreed, RoundRobin } struct StructureLootMethod { EnumLootMethod lootmethod; dynamic masterlooterPartyID; dynamic masterlooterRaidID; } // Battle.Net Structures struct StructureBattleNetInfo { int presenceID; int toonID; string currentBroadcast; bool bnetAFK; bool bnetDND; } struct StructureBattleNetFriendInfo { int presenceID; string givenName; string surname; string toonName; int toonID; string client; bool isOnline; } struct StructureBattleNetFriendInfoFromID { int presenceID; string givenName; string surname; string toonName; int toonID; string client; bool isOnline; DateTime lastOnline; bool isAFK; bool isDND; string messageText; string noteText; } struct StructureBattleNetToonInfo { dynamic unused1; dynamic unused2; string gameName; string realmName; string faction; dynamic unused3; string race; string charclass; dynamic unused4; string zoneName; int level; } // ****************************** // ** PLUGIN CORE ** // ****************************** public class RecruitAFriend : HBPlugin { // Name of the plugin public override string Name { get { return "RecruitAFriend"; } } // Give credits to the developer(s) public override string Author { get { return "RecruitAFriend Team"; } } // What is the version public override Version Version { get { return new Version(0, 0, 0, 0); } } // Enable plugin "settings" button public override bool WantButton { get { return false; } } // Set caption of "settings" button public override string ButtonText { get { return "Settings"; } } // What happens when a user clicks the "settings" button public override void OnButtonPress() { MessageBox.Show("Configuration options will be here later","Settings ...",MessageBoxButtons.YesNo); } // Code to run when the plugin is enabled in HonorBuddy public override void OnEnable() { try { // Battle.Net Lua.Events.AttachEvent("BN_CONNECTED", Events.BN_CONNECTED); Lua.Events.AttachEvent("BN_FRIEND_ACCOUNT_ONLINE", Events.BN_FRIEND_ACCOUNT_ONLINE); // Party Lua.Events.AttachEvent("PARTY_INVITE_REQUEST", Events.PARTY_INVITE_REQUEST); Lua.Events.AttachEvent("PARTY_MEMBERS_CHANGED", Events.PARTY_MEMBERS_CHANGED); // Recruit-A-Friend Lua.Events.AttachEvent("CONFIRM_SUMMON", Events.CONFIRM_SUMMON); Lua.Events.AttachEvent("LEVEL_GRANT_PROPOSED", Events.LEVEL_GRANT_PROPOSED); Lua.Events.AttachEvent("PLAYER_LEVEL_UP", Events.PLAYER_LEVEL_UP); base.OnEnable(); } catch (Exception e) { // Exception handling } finally { // Command completed properly } } // Code to run when the plugin is disabled in HonorBuddy public override void OnDisable() { try { // Battle.Net Lua.Events.DetachEvent("BN_CONNECTED", Events.BN_CONNECTED); Lua.Events.DetachEvent("BN_FRIEND_ACCOUNT_ONLINE", Events.BN_FRIEND_ACCOUNT_ONLINE); // Party Lua.Events.DetachEvent("PARTY_INVITE_REQUEST", Events.PARTY_INVITE_REQUEST); Lua.Events.DetachEvent("PARTY_MEMBERS_CHANGED", Events.PARTY_MEMBERS_CHANGED); // Recruit-A-Friend Lua.Events.DetachEvent("CONFIRM_SUMMON", Events.CONFIRM_SUMMON); Lua.Events.DetachEvent("LEVEL_GRANT_PROPOSED", Events.LEVEL_GRANT_PROPOSED); Lua.Events.DetachEvent("PLAYER_LEVEL_UP", Events.PLAYER_LEVEL_UP); base.OnDisable(); } catch (Exception e) { // Exception handling } finally { // Command completed properly } } // Code to run when HonorBuddy pings the plugin (on heartbeat return pulse) public override void Pulse() { } } // ****************************** // ** LUA EVENTS ** // ****************************** public class Events { public static LocalPlayer Me = StyxWoW.Me; // Battle.net Events public static void BN_CONNECTED(object sender, LuaEventArgs args) { } public static void BN_FRIEND_ACCOUNT_ONLINE(object sender, LuaEventArgs args) { } // Party Events public static void PARTY_MEMBERS_CHANGED(object sender, LuaEventArgs args) { } public static void PARTY_INVITE_REQUEST(object sender, LuaEventArgs args) { dynamic partyInviteSender = args.Args[0].ToString(); Lua.DoString("AcceptInvite()"); } // Recruit-A-Friend Events public static void CONFIRM_SUMMON(object sender, LuaEventArgs args) { } public static void LEVEL_GRANT_PROPOSED(object sender, LuaEventArgs args) { } public static void PLAYER_LEVEL_UP(object sender, LuaEventArgs args) { } } // ****************************** // ** LUA FUNCTIONS ** // ****************************** public class Functions { // Battle.Net Functions public static StructureBattleNetInfo BNGetInfo() { return new StructureBattleNetInfo(); } public static StructureBattleNetToonInfo BNGetToonInfo(string presence) // This may require a structure to be passed instead of a string { return new StructureBattleNetToonInfo(); } public static int BNGetNumFriends() { return 0; } public static StructureBattleNetFriendInfo BNGetFriendInfo(int index) { return new StructureBattleNetFriendInfo(); } public static StructureBattleNetFriendInfoFromID BNGetFriendInfoByID(int presence) { return new StructureBattleNetFriendInfoFromID(); } public static bool CanCooperateWithToon(StructureBattleNetInfo info) { return false; } // Party Functions public static bool IsPartyLeader() { return false; } public static void InviteUnit(string name) { return; } public static StructureLootMethod GetLootMethod() { return new StructureLootMethod(); } public static void SetLootMethod(EnumLootMethod method) { switch (method) { case EnumLootMethod.FreeForAll: break; case EnumLootMethod.Group: break; case EnumLootMethod.Master: break; case EnumLootMethod.NeedBeforeGreed: break; case EnumLootMethod.RoundRobin: break; } } public static void SetLootThreshold(EnumLootThreshold threshold) { } // Recruit-A-Friend Functions public static bool IsReferAFriendLinked(string name) { return false; } public static int GetSummonFriendCooldown() { return 3600; // 1 Hour } public static void SummonFriend(string name) { } public static void ConfirmSummon() { } public static void CancelSummon() { } public static void GrantLevel(string name) { } public static void AcceptLevelGrant() { } public static void DeclineLevelGrant() { } public static int CheckInteractDistance(string name, int distance) { return 100; } } } Real World Example of Some Features Some of the features will be ported from the Recruit-A-Friend LUA plugin (included in this post at the bottom for reference only ) THE LUA CODE BELOW IS FOR REFERENCE ONLY Recruit-A-Friend WoW LUA Plugin Custom friends list for RaF auto-invite/etc Auto accept level grants from players on custom friends list --- this is toggleable Auto accept summons from players on custom friends list --- this is toggleable Auto accept level grants from players on custom friends list --- this is toggleable Detect when a friend has come online and if RaF and on custom friends list, automatically invite to party if not in a party, or if you are party leader and party is not full, and the friend is friendly, and the friend is in WoW (aka... not Starcraft) -- ditto -- for Battle.net status change. Automatically confirm Bind-on-Equip, Ressurrections, and LFG ready checks Check the distance between chars and alerts player if it's safe to hand in quests. This part is buggy, couldn't get the UI to show. Code: local frame = CreateFrame("FRAME", "RecruitAFriendFrame"); local rafTarget = nil; local rafLevelGranted = nil; local maxcount = 3; frame:RegisterEvent("PARTY_INVITE_REQUEST"); frame:RegisterEvent("CONFIRM_SUMMON"); frame:RegisterEvent("ADDON_LOADED"); frame:RegisterEvent("LFG_PROPOSAL_SHOW"); frame:RegisterEvent("LEVEL_GRANT_PROPOSED"); frame:RegisterEvent("AUTOEQUIP_BIND_CONFIRM"); frame:RegisterEvent("PLAYER_TARGET_CHANGED"); frame:RegisterEvent("PLAYER_LEVEL_UP"); frame:RegisterEvent("BN_FRIEND_ACCOUNT_ONLINE"); frame:RegisterEvent("BN_CONNECTED"); frame:RegisterEvent("UNIT_TARGET"); frame:RegisterEvent("PARTY_MEMBERS_CHANGED"); frame:RegisterEvent("PLAYER_DEAD"); frame:RegisterEvent("CORPSE_IN_RANGE"); SLASH_RECRUITAFRIEND1, SLASH_RECRUITAFRIEND2 = '/raf', '/recruitafriend'; local function RecruitAFriendCommands(command, msg, arg1, arg2) if string.find(command, " ") == nil then RecruitAFriendForm:Show(); else var = { strsplit(" ", command) } if var[1]=="summon" then start, duration = GetSummonFriendCooldown(); name, realm = UnitName("target"); if duration==0 then if name==nil then if var[2]==nil then else SummonFriend(var[2]) end else SummonFriend(name) end else print("Your last summon was at "..SecondsToTime(start).." which is "..SecondsToTime(duration).." ago") end elseif var[1]=="invite" then name, realm = UnitName("target"); if name==nil then if var[2]==nil then else InviteUnit(var[2]) end else InviteUnit(name) end elseif var[1]=="grant" then name, realm = UnitName("target"); if name==nil then if var[2]==nil then else GrantLevel(var[2],1) end else GrantLevel(name,1) end elseif var[1]=="acceptlevels" then if var[2]=="1" then var[2]="Allow"; raAcceptLevels = 1; elseif var[2]=="on" then var[2]="Allow"; raAcceptLevels = 1; elseif var[2]=="enabled" then var[2]="Allow"; raAcceptLevels = 1; elseif var[2]=="yes" then var[2]="Allow"; raAcceptLevels = 1; elseif var[2]=="allow" then var[2]="Allow"; raAcceptLevels = 1; else var[2]="Do Not Allow"; raAcceptLevels = 0; end print(var[2].." automatic levels to be granted to this character") elseif var[1]=="acceptsummons" then if var[2]=="1" then var[2]="Allow"; raAcceptSummons = 1; elseif var[2]=="on" then var[2]="Allow"; raAcceptSummons = 1; elseif var[2]=="enabled" then var[2]="Allow"; raAcceptSummons = 1; elseif var[2]=="yes" then var[2]="Allow"; raAcceptSummons = 1; elseif var[2]=="allow" then var[2]="Allow"; raAcceptSummons = 1; else var[2]="Do Not Allow"; raAcceptSummons = 0; end print(var[2].." automatic summons to be sent to this character") elseif var[1]=="acceptinvites" then if var[2]=="1" then var[2]="Allow"; raAcceptInvites = 1; elseif var[2]=="on" then var[2]="Allow"; raAcceptInvites = 1; elseif var[2]=="enabled" then var[2]="Allow"; raAcceptInvites = 1; elseif var[2]=="yes" then var[2]="Allow"; raAcceptInvites = 1; elseif var[2]=="allow" then var[2]="Allow"; raAcceptInvites = 1; else var[2]="Do Not Allow"; raAcceptInvites = 0; end print(var[2].." automatic group invitations to be sent to this character") elseif var[1]=="add" then RAFriendAdd(var[2]) elseif var[1]=="friends" then for k,v in pairs(raFriends) do print("RAF Buddy: "..v) end else print("Recruit-A-Friend 4.2a Command List") print("/raf summon [friend]") print("/raf invite [friend]") print("/raf grant [friend]") print("/raf acceptlevels on/off") print("/raf acceptsummons on/off") print("/raf acceptinvites on/off") print("/raf add friend") print("/raf friends") end end end local function eventHandler(info, event, sender, name) if event=="PARTY_INVITE_REQUEST" then if sender==nil then isLinked=nil else isLinked = IsReferAFriendLinked(sender); rafToonName = sender; end if isLinked==nil then isLinked=RAFriendExists(sender); end if isLinked==1 then if raAcceptInvites==1 then AcceptGroup(); -- frame:RegisterEvent("PARTY_MEMBERS_CHANGED"); end end elseif event=="CONFIRM_SUMMON" then -- GetSummonConfirmSummoner() -- isLinked = IsReferAFriendLinked(sender); -- isLinked=nil; -- print("you are being summoned by "..name); -- if isLinked==nil then -- isLinked=RAFriendExists(sender); -- end isLinked=1; if isLinked==1 then if raAcceptSummons==1 then ConfirmSummon(); else -- print(sender); CancelSummon(); end else CancelSummon(); end elseif event=="UNIT_TARGET" then if(GetNumPartyMembers() > 0) then local numBNetTotal, numBNetOnline = BNGetNumFriends(); for i = 1, numBNetTotal do local presenceID, givenName, surname, toonName, toonID, client, isOnline = BNGetFriendInfo(i); _, _, gameName, realmName, faction, _, race, class, _, zoneName, level = BNGetToonInfo(presenceID); if (isOnline) and (client == "WoW") then if (CanCooperateWithToon(BNGetInfo(toonID))) then if (UnitInParty(toonName)) then if (IsReferAFriendLinked(toonName)) then rafToonName = toonName; rafLinkActive = "[RAF]"; inRange = CheckInteractDistance(toonName, 4); if (inRange) then RecruitAFriendDistance:Hide(); -- print(rafLinkActive .. givenName .. " [FULL RAF BENEFITS]"); else if(UnitInRange(toonName)) then RecruitAFriendDistance:Show(); -- print(rafLinkActive .. givenName .. " [DO NOT HAND IN QUESTS]"); else RecruitAFriendDistance:Show(); RecruitAFriendSummonForm:Show(); -- print(rafLinkActive .. givenName .. " [DO NOT HAND IN QUESTS OR KILL MONSTERS]"); end end end else if(RAFriendExists(toonName) == 1) then InviteUnit(toonName); end end end end end end elseif event=="LEVEL_GRANT_PROPOSED" then isLinked = IsReferAFriendLinked(sender); if isLinked==nil then isLinked=RAFriendExists(sender); end if isLinked==1 then if raAcceptLevels==1 then rafLevelGranted=sender; AcceptLevelGrant() print(sender); else DeclineLevelGrant(); end else DeclineLevelGrant(); end elseif event=="ADDON_LOADED" then if sender=="Recruit-A-Friend" then local presenceIDl, toonIDl, currentBroadcastl, bnetAFKl, bnetDNDl = BNGetInfo(); _, _, gameNamel, realmNamel, factionl, _, racel, classl, _, zoneNamel, levell = BNGetToonInfo(presenceIDl); if not ( raFriends ) then raFriends = { } end if not ( raAcceptLevels ) then raAcceptLevels = 0 end if not ( raAcceptSummons ) then raAcceptSummons = 1 end if not ( raAcceptInvites ) then raAcceptInvites = 1 end print("Recruit-A-Friend Addon Loaded") print("You have "..#raFriends.." friend(s) on your Recruit-A-Friend buddy list") print("You are on " .. realmNamel .. " on your level " .. levell .. " " .. racel .. " " .. classl); if raAcceptLevels==1 then print("Accepting granted levels") end if raAcceptSummons==1 then print("Accepting summons") end if raAcceptInvites==1 then print("Accepting party invitations") end end elseif event=="BN_CONNECTED" then local presenceIDl, toonIDl, currentBroadcastl, bnetAFKl, bnetDNDl = BNGetInfo(); _, _, gameNamel, realmNamel, factionl, _, racel, classl, _, zoneNamel, levell = BNGetToonInfo(presenceIDl); local numBNetTotal, numBNetOnline = BNGetNumFriends(); for i = 1, numBNetTotal do local presenceID, givenName, surname, toonName, toonID, client, isOnline = BNGetFriendInfo(i); _, _, gameName, realmName, faction, _, race, class, _, zoneName, level = BNGetToonInfo(presenceID); if (isOnline) and (client == "WoW") then if (CanCooperateWithToon(BNGetInfo(toonID))) then if(RAFriendExists(toonName) == 1) then rafToonName = toonName; if tonumber(level) > tonumber(levell) then leveldifference = tonumber(level) - tonumber(level); elseif tonumber(levell) > tonumber(level) then leveldifference = tonumber(levell) - tonumber(level); else leveldifference = 0; end if leveldifference < 5 then if (UnitInParty(toonName)) or (realmName ~= realmNamel) then print(givenName .. " just came online at " .. realmName .. " on their level " .. level .. " " .. race .. " " .. class ); else InviteUnit(toonName); end end end end end end elseif event=="BN_FRIEND_ACCOUNT_ONLINE" then local presenceIDl, toonIDl, currentBroadcastl, bnetAFKl, bnetDNDl = BNGetInfo(); _, _, gameNamel, realmNamel, factionl, _, racel, classl, _, zoneNamel, levell = BNGetToonInfo(presenceIDl); local presenceId = select(1, sender); local presenceID, givenName, surname, toonName, toonID, client, isOnline, lastOnline, isAFK, isDND, messageText, noteText = BNGetFriendInfoByID(presenceId); _, _, gameName, realmName, faction, _, race, class, _, zoneName, level = BNGetToonInfo(presenceID); if (isOnline) and (client == "WoW") then if (CanCooperateWithToon(BNGetInfo(toonID))) then if(RAFriendExists(toonName) == 1) then rafToonName = toonName; if tonumber(level) > tonumber(levell) then leveldifference = tonumber(level) - tonumber(level); elseif tonumber(levell) > tonumber(level) then leveldifference = tonumber(levell) - tonumber(level); else leveldifference = 0; end if (leveldifference < 6) then if (UnitInParty(toonName)) or (realmName ~= realmNamel) then print(givenName .. " just came online at " .. realmName .. " on their level " .. level .. " " .. race .. " " .. class ); else InviteUnit(toonName); rafToonName = toonName; end end end end end elseif event=="LFG_PROPOSAL_SHOW" then AcceptProposal(); elseif event=="PLAYER_DEAD" then frame:RegisterEvent("RESURRECT_REQUEST","acceptResurrection"); frame:RegisterEvent("PLAYER_UNGHOST","acceptResurrection"); elseif event=="CORPSE_IN_RANGE" then RetrieveCorpse(); elseif event=="AUTOEQUIP_BIND_CONFIRM" then ConfirmBindOnUse(); elseif event=="PLAYER_TARGET_CHANGED" then rafTarget = name elseif event=="PLAYER_LEVEL_UP" then local newlevel = sender local togo = MAX_PLAYER_LEVEL - newlevel rafLevelGranted = nil elseif event=="PARTY_MEMBERS_CHANGED" then StaticPopup_Hide("PARTY_INVITE"); --frame:UnregisterEvent("PARTY_MEMBERS_CHANGED"); if (rafToonName) then if (UnitInParty(rafToonName)) then RecruitAFriendSummonForm:Show(); local start, duration = GetSummonFriendCooldown(); local timeleft = start + duration - GetTime(); if(timeleft <= 0) then rafCaptionSummonFriend:Hide(); rafButtonSummonFriend:Show(); else rafButtonSummonFriend:Hide(); rafCaptionSummonFriend:Show(); rafCaptionSummonFriend:SetText(SecondsToTime(timeleft)); end if (IsPartyLeader()) then lootmethod, masterlooterPartyID, masterlooterRaidID = GetLootMethod(); if (lootmethod == "freeforall") then else SetLootMethod("freeforall"); SetLootThreshold(3); end end end else print("rafToonName is empty"); end end end function rafClosePartyPopup() StaticPopup_Hide("PARTY_INVITE"); -- frame:UnregisterEvent("PARTY_MEMBERS_CHANGED"); end function acceptResurrection(info, event, sender) AcceptResurrect(); frame:UnregisterEvent("RESURRECT_REQUEST"); frame:UnregisterEvent("PLAYER_UNGHOST"); end function RAFriendAdd(friend) if RAFriendExists(friend)==0 then table.insert(raFriends,friend) print(friend.." was added to your Recruit-A-Friend buddy list") else print(friend.." already exists on your Recruit-A-Friend buddy list") end end function RAFriendExists(friend) myreturn=0; if (#raFriends==0) then myreturn=0; else for k,v in pairs(raFriends) do if strlower(v)==strlower(friend) then myreturn=1; end end end return myreturn; end frame:SetScript("OnEvent", eventHandler); SlashCmdList["RECRUITAFRIEND"] = RecruitAFriendCommands;
Core Development Progress (wrapper code) : Completed Current working status: LEGEND Not Started Writing Code Completed Completed and Stable FEATURES Automatic party invitation to Linked accounts Automatic summoning by party leader to current questing zone Automatic summoning if other member is too far, but has completed all objectives. Waiting patiently (walking randomly around quest turn in point) if waiting on other player quest objectives. Automatic quest sharing for quests that are picked up by one bot, but the other has not received. Parked toon support (aka, automaticly summon to stormwind/etc to a parked RaF toon for quick banking/vendoring/etc) --- maybe* Full Questing support using current Questing profiles such as Kick's or Cava. Syncronizing and forcing zone switches when you have outleveled a zone. Stop and restart to jump to next area as specified in profiles for zones. Player shared mounting --- actually make use of the RaF two player mounts. Out of Zone detection. Internal bot communication system (have the the bots running pass details about the other game client/player/quest information back and forth) SummonFriend cooldown detection. Blacklisting of class quests [blacklisted quests will be completed without waiting for the other party member(s)]. * The list is in no particular order and stuff may be added / removed over time depending on it's necessity and feedback from players like yourself *
Hi, I have a good experience, a lot of time for testing, but the poor level of knowledge of English language ...
@Mhhh ... currently it is just a shell for the command structure. It doesn't do anything just yet aside from startup / stop when you check it, and open the settings window. We are working on this plugin so that you will have as smooth as possible questing experience.
looks nice buddy! but using 2 accounts that are almost always on the same spot is a bit weird maybe it's an idea to use the /follow so it's just looks like a multiboxer
Here you go: Detection if Summon Friend is ready: Code: public bool IsRaFSummonReady() { if (Styx.CommonBot.SpellManager.HasSpell(45927) && !SpellManager.Spells["Summon Friend"].Cooldown) { return true; } else { return false; } } If it is not ready, how for how long will it still be on CD?: Code: public double RaFSummonCdLeft() { if (Styx.CommonBot.SpellManager.HasSpell(45927) && SpellManager.Spells["Summon Friend"].Cooldown) { return SpellManager.Spells["Summon Friend"].CooldownTimeLeft.TotalMinutes; } else { return 0; } } Best regards, p4m
That one uses the previous two. Code: public List<WoWPlayer> RaFParty { get { if (!StyxWoW.Me.GroupInfo.IsInParty) return new List<WoWPlayer>(); ; return StyxWoW.Me.GroupInfo.RaidMembers.Where(p => p.RAFLinked) .Select(p => p.ToPlayer()) .Where(p => p != null && p.IsAlive && p.IsFriendly && !p.Combat && (p.WorldLocation.Distance(StyxWoW.Me.Location) > 150 || !Navigator.CanNavigateFully(StyxWoW.Me.Location, p.Location))).ToList(); } } public void SummonOutOfZonePartyMember() { if (StyxWoW.Me.IsGroupLeader && RaFParty.Count > 0 && IsRaFSummonCastable() && RaFSummonCdLeft() == 0) { Styx.CommonBot.SpellManager.Cast("Summon Friend", RaFParty.FirstOrDefault()); } } Best regards, p4m
Unfortunately, there is no proper way todetect other players' zone ID, so either we use the actual distance in yards (as done in the following code) or one would share ZoneIDs to an internal communication server and do comparisons there. First solution is alot easier to code, but not actual OutOfZone detections. One could of course use Landmarks for comparison, such as GrindArea or QuestArea, did not exactly get what you wanted from the description. Code: public bool IsOutOfZone(WoWPlayer player) { if (StyxWoW.Me.Location.Distance(player.Location) < 300) { return false; } else { return true; } } best regards
Here's a function that might be useful as a failsafe check. In case one of the characters outlevels another groupmember by more than 3 levels (the point from when the 300% exp bonus is no longer granted), he should leave the group until the other players catch up. Code: public List<WoWPlayer> RaFPartyLevels { get { if (!StyxWoW.Me.GroupInfo.IsInParty) return new List<WoWPlayer>(); ; return StyxWoW.Me.GroupInfo.RaidMembers.Where(p => p.RAFLinked) .Select(p => p.ToPlayer()) .Where(p => p != null && p.Level > (StyxWoW.Me.Level + 3)).ToList(); } } public bool AmITooHighLevel() { if (RaFPartyLevels.Count > 0) { return true; } else { return false; } } public void LeaveGroupBecauseIAmTooHighLevel() { if(AmITooHighLevel()) { Styx.WoWInternals.Lua.DoString("LeaveParty();"); } } Best regards, p4m
Here you go: Code: List<String> RaFChars = new List<string>(new string[] {"name1", "name2", "name3", "name4"}); public void InviteRaFChars() { foreach (string name in RaFChars) { Styx.WoWInternals.Lua.DoString("InviteUnit(\"" + name + "\");"); } } best regards
Here's a quick function for auto-kicking toons which are not RaF-linked (user-error mostly): Code: public List<WoWPlayer> PartyNonRaF { get { if (!StyxWoW.Me.GroupInfo.IsInParty) return new List<WoWPlayer>(); ; return StyxWoW.Me.GroupInfo.RaidMembers.Where(p => !p.RAFLinked) .Select(p => p.ToPlayer()) .Where(p => p != null).ToList(); } } public void KickNonRaFToons() { if (PartyNonRaF.Count > 0) { Styx.WoWInternals.Lua.DoString("UninviteUnit(\"" + PartyNonRaF.FirstOrDefault().Name.ToString() + "\");"); } } best regards, p4m
Add RaF toons to friendslist (should only be executed once - most likely on first startup/config): Uses the RaFChars list from GroupInvite, just posting it here again for completeness. Code: List<String> RaFChars = new List<string>(new string[] { "name1", "name2", "name3", "name4" }); private void AddRaFToonsToFriendslist() { foreach (string name in RaFChars) { Styx.WoWInternals.Lua.DoString("AddFriend(\"" + name + "\");"); } } best regards
Wait for all RaF toons to be in range (need to pulse WaitForAllToons() when needed): Code: public List<WoWPlayer> RaFParty { get { if (!StyxWoW.Me.GroupInfo.IsInParty) return new List<WoWPlayer>(); ; return StyxWoW.Me.GroupInfo.RaidMembers.Where(p => p.RAFLinked) .Select(p => p.ToPlayer()) .Where(p => p != null && p.Location.Distance(StyxWoW.Me.Location) < 30).ToList(); } } public void WaitForAllToons() { if (RaFParty.Count != StyxWoW.Me.GroupInfo.NumPartyMembers) { WoWMovement.MoveStop(); Styx.CommonBot.POI.BotPoi.Clear(); } } Best regards, p4m
Hi, i don't know what to do it doesn't work for me i cant select any characters in the settings window and i cant save the settings they reset all the time pls help