public TrinitySpell(Unit caster, TrinitySpellInfo info, TriggerCastFlags triggerFlags, Guid originalCasterId, bool skipCheck = false) { SpellValue = new SpellValue(info); Caster = caster; SpellInfo = info; CastId = Guid.NewGuid(); OriginalCastId = CastId; SkipCheck = skipCheck; ExecutedCurrently = false; ApplyMultiplierMask = 0; DamageMultipliers = new float[3]; ReferencedFromCurrentSpell = false; SpellSchoolMask = SpellInfo.SchoolMask; if (originalCasterId != Guid.Empty) { OriginalCasterGuid = originalCasterId; } else { OriginalCasterGuid = caster.Character.Id; } if (OriginalCasterGuid == caster.Character.Id) { OriginalCaster = caster; } else { OriginalCaster = ArenaManager.ArenaUnits.Find(unit => unit.Character.Id == OriginalCasterGuid); } SpellState = SpellState.NONE; TriggerCastFlags = triggerFlags; UnitTarget = null; DestTarget = null; Damage = 0; Variance = 0.0f; EffectHandleMode = SpellEffectHandleMode.LAUNCH; EffectInfo = null; DiminishLevel = DiminishingLevels.LEVEL_1; DiminishGroup = DiminishingGroup.NONE; EffectDamage = 0; EffectHealing = 0; SpellAura = null; SpellVisual = SpellInfo.VisualId; CanReflect = SpellInfo.DamageClass == SpellDamageClass.MAGIC && !SpellInfo.HasAttribute(SpellAttributes.CANT_BE_REFLECTED) && !SpellInfo.IsPassive() && !SpellInfo.IsPositive(); UniqueTargets = new List <TargetInfo>(); SpellEffects = new List <TrinitySpellEffectInfo>(SpellInfo.SpellEffectInfos); }
static bool HandleCastCommand(CommandHandler handler, SpellInfo spell, string triggeredStr) { Unit target = handler.GetSelectedUnit(); if (!target) { handler.SendSysMessage(CypherStrings.SelectCharOrCreature); return(false); } if (!CheckSpellExistsAndIsValid(handler, spell)) { return(false); } TriggerCastFlags triggerFlags = TriggerCastFlags.None; if (!triggeredStr.IsEmpty()) { if ("triggered".Contains(triggeredStr)) // check if "triggered" starts with *triggeredStr (e.g. "trig", "trigger", etc.) { triggerFlags = TriggerCastFlags.FullDebugMask; } else { return(false); } } handler.GetSession().GetPlayer().CastSpell(target, spell.Id, new CastSpellExtraArgs(triggerFlags)); return(true); }
public void CastSpell(Unit target, TrinitySpellInfo spellInfo, TriggerCastFlags triggerFlags, AuraEffect triggeredByAura, Guid originalCaster) { SpellCastTargets targets = new SpellCastTargets(); targets.UnitTarget = target; CastSpell(targets, spellInfo, triggerFlags, triggeredByAura, originalCaster); }
void HandleScriptEffect(uint effIndex) { Unit target = GetHitUnit(); if (target) { // Cannot be processed while pet is dead TriggerCastFlags castMask = (TriggerCastFlags.FullMask & ~TriggerCastFlags.IgnoreCasterAurastate); target.CastSpell(target, SpellIds.MastersCallTriggered, castMask); } }
public void CastSpell(Unit target, int spellId, TriggerCastFlags triggerFlags, AuraEffect triggeredByAura, Guid originalCaster) { TrinitySpellInfo spellInfo = WarcraftDatabase.SpellInfos.ContainsKey(spellId) ? WarcraftDatabase.SpellInfos[spellId] : null; if (spellInfo == null) { Debug.LogError("Unknown spell for unit: " + gameObject.name); return; } CastSpell(target, spellInfo, triggerFlags, triggeredByAura, originalCaster); }
public void CastSpell(SpellCastTargets targets, TrinitySpellInfo spellInfo, TriggerCastFlags triggerFlags, AuraEffect triggeredByAura, Guid originalCaster) { if (spellInfo == null) { Debug.LogError("Unknown spell for unit: " + gameObject.name); return; } TrinitySpell spell = new TrinitySpell(this, spellInfo, triggerFlags, originalCaster); spell.Prepare(targets, triggeredByAura); }
public SpellCastResult CheckCast(bool strict) { // check death state if (!Caster.IsAlive() && !SpellInfo.IsPassive()) { return(SpellCastResult.CASTER_DEAD); } // check cooldowns to prevent cheating if (!SpellInfo.IsPassive()) { if (!Caster.Character.SpellHistory.IsReady(SpellInfo, IsIgnoringCooldowns())) { if (TriggeredByAuraSpell != null) { return(SpellCastResult.DONT_REPORT); } else { return(SpellCastResult.NOT_READY); } } } // Check global cooldown if (strict && !(TriggerCastFlags.HasFlag(TriggerCastFlags.IGNORE_GCD) && HasGlobalCooldown())) { return(SpellCastResult.NOT_READY); } // Check for line of sight for spells with dest /*if (m_targets.HasDst()) * { * float x, y, z; * m_targets.GetDstPos()->GetPosition(x, y, z); * * if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !m_caster->IsWithinLOS(x, y, z)) * return SPELL_FAILED_LINE_OF_SIGHT; * }*/ SpellCastResult castResult = SpellCastResult.SPELL_CAST_OK; // Triggered spells also have range check /// @todo determine if there is some flag to enable/disable the check castResult = CheckRange(strict); if (castResult != SpellCastResult.SPELL_CAST_OK) { return(castResult); } return(SpellCastResult.SUCCESS); }
void HandleDummy(uint effIndex) { Unit ally = GetHitUnit(); if (ally) { Player caster = GetCaster().ToPlayer(); if (caster) { Pet target = caster.GetPet(); if (target) { TriggerCastFlags castMask = (TriggerCastFlags.FullMask & ~TriggerCastFlags.IgnoreCasterAurastate); target.CastSpell(ally, (uint)GetEffectValue(), castMask); } } } }
public static bool HasFlag(this TriggerCastFlags baseFlags, TriggerCastFlags flag) { return((baseFlags & flag) == flag); }
void HandleCastSpell(CastSpell cast) { // ignore for remote control state (for player case) Unit mover = GetPlayer().GetUnitBeingMoved(); if (mover != GetPlayer() && mover.IsTypeId(TypeId.Player)) { return; } SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(cast.Cast.SpellID, mover.GetMap().GetDifficultyID()); if (spellInfo == null) { Log.outError(LogFilter.Network, "WORLD: unknown spell id {0}", cast.Cast.SpellID); return; } if (spellInfo.IsPassive()) { return; } Unit caster = mover; if (caster.IsTypeId(TypeId.Unit) && !caster.ToCreature().HasSpell(spellInfo.Id)) { // If the vehicle creature does not have the spell but it allows the passenger to cast own spells // change caster to player and let him cast if (!GetPlayer().IsOnVehicle(caster) || spellInfo.CheckVehicle(GetPlayer()) != SpellCastResult.SpellCastOk) { return; } caster = GetPlayer(); } TriggerCastFlags triggerFlag = TriggerCastFlags.None; // client provided targets SpellCastTargets targets = new(caster, cast.Cast); // check known spell or raid marker spell (which not requires player to know it) if (caster.IsTypeId(TypeId.Player) && !caster.ToPlayer().HasActiveSpell(spellInfo.Id) && !spellInfo.HasEffect(SpellEffectName.ChangeRaidMarker) && !spellInfo.HasAttribute(SpellAttr8.RaidMarker)) { bool allow = false; // allow casting of unknown spells for special lock cases GameObject go = targets.GetGOTarget(); if (go != null) { if (go.GetSpellForLock(caster.ToPlayer()) == spellInfo) { allow = true; } } // allow casting of spells triggered by clientside periodic trigger auras if (caster.HasAuraTypeWithTriggerSpell(AuraType.PeriodicTriggerSpellFromClient, spellInfo.Id)) { allow = true; triggerFlag = TriggerCastFlags.FullMask; } if (!allow) { return; } } // Check possible spell cast overrides spellInfo = caster.GetCastSpellInfo(spellInfo); // can't use our own spells when we're in possession of another unit, if (GetPlayer().IsPossessing()) { return; } // Client is resending autoshot cast opcode when other spell is cast during shoot rotation // Skip it to prevent "interrupt" message // Also check targets! target may have changed and we need to interrupt current spell if (spellInfo.IsAutoRepeatRangedSpell()) { Spell autoRepeatSpell = caster.GetCurrentSpell(CurrentSpellTypes.AutoRepeat); if (autoRepeatSpell != null) { if (autoRepeatSpell.m_spellInfo == spellInfo && autoRepeatSpell.m_targets.GetUnitTargetGUID() == targets.GetUnitTargetGUID()) { return; } } } // auto-selection buff level base at target level (in spellInfo) if (targets.GetUnitTarget() != null) { SpellInfo actualSpellInfo = spellInfo.GetAuraRankForLevel(targets.GetUnitTarget().GetLevelForTarget(caster)); // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message if (actualSpellInfo != null) { spellInfo = actualSpellInfo; } } if (cast.Cast.MoveUpdate.HasValue) { HandleMovementOpcode(ClientOpcodes.MoveStop, cast.Cast.MoveUpdate.Value); } Spell spell = new(caster, spellInfo, triggerFlag); SpellPrepare spellPrepare = new(); spellPrepare.ClientCastID = cast.Cast.CastID; spellPrepare.ServerCastID = spell.m_castId; SendPacket(spellPrepare); spell.m_fromClient = true; spell.m_misc.Data0 = cast.Cast.Misc[0]; spell.m_misc.Data1 = cast.Cast.Misc[1]; spell.Prepare(targets); }
void HandlePetCastSpell(PetCastSpell petCastSpell) { Unit caster = Global.ObjAccessor.GetUnit(GetPlayer(), petCastSpell.PetGUID); if (!caster) { Log.outError(LogFilter.Network, "WorldSession.HandlePetCastSpell: Caster {0} not found.", petCastSpell.PetGUID.ToString()); return; } SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(petCastSpell.Cast.SpellID, caster.GetMap().GetDifficultyID()); if (spellInfo == null) { Log.outError(LogFilter.Network, "WorldSession.HandlePetCastSpell: unknown spell id {0} tried to cast by {1}", petCastSpell.Cast.SpellID, petCastSpell.PetGUID.ToString()); return; } // This opcode is also sent from charmed and possessed units (players and creatures) if (caster != GetPlayer().GetGuardianPet() && caster != GetPlayer().GetCharmed()) { Log.outError(LogFilter.Network, "WorldSession.HandlePetCastSpell: {0} isn't pet of player {1} ({2}).", petCastSpell.PetGUID.ToString(), GetPlayer().GetName(), GetPlayer().GetGUID().ToString()); return; } SpellCastTargets targets = new(caster, petCastSpell.Cast); TriggerCastFlags triggerCastFlags = TriggerCastFlags.None; if (spellInfo.IsPassive()) { return; } // cast only learned spells if (!caster.HasSpell(spellInfo.Id)) { bool allow = false; // allow casting of spells triggered by clientside periodic trigger auras if (caster.HasAuraTypeWithTriggerSpell(AuraType.PeriodicTriggerSpellFromClient, spellInfo.Id)) { allow = true; triggerCastFlags = TriggerCastFlags.FullMask; } if (!allow) { return; } } Spell spell = new(caster, spellInfo, triggerCastFlags); spell.m_fromClient = true; spell.m_misc.Data0 = petCastSpell.Cast.Misc[0]; spell.m_misc.Data1 = petCastSpell.Cast.Misc[1]; spell.m_targets = targets; SpellCastResult result = spell.CheckPetCast(null); if (result == SpellCastResult.SpellCastOk) { Creature creature = caster.ToCreature(); if (creature) { Pet pet = creature.ToPet(); if (pet) { // 10% chance to play special pet attack talk, else growl // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell if (pet.GetPetType() == PetType.Summon && (RandomHelper.IRand(0, 100) < 10)) { pet.SendPetTalk(PetTalk.SpecialSpell); } else { pet.SendPetAIReaction(petCastSpell.PetGUID); } } } SpellPrepare spellPrepare = new(); spellPrepare.ClientCastID = petCastSpell.Cast.CastID; spellPrepare.ServerCastID = spell.m_castId; SendPacket(spellPrepare); spell.Prepare(targets); } else { spell.SendPetCastResult(result); if (!caster.GetSpellHistory().HasCooldown(spellInfo.Id)) { caster.GetSpellHistory().ResetCooldown(spellInfo.Id, true); } spell.Finish(false); spell.Dispose(); } }
public Spell(Unit caster, SpellInfo info, TriggerCastFlags triggerFlags, ulong originalCasterGUID = 0, bool skipCheck = false) { m_spellInfo = SpellMgr.GetSpellForDifficultyFromSpell(info, caster); m_caster = Convert.ToBoolean(info.AttributesEx6 & SpellAttr6.CastByCharmer) ? null : caster;//&& caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster m_spellValue = new SpellValue(m_spellInfo); m_customError = SpellCustomErrors.None; m_skipCheck = skipCheck; m_selfContainer = null; m_referencedFromCurrentSpell = false; m_executedCurrently = false; m_needComboPoints = m_spellInfo.NeedsComboPoints(); m_comboPointGain = 0; m_delayStart = 0; m_delayAtDamageCount = 0; m_applyMultiplierMask = 0; m_auraScaleMask = 0; // Get data for type of attack switch (m_spellInfo.DmgClass) { case SpellDmgClass.Melee: if (Convert.ToBoolean(m_spellInfo.AttributesEx3 & SpellAttr3.ReqOffhand)) { m_attackType = WeaponAttackType.OffAttack; } else { m_attackType = WeaponAttackType.BaseAttack; } break; case SpellDmgClass.Ranged: m_attackType = m_spellInfo.IsRangedWeaponSpell() ? WeaponAttackType.RangedAttack : WeaponAttackType.BaseAttack; break; default: // Wands if (Convert.ToBoolean(m_spellInfo.AttributesEx2 & SpellAttr2.AutorepeatFlag)) { m_attackType = WeaponAttackType.RangedAttack; } else { m_attackType = WeaponAttackType.BaseAttack; } break; } m_spellSchoolMask = info.GetSchoolMask(); // Can be override for some spell (wand shoot for example) if (m_attackType == WeaponAttackType.RangedAttack) { if ((m_caster.getClassMask() & SharedConst.ClassMaskWandUsers) != 0 && m_caster.GetTypeId() == ObjectType.Player) { Item pItem = m_caster.ToPlayer().GetWeaponForAttack(WeaponAttackType.RangedAttack); //if (pItem != null) //m_spellSchoolMask = (SpellSchoolMask)(1 << (int)pItem.ItemInfo.ItemSparse.DamageType); } } if (originalCasterGUID != 0) { m_originalCasterGUID = originalCasterGUID; } else { m_originalCasterGUID = m_caster.GetGUID(); } if (m_originalCasterGUID == m_caster.GetGUID()) { m_originalCaster = m_caster; } else { m_originalCaster = ObjMgr.GetObject <Unit>(m_caster, m_originalCasterGUID); if (m_originalCaster != null && !m_originalCaster.IsInWorld) { m_originalCaster = null; } } m_spellState = SpellState.None; _triggeredCastFlags = triggerFlags; if (Convert.ToBoolean(info.AttributesEx4 & SpellAttr4.Triggered)) { _triggeredCastFlags = TriggerCastFlags.FullMask; } m_CastItem = null; m_castItemGUID = 0; unitTarget = null; itemTarget = null; gameObjTarget = null; focusObject = null; m_cast_count = 0; m_glyphIndex = 0; m_preCastSpell = 0; //m_triggeredByAuraSpell = null; //m_spellAura = null; //Auto Shot & Shoot (wand) m_autoRepeat = m_spellInfo.IsAutoRepeatRangedSpell(); m_runesState = 0; m_powerCost = 0; // setup to correct value in Spell::prepare, must not be used before. m_casttime = 0; // setup to correct value in Spell::prepare, must not be used before. m_timer = 0; // will set to castime in prepare //m_channelTargetEffectMask = 0; // Determine if spell can be reflected back to the caster // Patch 1.2 notes: Spell Reflection no longer reflects abilities m_canReflect = m_spellInfo.DmgClass == SpellDmgClass.Magic && !Convert.ToBoolean(m_spellInfo.Attributes & SpellAttr0.Ability) && !Convert.ToBoolean(m_spellInfo.AttributesEx & SpellAttr1.CantBeReflected) && !Convert.ToBoolean(m_spellInfo.Attributes & SpellAttr0.UnaffectedByInvulnerability) && !m_spellInfo.IsPassive() && !m_spellInfo.IsPositive(); CleanupTargetList(); for (var i = 0; i < SharedConst.MaxSpellEffects; ++i) { m_destTargets[i] = new SpellDestination(m_caster); } }
public bool IsIgnoringCooldowns() { return(TriggerCastFlags.HasFlag(TriggerCastFlags.IGNORE_SPELL_AND_CATEGORY_CD)); }