public void Update(long tick) { if (TCPManager.GetTimeStampMS() >= _channelStartTime + _channelInfo.CastTime) { SendChannelEnd(); _parent.NotifyChannelEnded(); _channelInfo = null; _channelBuff = null; } else if (TCPManager.GetTimeStampMS() >= _nextTickTime) { if (_channelInfo.ApCost > 0 && !_host.ConsumeActionPoints(_channelInfo.ApCost)) { _parent.CancelCast((byte)GameData.AbilityResult.ABILITYRESULT_AP); } else if (_playerHost != null && _channelInfo.SpecialCost > 3 && !_playerHost.CrrInterface.ConsumeResource((byte)_channelInfo.SpecialCost, true)) { _parent.CancelCast(1); } else if (_target != _host && !_host.IsInCastRange(_target, Math.Max((uint)25, _channelInfo.Range))) { _parent.CancelCast((byte)GameData.AbilityResult.ABILITYRESULT_OUTOFRANGE); } else if (_checkVisibility && !_host.LOSHit(_target)) { _parent.CancelCast((byte)GameData.AbilityResult.ABILITYRESULT_NOT_VISIBLE); } else { _nextTickTime += 1000; } } }
public void OnCastAbility(AbilityInfo Ab) { for (int i = 0; i < Scripts.Count; ++i) { Scripts[i].OnCastAbility(Ab); } }
public void ModifyInitials(AbilityInfo abInfo) { if (_generalPreCastModifiers.Count != 0) { foreach (var modifier in _generalPreCastModifiers) { modifier.ModifyAbility(_myPlayer, abInfo); } } if (abInfo.ConstantInfo.MasteryTree != 0 && _speclinePreCastModifiers.ContainsKey((byte)(abInfo.ConstantInfo.MasteryTree - 1))) { foreach (var modifier in _speclinePreCastModifiers[(byte)(abInfo.ConstantInfo.MasteryTree - 1)]) { modifier.ModifyAbility(_myPlayer, abInfo); } } if (_abilityPreCastModifiers.ContainsKey(abInfo.Entry)) { foreach (var modifier in _abilityPreCastModifiers[abInfo.Entry]) { modifier.ModifyAbility(_myPlayer, abInfo); } } }
public void ModifyFinals(AbilityInfo abInfo) { if (_generalModifiers.Count != 0) { foreach (var modifier in _generalModifiers) { modifier.ModifyAbility(_myPlayer, abInfo); } } if (abInfo.ConstantInfo.MasteryTree != 0 && _speclineModifiers.ContainsKey((byte)(abInfo.ConstantInfo.MasteryTree - 1))) { foreach (var modifier in _speclineModifiers[(byte)(abInfo.ConstantInfo.MasteryTree - 1)]) { modifier.ModifyAbility(_myPlayer, abInfo); } } if (_abilityModifiers.ContainsKey(abInfo.Entry)) { foreach (var modifier in _abilityModifiers[abInfo.Entry]) { modifier.ModifyAbility(_myPlayer, abInfo); } } if (_myPlayer.CrrInterface.ExperimentalMode) { _myPlayer.CrrInterface.ExperimentalModeModifyAbility(abInfo); } }
public void AddAbilities(ushort minBound, ushort maxBound) { if (maxBound == 0) { AbilityInfo abInfo = AbilityMgr.GetAbilityInfo(minBound); if (abInfo != null && abInfo.ConstantInfo.MinimumRank <= Level) { NPCAbility npcAbility = new NPCAbility(abInfo.Entry, abInfo.ConstantInfo.AIRange, (byte)abInfo.Cooldown, true, ""); AbtInterface.NPCAbilities.Add(npcAbility); SendPetAbility(npcAbility); } } else { for (ushort i = minBound; i <= maxBound; ++i) { AbilityInfo abInfo = AbilityMgr.GetAbilityInfo(i); if (abInfo == null || abInfo.ConstantInfo.MinimumRank > Level) { continue; } NPCAbility npcAbility = new NPCAbility(abInfo.Entry, abInfo.ConstantInfo.AIRange, (byte)abInfo.Cooldown, true, ""); AbtInterface.NPCAbilities.Add(npcAbility); SendPetAbility(npcAbility); } } }
/// <summary> /// Callback to start the channel proper /// </summary> public void ChannelInitialization(NewBuff channelBuff) { // Was cancelled before the channel callback if (_channelInfo == null || _host == null || _host.IsDead) { if (channelBuff != null) { channelBuff.BuffHasExpired = true; _channelBuff = null; } } // Couldn't create a channel buff, so cancel else if (channelBuff == null) { _parent.CancelCast(0); _channelInfo = null; } // Successful link else { _channelBuff = channelBuff; _channelBuff.ChannelHandler = this; // Oil if (_host is Siege) { _channelBuff.OptionalObject = _host; } _host.BuffInterface.NotifyAbilityCasted(_channelInfo); } }
/* * public override bool SetExperimentalMode(bool fullExplanation) * { * myPlayer.SendClientMessage("Experimental mode for this class is no longer available.", ChatLogFilters.CHATLOGFILTERS_CSR_TELL_RECEIVE); * return false; * * if (ExperimentalMode) * { * PrintExModeChangeset(); * myPlayer.SendClientMessage("Experimental mode for this class has been forced for a short period, and cannot be disabled.", ChatLogFilters.CHATLOGFILTERS_CSR_TELL_RECEIVE); * return false; * } * * CurrentStance = 0; * * if (fullExplanation) * { * if (myPlayer.Info.CareerLine == (int) GameData.CareerLine.CAREERLINE_WARRIOR_PRIEST) * { * myPlayer.BuffInterface.RemoveBuffByEntry(8242); * myPlayer.BuffInterface.RemoveBuffByEntry(8243); * myPlayer.BuffInterface.RemoveBuffByEntry(8249); * } * else * { * myPlayer.BuffInterface.RemoveBuffByEntry(9559); * myPlayer.BuffInterface.RemoveBuffByEntry(9563); * myPlayer.BuffInterface.RemoveBuffByEntry(9567); * } * } * * ExperimentalMode = !ExperimentalMode; * * if (!fullExplanation && ExperimentalMode) * { * myPlayer.SendClientMessage("Experimental mode for Warrior Priest and Disciple of Khaine is currently enabled.", ChatLogFilters.CHATLOGFILTERS_CSR_TELL_RECEIVE); * return true; * } * * if (ExperimentalMode) * { * PrintExModeChangeset(); * } * * else * myPlayer.SendClientMessage("Experimental mode for Warrior Priest and Disciple of Khaine has been disabled.", ChatLogFilters.CHATLOGFILTERS_CSR_TELL_RECEIVE); * * return true; * } * * private void PrintExModeChangeset() * { * myPlayer.SendClientMessage("Experimental mode for Warrior Priest and Disciple of Khaine has been enabled.", ChatLogFilters.CHATLOGFILTERS_CSR_TELL_RECEIVE); * myPlayer.SendClientMessage("General changes:", ChatLogFilters.CHATLOGFILTERS_CSR_TELL_RECEIVE); * myPlayer.SendClientMessage("- Righteous Fury and Soul Essence regeneration from tomes and chalices is linked to the Morale bonus scaler."); * myPlayer.SendClientMessage("- Switching between Prayers and Covenants invokes a 15 second cooldown for all Prayers and Covenants."); * myPlayer.SendClientMessage("- When switching into or out of the Prayer of Righteousness or the Covenant of Celerity, a 5 minute cooldown is used instead."); * myPlayer.SendClientMessage("- If in combat, switching to or from Righteousness or Celerity consumes all action points and mechanic points."); * myPlayer.SendClientMessage("- The cooldown of Absence of Faith is now 10 seconds."); * myPlayer.SendClientMessage("Prayer of Absolution and Covenant of Tenacity:", ChatLogFilters.CHATLOGFILTERS_CSR_TELL_RECEIVE); * myPlayer.SendClientMessage("+ Provide 8 Righteous Fury / Soul Essence per second."); * myPlayer.SendClientMessage("+ Convert your Strength and Melee Power bonus from items into Willpower and Healing Power."); * myPlayer.SendClientMessage("- Reduce your armor by 50%. This is a multiplicative modifier, and thus also reduces the effect of potions, talismans and debuffs for armor."); * myPlayer.SendClientMessage("Prayer of Devotion and Covenant of Vitality:", ChatLogFilters.CHATLOGFILTERS_CSR_TELL_RECEIVE); * myPlayer.SendClientMessage("+ Convert your Willpower and Healing Power bonus from items into Strength and Melee Power."); * myPlayer.SendClientMessage("- You will inflict 50% less damage."); * myPlayer.SendClientMessage("+ You will gain 50% of your Strength bonus from items as Willpower whenever you strike a target with a Path of Grace or Path of Sacrifice ability."); * myPlayer.SendClientMessage("This effect stacks up to three times and lasts for 12 seconds, and will be removed if you remove the Prayer or Covenant."); * myPlayer.SendClientMessage("+ Your detaunt will gain the effect of the Intimidating Repent or Terrifying Aura tactic, becoming AoE."); * myPlayer.SendClientMessage("- The cooldown of your detaunt increases to 25 seconds."); * myPlayer.SendClientMessage("+ Sigmar's Radiance and Transfer Essence gain 20% strikethrough, and heal for 250% of the damage dealt and mitigated, with no base component."); * myPlayer.SendClientMessage("+ Sigmar's Shield gains 20% strikethrough."); * myPlayer.SendClientMessage("+ Rend Soul and Divine Assault become undefendable, healing for 75% more and healing for the mitigated value as well."); * myPlayer.SendClientMessage("Prayer of Righteousness:", ChatLogFilters.CHATLOGFILTERS_CSR_TELL_RECEIVE); * myPlayer.SendClientMessage("+ Convert your Willpower and Healing Power bonus from items into Strength and Melee Power."); * myPlayer.SendClientMessage("+ The damage inflicted by Path of Wrath skills increases based on your Righteous Fury level, to a maximum of 40%."); * myPlayer.SendClientMessage("- Any time you use a Path of Wrath skill, you will lose 5 Righteous Fury per second for 10 seconds."); * myPlayer.SendClientMessage("+ Absence of Faith will debuff heals by 50%."); * myPlayer.SendClientMessage("+ When you trigger your Prayer of Righteousness, it will increase your movement speed by 20% for 5 seconds. This will only affect you."); * myPlayer.SendClientMessage("Covenant of Celerity:", ChatLogFilters.CHATLOGFILTERS_CSR_TELL_RECEIVE); * myPlayer.SendClientMessage("+ Convert your Willpower and Healing Power bonus from items into Strength and Melee Power."); * myPlayer.SendClientMessage("+ The damage inflicted by Path of Torture skills increases based on your Soul Essence level, to a maximum of 25%."); * myPlayer.SendClientMessage("- Any time you use a Path of Torture skill, you will lose 5 Soul Essence per second for 10 seconds."); * }*/ public override bool ExperimentalModeCheckAbility(AbilityInfo abInfo) { if (!ExperimentalMode) { /*// Repent -> Intimidating Repent * if (abInfo.Entry == 8245) * { * Item mainHand = myPlayer.ItmInterface.GetItemInSlot((ushort) EquipSlot.MAIN_HAND); * * return mainHand?.Info != null && mainHand.Info.TwoHanded; * }*/ return(false); } switch (abInfo.Entry) { // Repent -> Intimidating Repent if Devotion is on // Terrifying Vision -> Terrifying Aura if Vitality is on case 8245: case 9555: return(_currentStance == 2); } return(true); }
private void StartDelayedCast(object creature) { var Params = (List <object>)creature; Unit _unit = Params[0] as Unit; ushort Ability = (ushort)Params[1]; // This is used by random ability cast if (_unit != null && !_unit.IsDead) { _unit.AbtInterface.StartCast(_unit, Ability, 1); if (!(_unit is Pet)) { _unit.MvtInterface.StopMove(); AbilityInfo AbiInfo = AbilityMgr.GetAbilityInfo(Ability); if (!AbiInfo.CanCastWhileMoving) { _unit.EvtInterface.AddEvent(DelayedChase, AbiInfo.CastTime + 100, 1); } else { Chase(_unit.CbtInterface.GetCurrentTarget(), true); } } } }
public static void LoadCreatureAbilities() { CreatureAbilities.Clear(); IList <Creature_abilities> creaAbs = WorldMgr.Database.SelectAllObjects <Creature_abilities>(); Dictionary <uint, List <NPCAbility> > temp = new Dictionary <uint, List <NPCAbility> >(); foreach (var cAb in creaAbs) { if (!temp.ContainsKey(cAb.ProtoEntry)) { temp.Add(cAb.ProtoEntry, new List <NPCAbility>()); } AbilityInfo abInfo = GetAbilityInfo(cAb.AbilityId); if (abInfo != null) { temp[cAb.ProtoEntry].Add(new NPCAbility(cAb.AbilityId, abInfo.ConstantInfo.AIRange, Math.Max(abInfo.Cooldown, cAb.Cooldown), true, cAb.Text, cAb.TimeStart, cAb.ActivateAtHealthPercent, cAb.AbilityCycle, cAb.Active, cAb.ActivateOnCombatStart, cAb.RandomTarget, cAb.DisableAtHealthPercent, cAb.MinRange)); } } foreach (uint key in temp.Keys) { CreatureAbilities[key] = temp[key].OrderByDescending(x => x.Cooldown).ToList(); } }
/// <summary>Run to check whether an ability called through the DO_ABILITY packet is valid.</summary> public bool IsValidAbility(AbilityInfo info) { if (!HasPlayer()) { return(true); } Player plr = GetPlayer(); // Lock out abilities the player shouldn't have access to if (!_abilitySet.Contains(info.Entry)) { return(false); } if (info.ConstantInfo.MinimumRank > plr.AdjustedLevel || info.ConstantInfo.MinimumRenown > plr.RenownRank) { return(false); } if (info.CareerLine != 0 && (plr.Info.CareerFlags & info.ConstantInfo.CareerLine) == 0) { return(false); } return(true); }
public bool StartCastAtPos(Unit instigator, ushort abilityID, Point3D worldPos, ushort zoneId, byte castSequence) { if (PreventCasting) { if (_Owner is Player) { Player owner = _Owner as Player; owner?.SendClientMessage("A developer has disabled all abilities.", ChatLogFilters.CHATLOGFILTERS_USER_ERROR); } return(false); } // Allow only interruption of channeled skills of a different ID to the skill being used if (IsCasting() && (!_abilityProcessor.IsChannelling || _abilityProcessor.AbInfo.Entry == abilityID)) { return(false); } AbilityInfo abInfo = AbilityMgr.GetAbilityInfo(abilityID); if (abInfo == null || (abInfo.ConstantInfo.Origin != AbilityOrigin.AO_ITEM && !IsValidAbility(abInfo))) { return(false); } try { if (AbilityMgr.HasCommandsFor(abilityID) || abInfo.ConstantInfo.ChannelID != 0) { if (_abilityProcessor == null) { _abilityProcessor = new AbilityProcessor(_unitOwner, this); } abInfo.Instigator = instigator; if (!_abilityProcessor.HasInfo()) { _abilityProcessor.StartAbilityAtPos(abInfo, castSequence, worldPos, zoneId); } return(true); } if (_Owner is Player) { var owner = _Owner as Player; owner?.SendClientMessage(abilityID + " " + AbilityMgr.GetAbilityNameFor(abilityID) + " has no implementation.", ChatLogFilters.CHATLOGFILTERS_USER_ERROR); } return(false); } catch (Exception e) { if (_Owner is Player) { var owner = _Owner as Player; owner?.SendClientMessage(abilityID + " " + AbilityMgr.GetAbilityNameFor(abilityID) + " threw an unhandled " + e.GetType().Name + " from " + e.TargetSite + "."); } return(false); } }
public AbilityInfo Clone() { AbilityInfo cAbInfo = (AbilityInfo)MemberwiseClone(); cAbInfo.CommandInfo = new List <AbilityCommandInfo>(); return(cAbInfo); }
public void Interrupt() { _channelInfo = null; if (_channelBuff != null && !_channelBuff.BuffHasExpired) { _channelBuff.RemoveBuff(true); } _channelBuff = null; }
/* * public void Initialize(Unit caster, Unit target, ushort baseEntry, ushort channelId, byte castSequence) * { * _target = target; * _caster = caster; * _castSequence = castSequence; * _baseEntry = baseEntry; * _channelInfo = AbilityMgr.GetAbilityInfo(channelId); * if (_channelInfo == null) * Log.Error("NewChannelHandler", "Couldn't find the channel info for ID: " + channelId); * else StartChannel(); * } */ public void Initialize(AbilityInfo abInfo, byte castSequence) { _target = abInfo.Target; _caster = abInfo.Instigator; _castSequence = castSequence; _baseEntry = abInfo.Entry; _channelInfo = abInfo; StartChannel(); }
public void NotifyAbilityCasted(AbilityInfo abInfo) { if (_buffCombatSubs[(byte)BuffCombatEvents.AbilityCasted - 1].Count == 0) { return; } foreach (var buff in _buffCombatSubs[(byte)BuffCombatEvents.AbilityCasted - 1]) { buff.InvokeCastEvent((byte)BuffCombatEvents.AbilityCasted, abInfo); } }
public void CancelPendingCast() { // Failed attempt to break a channel if (AbInfo != null) { return; } if (_pendingInfo.ConstantInfo.ChannelID != 0) { PacketOut Out = new PacketOut((byte)Opcodes.F_SET_ABILITY_TIMER, 12); Out.WriteUInt16(_pendingInfo.Entry); Out.Fill(0, 4); Out.WriteUInt16(0); Out.Fill(0, 4); if (_caster is Pet) { ((Pet)_caster).Owner.SendPacket(Out); } else if (_caster is Player) { ((Player)_caster).SendPacket(Out); } } if (_pendingInfo.SpecialCost < 0) { Player plr = _caster as Player; if (plr != null) { PacketOut Out = new PacketOut((byte)Opcodes.F_SET_ABILITY_TIMER, 12); Out.WriteUInt16(0); Out.WriteUInt16(0x200); // Morale timer Out.WriteUInt32(0); // cooldown Out.WriteUInt32(0); plr.SendPacket(Out); } } AbInfo = _pendingInfo; _castSequence = _pendingCastSequence; CancelCast(0); AbInfo = null; _castSequence = 0; _pendingInfo = null; _pendingItemCooldownGroup = 0; _pendingCastSequence = 0; }
/// <summary> /// Modifies the cast time, cooldown, range and AP cost of an ability according to stats. /// </summary> /// <param name="abInfo"></param> public void ModifyAbilityVolatiles(AbilityInfo abInfo) { if (abInfo.ConstantInfo.ChannelID == 0) { int castMod = GetStatLinearModifier(Stats.BuildTime); if (abInfo.CastTime + castMod <= 0) { abInfo.CastTime = 0; } else { abInfo.CastTime = (ushort)((abInfo.CastTime + castMod) * GetStatPercentageModifier(Stats.BuildTime)); } if (abInfo.CastTime == 0) { abInfo.CanCastWhileMoving = true; } } if (abInfo.Entry != 9553 && abInfo.Entry != 8239 && abInfo.Entry != 9035 && abInfo.Entry != 1734) // exempt divine mend, khaine's invigoration, sudden shift and changin' da plan { short cooldownMod = (short)(GetStatLinearModifier(Stats.Cooldown) / 1000); if (abInfo.Cooldown + cooldownMod <= 0) { abInfo.Cooldown = 0; } else { abInfo.Cooldown = (ushort)((abInfo.Cooldown + cooldownMod) * (GetStatPercentageModifier(Stats.Cooldown))); } } float rangeMod = GetStatPercentageModifier(Stats.Range); abInfo.FlightTimeMod = 1f / rangeMod; if (abInfo.Range != 0) { abInfo.Range = (ushort)(abInfo.Range * rangeMod); } if (abInfo.ApCost != 0) { abInfo.ApCost = (byte)((abInfo.ApCost + GetTotalStat(Stats.ActionPointCost)) * GetStatPercentageModifier(Stats.ActionPointCost)); } }
private void Clear() { if (AbInfo.ConstantInfo.ChannelID != 0 && AbInfo.SpecialCost == -4) { _caster.RemoveCrowdControlImmunity((int)CrowdControlTypes.Unstoppable); _caster.IsImmovable = false; } AbInfo = null; _castStartTime = 0; _inCastCompletion = false; _failureCode = 0; _shouldCheckRange = false; }
public static void GetCommandsFor(Unit caster, AbilityInfo abInfo) { if (AbilityCommandInfos.ContainsKey(abInfo.Entry)) { // Add commands to the new info if they're applicable to the player. // Has to be done here because of bloody tactics and career crap foreach (AbilityCommandInfo abCommand in AbilityCommandInfos[abInfo.Entry]) { if (!abCommand.NoAutoUse) { abInfo.CommandInfo.Add(abCommand.Clone(caster)); for (AbilityCommandInfo slaveCommand = abCommand.NextCommand; slaveCommand != null; slaveCommand = slaveCommand.NextCommand) { if (!slaveCommand.NoAutoUse) { abInfo.CommandInfo[(byte)(abInfo.CommandInfo.Count - 1)].AddCommandToChain(slaveCommand.Clone(caster)); } } } } } }
public static void LoadNewAbilityInfo() { Log.Info("AbilityMgr", "Loading New Ability Info..."); IObjectDatabase db = WorldMgr.Database; #region Database List <DBAbilityInfo> dbAbilities = (List <DBAbilityInfo>)db.SelectAllObjects <DBAbilityInfo>(); List <AbilityInfo> abVolatiles = AbilityInfo.Convert(dbAbilities); Dictionary <ushort, AbilityConstants> abConstants = AbilityConstants.Convert(dbAbilities).ToDictionary(key => key.Entry); List <AbilityDamageInfo> abDmgHeals = AbilityDamageInfo.Convert(db.SelectAllObjects <DBAbilityDamageInfo>().OrderBy(dmg => dmg.ParentCommandID).ThenBy(dmg => dmg.ParentCommandSequence).ToList()); List <AbilityCommandInfo> abCommands = AbilityCommandInfo.Convert(db.SelectAllObjects <DBAbilityCommandInfo>().OrderBy(cmd => cmd.CommandID).ToList()); IList <AbilityModifierCheck> abChecks = db.SelectAllObjects <AbilityModifierCheck>().OrderBy(check => check.ID).ToList(); IList <AbilityModifierEffect> abMods = db.SelectAllObjects <AbilityModifierEffect>().OrderBy(mod => mod.Sequence).ToList(); List <BuffInfo> buffInfos = BuffInfo.Convert((List <DBBuffInfo>)db.SelectAllObjects <DBBuffInfo>()); List <BuffCommandInfo> buffCommands = BuffCommandInfo.Convert(db.SelectAllObjects <DBBuffCommandInfo>().OrderBy(buffcmd => buffcmd.CommandID).ToList()); IList <AbilityKnockbackInfo> knockbackInfos = db.SelectAllObjects <AbilityKnockbackInfo>().OrderBy(kbinfo => kbinfo.Id).ToList(); List <AbilityCommandInfo> slaveCommands = new List <AbilityCommandInfo>(); List <BuffCommandInfo> slaveBuffCommands = new List <BuffCommandInfo>(); Dictionary <ushort, int> damageTypeDictionary = new Dictionary <ushort, int>(); #endregion for (byte i = 0; i < 24; ++i) { CareerAbilities[i] = new List <AbilityInfo>(); } #region AbilityChecks foreach (AbilityModifierCheck check in abChecks) { switch (check.PreOrPost) { case 0: if (!AbilityPreCastModifiers.ContainsKey(check.Entry)) { AbilityPreCastModifiers.Add(check.Entry, new List <AbilityModifier>()); while (AbilityPreCastModifiers[check.Entry].Count < check.ID + 1) { AbilityPreCastModifiers[check.Entry].Add(new AbilityModifier(check.Entry, check.Affecting)); } AbilityPreCastModifiers[check.Entry][check.ID].AddCheck(check); } else { if (AbilityPreCastModifiers[check.Entry].Count == check.ID) { AbilityPreCastModifiers[check.Entry].Add(new AbilityModifier(check.Entry, check.Affecting)); } AbilityPreCastModifiers[check.Entry][check.ID].AddCheck(check); } break; case 1: if (!AbilityModifiers.ContainsKey(check.Entry)) { AbilityModifiers.Add(check.Entry, new List <AbilityModifier>()); while (AbilityModifiers[check.Entry].Count < check.ID + 1) { AbilityModifiers[check.Entry].Add(new AbilityModifier(check.Entry, check.Affecting)); } AbilityModifiers[check.Entry][check.ID].AddCheck(check); } else { if (AbilityModifiers[check.Entry].Count == check.ID) { AbilityModifiers[check.Entry].Add(new AbilityModifier(check.Entry, check.Affecting)); } AbilityModifiers[check.Entry][check.ID].AddCheck(check); } break; case 2: if (!BuffModifiers.ContainsKey(check.Entry)) { BuffModifiers.Add(check.Entry, new List <AbilityModifier>()); while (BuffModifiers[check.Entry].Count < check.ID + 1) { BuffModifiers[check.Entry].Add(new AbilityModifier(check.Entry, check.Affecting)); } BuffModifiers[check.Entry][check.ID].AddCheck(check); } else { if (BuffModifiers[check.Entry].Count == check.ID) { BuffModifiers[check.Entry].Add(new AbilityModifier(check.Entry, check.Affecting)); } BuffModifiers[check.Entry][check.ID].AddCheck(check); } break; case 3: if (!AbilityDelayedModifiers.ContainsKey(check.Entry)) { AbilityDelayedModifiers.Add(check.Entry, new List <AbilityModifier>()); while (AbilityDelayedModifiers[check.Entry].Count < check.ID + 1) { AbilityDelayedModifiers[check.Entry].Add(new AbilityModifier(check.Entry, check.Affecting)); } AbilityDelayedModifiers[check.Entry][check.ID].AddCheck(check); } else { if (AbilityDelayedModifiers[check.Entry].Count == check.ID) { AbilityDelayedModifiers[check.Entry].Add(new AbilityModifier(check.Entry, check.Affecting)); } AbilityDelayedModifiers[check.Entry][check.ID].AddCheck(check); } break; } } #endregion #region AbilityModifiers foreach (AbilityModifierEffect effect in abMods) { switch (effect.PreOrPost) { case 0: if (!AbilityPreCastModifiers.ContainsKey(effect.Entry)) { AbilityPreCastModifiers.Add(effect.Entry, new List <AbilityModifier>()); AbilityPreCastModifiers[effect.Entry].Add(new AbilityModifier(effect.Entry, effect.Affecting)); AbilityPreCastModifiers[effect.Entry][0].AddModifier(effect); } else { if (AbilityPreCastModifiers[effect.Entry].Count == effect.Sequence) { AbilityPreCastModifiers[effect.Entry].Add(new AbilityModifier(effect.Entry, effect.Affecting)); } AbilityPreCastModifiers[effect.Entry][effect.Sequence].AddModifier(effect); } break; case 1: if (!AbilityModifiers.ContainsKey(effect.Entry)) { AbilityModifiers.Add(effect.Entry, new List <AbilityModifier>()); AbilityModifiers[effect.Entry].Add(new AbilityModifier(effect.Entry, effect.Affecting)); AbilityModifiers[effect.Entry][0].AddModifier(effect); } else { if (AbilityModifiers[effect.Entry].Count == effect.Sequence) { AbilityModifiers[effect.Entry].Add(new AbilityModifier(effect.Entry, effect.Affecting)); } AbilityModifiers[effect.Entry][effect.Sequence].AddModifier(effect); } break; case 2: if (!BuffModifiers.ContainsKey(effect.Entry)) { BuffModifiers.Add(effect.Entry, new List <AbilityModifier>()); BuffModifiers[effect.Entry].Add(new AbilityModifier(effect.Entry, effect.Affecting)); BuffModifiers[effect.Entry][0].AddModifier(effect); } else { if (BuffModifiers[effect.Entry].Count == effect.Sequence) { BuffModifiers[effect.Entry].Add(new AbilityModifier(effect.Entry, effect.Affecting)); } BuffModifiers[effect.Entry][effect.Sequence].AddModifier(effect); } break; case 3: if (!AbilityDelayedModifiers.ContainsKey(effect.Entry)) { AbilityDelayedModifiers.Add(effect.Entry, new List <AbilityModifier>()); AbilityDelayedModifiers[effect.Entry].Add(new AbilityModifier(effect.Entry, effect.Affecting)); AbilityDelayedModifiers[effect.Entry][0].AddModifier(effect); } else { if (AbilityDelayedModifiers[effect.Entry].Count == effect.Sequence) { AbilityDelayedModifiers[effect.Entry].Add(new AbilityModifier(effect.Entry, effect.Affecting)); } AbilityDelayedModifiers[effect.Entry][effect.Sequence].AddModifier(effect); } break; } } #endregion #region CommandInfo // Ability commands foreach (AbilityCommandInfo abCommand in abCommands) { if (abCommand.CommandSequence != 0) { slaveCommands.Add(abCommand); } else { if (!AbilityCommandInfos.ContainsKey(abCommand.Entry)) { AbilityCommandInfos.Add(abCommand.Entry, new List <AbilityCommandInfo>()); } AbilityCommandInfos[abCommand.Entry].Add(abCommand); } } foreach (AbilityCommandInfo slaveCommand in slaveCommands) { if (AbilityCommandInfos.ContainsKey(slaveCommand.Entry)) { AbilityCommandInfos[slaveCommand.Entry][slaveCommand.CommandID].AddCommandToChain(slaveCommand); } else { Log.Debug("AbilityMgr", "Slave command with entry " + slaveCommand.Entry + " and depending upon master command ID " + slaveCommand.CommandID + " has no master!"); } } #endregion #region BuffCommands foreach (BuffCommandInfo buffCommand in buffCommands) { if (buffCommand.CommandSequence != 0) { slaveBuffCommands.Add(buffCommand); } else { if (!BuffCommandInfos.ContainsKey(buffCommand.Entry)) { BuffCommandInfos.Add(buffCommand.Entry, new List <BuffCommandInfo>()); } BuffCommandInfos[buffCommand.Entry].Add(buffCommand); } } foreach (BuffCommandInfo slaveBuffCommand in slaveBuffCommands) { if (BuffCommandInfos.ContainsKey(slaveBuffCommand.Entry)) { BuffCommandInfos[slaveBuffCommand.Entry][slaveBuffCommand.CommandID].AddCommandToChain(slaveBuffCommand); } else { Log.Debug("AbilityMgr", "Slave buff command with entry " + slaveBuffCommand.Entry + " and depending upon master command ID " + slaveBuffCommand.CommandID + " has no master!"); } } #endregion #region Damage/Heals // Damage and heal info gets tacked onto the command that's going to use it foreach (AbilityDamageInfo abDmgHeal in abDmgHeals) { if (abDmgHeal.DisplayEntry == 0) { abDmgHeal.DisplayEntry = abDmgHeal.Entry; } switch (abDmgHeal.Index) { case 0: if (AbilityCommandInfos.ContainsKey(abDmgHeal.Entry)) { AbilityCommandInfo desiredCommand = AbilityCommandInfos[abDmgHeal.Entry][abDmgHeal.ParentCommandID].GetSubcommand(abDmgHeal.ParentCommandSequence); if (desiredCommand != null) { desiredCommand.DamageInfo = abDmgHeal; } } if (!damageTypeDictionary.ContainsKey(abDmgHeal.Entry)) { damageTypeDictionary.Add(abDmgHeal.Entry, (int)abDmgHeal.DamageType); } break; case 1: if (BuffCommandInfos.ContainsKey(abDmgHeal.Entry)) { try { BuffCommandInfo desiredCommand = BuffCommandInfos[abDmgHeal.Entry][abDmgHeal.ParentCommandID].GetSubcommand(abDmgHeal.ParentCommandSequence); if (desiredCommand != null) { desiredCommand.DamageInfo = abDmgHeal; } } catch { Log.Error("AbilityMgr", "Failed Load: " + abDmgHeal.Entry + " " + abDmgHeal.ParentCommandID); } if (!damageTypeDictionary.ContainsKey(abDmgHeal.Entry)) { damageTypeDictionary.Add(abDmgHeal.Entry, (int)abDmgHeal.DamageType); } } break; case 2: if (!ExtraDamage.ContainsKey(abDmgHeal.Entry)) { ExtraDamage.Add(abDmgHeal.Entry, new List <List <AbilityDamageInfo> >()); } if (ExtraDamage[abDmgHeal.Entry].Count == abDmgHeal.ParentCommandID) { ExtraDamage[abDmgHeal.Entry].Add(new List <AbilityDamageInfo>()); } ExtraDamage[abDmgHeal.Entry][abDmgHeal.ParentCommandID].Add(abDmgHeal); break; default: throw new Exception("Invalid index specified for ability damage with ID " + abDmgHeal.Entry); } } #endregion #region KnockbackInfo foreach (var kbInfo in knockbackInfos) { if (!KnockbackInfos.ContainsKey(kbInfo.Entry)) { KnockbackInfos.Add(kbInfo.Entry, new List <AbilityKnockbackInfo>()); } KnockbackInfos[kbInfo.Entry].Add(kbInfo); } #endregion // Volatiles -> Constants // -> Commands -> DamageHeals foreach (AbilityInfo abVolatile in abVolatiles) { if (!NewAbilityVolatiles.ContainsKey(abVolatile.Entry)) { NewAbilityVolatiles.Add(abVolatile.Entry, abVolatile); } if (AbilityCommandInfos.ContainsKey(abVolatile.Entry)) { abVolatile.TargetType = AbilityCommandInfos[abVolatile.Entry][0].TargetType; if (AbilityCommandInfos[abVolatile.Entry][0].AoESource != 0) { abVolatile.TargetType = AbilityCommandInfos[abVolatile.Entry][0].AoESource; } } } #region ConstantInfo foreach (AbilityConstants abConstant in abConstants.Values) { if (NewAbilityVolatiles.ContainsKey(abConstant.Entry)) { NewAbilityVolatiles[abConstant.Entry].ConstantInfo = abConstant; if (damageTypeDictionary.ContainsKey(abConstant.Entry)) { if (damageTypeDictionary[abConstant.Entry] == (ushort)DamageTypes.Healing || damageTypeDictionary[abConstant.Entry] == (ushort)DamageTypes.RawHealing) { abConstant.IsHealing = true; } else { abConstant.IsDamaging = true; } } uint careerRequirement = abConstant.CareerLine; byte count = 0; while (careerRequirement > 0 && count < 24) { if ((careerRequirement & 1) > 0) { CareerAbilities[count].Add(NewAbilityVolatiles[abConstant.Entry]); } careerRequirement = careerRequirement >> 1; count++; } } } #endregion #region Damage to ConstantInfo linkage foreach (AbilityDamageInfo damageInfo in abDmgHeals) { if (abConstants.ContainsKey(damageInfo.Entry)) { damageInfo.MasteryTree = abConstants[damageInfo.Entry].MasteryTree; } } #endregion #region Buff/Command linkage foreach (BuffInfo buffInfo in buffInfos) { if (!BuffInfos.ContainsKey(buffInfo.Entry)) { BuffInfos.Add(buffInfo.Entry, buffInfo); } if (BuffCommandInfos.ContainsKey(buffInfo.Entry)) { buffInfo.CommandInfo = BuffCommandInfos[buffInfo.Entry]; } if (abConstants.ContainsKey(buffInfo.Entry)) { buffInfo.MasteryTree = abConstants[buffInfo.Entry].MasteryTree; } } #endregion Log.Success("AbilityMgr", "Finished loading " + NewAbilityVolatiles.Count + " abilities and " + BuffInfos.Count + " buffs!"); LoadCreatureAbilities(); }
public override void ExperimentalModeModifyAbility(AbilityInfo abInfo) { switch (abInfo.Entry) { case 8252: // Sigmar's Radiance case 9562: // Transfer Essence if (_currentStance == 2) { foreach (AbilityCommandInfo command in abInfo.CommandInfo) { for (AbilityCommandInfo cmd = command; cmd != null; cmd = cmd.NextCommand) { // Is undefendable, to compensate deals half damage but heals for more if (cmd.CommandName == "StealLife") { cmd.DamageInfo.MinDamage = 0; cmd.DamageInfo.MaxDamage = 0; cmd.PrimaryValue = (short)(cmd.PrimaryValue * 5f); } else if (cmd.DamageInfo != null) { cmd.DamageInfo.Defensibility -= 20; cmd.DamageInfo.ResultFromRaw = true; } } } } break; case 8267: // Sigmar's Shield if (_currentStance == 2) { foreach (AbilityCommandInfo command in abInfo.CommandInfo) { for (AbilityCommandInfo cmd = command; cmd != null; cmd = cmd.NextCommand) { if (cmd.DamageInfo != null) { cmd.DamageInfo.Defensibility -= 20; } } } } break; case 8270: // Absence of Faith abInfo.Cooldown = 10; break; case 9555: // Terrifying Vision case 8245: // Repent if (_currentStance == 2) { abInfo.Cooldown = 25; } break; case 8242: // Prayer of Absolution case 9563: // Covenant of Tenacity case 8249: // Prayer of Devotion case 9567: // Covenant of Vitality if (_currentStance == 1) { abInfo.Cooldown = (ushort)(DPS_SWITCH_CD_MS / 1000); } else { abInfo.Cooldown = (ushort)(SWITCH_CD_MS / 1000); } break; case 8243: // Prayer of Righteousness case 9559: // Covenant of Celerity abInfo.Cooldown = (ushort)(DPS_SWITCH_CD_MS / 1000); break; } }
public virtual void InvokeCastEvent(byte eventID, AbilityInfo abInfo) { if (BuffState != (byte)EBuffState.Running) { return; } BuffCommandInfo myCommand = EventCommands.Find(evtpair => evtpair.Item1 == eventID).Item2; if (myCommand == null) { return; } if (myCommand.EventChance > 0 && StaticRandom.Instance.Next(0, 100) > myCommand.EventChance) { return; } // Lazy checking for some tactics that don't warrant creating new delegates. switch (Entry) { // Scourged Warping (requires Scourge to be the ability casted) case 3765: if (abInfo.Entry != 8548) { return; } break; // Flashfire (requires that the ability have a cast time) case 3422: if (abInfo.ConstantInfo.BaseCastTime == 0 || abInfo.ConstantInfo.ChannelID > 0 || abInfo.ConstantInfo.Origin == AbilityOrigin.AO_ITEM) { return; } break; // Shadow Prowler, Incognito (ability must break) case 8090: case 9393: if (abInfo.ConstantInfo.StealthInteraction == AbilityStealthType.Ignore) { return; } break; } if (myCommand.ConsumesStack) { while (Interlocked.CompareExchange(ref BuffStackLock, 1, 0) != 0) { ; } if (StackLevel == 0) { Interlocked.Exchange(ref BuffStackLock, 0); return; } RemoveStack(); Interlocked.Exchange(ref BuffStackLock, 0); } if (myCommand.CommandName == "None") { return; } BuffEffectInvoker.InvokeAbilityUseCommand(this, myCommand, abInfo); }
public virtual void OnCastAbility(AbilityInfo Ab) { }
public override void InvokeCastEvent(byte eventID, AbilityInfo abInfo) { HasSentEnd = true; TryCancel(); }
/// <summary> /// Sets and transmits the cooldown of the given ability. /// </summary> /// <param name="abilityId">Ifd of ability to reset</param> /// <param name="duration">Cooldown duration in milliseconds, -1 to reset</param> /// <param name="silent">False to transmit new value to client, true otherwise</param> public void SetCooldown(ushort abilityId, long duration, bool silent = false) { #if DEBUG && ABILITY_DEVELOPMENT duration = 0; #endif if (abilityId == ushort.MaxValue) { return; } AbilityInfo abInfo = AbilityMgr.GetAbilityInfo(abilityId); if (abInfo.IgnoreCooldownReduction == 1 && (abInfo.Cooldown * 1000) >= duration) { long nextTimestamp = 0; if (abInfo.CDcap != null && abInfo.CDcap * 1000 > duration) { nextTimestamp = (abInfo.CDcap * 1000) + TCPManager.GetTimeStampMS(); } else { nextTimestamp = (abInfo.Cooldown * 1000) + TCPManager.GetTimeStampMS(); } Cooldowns[abilityId] = nextTimestamp; if (silent) { return; } PacketOut Out = new PacketOut((byte)Opcodes.F_SET_ABILITY_TIMER, 12); Out.WriteUInt16(abilityId); Out.Fill(0, 2); Out.WriteUInt32(((uint)abInfo.Cooldown * 1000)); Out.Fill(0, 4); if (_Owner.IsPet()) { _Owner.GetPet().Owner.SendPacket(Out); } else { _playerOwner?.SendPacket(Out); } } if (abInfo.IgnoreCooldownReduction != 1 || (abInfo.IgnoreCooldownReduction == 1 && (abInfo.Cooldown * 1000) < duration)) { long nextTimestamp = 0; if (abInfo.CDcap != null && abInfo.CDcap * 1000 > duration) { nextTimestamp = (abInfo.CDcap * 1000) + TCPManager.GetTimeStampMS(); } else { nextTimestamp = (duration) + TCPManager.GetTimeStampMS(); } if (duration == -1 && abInfo.CDcap == null) { nextTimestamp = 0; } Cooldowns[abilityId] = nextTimestamp; if (silent) { return; } PacketOut Out = new PacketOut((byte)Opcodes.F_SET_ABILITY_TIMER, 12); Out.WriteUInt16(abilityId); Out.Fill(0, 2); Out.WriteUInt32(duration != -1 ? (uint)duration : 0); Out.Fill(0, 4); if (_Owner.IsPet()) { _Owner.GetPet().Owner.SendPacket(Out); } else { _playerOwner?.SendPacket(Out); } } }
public bool IsOnCooldown(AbilityInfo abInfo) { return((!CanCastCooldown(0) && !abInfo.ConstantInfo.IgnoreGlobalCooldown) || !CanCastCooldown(abInfo.ConstantInfo.CooldownEntry != 0 ? abInfo.ConstantInfo.CooldownEntry : abInfo.Entry)); }
/// <summary> /// Queried by the modifier check "Experimental Mode" to determine whether a given ability should be modified. /// </summary> public virtual bool ExperimentalModeCheckAbility(AbilityInfo abInfo) { return(_experimentalMode); }
public virtual void ExperimentalModeModifyAbility(AbilityInfo abInfo) { }
public bool StartCast(Unit instigator, ushort abilityID, byte castSequence, byte cooldownGroup = 0, byte overrideAbilityLevel = 0, bool enemyVisible = true, bool friendlyVisible = true, bool moving = false) { if (PreventCasting) { if (_Owner is Player) { (_Owner as Player)?.SendClientMessage("A developer has disabled all abilities.", ChatLogFilters.CHATLOGFILTERS_USER_ERROR); } return(false); } // Allow only interruption of channeled skills of a different ID to the skill being used if (IsCasting() && (!_abilityProcessor.IsChannelling || _abilityProcessor.AbInfo.Entry == abilityID)) { return(false); } AbilityInfo abInfo = AbilityMgr.GetAbilityInfo(abilityID); if (abInfo == null || (abInfo.ConstantInfo.Origin != AbilityOrigin.AO_ITEM && !IsValidAbility(abInfo))) { return(false); } //Fix so that WE/WH cant use all their 3 openers at the same time, this is in conjunction with whats in AbilityProcessor if (_Owner is Player) { if ((_Owner as Player).StealthLevel == 0 && (abilityID == 9406 || abilityID == 9401 || abilityID == 9411 || abilityID == 8091 || abilityID == 8096 || abilityID == 8098)) { return(false); } } try { if (AbilityMgr.HasCommandsFor(abilityID) || abInfo.ConstantInfo.ChannelID != 0) { if (_abilityProcessor == null) { _abilityProcessor = new AbilityProcessor(_unitOwner, this); } abInfo.Instigator = instigator; abInfo.Level = overrideAbilityLevel; return(_abilityProcessor.StartAbility(abInfo, castSequence, cooldownGroup, enemyVisible, friendlyVisible, moving)); } if (_Owner is Player) { Player owner = _Owner as Player; owner?.SendClientMessage(abilityID + " " + AbilityMgr.GetAbilityNameFor(abilityID) + " has no implementation.", ChatLogFilters.CHATLOGFILTERS_USER_ERROR); } return(false); } catch (Exception e) { if (_Owner is Player) { (_Owner as Player)?.SendClientMessage(abilityID + " " + AbilityMgr.GetAbilityNameFor(abilityID) + " threw an unhandled " + e.GetType().Name + " from " + e.TargetSite + "."); } Log.Error("Ability System", e.ToString()); return(false); } }
/// <summary> /// Identifies target of an ability before it is casted and checks its validity (pvp flag, visibility...). /// </summary> /// <param name="abInfo">Ability that is about to be casted</param> /// <param name="instigator">Instigator of the ability</param> /// <param name="foeVisible">True if current targeted foe is visible</param> /// <param name="allyVisible">True if current targeted ally is visible</param> /// <returns>True if target is valid for the ability</returns> private bool GetTarget(AbilityInfo abInfo, Unit instigator, bool foeVisible, bool allyVisible) { if (_pendingInfo.Range == 0 || _pendingInfo.CommandInfo == null) { _pendingInfo.Target = _caster; return(true); } if (_pendingInfo.TargetType == CommandTargetTypes.SiegeCannon) { _pendingInfo.Target = ((Creature)_caster).SiegeInterface.BuildTargetList(instigator); return(true); } CommandTargetTypes selectType = (CommandTargetTypes)((int)_pendingInfo.TargetType & 7); switch (selectType) { case CommandTargetTypes.Caster: _pendingInfo.Target = _caster; break; case CommandTargetTypes.Ally: if (!allyVisible) { return(false); } _pendingInfo.Target = _caster.CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ALLY); if (_pendingInfo.Target == _caster || !CombatInterface.IsFriend(_caster, _pendingInfo.Target) || (_pendingInfo.Target is Creature && !(_pendingInfo.Target is Pet))) { return(false); } if (_pendingInfo.TargetType.HasFlag(CommandTargetTypes.Groupmates)) { Group myGroup = ((Player)_caster).PriorityGroup; if (myGroup == null || !myGroup.HasMember(_pendingInfo.Target)) { return(false); } } break; case CommandTargetTypes.AllyOrSelf: if (!allyVisible) { return(false); } _pendingInfo.Target = _caster.CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ALLY) ?? _caster; if (!CombatInterface.IsFriend(_caster, _pendingInfo.Target) || (_pendingInfo.Target is Creature && !(_pendingInfo.Target is Pet))) { return(false); } if (_pendingInfo.Target != _caster) { if (_pendingInfo.TargetType.HasFlag(CommandTargetTypes.Groupmates)) { Group myGroup = ((Player)_caster).PriorityGroup; if (myGroup == null || !myGroup.HasMember(_pendingInfo.Target)) { return(false); } } } break; case CommandTargetTypes.AllyOrCareerTarget: if (!allyVisible) { return(false); } _pendingInfo.Target = _caster.CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ALLY); if (!CombatInterface.IsFriend(_caster, _pendingInfo.Target) || _pendingInfo.Target != null && (_pendingInfo.Target is Creature && !(_pendingInfo.Target is Pet))) { return(false); } if (_pendingInfo.Target != null && _pendingInfo.Target != _caster) { if (_pendingInfo.TargetType.HasFlag(CommandTargetTypes.Groupmates)) { Group myGroup = ((Player)_caster).PriorityGroup; if (myGroup == null || !myGroup.HasMember(_pendingInfo.Target)) { return(false); } } } else { Player petCareerPlr = null; if (_caster is Player) { petCareerPlr = _caster as Player; } if (petCareerPlr != null) { _pendingInfo.Target = petCareerPlr.CrrInterface.GetTargetOfInterest(); } if (_pendingInfo.Target == null || _pendingInfo.Target == _caster) { _pendingInfo.Target = null; return(false); } } break; case CommandTargetTypes.Enemy: if (!foeVisible) { return(false); } _pendingInfo.Target = _caster.CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ENEMY); if (!CombatInterface.CanAttack(_caster, _pendingInfo.Target)) { _pendingInfo.Target = null; } else { if (!_caster.CbtInterface.IsPvp) { Player plrCaster = _caster as Player; if (plrCaster != null && _pendingInfo.Target.CbtInterface.IsPvp) { ((CombatInterface_Player)plrCaster.CbtInterface).EnablePvp(); } } } Player plrTarget = _pendingInfo.Target as Player; if (plrTarget != null && plrTarget.Palisade != null && (plrTarget.Palisade.IsObjectInFront(_caster, 180) ^ plrTarget.Palisade.IsObjectInFront(plrTarget, 180))) { _pendingInfo.Target = plrTarget.Palisade; } //8410 - Terrible Embrace ; 9057 - Wings of Heaven ; 9178 - Fetch! ; 9186 - Pounce if (_pendingInfo.Target != null && (abInfo.Entry == 8410 || abInfo.Entry == 9057 || abInfo.Entry == 9178 || abInfo.Entry == 9186) && Math.Abs(_caster.Z - _pendingInfo.Target.Z) > 300) { _caster.AbtInterface.SetCooldown(abInfo.Entry, -1); return(false); } break; case CommandTargetTypes.CareerTarget: // Target of Interest (oath friend/dark protector/pet if player, master if pet) var player = _caster as Player; if (player != null) { _pendingInfo.Target = player.CrrInterface.GetTargetOfInterest(); } else { var pet = _caster as Pet; if (pet != null) { _pendingInfo.Target = pet.Owner; } else { Log.Error("NewAbility", "Ability " + _pendingInfo.Entry + " with targettype 5 has no target!"); _pendingInfo.Target = null; } } break; default: Log.Error("NewAbility", "Ability " + _pendingInfo.Entry + " with TargetType zero in 3 LSBs!"); _pendingInfo.Target = _caster; break; } if (_pendingInfo.TargetType.HasFlag(CommandTargetTypes.Groupmates) && _pendingInfo.Target != _caster) { Group myGroup = ((Player)_caster).PriorityGroup; if (myGroup == null || !myGroup.HasMember(_pendingInfo.Target)) { return(false); } } return(_pendingInfo.Target != null); }