public static void HandleSummonAttack(Character chr, Packet packet) { if (!ParseAttackData(chr, packet, out AttackData ad, AttackTypes.Summon)) { return; } var summonId = ad.SummonID; if (chr.Summons.GetSummon(summonId, out var summon)) { //SendMagicAttack(chr, ad); SendSummonAttack(chr, summon, ad); var totalDamage = 0; foreach (var ai in ad.Attacks) { try { var mob = chr.Field.GetMob(ai.MobMapId); if (mob != null) { foreach (int amount in ai.Damages) { totalDamage += amount; mob.GiveDamage(chr, amount); } var dead = mob.CheckDead(mob.Position, ai.HitDelay, chr.PrimaryStats.BuffMesoUP.N); if (!dead) { switch (summon.SkillId) { case Constants.Ranger.Skills.SilverHawk: case Constants.Sniper.Skills.GoldenEagle: var sld = CharacterSkills.GetSkillLevelData(summon.SkillId, summon.SkillLevel); if (!mob.IsBoss && totalDamage > 0 && Rand32.NextBetween(0, 100) < sld.Property) { int stunTime = ai.HitDelay + 4000; long expireTime = MasterThread.CurrentTime + stunTime; var stat = mob.Status.BuffStun.Set(summon.SkillId, -1, expireTime); MobPacket.SendMobStatsTempSet(mob, ai.HitDelay, stat); } break; } } } } catch (Exception ex) { Program.MainForm.LogAppend(ex.ToString()); } } } }
public static void HandleMagicAttack(Character chr, Packet packet) { //Program.MainForm.LogAppend("Handling Magic"); if (!ParseAttackData(chr, packet, out AttackData ad, AttackTypes.Magic)) { return; } int TotalDamage; double MaxSpellDamage; bool died; Mob mob; SendMagicAttack(chr, ad); if (ad.SkillID != 0) { chr.Skills.UseMeleeAttack(ad.SkillID, ad); } int StolenMP = 0; int MpStealSkillID = chr.Skills.GetMpStealSkillData(2, out int MpStealProp, out int MpStealPercent, out byte MpStealLevel); foreach (var ai in ad.Attacks) { try { TotalDamage = 0; mob = chr.Field.GetMob(ai.MobMapId); if (mob == null) { continue; } foreach (int amount in ai.Damages) { mob.GiveDamage(chr, amount); TotalDamage += amount; } if (MpStealPercent > 0) { StolenMP += mob.OnMobMPSteal(MpStealProp, MpStealPercent / ad.Targets); } if (TotalDamage == 0) { continue; } died = mob.CheckDead(ai.HitPosition, ai.HitDelay, chr.PrimaryStats.BuffMesoUP.N); if (!died) { var sld = DataProvider.Skills[ad.SkillID].Levels[ad.SkillLevel]; long buffTime = sld.BuffTime * 1000; //TODO refactor element code when we get the proper element loading with calcdamage branch if ((sld.ElementFlags == SkillElement.Ice || ad.SkillID == Constants.ILMage.Skills.ElementComposition) && !mob.IsBoss) { var stat = mob.Status.BuffFreeze.Set(ad.SkillID, 1, MasterThread.CurrentTime + buffTime); MobPacket.SendMobStatsTempSet(mob, ai.HitDelay, stat); } if (ad.SkillID == Constants.FPMage.Skills.ElementComposition && !mob.IsBoss) { if (Rand32.NextBetween(0, 100) < sld.Property) { mob.DoPoison(chr.ID, chr.Skills.GetSkillLevel(ad.SkillID), buffTime, ad.SkillID, sld.MagicAttack, ai.HitDelay); } } if (ad.SkillID == Constants.FPWizard.Skills.PoisonBreath) { if (Rand32.NextBetween(0, 100) < sld.Property) { mob.DoPoison(chr.ID, chr.Skills.GetSkillLevel(ad.SkillID), buffTime, ad.SkillID, sld.MagicAttack, ai.HitDelay); } } if (StolenMP > 0) { chr.ModifyMP((short)StolenMP); MapPacket.SendPlayerSkillAnimSelf(chr, MpStealSkillID, MpStealLevel); MapPacket.SendPlayerSkillAnim(chr, MpStealSkillID, MpStealLevel); } } switch (ad.SkillID) { case Constants.Magician.Skills.MagicClaw: // If the Spell is Magic Claw (since it registers two hits) MaxSpellDamage = DamageFormula.MaximumSpellDamage(chr, mob, ad.SkillID) * 2; break; case Constants.Cleric.Skills.Heal: // If the Spell is Heal (since it has a special snowflake calculation for it) if (mob.Data.Undead == false) { chr.PermaBan("Heal damaging regular mobs exploit"); return; } MaxSpellDamage = DamageFormula.MaximumHealDamage(chr, mob, ad.Targets); break; default: MaxSpellDamage = DamageFormula.MaximumSpellDamage(chr, mob, ad.SkillID); break; } if (TotalDamage > MaxSpellDamage) { if (ReportDamagehack(chr, ad, TotalDamage, (int)MaxSpellDamage)) { return; } } } catch (Exception ex) { Program.MainForm.LogAppend(ex.ToString()); } } }