public bool StartAbility(AbilityInfo abInfo, byte castSequence, byte cooldownGroup, bool foeVisible, bool allyVisible, bool moving) { _pendingInfo = abInfo; _pendingItemCooldownGroup = cooldownGroup; _pendingCastSequence = castSequence; //Cut in to manage toggle abilities here. if (_pendingInfo.ConstantInfo.ToggleEntry > 0) { NewBuff toToggle = _caster.BuffInterface.GetBuff(_pendingInfo.ConstantInfo.ToggleEntry, _caster); if (toToggle != null) { toToggle.BuffHasExpired = true; CancelPendingCast(); _abInterface.SetCooldown(abInfo.ConstantInfo.CooldownEntry != 0 ? abInfo.ConstantInfo.CooldownEntry : abInfo.Entry, abInfo.Cooldown * 1000); return(true); } } if (!GetTarget(abInfo, _pendingInfo.Instigator, foeVisible, allyVisible) && _pendingInfo.Range > 0) { CancelPendingCast(); return(false); } byte result = ModifyInitials(); if (!_pendingInfo.CanCastWhileMoving && _pendingInfo.CastTime > 0 && _pendingInfo.ConstantInfo.ChannelID == 0 && moving) { CancelPendingCast(); return(false); } if (result == 1 || !AllowStartCast()) { CancelPendingCast(); return(false); } if (result == 2) { _abInterface.SetGlobalCooldown(); CancelPendingCast(); return(false); } if (result == 3) { _abInterface.SetCooldown(_pendingInfo.ConstantInfo.CooldownEntry != 0 ? _pendingInfo.ConstantInfo.CooldownEntry : _pendingInfo.Entry, _pendingInfo.Cooldown * 1000); CancelPendingCast(); return(false); } if (!_caster.HasActionPoints(_pendingInfo.ApCost)) { CancelPendingCast(); return(false); } //fix so that WE/WH cant use all their 3 openers at the same time, this in conjunction with whats in AbilityInterface if (_caster is Player) { if ((_caster as Player).StealthLevel > 0 && (abInfo.Entry == 9406 || abInfo.Entry == 9401 || abInfo.Entry == 9411 || abInfo.Entry == 8091 || abInfo.Entry == 8096 || abInfo.Entry == 8098)) { (_caster as Player).Uncloak(); } } // Cast success. Cancel existing ability if any if (AbInfo != null) { CancelCast(0); } // Ether Dance / T'ree Hit Combo hold the resource state - need to check if they were broken using an attack of the same level if (_pendingInfo.SpecialCost > 0) { Player plr = _caster as Player; if (plr != null) { if (_pendingInfo.SpecialCost > 0) { if (!plr.CrrInterface.HasResource((byte)_pendingInfo.SpecialCost)) { CancelPendingCast(); return(false); } } } } AbInfo = _pendingInfo; _pendingInfo = null; _pendingItemCooldownGroup = 0; _pendingCastSequence = 0; if (AbInfo.Level == 0) { AbInfo.Level = _abInterface.GetMasteryLevelFor(AbInfo.ConstantInfo.MasteryTree); } _castSequence = castSequence; _itemCooldownGroup = cooldownGroup; _castStartTime = TCPManager.GetTimeStampMS(); _caster.BuffInterface.NotifyAbilityStarted(AbInfo); SendStart(); //Secondary system for VFX if (abInfo.VFXTarget != null && abInfo.abilityID != 0 && _caster is Player) { string temp = ""; if (abInfo.VFXTarget.Contains("Self")) { temp = (_caster as Player).Name; } else if (abInfo.VFXTarget.Contains("Hostile") && (_caster as Player).CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ENEMY) != null) { temp = (_caster as Player).CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ENEMY).Name; } else if (abInfo.VFXTarget.Contains("Friendly") && (_caster as Player).CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ALLY) != null) { temp = (_caster as Player).CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ALLY).Name; } //Pets are handled differently, dont ask me why /Natherul else if (abInfo.VFXTarget.Contains("Pet") && (_caster as Player).CrrInterface.GetTargetOfInterest() != null) { temp = (_caster as Player).CrrInterface.GetTargetOfInterest().Name; } temp += " " + abInfo.abilityID.ToString(); if (abInfo.effectID2 != 0) { temp += " " + abInfo.effectID2.ToString(); } if (abInfo.Time != 0 && (!abInfo.VFXTarget.Contains("Pet") || (abInfo.VFXTarget.Contains("Hostile") && (_caster as Player).CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ENEMY).IsPlayer()) || (abInfo.VFXTarget.Contains("Friendly") && (_caster as Player).CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ALLY).IsPlayer()))) { temp += " " + abInfo.Time.ToString() + " 0"; } if (abInfo.VFXTarget.Contains("aoe")) { temp += " " + abInfo.VFXTarget.Remove(0, abInfo.VFXTarget.IndexOf(' ') + 1); } List <string> paramValue = temp.Split(' ').ToList(); if (Regex.IsMatch(paramValue[0], @"^[a-zA-Z]+$")) { BaseCommands.PlayAbility((_caster as Player), ref paramValue); } } if (!AbInfo.ConstantInfo.IgnoreGlobalCooldown) { _abInterface.SetGlobalCooldown(); } if (AbInfo.ConstantInfo.ChannelID != 0) { // Channeled Morale 4s grant immunity and cannot be interrupted if (AbInfo.SpecialCost == -4) { _caster.AddCrowdControlImmunity((int)CrowdControlTypes.Unstoppable); _caster.IsImmovable = true; } _channelHandler.Initialize(AbInfo, castSequence); } // Instants else if (AbInfo.CastTime == 0) { Cast(); } // Casts need to check range 60% of the way in else { _shouldCheckRange = true; } if (_setbacks.Count > 0) { lock (_setbacks) _setbacks.Clear(); } return(true); }