/// <summary> /// Gets a spell info. /// </summary> /// <param name="id">The id.</param> /// <param name="level">The level.</param> /// <returns>The spell info if existing, null otherwise.</returns> public static Models.Spells.SpellInfo GetSpellInfo(ushort id, byte level) { Models.Spells.SpellInfo spellInfo = null; if (_spells.ContainsKey(id)) { _spells[id].TryGetValue(level, out spellInfo); } return(spellInfo); }
/// <summary> /// Handles line skills. /// </summary> /// <param name="attacker">The attacker.</param> /// <param name="packet">The packet.</param> /// <param name="spellPacket">The spell packet.</param> /// <param name="spellInfo">The spell info.</param> /// <returns>True if the skill was handled.</returns> public static bool Handle(AttackableEntityController attacker, Models.Packets.Entities.InteractionPacket packet, Models.Packets.Spells.SpellPacket spellPacket, Models.Spells.SpellInfo spellInfo) { spellPacket.Process = true; if (packet.TargetClientId == attacker.AttackableEntity.ClientId) { return(false); } var ila = new Tools.ILA( attacker.MapObject.X, packet.X, attacker.MapObject.Y, packet.Y, (byte)spellInfo.DbSpellInfo.Range); foreach (var possibleTarget in attacker.GetAllInScreen()) { if (spellPacket.Targets.Count > 8) { return(true); } var target = possibleTarget as AttackableEntityController; if (target != null) { if (!TargetValidation.Validate(attacker, target)) { continue; } if (target.ContainsStatusFlag(Enums.StatusFlag.Fly)) { continue; } if (!ila.InLine(target.MapObject.X, target.MapObject.Y)) { continue; } uint damage = Calculations.PhysicalCalculations.GetDamage(attacker.AttackableEntity, target.AttackableEntity); Damage.Process(attacker, target, ref damage, false); if (damage > 0) { TargetFinalization.SkillFinalize(attacker, target, spellPacket, damage); } } } return(true); }
/// <summary> /// Loads all the spell infos. /// </summary> public static void Load() { var spells = Database.Dal.Spells.GetAllSpellInfos(); foreach (var dbSpell in spells) { var spellInfo = new Models.Spells.SpellInfo(dbSpell); if (_spells.ContainsKey(spellInfo.Id)) { _spells[spellInfo.Id].TryAdd(spellInfo.Level, spellInfo); } else { if (_spells.TryAdd(spellInfo.Id)) { _spells[spellInfo.Id].TryAdd(spellInfo.Level, spellInfo); } } switch (spellInfo.Id) { case 5010: case 7020: case 1290: case 1260: case 5030: case 5040: case 7000: case 7010: case 7030: case 7040: case 1250: case 5050: case 5020: case 10490: case 1300: { if (spellInfo.DbSpellInfo.Distance >= 3) { spellInfo.DbSpellInfo.Distance = 3; } if (spellInfo.DbSpellInfo.Range > 3) { spellInfo.DbSpellInfo.Range = 3; } _weaponSpells.TryAdd(spellInfo.WeaponSubtype, spellInfo.Id); break; } } } }
/// <summary> /// Gets the higest level spell for a specific spell. /// </summary> /// <param name="id">The id.</param> /// <returns>The higest level spell for that specific spell.</returns> public static Models.Spells.SpellInfo GetHighestSpell(ushort id) { Models.Spells.SpellInfo spellInfo = null; if (_spells.ContainsKey(id)) { var spellCollection = _spells[id]; spellInfo = spellCollection[(byte)(spellCollection.Count - 1)]; } return(spellInfo); }
/// <summary> /// Handles a self curing skill. /// </summary> /// <param name="attacker">The attack.</param> /// <param name="target">The target.</param> /// <param name="packet">The packet.</param> /// <param name="spellPacket">The spell packet.</param> /// <param name="spellInfo">The spell info.</param> /// <returns>True if the skill was handled correct.</returns> public static bool HandleSelf(AttackableEntityController attacker, AttackableEntityController target, Models.Packets.Entities.InteractionPacket packet, Models.Packets.Spells.SpellPacket spellPacket, Models.Spells.SpellInfo spellInfo) { if (target == null) { target = attacker; } if (target.AttackableEntity.ClientId != attacker.AttackableEntity.ClientId) { return(false); } var attackerPlayer = attacker as Models.Entities.Player; if (attackerPlayer != null) { if (DateTime.UtcNow < attackerPlayer.NextSmallLongSkill) { attackerPlayer.SendSystemMessage("REST"); return(false); } attackerPlayer.NextSmallLongSkill = DateTime.UtcNow.AddMilliseconds(Data.Constants.Time.SmallLongSkillTime); } if (spellInfo.Id == 1190 || spellInfo.Id == 7016) { attacker.AttackableEntity.HP += spellInfo.DbSpellInfo.Power; } else { attacker.AttackableEntity.MP += spellInfo.DbSpellInfo.Power; } if (attackerPlayer != null) { uint newExperience = (uint)Drivers.Repositories.Safe.Random.Next((int)spellInfo.DbSpellInfo.Power, ((int)spellInfo.DbSpellInfo.Power * 2)); var skill = attackerPlayer.Spells.GetOrCreateSkill(spellInfo.Id); if (skill != null) { skill.Raise(newExperience); } } TargetFinalization.SkillFinalize(attacker, null, spellPacket, spellInfo.DbSpellInfo.Power); return(true); }
/// <summary> /// Handles the scatter skill. /// </summary> /// <param name="attacker">The attacker.</param> /// <param name="packet">The packet.</param> /// <param name="spellPacket">The spell packet.</param> /// <param name="spellInfo">The spell info.</param> /// <returns>True if the skill was handled correctly.</returns> public static bool Handle(AttackableEntityController attacker, Models.Packets.Entities.InteractionPacket packet, Models.Packets.Spells.SpellPacket spellPacket, Models.Spells.SpellInfo spellInfo) { spellPacket.Process = true; var attackerPlayer = attacker as Models.Entities.Player; if (attackerPlayer != null) { if (!Ranged.ProcessPlayer(attackerPlayer, packet, 3)) { return(false); } } var sector = new Tools.Sector(attacker.MapObject.X, attacker.MapObject.Y, packet.X, packet.Y); sector.Arrange(spellInfo.Sector, spellInfo.DbSpellInfo.Range); foreach (var possibleTarget in attacker.GetAllInScreen()) { if (spellPacket.Targets.Count > 8) { return(true); } var target = possibleTarget as AttackableEntityController; if (target != null) { if (!TargetValidation.Validate(attacker, target)) { continue; } if (target.ContainsStatusFlag(Enums.StatusFlag.Fly)) { continue; } if (!sector.Inside(target.MapObject.X, target.MapObject.Y)) { continue; } uint damage = Calculations.RangedCalculations.GetDamage(attacker.AttackableEntity, target.AttackableEntity); Damage.Process(attacker, target, ref damage, false); if (damage > 0) { TargetFinalization.SkillFinalize(attacker, target, spellPacket, damage); } } } if (attackerPlayer != null && spellPacket.Targets.Count > 0) { Ranged.DecreaseArrows(attackerPlayer, 3); } return(true); }
/// <summary> /// Handles a circular skill. /// </summary> /// <param name="attacker">The attacker.</param> /// <param name="packet">The packet.</param> /// <param name="spellPacket">The spell packet.</param> /// <param name="spellInfo">The spell info.</param> /// <param name="isMagic">Boolean determining whether the circular skill is a magic skill or not.</param> /// <returns>True if the skill was handled correct.</returns> /// <remarks>This handles all types of circular skills (Physical, Magic, Ranged.) however ranged and physical is determined from either the skill id or whether isMagic is set.</remarks> public static bool Handle(AttackableEntityController attacker, Models.Packets.Entities.InteractionPacket packet, Models.Packets.Spells.SpellPacket spellPacket, Models.Spells.SpellInfo spellInfo, bool isMagic) { spellPacket.Process = true; if (!isMagic && spellInfo.Id < 8000 && packet.TargetClientId == attacker.AttackableEntity.ClientId) { return(false); } var attackerPlayer = attacker as Models.Entities.Player; if (attackerPlayer != null) { if (DateTime.UtcNow < attackerPlayer.NextLongSkill) { attackerPlayer.SendSystemMessage("REST"); return(false); } attackerPlayer.NextLongSkill = DateTime.UtcNow.AddMilliseconds(Data.Constants.Time.LongSkillTime); } foreach (var possibleTarget in attacker.GetAllInScreen()) { if (spellPacket.Targets.Count > 8) { return(true); } var target = possibleTarget as AttackableEntityController; if (target != null) { if (!TargetValidation.Validate(attacker, target)) { continue; } if (target.ContainsStatusFlag(Enums.StatusFlag.Fly)) { continue; } if (Tools.RangeTools.GetDistanceU(attacker.MapObject.X, attacker.MapObject.Y, target.MapObject.X, target.MapObject.Y) >= 8) { continue; } bool isRanged = (spellInfo.Id == 8030 || spellInfo.Id == 10308 || spellInfo.Id == 7013 || spellInfo.Id > 10360); uint damage = isRanged ? Calculations.RangedCalculations.GetDamage(attacker.AttackableEntity, target.AttackableEntity) : isMagic? Calculations.MagicCalculations.GetDamage(attacker.AttackableEntity, target.AttackableEntity, spellInfo) : Calculations.PhysicalCalculations.GetDamage(attacker.AttackableEntity, target.AttackableEntity); Damage.Process(attacker, target, ref damage, false); if (isRanged && attackerPlayer != null) { Ranged.DecreaseArrows(attackerPlayer, 3); } if (damage > 0) { TargetFinalization.SkillFinalize(attacker, target, spellPacket, damage); } } } return(true); }
/// <summary> /// Handles the sector skills. /// </summary> /// <param name="attacker">The attacker.</param> /// <param name="packet">The packet.</param> /// <param name="spellPacket">The spell packet.</param> /// <param name="spellInfo">The spell info.</param> /// <param name="isMagic">Boolean determining whether the attack is magic or not.</param> /// <param name="isPoison">Booealning determining whether the attack is poisonous (Toxic fog.)</param> /// <returns>True if the skill was handled correctly.</returns> public static bool Handle(AttackableEntityController attacker, Models.Packets.Entities.InteractionPacket packet, Models.Packets.Spells.SpellPacket spellPacket, Models.Spells.SpellInfo spellInfo, bool isMagic, bool isPoison = false) { spellPacket.Process = true; if (packet.TargetClientId == attacker.AttackableEntity.ClientId) { return(false); } if (isPoison && Tools.RangeTools.GetDistanceU(attacker.MapObject.X, attacker.MapObject.Y, packet.X, packet.Y) >= 9) { return(false); } var attackerPlayer = attacker as Models.Entities.Player; if (attackerPlayer != null) { if (DateTime.UtcNow < attackerPlayer.NextLongSkill) { attackerPlayer.SendSystemMessage("REST"); return(false); } attackerPlayer.NextLongSkill = DateTime.UtcNow.AddMilliseconds(Data.Constants.Time.LongSkillTime); } ushort x = attacker.MapObject.X; ushort y = attacker.MapObject.Y; if (spellInfo.Id == 6001) { if (Tools.RangeTools.GetDistanceU(x, y, packet.X, packet.Y) > spellInfo.DbSpellInfo.Distance) { return(false); } x = packet.X; y = packet.Y; } var sector = new Tools.Sector(x, y, packet.X, packet.Y); sector.Arrange(spellInfo.Sector, spellInfo.DbSpellInfo.Range); foreach (var possibleTarget in attacker.GetAllInScreen()) { if (spellPacket.Targets.Count > 8) { return(true); } var target = possibleTarget as AttackableEntityController; if (target != null) { if (!TargetValidation.Validate(attacker, target)) { continue; } if (target.ContainsStatusFlag(Enums.StatusFlag.Fly)) { continue; } if (!sector.Inside(target.MapObject.X, target.MapObject.Y)) { continue; } if (isPoison && target.ContainsStatusFlag(Enums.StatusFlag.Poisoned)) { continue; } uint damage = isPoison ? (uint)target.AttackableEntity.HP / 10 : isMagic? Calculations.MagicCalculations.GetDamage(attacker.AttackableEntity, target.AttackableEntity, spellInfo) : Calculations.PhysicalCalculations.GetDamage(attacker.AttackableEntity, target.AttackableEntity); if (isPoison) { target.AttackableEntity.PoisonEffect = (spellInfo.DbSpellInfo.Power - 30000); target.AddStatusFlag(Enums.StatusFlag.Poisoned, 60000); } Damage.Process(attacker, target, ref damage, false); if (damage > 0) { TargetFinalization.SkillFinalize(attacker, target, spellPacket, damage); } } } return(true); }
/// <summary> /// Handles single skills. /// </summary> /// <param name="attacker">The attacker.</param> /// <param name="target">The target.</param> /// <param name="packet">The packet.</param> /// <param name="spellPacket">The spell packet.</param> /// <param name="spellInfo">The spell info.</param> /// <param name="isMagic">Boolean determining whether the single attack is magic.</param> /// <param name="isRanged">Boolean determining whether the single attack is ranged.</param> /// <returns>True if the skill was handled correctly.</returns> /// <remarks>If both isMagic and isRanged is set to false then it's assumed as a physical skill.</remarks> public static bool Handle(AttackableEntityController attacker, AttackableEntityController target, Models.Packets.Entities.InteractionPacket packet, Models.Packets.Spells.SpellPacket spellPacket, Models.Spells.SpellInfo spellInfo, bool isMagic, bool isRanged = false) { if (target == null) { return(false); } if (attacker.AttackableEntity.ClientId == target.AttackableEntity.ClientId) { return(false); } if (!TargetValidation.Validate(attacker, target)) { return(false); } var attackerPlayer = attacker as Models.Entities.Player; if (isRanged) { if (attackerPlayer != null) { if (!Ranged.ProcessPlayer(attackerPlayer, packet, 1)) { return(false); } } Ranged.DecreaseArrows(attackerPlayer, 1); } uint damage = isRanged ? Calculations.RangedCalculations.GetDamage(attacker.AttackableEntity, target.AttackableEntity) : isMagic? Calculations.MagicCalculations.GetDamage(attacker.AttackableEntity, target.AttackableEntity, spellInfo) : Calculations.PhysicalCalculations.GetDamage(attacker.AttackableEntity, target.AttackableEntity); if (!isMagic) { damage = (uint)Math.Max(1, (int)(((double)damage) * (1.1 + (0.1 * spellInfo.Level)))); if (spellInfo.Id == 1290 && damage > 0 && !isRanged) { double damagePercentage = (double)((damage / 100) * 26.6); damage += (uint)(damagePercentage * spellInfo.Level); } if (spellInfo.Id == 6000 && damage > 0 && !isRanged) { damage = (uint)((damage / 100) * (spellInfo.DbSpellInfo.Power - 30000)); } } Damage.Process(attacker, target, ref damage, true); if (damage > 0) { TargetFinalization.SkillFinalize(attacker, target, spellPacket, damage); return(true); } return(false); }
/// <summary> /// Handling buffs and curse skills /// </summary> /// <param name="attacker">The attacker.</param> /// <param name="target">The target.</param> /// <param name="packet">The packet.</param> /// <param name="spellPacket">The spell packet.</param> /// <param name="spellInfo">The spell info.</param> /// <param name="curse">Boolean determining whether it should handle the skill as a curse.</param> /// <param name="disspell">Boolean determining whether it should handle the skill as a disspelling skill.</param> /// <returns>True if the skill was handled correct.</returns> public static bool Handle(AttackableEntityController attacker, AttackableEntityController target, Models.Packets.Entities.InteractionPacket packet, Models.Packets.Spells.SpellPacket spellPacket, Models.Spells.SpellInfo spellInfo, bool curse = false, bool disspell = false) { if (target == null) { return(false); } var targetPlayer = target as Models.Entities.Player; if (targetPlayer == null) { return(false); } if (!attacker.AttackableEntity.Alive) { return(false); } var attackerPlayer = attacker as Models.Entities.Player; if (attackerPlayer != null) { if (DateTime.UtcNow < attackerPlayer.NextSmallLongSkill) { attackerPlayer.SendSystemMessage("REST"); return(false); } attackerPlayer.NextSmallLongSkill = DateTime.UtcNow.AddMilliseconds(Data.Constants.Time.SmallLongSkillTime); } if (!targetPlayer.LoggedIn) { return(false); } uint damage = 0; if (curse) { if (!TargetValidation.Validate(attacker, target)) { return(false); } targetPlayer.AddStatusFlag(Enums.StatusFlag.NoPotion, (5000 * (spellInfo.Level + 1))); } else if (disspell) { targetPlayer.RemoveStatusFlag(Enums.StatusFlag.Fly); damage = (uint)Math.Max(1, (targetPlayer.HP / 10)); if (damage > 0) { Damage.Process(attacker, target, ref damage, false); } } else { var duration = spellInfo.DbSpellInfo.StepSecs * 1000; switch (spellInfo.Id) { case 1075: targetPlayer.AddStatusFlag(Enums.StatusFlag.PartiallyInvisible, duration); break; case 1085: targetPlayer.AddStatusFlag(Enums.StatusFlag.StarOfAccuracy, duration); break; case 1090: targetPlayer.AddStatusFlag(Enums.StatusFlag.Shield, duration); break; case 1095: targetPlayer.AddStatusFlag(Enums.StatusFlag.Stigma, duration); break; } } var maxExp = (int)(Math.Max(25, (int)targetPlayer.Level) / 2); uint newExperience = (uint)Drivers.Repositories.Safe.Random.Next(maxExp / 2, maxExp); var skill = targetPlayer.Spells.GetOrCreateSkill(spellInfo.Id); if (skill != null) { skill.Raise(newExperience); } TargetFinalization.SkillFinalize(attackerPlayer, targetPlayer, spellPacket, damage); return(true); }
/// <summary> /// Processes a player using a magic attack. /// </summary> /// <param name="player">The player.</param> /// <param name="packet">The packet.</param> /// <param name="spellPacket">The spell packet.</param> /// <param name="spellInfo">The spell info.</param> /// <returns>True if the player can handle the magic attack.</returns> private static bool ProcessPlayer(Player player, Models.Packets.Entities.InteractionPacket packet, Models.Packets.Spells.SpellPacket spellPacket, out Models.Spells.SpellInfo spellInfo) { spellInfo = null; ushort spellId = packet.MagicType; if (player.MaskedSkills.Contains(spellId)) { spellInfo = Collections.SpellInfoCollection.GetHighestSpell(spellId); } else { if (spellId >= 3090 && spellId <= 3306) { spellId = 3090; } if (spellId == 6012) { spellInfo = Collections.SpellInfoCollection.GetSpellInfo(6010, 0); packet.X = player.X; packet.Y = player.Y; } else { byte choseLevel = 0; if (spellId == packet.MagicType) { if (!player.Spells.ContainsSkill(spellId)) { return(false); } choseLevel = (byte)player.Spells.GetOrCreateSkill(spellId).Level; } if (!Collections.SpellInfoCollection.ContainsSpell(spellId, choseLevel)) { spellInfo = Collections.SpellInfoCollection.GetHighestSpell(spellId); } else { spellInfo = Collections.SpellInfoCollection.GetSpellInfo(spellId, choseLevel); } } } if (spellInfo == null) { return(false); } spellPacket.SpellId = spellInfo.Id; spellPacket.SpellLevel = spellInfo.Level; if (player.Battle != null) { return(player.Battle.HandleBeginHit_Magic(player, spellPacket)); } return(true); }
/// <summary> /// Handling a base magic attack. /// </summary> /// <param name="attacker">The attacker.</param> /// <param name="packet">The packet.</param> public static void Handle(Controllers.Entities.AttackableEntityController attacker, Models.Packets.Entities.InteractionPacket packet) { if (packet == null) { return; } Controllers.Entities.AttackableEntityController target; var canAttack = ValidateMagicAttack(attacker, packet, out target); if (canAttack == 0) { var spellPacket = new Models.Packets.Spells.SpellPacket { ClientId = attacker.AttackableEntity.ClientId, SpellId = packet.MagicType, SpellX = packet.X, SpellY = packet.Y, SpellLevel = 0 }; Models.Spells.SpellInfo spellInfo = null; var player = attacker as Player; var monster = attacker as Monster; if (player != null) { if (!ProcessPlayer(player, packet, spellPacket, out spellInfo)) { return; } // TODO: AI BOT ... } else if (monster != null) { if (Collections.SpellInfoCollection.ContainsSpell(packet.MagicType)) { spellInfo = Collections.SpellInfoCollection.GetHighestSpell(packet.MagicType); } } if (spellInfo != null) { if (packet.ClientId != attacker.AttackableEntity.ClientId && target != null) { spellPacket.SpellX = target.MapObject.X; spellPacket.SpellY = target.MapObject.Y; } if (spellInfo.DbSpellInfo.UseEP > 0) { if (player != null) { // TODO: IF NOT AI BOT if (spellInfo.Id != 7001 && player.Stamina < spellInfo.DbSpellInfo.UseEP || spellInfo.Id == 7001 && player.ContainsStatusFlag(Enums.StatusFlag.Riding) && player.Stamina < spellInfo.DbSpellInfo.UseEP) { return; } } } if (spellInfo.DbSpellInfo.UseMP > 0) { if (monster != null) { if (monster.MP < spellInfo.DbSpellInfo.UseMP && !monster.IsGuard) { return; } } else if (attacker.AttackableEntity.MP < spellInfo.DbSpellInfo.UseMP) { return; } } if (attacker.MapObject.Map == null) { return; } bool success = false; switch (packet.MagicType) { #region Line Skills case 1045: case 1046: case 11005: case 11000: success = Skills.LineSkills.Handle(attacker, packet, spellPacket, spellInfo); break; #endregion #region SectorSkills #region Magic case 1165: case 7014: success = Skills.SectorSkills.Handle(attacker, packet, spellPacket, spellInfo, true); break; #endregion #region Physical case 1250: case 5050: case 5020: case 1300: success = Skills.SectorSkills.Handle(attacker, packet, spellPacket, spellInfo, false); break; #endregion #endregion #region Single #region Magic case 10310: case 1000: case 1001: case 1002: case 1150: case 1160: case 1180: success = Skills.SingleSkills.Handle(attacker, target, packet, spellPacket, spellInfo, true); break; #endregion #region Physical case 1290: case 5030: case 5040: case 7000: case 7010: case 7030: case 7040: success = Skills.SingleSkills.Handle(attacker, target, packet, spellPacket, spellInfo, false); break; #endregion #endregion #region Circle #region Magic case 1010: //lightning tao case 1120: //fc case 1125: //volc case 3090: //pervade case 5001: //speed case 8030: //arrows case 7013: //flame shower case 30011: //small ice circle case 30012: //large ice circle case 10360: case 10361: case 10392: case 10308: success = Skills.CircleSkills.Handle(attacker, packet, spellPacket, spellInfo, true); break; #endregion #region Physical case 5010: case 7020: case 1115: //herc success = Skills.CircleSkills.Handle(attacker, packet, spellPacket, spellInfo, false); break; #endregion #endregion #region MountSkill case 7001: if (player != null) { success = Skills.MountSkill.Handle(player, spellPacket); } else { success = false; } break; #endregion #region Buff case 1075: case 1085: case 1090: case 1095: success = Skills.BuffCurseSkills.Handle(attacker, target, packet, spellPacket, spellInfo); break; #endregion #region Revive case 1050: case 1100: success = Skills.ReviveSkills.Handle(attacker, target, packet, spellPacket); break; #endregion #region Fly case 8002: case 8003: success = Skills.FlySkills.Handle(attacker); break; #endregion #region Scatter case 8001: success = Skills.ScatterSkill.Handle(attacker, packet, spellPacket, spellInfo); break; #endregion #region Cure #region Self case 1190: case 1195: case 7016: success = Skills.CureSkills.HandleSelf(attacker, target, packet, spellPacket, spellInfo); break; #endregion #region Surroundings case 1005: case 1055: case 1170: case 1175: success = Skills.CureSkills.HandleSurroundings(attacker, target, packet, spellPacket, spellInfo); break; #endregion #endregion #region Archer case 10313: case 8000: case 9991: case 7012: case 7015: case 7017: case 1320: success = Skills.SingleSkills.Handle(attacker, target, packet, spellPacket, spellInfo, false, true); break; #endregion #region Ninja #region Toxic Fog case 6001: success = Skills.SectorSkills.Handle(attacker, packet, spellPacket, spellInfo, false, true); break; #endregion #region TwoFold case 6000: success = Skills.SingleSkills.Handle(attacker, target, packet, spellPacket, spellInfo, false, false); break; #endregion #region PoisonStar case 6002: success = Skills.BuffCurseSkills.Handle(attacker, target, packet, spellPacket, spellInfo, true); break; #endregion #region ArcherBane case 6004: success = Skills.BuffCurseSkills.Handle(attacker, target, packet, spellPacket, spellInfo, false, true); break; #endregion #endregion default: { if (player != null) { player.SendFormattedSystemMessage("INVALID_SKILL", true, spellInfo.Id); } success = false; break; } } if (success) { if (spellInfo.DbSpellInfo.UseEP > 0) { if (player != null) { player.Stamina = (byte)Math.Max(0, (((int)player.Stamina) - spellInfo.DbSpellInfo.UseEP)); } } if (spellInfo.DbSpellInfo.UseMP > 0) { attacker.AttackableEntity.MP -= spellInfo.DbSpellInfo.UseMP; } attacker.UpdateScreen(false, spellPacket); // Not a single skill and skill is not safe, do damage here ... if (spellPacket.Targets.Count > 0 && !spellPacket.Safe && spellPacket.Process) { foreach (var spellTarget in spellPacket.Targets) { if (spellTarget.AssociatedEntity != null) { Damage.Hit(attacker, spellTarget.AssociatedEntity, spellTarget.Damage); } } } if (player != null) { player.ClientSocket.Send(spellPacket); if (spellPacket.SpellId >= 1000 && spellPacket.SpellId <= 1002) { packet.ActivationType = 0; packet.ActivationValue = 0; player.AttackPacket = packet; player.UseAutoAttack(packet); } } } } } }
/// <summary> /// Handles cure skills for surroundings. /// </summary> /// <param name="attacker">The attacker.</param> /// <param name="target">The target.</param> /// <param name="packet">The packet.</param> /// <param name="spellPacket">The spell packet.</param> /// <param name="spellInfo">The spell info.</param> /// <returns>True if the skill was handled correct.</returns> public static bool HandleSurroundings(AttackableEntityController attacker, AttackableEntityController target, Models.Packets.Entities.InteractionPacket packet, Models.Packets.Spells.SpellPacket spellPacket, Models.Spells.SpellInfo spellInfo) { spellPacket.Safe = true; if (target == null) { return(false); } var attackerPlayer = attacker as Models.Entities.Player; if (attackerPlayer != null) { if (DateTime.UtcNow < attackerPlayer.NextSmallLongSkill) { attackerPlayer.SendSystemMessage("REST"); return(false); } attackerPlayer.NextSmallLongSkill = DateTime.UtcNow.AddMilliseconds(Data.Constants.Time.SmallLongSkillTime); } var targetMonster = target as Models.Entities.Monster; if (targetMonster != null) { if (targetMonster.IsGuard) { return(false); } } target.AttackableEntity.HP += spellInfo.DbSpellInfo.Power; TargetFinalization.SkillFinalize(attacker, target, spellPacket, spellInfo.DbSpellInfo.Power); if (spellInfo.Id == 1055) { foreach (var possibleTarget in attacker.GetAllInScreen()) { if (possibleTarget.ClientId == target.AttackableEntity.ClientId) { continue; } if (Tools.RangeTools.GetDistanceU(possibleTarget.X, possibleTarget.Y, target.MapObject.X, target.MapObject.Y) > spellInfo.DbSpellInfo.Distance) { continue; } target = possibleTarget as AttackableEntityController; if (target == null) { continue; } targetMonster = possibleTarget as Models.Entities.Monster; if (targetMonster != null) { if (targetMonster.IsGuard) { continue; } } var targetPlayer = possibleTarget as Models.Entities.Player; if (targetPlayer != null) { if (!targetPlayer.LoggedIn) { continue; } } TargetFinalization.SkillFinalize(attacker, target, spellPacket, spellInfo.DbSpellInfo.Power); } } if (attackerPlayer != null) { uint newExperience = (uint)Drivers.Repositories.Safe.Random.Next((int)spellInfo.DbSpellInfo.Power, (int)(spellInfo.DbSpellInfo.Power * 2)); newExperience *= (uint)spellPacket.Targets.Count; var skill = attackerPlayer.Spells.GetOrCreateSkill(spellInfo.Id); if (skill != null) { skill.Raise(newExperience); } } return(true); }