I'm basically doing what Droidz is doing. Using the GUIDs to get make sure the user is correct.
This code is tested and should work (I modified it to return any role, but I'll test again and make sure). Here's my code:
public enum Roles
{
TANK,
HEALER,
DAMAGER
}
public static List<string> GetGUIDsByRole(Roles role)
{
string lua =
@"guids = """";
for groupindex = 1,GetNumGroupMembers() do
if IsInRaid() then
local role = UnitGroupRolesAssigned(""raid"" .. groupindex);
if role == ""{0}"" then
local name = UnitGUID(""raid"" .. groupindex);
guids = guids .. name .. "" "";
end
elseif IsInGroup() then
local role = UnitGroupRolesAssigned(""party"" .. groupindex)
if role == ""{0}"" then
local name = UnitGUID(""party"" .. groupindex);
guids = name;
return;
end
end
end ";
var val = Lua.LuaDoString(string.Format(lua, role), "guids");
if (string.IsNullOrWhiteSpace(val))
{
Logging.WriteFight("No tanks found!");
return new List<string>();
}
var tankNames = val.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
return tankNames;
}
And Here's where I map them to units:
public static List<WoWPlayer> GetPartyMembersByRole(Roles role, Vector3 positionCenter, int maxHealthPercent = 100, float maxDistance = float.MaxValue, bool orderByHealth = true)
{
var guids = GetGUIDsByRole(role);
if (guids.Count == 0)
return new List<WoWPlayer>();
var units = Party.GetPartyHomeAndInstance().Where(m => guids.Contains(m.Guid128.ToString()) && m.IsValid && m.IsAlive && m.HealthPercent < maxHealthPercent && m.Position.DistanceTo(positionCenter) <= maxDistance);
if (orderByHealth)
units = units.OrderBy(p => p.HealthPercent);
return units.ToList();
}
This issue would also break SpellManager.CastSpellByNameOn(), so I do this to get the full/CRZ name when casting a heal:
public static string GetCRZName(WoWUnit unit)
{
if (!(unit is WoWPlayer))
return unit.Name;
string lua = @"class, classFilename, race, raceFilename, sex, name, realm = GetPlayerInfoByGUID(UnitGUID(""{0}""));
if(realm ~= nil and realm ~= """") then
name = name .. ""-"" .. realm;
end";
var name = Lua.LuaDoString(string.Format(lua, unit.Guid128.ToString()), "name");
return name;
}
public static async Task<bool> CastHeal(Spell spell, WoWUnit unit, bool reqs, bool ignoreUsable = false)
{
if (!reqs) return false;
string myspell = spell.Name;
if (!spell.KnownSpell) return false;
if (!spell.IsSpellUsable && !ignoreUsable) return false;
if (SpellManager.GetSpellCooldownTimeLeft(myspell) > 0) return false;
try
{
SpellManager.CastSpellByNameOn(myspell, GetCRZName(unit));
if (LastLog != myspell)
{
Logging.WriteFight(myspell);
LastLog = myspell;
}
await Task.Delay(Usefuls.Latency);
return true;
}
catch (Exception e) { Logging.WriteFight("CastOn: " + myspell + " " + e.ToString()); }
return false;
}
Note: I check to see if realm is nil or empty because realm isn't returned if the player is on the same realm. I also check to make sure the WoWUnit is a player before executing the code because it will error out otherwise.
If you're willing to get your feet wet and launch Visual Studio, this Fight Class Framework file is amazing and includes logic for healers, getting tanks, etc. I made a pretty beast Holy Pally routine using it
I use it on live and I like it. The community is small so you will need to educate yourself on the basics of xml and C# (and lua, definitely brush up on lua), but that's a good thing imo because it keeps those away who tend to do dumb shit that would get the bot on Blizz's radar.
There are a few hiccups with the bot, but nothing I haven't been able to fix with a plugin or whatnot.
I use it on live and I like it. The community is small so you will need to educate yourself on the basics of xml and C# (and lua, definitely brush up on lua), but that's a good thing imo because it keeps those away who tend to do dumb shit that would get the bot on Blizz's radar.
There are a few hiccups with the bot, but nothing I haven't been able to fix with a plugin or whatnot.