Nookz reacted to
Droidz in Healing Class Legion
/*
Changelog:
1.0.0 - initial release
1.0.1 - fixed not healing "recruit a friend" connected payers
- fixed endless resurrection tries
1.0.2 - fixed FollowTank trying to follow target which is not in line of sight
- improved FollowTank function
- added Spell Circle of Healing
- added Mass Resurrection if option "Resurrection on" is set to "all"
- attack spells will now also be casted if your own target is the only valid one
- purify will now check for debuffed partymembers instead of only low health partymembers
- modified usage of Holy Word: Chastise
- minor code fixes
1.0.3 - changed purify behaviour: wont move to target anymore
- added option "Max healrange" - partymembers out of range will be ignored
- changed Renew and Flash Heal to make use of "Max healrange"
1.0.4 - the debuff recognition is now much more strict
- purify should work much more efficient now
*/
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using robotManager;
using robotManager.FiniteStateMachine;
using robotManager.Helpful;
using Timer = robotManager.Helpful.Timer;
using wManager.Wow.Class;
using wManager.Wow.Enums;
using wManager.Wow.Helpers;
using wManager.Wow.ObjectManager;
public class Main : ICustomClass
{
private MonkMistweaver _monk;
public float Range { get { return 39.0f; } }
private bool IsRunning;
public void Initialize()
{
MonkMistWeaverSettings.Load();
if (!IsRunning)
{
_monk = new MonkMistweaver();
_monk.Pulse();
IsRunning = true;
}
}
public void Dispose()
{
if (IsRunning)
{
_monk.Stop();
IsRunning = false;
}
}
public void ShowConfiguration()
{
MonkMistWeaverSettings.Load();
MonkMistWeaverSettings.CurrentSetting.ToForm();
MonkMistWeaverSettings.CurrentSetting.Save();
}
class MonkMistweaver
{
public static float HealRange = 40;
public int maxhealrange;
// Property:
private bool _isLaunched;
public bool IsLaunched
{
get { return _isLaunched; }
set { _isLaunched = value; }
}
// Spells:
private Spell _vivify;
private Spell _envelopingmist;
private Spell _zenpulse;
private Spell _detox;
private Spell _renewingmist;
private Spell _Revival;
private Spell _Lifecocoon;
public MonkMistweaver()
{
_envelopingmist = new Spell("Enveloping Mist");
_vivify = new Spell("Vivify");
_zenpulse = new Spell("Zen Pulse");
_detox = new Spell("Detox");
_renewingmist = new Spell("Renewing Mist");
_Revival = new Spell("Revival");
_Lifecocoon = new Spell("Life Cocoon");
}
public void Pulse()
{
_isLaunched = true;
var thread = new Thread(RoutineThread) { Name = "Monk MistWeaver Healing Class" };
thread.Start();
}
public void Stop()
{
_isLaunched = false;
Logging.WriteFight("Stop 'MistWeaver Monk'");
}
#region Routine
void RoutineThread()
{
Logging.WriteFight("'MistWeaver Monk' Started");
if (MonkMistWeaverSettings.CurrentSetting.maxhealrange != null | MonkMistWeaverSettings.CurrentSetting.maxhealrange > 0)
{
maxhealrange = MonkMistWeaverSettings.CurrentSetting.maxhealrange;
}
else
{
maxhealrange = 80;
}
while (_isLaunched)
{
Routine();
Thread.Sleep(25); // time between Routine steps in ms - lower time results in higher cpu usage
}
Logging.WriteFight("'MistWeaver Monk' Stopped");
}
void Routine()
{
if (!Conditions.InGameAndConnectedAndAlive || ObjectManager.Me.IsMounted || ObjectManager.Me.IsStunned || ObjectManager.Me.Silenced)
{
return;
}
if (!ObjectManager.Me.InCombat && !ObjectManager.Me.IsMounted )
{
ZenPulse();
Vivify();
Detox();
FollowTank();
return;
}
// if (!Conditions.InGameAndConnectedAndAlive || ObjectManager.Me.IsMounted || !ObjectManager.Me.InCombat) // || !ObjectManager.Me.InCombat return;
if (LifeCocoon()) return;
if (Revival()) return;
if (EnvelopingMist()) return;
if (ZenPulse()) return;
if (RenewingMist()) return;
if (Vivify()) return;
if (Detox()) return;
if (FollowTank()) return;
}
#endregion
#region Follow Tank
bool FollowTank()
{
if (MonkMistWeaverSettings.CurrentSetting.FollowTank == false) return false;
if (MonkMistWeaverSettings.CurrentSetting.FollowTank == null) return false;
var FollowTanks = getTanks().Where(o => o.IsValid && !o.IsMounted).OrderBy(o => o.GetDistance);
int FollowTankDistance = MonkMistWeaverSettings.CurrentSetting.FollowTankDistance;
if (FollowTanks.Count() > 0)
{
var u = FollowTanks.First();
WoWPlayer tank = new WoWPlayer(u.GetBaseAddress);
if (tank.GetDistance > FollowTankDistance)
{
while ((float)(System.Math.Round((tank.GetDistance),0)) > FollowTankDistance)
{
MovementManager.MoveTo(tank.Position);
/*
Logging.WriteDebug("Following Tank " + tank.Name);
Logging.WriteDebug("Current Tank distance " + tank.GetDistance);
Logging.WriteDebug("Wanted Tank distance " + FollowTankDistance);
*/
if ((float)(System.Math.Round((tank.GetDistance),0)) < FollowTankDistance)
{
MovementManager.StopMove();
return true;
}
}
MovementManager.StopMove();
return true;
}
return false;
}
var FollowParty = getPartymembers().Where(o => o.IsValid && !o.IsMounted && (o.Name != ObjectManager.Me.Name)).OrderBy(o => o.GetDistance);
if (FollowParty.Count() > 0)
{
var k = FollowParty.First();
WoWPlayer party = new WoWPlayer(k.GetBaseAddress);
//Logging.WriteDebug("Is partymember in line of sight? " + TraceLine.TraceLineGo(party.Position));
if (party.GetDistance > FollowTankDistance)
{
MovementManager.MoveTo(party);
//Logging.WriteDebug("Following Partymember " + party.Name);
return false;
}
}
return false;
}
#endregion
#region RenewingMist
bool RenewingMist()
{
if (!_renewingmist.KnownSpell) return false;
if (!_renewingmist.IsSpellUsable) return false;
var buffTanks = getTanks().Where(o => o.IsValid && !(o.HaveBuff("Renewing Mist"))).OrderBy(o => o.GetDistance);
var buffHealers = getHealers().Where(o => o.IsValid && !(o.HaveBuff("Renewing Mist"))).OrderBy(o => o.GetDistance);
if (buffTanks.Count() > 0 && buffHealers.Count() > 0)
{
var u = buffTanks.First();
WoWPlayer tank = new WoWPlayer(u.GetBaseAddress);
if (!TraceLine.TraceLineGo(tank.Position) && (tank.Name != ObjectManager.Me.Name))
{
//Logging.WriteDebug("Is " + tank.Name + " a healer? " + IsHealer(tank.Name) + " - " + GetHealerName() + " is the healer.");
Interact.InteractGameObject(tank.GetBaseAddress, false);
_renewingmist.Launch();
return true;
}
}
return false;
}
#endregion
#region Life Cocoon
bool LifeCocoon()
{
if (!_Lifecocoon.KnownSpell) return false;
if (!_Lifecocoon.IsSpellUsable) return false;
if (MonkMistWeaverSettings.CurrentSetting.PercentLifeCocoonHealth == null) return false;
int HandsHealth = MonkMistWeaverSettings.CurrentSetting.PercentLifeCocoonHealth;
if (HandsHealth == 0) return false;
var members = getPartymembers().Where(o => o.IsValid
&& o.IsAlive
&& o.HealthPercent <= HandsHealth
&& !TraceLine.TraceLineGo(o.Position)).OrderBy(o => o.HealthPercent);
if (members.Count() > 0)
{
var u = members.First();
WoWPlayer healTarget = new WoWPlayer(u.GetBaseAddress);
if (healTarget.IsAlive || healTarget.HealthPercent > 0)
{
while (TraceLine.TraceLineGo(healTarget.Position))
{
MovementManager.MoveTo(healTarget);
}
MovementManager.StopMove();
Interact.InteractGameObject(healTarget.GetBaseAddress, false);
_Lifecocoon.Launch();
return true;
}
}
return false;
}
#endregion
#region Enveloping Mist
bool EnvelopingMist()
{
if (!_envelopingmist.KnownSpell) return false;
if (!_envelopingmist.IsSpellUsable) return false;
if (MonkMistWeaverSettings.CurrentSetting.PercentEnvelopingMistHealth == null) return false;
int HandsHealth = MonkMistWeaverSettings.CurrentSetting.PercentEnvelopingMistHealth;
if (HandsHealth == 0) return false;
var members = getPartymembers().Where(o => o.IsValid
&& o.IsAlive
&& o.HealthPercent <= HandsHealth
&& !TraceLine.TraceLineGo(o.Position)).OrderBy(o => o.HealthPercent);
if (members.Count() > 0)
{
var u = members.First();
WoWPlayer healTarget = new WoWPlayer(u.GetBaseAddress);
if (healTarget.IsAlive || healTarget.HealthPercent > 0)
{
while (TraceLine.TraceLineGo(healTarget.Position))
{
MovementManager.MoveTo(healTarget);
}
MovementManager.StopMove();
Interact.InteractGameObject(healTarget.GetBaseAddress, false);
_envelopingmist.Launch();
return true;
}
}
return false;
}
#endregion
#region Vivify
bool Vivify()
{
if (!_vivify.KnownSpell) return false;
if (!_vivify.IsSpellUsable) return false;
if (MonkMistWeaverSettings.CurrentSetting.PercentVivifyHealth == null) return false;
int VivifyHealth = MonkMistWeaverSettings.CurrentSetting.PercentVivifyHealth;
if (VivifyHealth == 0) return false;
var members = getPartymembers().Where(o => o.IsValid
&& (o.IsAlive || o.HealthPercent > 0)
&& o.HealthPercent <= VivifyHealth).OrderBy(o => o.HealthPercent);
if (members.Count() > 0)
{
var u = members.First();
WoWPlayer healTarget = new WoWPlayer(u.GetBaseAddress);
if (healTarget.IsAlive || healTarget.HealthPercent > 0)
{
while (TraceLine.TraceLineGo(healTarget.Position))
{
MovementManager.MoveTo(healTarget);
}
MovementManager.StopMove();
Interact.InteractGameObject(healTarget.GetBaseAddress, false);
_vivify.Launch();
return true;
}
}
return false;
}
#endregion
#region Revival
/* public int healthTr
{
get
{
return MonkMistWeaverSettings.CurrentSetting.PercentRevivalHealth != null
? MonkMistWeaverSettings.CurrentSetting.PercentRevivalHealth : 0;
}
}
public int maxPlayersTr
{
get
{
return MonkMistWeaverSettings.CurrentSetting.PlayersCountRevival != null ? MonkMistWeaverSettings.CurrentSetting.PlayersCountRevival : 0;
}
}*/
bool Revival()
{
if (!_Revival.KnownSpell) return false;
if (!_Revival.IsSpellUsable) return false;
int healthTr = MonkMistWeaverSettings.CurrentSetting.PercentRevivalHealth;
int maxPlayersTr = MonkMistWeaverSettings.CurrentSetting.Players; // PlayersCountRevival ???
if (healthTr == 0) return false;
if (maxPlayersTr == 0) return false;
var members = getPartymembers().Where(o => o.IsValid
&& o.IsAlive
&& o.HealthPercent <= healthTr
&& o.GetDistance <= 40);
if (members.Count() >= maxPlayersTr)
{
_Revival.Launch();
return true;
}
return false;
}
#endregion
#region Zen Pulse
public int healthPOH
{
get
{
return MonkMistWeaverSettings.CurrentSetting.PercentZenPulseHealth != null ? MonkMistWeaverSettings.CurrentSetting.PercentZenPulseHealth : 0;
}
}
public int maxplayersPOH
{
get
{
return MonkMistWeaverSettings.CurrentSetting.PlayersCountZenPulse != null ? MonkMistWeaverSettings.CurrentSetting.PlayersCountZenPulse : 0;
}
}
bool ZenPulse()
{
if (!_zenpulse.KnownSpell) return false;
if (!_zenpulse.IsSpellUsable) return false;
if (healthPOH == 0) return false;
if (maxplayersPOH == 0) return false;
//Logging.WriteDebug("Wild Growth health : " + healthPOH);
//Logging.WriteDebug("Wild Growth players: " + maxplayersPOH);
var members = getPartymembers().Where(o => o.IsValid
&& o.IsAlive
&& o.HealthPercent <= healthPOH
&& !TraceLine.TraceLineGo(o.Position)).OrderBy(o => o.HealthPercent);
if (members.Count() >= maxplayersPOH)
{
var u = members.First();
WoWPlayer healTarget = new WoWPlayer(u.GetBaseAddress);
if (!TraceLine.TraceLineGo(healTarget.Position) && healTarget.IsAlive)
{
{
Interact.InteractGameObject(healTarget.GetBaseAddress, false);
_zenpulse.Launch();
return true;
}
}
}
return false;
}
#endregion
#region Detox
bool Detox()
{
if (!_detox.KnownSpell) return false;
if (!_detox.IsSpellUsable) return false;
var members = GetDebuffedPartymembers().OrderBy(o => o.HealthPercent);
if (members.Count() > 0)
{
var u = members.First();
WoWPlayer healTarget = new WoWPlayer(u.GetBaseAddress);
if (!TraceLine.TraceLineGo(healTarget.Position) && healTarget.IsAlive)
{
Interact.InteractGameObject(healTarget.GetBaseAddress, false);
if (Lua.LuaDoString<bool>("for j=1,40 do local m=5; local d={UnitDebuff(\"target\",j)}; if (d[5]==\"Magic\" or d[5]==\"Disease\" or d[5]==\"Poison\") and d[7]>m then j=41 return 1 end end;"))
{
_detox.Launch();
Logging.WriteDebug("Detox " + healTarget.Name);
return true;
}
return false;
}
}
return false;
}
#endregion
#region get in Healingrange
bool GetInHealingrange(WoWPlayer healTarget)
{
if (healTarget.GetDistance > HealRange)
{
Logging.WriteDebug(healTarget.Name + " is out of range, lets move to him. ");
while (healTarget.GetDistance > HealRange)
{
MovementManager.MoveTo(healTarget);
}
MovementManager.StopMove();
return true;
}
return false;
}
#endregion
#region get party
List<WoWPlayer> getPartymembers()
{
List<WoWPlayer> ret = new List<WoWPlayer>();
var u = Party.GetPartyHomeAndInstance().Where(p => p.GetDistance < maxhealrange && p.IsValid && !TraceLine.TraceLineGo(p.Position));
if (u.Count() > 0)
{
foreach (var unit in u)
{
WoWPlayer p = new WoWPlayer(unit.GetBaseAddress);
ret.Add(p);
}
}
WoWPlayer v = new WoWPlayer(ObjectManager.Me.GetBaseAddress);
ret.Add(v);
return ret;
}
List<WoWPlayer> getAllPartymembers()
{
List<WoWPlayer> ret = new List<WoWPlayer>();
var u = Party.GetPartyHomeAndInstance().Where(p => p.GetDistance < 80 && p.IsValid);
if (u.Count() > 0)
{
foreach (var unit in u)
{
WoWPlayer p = new WoWPlayer(unit.GetBaseAddress);
ret.Add(p);
}
}
WoWPlayer v = new WoWPlayer(ObjectManager.Me.GetBaseAddress);
ret.Add(v);
return ret;
}
List<WoWUnit> GetPartyTargets()
{
List<WoWPlayer> party = Party.GetPartyHomeAndInstance();
List<WoWPlayer> partyMembers = new List<WoWPlayer>();
var ret = new List<WoWUnit>();
partyMembers.AddRange(party.Where(p => p.GetDistance < 40 && p.IsValid && p.HealthPercent > 0));
WoWPlayer Me = new WoWPlayer(ObjectManager.Me.GetBaseAddress);
partyMembers.Add(Me);
foreach (var m in partyMembers)
{
var targetUnit = new WoWUnit(ObjectManager.GetObjectByGuid(m.Target).GetBaseAddress);
if (m.IsValid && (m.HealthPercent > 0) && (m.InCombat || targetUnit.InCombat) && m.Target.IsNotZero())
{
if (ret.All(u => u.Guid != m.Target)) // prevent double list entrys
{
if (targetUnit.IsValid && targetUnit.IsAlive)
{
ret.Add(targetUnit);
}
}
}
}
return ret;
}
List<WoWPlayer> GetDebuffedPartymembers()
{
List<WoWPlayer> ret = new List<WoWPlayer>();
List<WoWPlayer> u = new List<WoWPlayer>();
List<WoWPlayer> party = Party.GetPartyHomeAndInstance();
WoWPlayer Me = new WoWPlayer(ObjectManager.Me.GetBaseAddress);
u.AddRange(party.Where(p => p.GetDistance < 40 && p.IsValid && p.HealthPercent > 0 && !TraceLine.TraceLineGo(p.Position)));
u.Add(Me);
if (u.Count() > 0)
{
//Logging.WriteDebug("Checking" + u.Count + " players for debuffs.");
foreach (var unit in u)
{
WoWPlayer p = new WoWPlayer(unit.GetBaseAddress);
List<Aura> debuffs = new List<Aura>();
debuffs = p.GetAllBuff();
//Logging.WriteDebug("Found " + debuffs.Count + " buffs on " + unit.Name);
foreach (var m in debuffs)
{
//Logging.WriteDebug("Buff: " + m.GetSpell + " Flags: " + m.Flag);
if (!m.Flag.HasFlag(AuraFlags.Passive) && m.Flag.HasFlag(AuraFlags.Harmful) && m.Flag.HasFlag(AuraFlags.Active) && m.Flag.HasFlag(AuraFlags.Negative) && m.Flag.HasFlag(AuraFlags.Duration))
{
ret.Add(p);
return ret;
}
}
}
}
return ret;
}
#endregion
#region get tanks
List<WoWPlayer> getTanks()
{
List<WoWPlayer> ret = new List<WoWPlayer>();
var u = Party.GetPartyHomeAndInstance().Where(p => p.GetDistance < 80 && p.IsValid && !TraceLine.TraceLineGo(p.Position));
if (u.Count() > 0)
{
foreach (var unit in u)
{
//Logging.WriteDebug("Unit name: " + unit.Name.ToString().Trim());
if (IsTank(unit.Name.ToString()))
{
WoWPlayer p = new WoWPlayer(unit.GetBaseAddress);
ret.Add(p);
}
}
}
/* if (ret.Count() == 0)
{
Logging.WriteDebug("Could not find a tank!");
WoWPlayer v = new WoWPlayer(ObjectManager.Me.GetBaseAddress);
ret.Add(v);
}
*/
return ret;
}
string GetTankPlayerName()
{
var lua = new[]
{
"partyTank = \"\";",
"for groupindex = 1,MAX_PARTY_MEMBERS do",
" if (UnitInParty(\"party\" .. groupindex)) then",
" local role = UnitGroupRolesAssigned(\"party\" .. groupindex);",
" if role == \"TANK\" then",
" local name, realm = UnitName(\"party\" .. groupindex);",
" partyTank = name;",
" return;",
" end",
" end",
"end",
};
return Lua.LuaDoString(lua, "partyTank");
}
public bool IsTank(string unit)
{
var tankNaam = GetTankPlayerName();
WoWPlayer v = new WoWPlayer(ObjectManager.Me.GetBaseAddress);
if (tankNaam.Contains(unit))
{
return true;
}
return false;
}
#endregion
#region getHealers
List<WoWPlayer> getHealers()
{
List<WoWPlayer> ret = new List<WoWPlayer>();
var u = Party.GetPartyHomeAndInstance().Where(p => p.GetDistance < 80 && p.IsValid && !TraceLine.TraceLineGo(p.Position));
if (u.Count() > 0)
{
foreach (var unit in u)
{
//Logging.WriteDebug("Healer name: " + unit.Name.ToString().Trim());
if (IsHealer(unit.Name.ToString()))
{
WoWPlayer p = new WoWPlayer(unit.GetBaseAddress);
ret.Add(p);
}
}
}
return ret;
}
string GetHealerName()
{
var lua = new[]
{
"partyHealer = \"\";",
"for groupindex = 1,MAX_PARTY_MEMBERS do",
" if (UnitInParty(\"party\" .. groupindex)) then",
" local role = UnitGroupRolesAssigned(\"party\" .. groupindex);",
" if role == \"HEALER\" then",
" local name, realm = UnitName(\"party\" .. groupindex);",
" partyHeaer = name;",
" return;",
" end",
" end",
"end",
};
return Lua.LuaDoString(lua, "partyHealer");
}
public bool IsHealer(string unit)
{
var healerNaam = GetHealerName();
if (healerNaam.Contains(unit))
{
return true;
}
return false;
}
#endregion
}
#region settings
[Serializable]
public class MonkMistWeaverSettings : Settings
{
[Setting, DefaultValue(0)]
[Category("Healing Spells")]
[DisplayName("Life Cocoon HP%")]
[Description("Cast Life Cocoon when HP% <= Value")]
public int PercentLifeCocoonHealth { get; set; }
[Setting, DefaultValue(0)]
[Category("Group Healing Spells")]
[DisplayName("Zen Pulse Players")]
[Description("Cast Zen Pulse when player count with low HP >= Value. 0 = Disable")]
public int PlayersCountZenPulse { get; set; }
[Setting, DefaultValue(0)]
[Category("Group Healing Spells")]
[DisplayName("Zen Pulse HP%")]
[Description("Cast Zen Pulse when players HP% <= Value")]
public int PercentZenPulseHealth { get; set; }
[Setting, DefaultValue(0)]
[Category("Group Healing Spells")]
[DisplayName("Revival HP%")]
[Description("Cast Revival when players HP% <= Value")]
public int PercentRevivalHealth { get; set; }
[Setting, DefaultValue(0)]
[Category("Group Healing Spells")]
[DisplayName("Revival Players")]
[Description("Cast Revival when playercount with low HP >= Value. 0 = Disable")]
public int Players { get; set; }
[Setting, DefaultValue(0)]
[Category("Healing Spells")]
[DisplayName("Vivify HP%")]
[Description("Cast Vivify when HP% <= Value")]
public int PercentVivifyHealth { get; set; }
[Setting, DefaultValue(0)]
[Category("Healing Spells")]
[DisplayName("Enveloping Mist HP%")]
[Description("Cast Enveloping Mist when HP% <= Value")]
public int PercentEnvelopingMistHealth { get; set; }
[Setting, DefaultValue(80)]
[Category("Behaviour")]
[DisplayName("Max Healrange")]
[Description("Maximal distance between you and a valid healtarget")]
public int maxhealrange { get; set; }
[Setting, DefaultValue(false)]
[Category("Behaviour")]
[DisplayName("Follow Tank")]
[Description("Follow the tank while in fight")]
public bool FollowTank { get; set; }
[Setting, DefaultValue(0)]
[Category("Behaviour")]
[DisplayName("Follow Tank Distance")]
[Description("Move to tank if distance is higher than value")]
public int FollowTankDistance { get; set; }
private MonkMistWeaverSettings()
{
ConfigWinForm(new System.Drawing.Point(400, 600), "MistWeaver Monk " + Translate.Get("Settings"));
}
public static MonkMistWeaverSettings CurrentSetting { get; set; }
public bool Save()
{
try
{
return Save(AdviserFilePathAndName("CustomClass-MistWeaver Monk", ObjectManager.Me.Name + "." + Usefuls.RealmName));
}
catch (Exception e)
{
Logging.WriteError("MonkMistWeaverSettings > Save(): " + e);
return false;
}
}
public static bool Load()
{
try
{
if (File.Exists(AdviserFilePathAndName("CustomClass-MistweaverMonk", ObjectManager.Me.Name + "." + Usefuls.RealmName)))
{
CurrentSetting =
Load<MonkMistWeaverSettings>(AdviserFilePathAndName("CustomClass-MistweaverMonk",
ObjectManager.Me.Name + "." + Usefuls.RealmName));
return true;
}
CurrentSetting = new MonkMistWeaverSettings();
}
catch (Exception e)
{
Logging.WriteError("MonkMistWeaverSettings > Load(): " + e);
}
return false;
}
}
#endregion
}
It's code fixed (but no tested)