public bool HasCooldown(int spellInfoId, bool ignoreCategoryCooldown) { if (SpellCooldowns.ContainsKey(spellInfoId)) { return(true); } return(false); }
public void AddCooldown(int spellId, float cooldownEnd) { CooldownEntry cooldownEntry = new CooldownEntry(spellId, cooldownEnd); if (SpellCooldowns.ContainsKey(spellId)) { SpellCooldowns[spellId] = cooldownEntry; } else { SpellCooldowns.Add(spellId, cooldownEntry); } }
private void TryCastSpells() { // Check if NPC is stunned/sleeping if (IsStunnedOrSleeping) { return; } //Check if NPC is casting a spell if (CastTime > Globals.Timing.TimeMs) { return; //can't move while casting } if (CastFreq >= Globals.Timing.TimeMs) { return; } // Check if the NPC is able to cast spells if (IsUnableToCastSpells) { return; } if (Base.Spells == null || Base.Spells.Count <= 0) { return; } // Pick a random spell var spellIndex = Randomization.Next(0, Spells.Count); var spellId = Base.Spells[spellIndex]; var spellBase = SpellBase.Get(spellId); if (spellBase == null) { return; } if (spellBase.Combat == null) { Log.Warn($"Combat data missing for {spellBase.Id}."); } var range = spellBase.Combat?.CastRange ?? 0; var targetType = spellBase.Combat?.TargetType ?? SpellTargetTypes.Single; var projectileBase = spellBase.Combat?.Projectile; if (spellBase.SpellType == SpellTypes.CombatSpell && targetType == SpellTargetTypes.Projectile && projectileBase != null && InRangeOf(Target, projectileBase.Range)) { range = projectileBase.Range; var dirToEnemy = DirToEnemy(Target); if (dirToEnemy != Dir) { if (LastRandomMove >= Globals.Timing.TimeMs) { return; } //Face the target -- next frame fire -- then go on with life ChangeDir(dirToEnemy); // Gotta get dir to enemy LastRandomMove = Globals.Timing.TimeMs + Randomization.Next(1000, 3000); return; } } if (spellBase.VitalCost == null) { return; } if (spellBase.VitalCost[(int)Vitals.Mana] > GetVital(Vitals.Mana)) { return; } if (spellBase.VitalCost[(int)Vitals.Health] > GetVital(Vitals.Health)) { return; } var spell = Spells[spellIndex]; if (spell == null) { return; } if (SpellCooldowns.ContainsKey(spell.SpellId) && SpellCooldowns[spell.SpellId] >= Globals.Timing.RealTimeMs) { return; } if (!InRangeOf(Target, range)) { // ReSharper disable once SwitchStatementMissingSomeCases switch (targetType) { case SpellTargetTypes.Self: case SpellTargetTypes.AoE: return; } } CastTime = Globals.Timing.TimeMs + spellBase.CastDuration; if (spellBase.VitalCost[(int)Vitals.Mana] > 0) { SubVital(Vitals.Mana, spellBase.VitalCost[(int)Vitals.Mana]); } else { AddVital(Vitals.Mana, -spellBase.VitalCost[(int)Vitals.Mana]); } if (spellBase.VitalCost[(int)Vitals.Health] > 0) { SubVital(Vitals.Health, spellBase.VitalCost[(int)Vitals.Health]); } else { AddVital(Vitals.Health, -spellBase.VitalCost[(int)Vitals.Health]); } if ((spellBase.Combat?.Friendly ?? false) && spellBase.SpellType != SpellTypes.WarpTo) { CastTarget = this; } else { CastTarget = Target; } switch (Base.SpellFrequency) { case 0: CastFreq = Globals.Timing.TimeMs + 30000; break; case 1: CastFreq = Globals.Timing.TimeMs + 15000; break; case 2: CastFreq = Globals.Timing.TimeMs + 8000; break; case 3: CastFreq = Globals.Timing.TimeMs + 4000; break; case 4: CastFreq = Globals.Timing.TimeMs + 2000; break; } SpellCastSlot = spellIndex; if (spellBase.CastAnimationId != Guid.Empty) { PacketSender.SendAnimationToProximity(spellBase.CastAnimationId, 1, Id, MapId, 0, 0, (sbyte)Dir); //Target Type 1 will be global entity } PacketSender.SendEntityVitals(this); PacketSender.SendEntityCastTime(this, spellId); }