public void TargetHit(IBattleEntity target, TargetHitType hitType, Skill skill, short?skillEffect = null, short?mapX = null, short?mapY = null, ComboDTO skillCombo = null, bool showTargetAnimation = false, bool isPvp = false) { if (!target.IsTargetable(Entity.SessionType(), isPvp) || (target.Faction == Entity.Faction && ServerManager.Instance.Act4Maps.Any(m => m == Entity.MapInstance))) { if (Session is Character cha) { cha.Session.SendPacket($"cancel 2 {target.GetId()}"); } return; } MapInstance mapInstance = target.MapInstance; int hitmode = 0; bool onyxWings = false; ushort damage = GenerateDamage(target, skill, ref hitmode, ref onyxWings); if (Session is Character charact && onyxWings && mapInstance != null) { short onyxX = (short)(charact.PositionX + 2); short onyxY = (short)(charact.PositionY + 2); int onyxId = mapInstance.GetNextId(); var onyx = new MapMonster { MonsterVNum = 2371, MapX = onyxX, MapY = onyxY, MapMonsterId = onyxId, IsHostile = false, IsMoving = false, ShouldRespawn = false }; mapInstance.Broadcast($"guri 31 1 {charact.CharacterId} {onyxX} {onyxY}"); onyx.Initialize(mapInstance); mapInstance.AddMonster(onyx); mapInstance.Broadcast(onyx.GenerateIn()); target.GetDamage(damage / 2, Entity, false); Observable.Timer(TimeSpan.FromMilliseconds(350)).Subscribe(o => { mapInstance.Broadcast($"su 3 {onyxId} 3 {target.GetId()} -1 0 -1 {skill.Effect} -1 -1 1 {(int)(target.CurrentHp / (double)target.MaxHp * 100)} {damage / 2} 0 0"); mapInstance.RemoveMonster(onyx); mapInstance.Broadcast(onyx.GenerateOut()); }); } if (target.GetSession() is Character character) { damage = (ushort)(character.HasGodMode ? 0 : damage); if (character.IsSitting) { character.IsSitting = false; character.MapInstance.Broadcast(character.GenerateRest()); } } else if (target.GetSession() is Mate mate) { if (mate.IsSitting) { mate.IsSitting = false; mate.Owner.MapInstance.Broadcast(mate.GenerateRest()); } } int castTime = 0; if (skill != null && skill.CastEffect != 0) { Entity.MapInstance.Broadcast(Entity.GenerateEff(skill.CastEffect), Entity.GetPos().X, Entity.GetPos().Y); castTime = skill.CastTime * 100; } Observable.Timer(TimeSpan.FromMilliseconds(castTime)).Subscribe(o => TargetHit2(target, hitType, skill, damage, hitmode, skillEffect, mapX, mapY, skillCombo, showTargetAnimation, isPvp)); }
public ushort GenerateDamage(IBattleEntity targetEntity, Skill skill, ref int hitmode, ref bool onyxEffect) { BattleEntity target = targetEntity?.BattleEntity; if (target == null) { return(0); } #region Definitions // Percent Damage if (target.Session is MapMonster monster && monster.IsPercentage && monster.TakesDamage > 0) { return((ushort)monster.TakesDamage); } AttackType attackType = Entity.GetAttackType(skill); int morale = Level + GetBuff(CardType.Morale, (byte)AdditionalTypes.Morale.MoraleIncreased)[0] - GetBuff(CardType.Morale, (byte)AdditionalTypes.Morale.MoraleDecreased)[0]; short upgrade = AttackUpgrade; int critChance = Critical; int critHit = CriticalRate; int minDmg = MinDamage; int maxDmg = MaxDamage; int hitRate = HitRate; #endregion #region Get Weapon Stats if (Session is Character character) { if (skill == null) { return(0); } if (skill.SkillVNum == 1085) // pas de bcard ... { character.TeleportOnMap(targetEntity.GetPos().X, targetEntity.GetPos().Y); } if (character.Inventory.LoadBySlotAndType <WearableInstance>((byte)EquipmentType.Amulet, InventoryType.Equipment)?.Item?.Effect == 932) { upgrade += 1; } DefenceUpgrade = character.Inventory?.Armor?.Upgrade ?? 0; if (CharacterHelper.Instance.GetClassAttackType(character.Class) == attackType) { minDmg += character.MinHit; maxDmg += character.MaxHit; hitRate += character.HitRate; critChance += character.HitCriticalRate; critHit += character.HitCritical; upgrade += character.Inventory.PrimaryWeapon?.Upgrade ?? 0; } else { minDmg += character.MinDistance; maxDmg += character.MaxDistance; hitRate += character.DistanceRate; critChance += character.DistanceCriticalRate; critHit += character.DistanceCritical; upgrade += character.Inventory.SecondaryWeapon?.Upgrade ?? 0; } } #endregion skill?.BCards?.ToList().ForEach(s => SkillBcards.Add(s)); #region Switch skill.Type int targetDefence = target.GetBuff(CardType.Defence, (byte)AdditionalTypes.Defence.AllIncreased)[0] - target.GetBuff(CardType.Defence, (byte)AdditionalTypes.Defence.AllDecreased)[0]; byte targetDefenseUpgrade = (byte)(target.GetBuff(CardType.Defence, (byte)AdditionalTypes.Defence.DefenceLevelIncreased)[0] - target.GetBuff(CardType.Defence, (byte)AdditionalTypes.Defence.DefenceLevelDecreased)[0]); int targetDodge = target.GetBuff(CardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DodgeIncreased)[0] - target.GetBuff(CardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DodgeDecreased)[0]; int targetMorale = target.Level + target.GetBuff(CardType.Morale, (byte)AdditionalTypes.Morale.MoraleIncreased)[0] - target.GetBuff(CardType.Morale, (byte)AdditionalTypes.Morale.MoraleDecreased)[0]; int targetBoostpercentage = 0; int boost = GetBuff(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.AllAttacksIncreased)[0] - GetBuff(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.AllAttacksDecreased)[0]; int boostpercentage = GetBuff(CardType.Damage, (byte)AdditionalTypes.Damage.DamageIncreased)[0] - GetBuff(CardType.Damage, (byte)AdditionalTypes.Damage.DamageDecreased)[0]; switch (attackType) { case AttackType.Close: targetDefence += target.CloseDefence; targetDodge += target.DefenceRate; targetBoostpercentage = target.GetBuff(CardType.Defence, (byte)AdditionalTypes.Defence.MeleeIncreased)[0] - target.GetBuff(CardType.Defence, (byte)AdditionalTypes.Defence.MeleeDecreased)[0]; boost += GetBuff(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksIncreased)[0] - GetBuff(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksDecreased)[0]; boostpercentage += GetBuff(CardType.Damage, (byte)AdditionalTypes.Damage.MeleeIncreased)[0] - GetBuff(CardType.Damage, (byte)AdditionalTypes.Damage.MeleeDecreased)[0]; break; case AttackType.Ranged: targetDefence += target.RangedDefence; targetDodge += target.DistanceDefenceRate; targetBoostpercentage = target.GetBuff(CardType.Defence, (byte)AdditionalTypes.Defence.RangedIncreased)[0] - target.GetBuff(CardType.Defence, (byte)AdditionalTypes.Defence.RangedDecreased)[0]; boost += GetBuff(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.RangedAttacksIncreased)[0] - GetBuff(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.RangedAttacksDecreased)[0]; boostpercentage += GetBuff(CardType.Damage, (byte)AdditionalTypes.Damage.RangedIncreased)[0] - GetBuff(CardType.Damage, (byte)AdditionalTypes.Damage.RangedDecreased)[0]; break; case AttackType.Magical: targetDefence += target.MagicDefence; targetBoostpercentage = target.GetBuff(CardType.Defence, (byte)AdditionalTypes.Defence.MagicalIncreased)[0] - target.GetBuff(CardType.Defence, (byte)AdditionalTypes.Defence.MeleeDecreased)[0]; boost += GetBuff(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MagicalAttacksIncreased)[0] - GetBuff(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MagicalAttacksDecreased)[0]; boostpercentage += GetBuff(CardType.Damage, (byte)AdditionalTypes.Damage.MagicalIncreased)[0] - GetBuff(CardType.Damage, (byte)AdditionalTypes.Damage.MagicalDecreased)[0]; break; } targetDefence = (int)(targetDefence * (1 + targetBoostpercentage / 100D)); minDmg += boost; maxDmg += boost; minDmg = (int)(minDmg * (1 + boostpercentage / 100D)); maxDmg = (int)(maxDmg * (1 + boostpercentage / 100D)); #endregion upgrade -= (short)(target.DefenceUpgrade + targetDefenseUpgrade); #region Detailed Calculation #region Dodge if (attackType != AttackType.Magical) { double multiplier = targetDodge / (hitRate + 1); if (multiplier > 5) { multiplier = 5; } double chance = -0.25 * Math.Pow(multiplier, 3) - 0.57 * Math.Pow(multiplier, 2) + 25.3 * multiplier - 1.41; if (chance <= 1) { chance = 1; } if (GetBuff(CardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DodgeIncreased)[0] != 0) { chance = 10; } if (skill?.Type == 0 || skill?.Type == 1) { if (ServerManager.Instance.RandomNumber() <= chance) { hitmode = 1; SkillBcards.Clear(); return(0); } } } #endregion #region Base Damage int baseDamage = ServerManager.Instance.RandomNumber(minDmg, maxDmg < minDmg ? minDmg + 1 : maxDmg) + morale - targetMorale; double upgradeBonus = 0; switch (Math.Abs(upgrade)) { case 1: upgradeBonus = 0.1; break; case 2: upgradeBonus = 0.15; break; case 3: upgradeBonus = 0.22; break; case 4: upgradeBonus = 0.32; break; case 5: upgradeBonus = 0.43; break; case 6: upgradeBonus = 0.54; break; case 7: upgradeBonus = 0.65; break; case 8: upgradeBonus = 0.9; break; case 9: upgradeBonus = 1.2; break; case 10: upgradeBonus = 2; break; } if (upgrade < 0) { targetDefence += (int)(targetDefence * upgradeBonus); } else { baseDamage += (int)(baseDamage * upgradeBonus); } baseDamage -= target.HasBuff(CardType.SpecialDefence, (byte)AdditionalTypes.SpecialDefence.AllDefenceNullified) ? 0 : targetDefence; if (skill?.Type == 1 && Map.Map.GetDistance(Entity.GetPos(), targetEntity.GetPos()) < 4) { baseDamage = (int)(baseDamage * 0.85); } #endregion #region Elementary Damage #region Calculate Elemental Boost + Rate double elementalBoost = 0; int targetResistance = 0; int elementalDamage = GetBuff(CardType.Element, (byte)AdditionalTypes.Element.AllIncreased)[0] - GetBuff(CardType.Element, (byte)AdditionalTypes.Element.AllDecreased)[0]; int bonusrez = target.GetBuff(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllIncreased)[0] - target.GetBuff(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllDecreased)[0]; switch (Element) { case 1: bonusrez += target.GetBuff(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.FireIncreased)[0] - target.GetBuff(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.FireDecreased)[0]; elementalDamage += GetBuff(CardType.Element, (byte)AdditionalTypes.Element.FireIncreased)[0] - GetBuff(CardType.Element, (byte)AdditionalTypes.Element.FireDecreased)[0]; targetResistance = target.FireResistance; switch (target.Element) { case 0: elementalBoost = 1.3; // Damage vs no element break; case 1: elementalBoost = 1; // Damage vs fire break; case 2: elementalBoost = 2; // Damage vs water break; case 3: elementalBoost = 1; // Damage vs light break; case 4: elementalBoost = 1.5; // Damage vs darkness break; } break; case 2: bonusrez += target.GetBuff(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.WaterIncreased)[0] - target.GetBuff(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.WaterDecreased)[0]; elementalDamage += GetBuff(CardType.Element, (byte)AdditionalTypes.Element.WaterIncreased)[0] - GetBuff(CardType.Element, (byte)AdditionalTypes.Element.WaterDecreased)[0]; targetResistance = target.WaterResistance; switch (target.Element) { case 0: elementalBoost = 1.3; break; case 1: elementalBoost = 2; break; case 2: elementalBoost = 1; break; case 3: elementalBoost = 1.5; break; case 4: elementalBoost = 1; break; } break; case 3: bonusrez += target.GetBuff(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.LightIncreased)[0] - target.GetBuff(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.LightDecreased)[0]; elementalDamage += GetBuff(CardType.Element, (byte)AdditionalTypes.Element.LightIncreased)[0] - GetBuff(CardType.Element, (byte)AdditionalTypes.Element.LightDecreased)[0]; targetResistance = target.LightResistance; switch (target.Element) { case 0: elementalBoost = 1.3; break; case 1: elementalBoost = 1.5; break; case 2: elementalBoost = 1; break; case 3: elementalBoost = 1; break; case 4: elementalBoost = 3; break; } break; case 4: bonusrez += target.GetBuff(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.DarkIncreased)[0] - target.GetBuff(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.DarkDecreased)[0]; targetResistance = target.DarkResistance; elementalDamage += GetBuff(CardType.Element, (byte)AdditionalTypes.Element.DarkIncreased)[0] - GetBuff(CardType.Element, (byte)AdditionalTypes.Element.DarkDecreased)[0]; switch (target.Element) { case 0: elementalBoost = 1.3; break; case 1: elementalBoost = 1; break; case 2: elementalBoost = 1.5; break; case 3: elementalBoost = 3; break; case 4: elementalBoost = 1; break; } break; } #endregion ; if (skill?.Element == 0) { switch (elementalBoost) { case 0.5: elementalBoost = 0; break; case 1: elementalBoost = 0.05; break; case 1.3: case 1.5: elementalBoost = 0.15; break; case 2: case 3: elementalBoost = 0.2; break; } } else if (skill?.Element != Element) { elementalBoost = 0; } int resistance = targetResistance + bonusrez; elementalDamage = (int)(elementalDamage + (baseDamage + 100) * ((ElementRate + ElementRateSp) / 100D)); elementalDamage = (int)(elementalDamage / 100D * (100 - (resistance > 100 ? 100 : resistance)) * elementalBoost); #endregion #region Critical Damage critChance += GetBuff(CardType.Critical, (byte)AdditionalTypes.Critical.InflictingIncreased)[0] - GetBuff(CardType.Critical, (byte)AdditionalTypes.Critical.InflictingReduced)[0]; critHit += GetBuff(CardType.Critical, (byte)AdditionalTypes.Critical.DamageIncreased)[0] - GetBuff(CardType.Critical, (byte)AdditionalTypes.Critical.DamageIncreasedInflictingReduced)[0]; if (ServerManager.Instance.RandomNumber() <= critChance) { if (skill?.Type != 2 && attackType != AttackType.Magical) { double multiplier = critHit / 100D; multiplier = multiplier > 3 ? 3 : multiplier; baseDamage += (int)(baseDamage * multiplier); hitmode = 3; } } #endregion // OFFENSIVE POTION baseDamage += (int)(baseDamage * GetBuff(CardType.Item, (byte)AdditionalTypes.Item.AttackIncreased)[0] / 100D); if (Session is Character charact) { int[] weaponSoftDamage = charact.GetWeaponSoftDamage(); if (ServerManager.Instance.RandomNumber() < weaponSoftDamage[0]) { charact.MapInstance.Broadcast(charact.GenerateEff(15)); baseDamage += (int)(baseDamage * (1 + (weaponSoftDamage[1] / 100D))); } if (charact.HasBuff(CardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.IncreasingPropability, true)) { charact.MapInstance.Broadcast(charact.GenerateEff(15)); baseDamage += (int)(baseDamage * (1 + GetBuff(CardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage .IncreasingPropability)[0] / 100D)); } if (charact.ChargeValue > 0) { baseDamage += charact.ChargeValue; charact.ChargeValue = 0; charact.RemoveBuff(0); } baseDamage += charact.Class == ClassType.Adventurer ? 20 : 0; } #region Total Damage int totalDamage = baseDamage + elementalDamage; totalDamage = totalDamage < 5 ? ServerManager.Instance.RandomNumber(1, 6) : totalDamage; #endregion if (Session is MapMonster) { if (Level < 45) { //no minimum damage } else if (Level < 55) { totalDamage += Level; } else if (Level < 60) { totalDamage += Level * 2; } else if (Level < 65) { totalDamage += Level * 3; } else if (Level < 70) { totalDamage += Level * 4; } else { totalDamage += Level * 5; } } if (targetEntity.GetSession() is Character chara && target.HasBuff(CardType.NoDefeatAndNoDamage, (byte)AdditionalTypes.NoDefeatAndNoDamage.TransferAttackPower)) { chara.ChargeValue = totalDamage; chara.AddBuff(new Buff.Buff(0)); totalDamage = 0; hitmode = 1; } #endregion totalDamage = totalDamage > ushort.MaxValue ? ushort.MaxValue : totalDamage; #region Onyx Wings onyxEffect = GetBuff(CardType.StealBuff, (byte)AdditionalTypes.StealBuff.ChanceSummonOnyxDragon)[0] > ServerManager.Instance.RandomNumber(); #endregion SkillBcards.Clear(); totalDamage = totalDamage > ushort.MaxValue ? ushort.MaxValue : totalDamage; if (Session is Character charac && targetEntity is MapMonster cali && cali.MonsterVNum == 2305 && Caligor.IsRunning) { switch (charac.Faction) { case FactionType.Angel: Caligor.AngelDamage += totalDamage + (onyxEffect ? totalDamage / 2 : 0); break; case FactionType.Demon: Caligor.DemonDamage += totalDamage + (onyxEffect ? totalDamage / 2 : 0); break; } } return((ushort)totalDamage); }
/// <summary> /// Hostility on actual Target /// </summary> internal void HostilityTarget() { if (!IsHostile || Target != null) { return; } IBattleEntity target = MapInstance.BattleEntities.FirstOrDefault(e => e.IsTargetable(SessionType()) && IsFactionTargettable(e.Faction) && Map.GetDistance(GetPos(), e.GetPos()) < (NoticeRange == 0 ? Monster.NoticeRange : NoticeRange)); if (target == null || MoveEvent != null) { return; } if (OnNoticeEvents.Any()) { OnNoticeEvents.ToList().ForEach(e => { EventHelper.Instance.RunEvent(e, monster: this); }); OnNoticeEvents.Clear(); return; } Target = target; if (!Monster.NoAggresiveIcon && LastEffect.AddSeconds(5) < DateTime.Now && target.GetSession() is Character character) { character?.Session.SendPacket(GenerateEff(5000)); } }
private void TargetHit2(IBattleEntity target, TargetHitType hitType, Skill skill, int damage, int hitmode, short?skillEffect = null, short?mapX = null, short?mapY = null, ComboDTO skillCombo = null, bool showTargetAnimation = false, bool isPvp = false, bool isRange = false) { target.GetDamage(target.BattleEntity.IsReflecting ? 0 : target.DealtDamage, Entity, !(Session is MapMonster mon && mon.IsInvicible)); string str = $"su {(byte)Entity.SessionType()} {Entity.GetId()} {(byte)target.SessionType()} {target.GetId()} {skill?.SkillVNum ?? 0} {skill?.Cooldown ?? 0}"; switch (hitType) { case TargetHitType.SingleTargetHit: str += $" {skill?.AttackAnimation ?? 11} {skill?.Effect ?? skillEffect ?? 0} {Entity.GetPos().X} {Entity.GetPos().Y} {(target.CurrentHp > 0 ? 1 : 0)} {(int)(target.CurrentHp / (double)target.MaxHp * 100)} {(target.BattleEntity.IsReflecting ? 0 : target.DealtDamage)} {hitmode} {skill?.SkillType - 1 ?? 0}"; break; case TargetHitType.SingleTargetHitCombo: str += $" {skillCombo?.Animation ?? 0} {skillCombo?.Effect ?? 0} {Entity.GetPos().X} {Entity.GetPos().Y} {(target.CurrentHp > 0 ? 1 : 0)} {(int)(target.CurrentHp / (double)target.MaxHp * 100)} {(target.BattleEntity.IsReflecting ? 0 : target.DealtDamage)} {hitmode} {skill.SkillType - 1}"; break; case TargetHitType.SingleAOETargetHit: switch (hitmode) { case 1: hitmode = 4; break; case 3: hitmode = 6; break; default: hitmode = 5; break; } if (showTargetAnimation) { Entity.MapInstance.Broadcast( $" {skill?.AttackAnimation ?? 0} {skill?.Effect ?? 0} 0 0 {(target.CurrentHp > 0 ? 1 : 0)} {(int)(target.CurrentHp / (double)target.MaxHp * 100)} 0 0 {skill.SkillType - 1}"); } str += $" {skill?.AttackAnimation ?? 0} {skill?.Effect ?? 0} {Entity.GetPos().X} {Entity.GetPos().Y} {(target.CurrentHp > 0 ? 1 : 0)} {(int)(target.CurrentHp / (double)target.MaxHp * 100)} {(target.BattleEntity.IsReflecting ? 0 : target.DealtDamage)} {hitmode} {skill.SkillType - 1}"; break; case TargetHitType.AOETargetHit: switch (hitmode) { case 1: hitmode = 4; break; case 3: hitmode = 6; break; default: hitmode = 5; break; } str += $" {skill?.AttackAnimation ?? 0} {skill?.Effect ?? 0} {Entity.GetPos().X} {Entity.GetPos().Y} {(target.CurrentHp > 0 ? 1 : 0)} {(int)(target.CurrentHp / (double)target.MaxHp * 100)} {(target.BattleEntity.IsReflecting ? 0 : target.DealtDamage)} {hitmode} {skill.SkillType - 1}"; break; case TargetHitType.ZoneHit: str += $" {skill?.AttackAnimation ?? 0} {skillEffect ?? 0} {mapX ?? Entity.GetPos().X} {mapY ?? Entity.GetPos().Y} {(target.CurrentHp > 0 ? 1 : 0)} {(int)(target.CurrentHp / (double)target.MaxHp * 100)} {(target.BattleEntity.IsReflecting ? 0 : target.DealtDamage)} 5 {skill.SkillType - 1}"; break; case TargetHitType.SpecialZoneHit: str += $" {skill?.AttackAnimation ?? 0} {skillEffect ?? 0} {Entity.GetPos().X} {Entity.GetPos().Y} {(target.CurrentHp > 0 ? 1 : 0)} {(int)(target.CurrentHp / (double)target.MaxHp * 100)} {(target.BattleEntity.IsReflecting ? 0 : target.DealtDamage)} 0 {skill.SkillType - 1}"; break; } Entity.MapInstance.Broadcast(str); bool isBoss = false; if (Entity.GetSession() is Character character) { character.LastSkillUse = DateTime.Now; RemoveBuff(85); // Hideout } else if (Entity.GetSession() is Mate mate) { mate.LastSkillUse = DateTime.Now; } if (target.GetSession() is MapMonster monster) { if (monster.Target == null) { monster.LastSkill = DateTime.Now; } monster.Target = Entity; isBoss = monster.IsBoss; if (isBoss) { Entity.MapInstance?.Broadcast(monster.GenerateBoss()); } monster.DamageList.AddOrUpdate(Entity, damage, (key, oldValue) => oldValue + damage); } if (!isBoss && skill != null && hitmode != 1) { if ((target.BattleEntity.CostumeHatBcards == null || !target.BattleEntity.CostumeHatBcards.Any()) && target is Character targetCharacter) { var hat = targetCharacter.Inventory.LoadBySlotAndType <WearableInstance>((byte)EquipmentType.CostumeHat, InventoryType.Wear); hat?.Item.BCards.ForEach(s => target.BattleEntity.CostumeHatBcards.Add(s)); } if ((target.BattleEntity.CostumeSuitBcards == null || !target.BattleEntity.CostumeSuitBcards.Any()) && target is Character targetCharacter2) { var costume = targetCharacter2.Inventory.LoadBySlotAndType <WearableInstance>((byte)EquipmentType.CostumeHat, InventoryType.Wear); costume?.Item.BCards.ForEach(s => target.BattleEntity.CostumeSuitBcards.Add(s)); } foreach (BCard bcard in target.BattleEntity.CostumeSuitBcards.Where(s => s != null)) { switch ((CardType)bcard.Type) { case CardType.Buff: var b = new Buff.Buff(bcard.SecondData); switch (b.Card?.BuffType) { case BuffType.Bad: bcard.ApplyBCards(Entity, Entity); break; case BuffType.Good: case BuffType.Neutral: bcard.ApplyBCards(target, Entity); break; } break; } } foreach (BCard bcard in target.BattleEntity.CostumeSuitBcards.Where(s => s != null)) { switch ((CardType)bcard.Type) { case CardType.Buff: var b = new Buff.Buff(bcard.SecondData); switch (b.Card?.BuffType) { case BuffType.Bad: bcard.ApplyBCards(Entity, Entity); break; case BuffType.Good: case BuffType.Neutral: bcard.ApplyBCards(target, Entity); break; } break; } } foreach (BCard bc in StaticBcards.Where(s => s != null)) { switch ((CardType)bc.Type) { case CardType.Buff: var b = new Buff.Buff(bc.SecondData); switch (b.Card?.BuffType) { case BuffType.Bad: bc.ApplyBCards(target, Entity); break; case BuffType.Good: case BuffType.Neutral: bc.ApplyBCards(Entity, Entity); break; } break; } } foreach (BCard bcard in skill.BCards.Where(b => b != null)) { switch ((CardType)bcard.Type) { case CardType.Buff: var b = new Buff.Buff(bcard.SecondData); switch (b.Card?.BuffType) { case BuffType.Bad: bcard.ApplyBCards(target, Entity); break; case BuffType.Good: case BuffType.Neutral: bcard.ApplyBCards(Entity, Entity); break; } break; case CardType.HealingBurningAndCasting: switch ((AdditionalTypes.HealingBurningAndCasting)bcard.SubType) { case AdditionalTypes.HealingBurningAndCasting.RestoreHP: case AdditionalTypes.HealingBurningAndCasting.RestoreHPWhenCasting: bcard.ApplyBCards(Entity, Entity); break; default: bcard.ApplyBCards(target, Entity); break; } break; case CardType.MeditationSkill: bcard.ApplyBCards(Entity); break; default: bcard.ApplyBCards(target, Entity); break; } } } if (skill == null || skill.Range <= 0 && skill.TargetRange <= 0 || isRange || !(Entity.GetSession() is MapMonster)) { return; } foreach (IBattleEntity entitiesInRange in Entity.MapInstance ?.GetBattleEntitiesInRange(Entity.GetPos(), skill.TargetRange) .Where(e => e != target && e.IsTargetable(Entity.SessionType()))) { TargetHit2(entitiesInRange, TargetHitType.SingleTargetHit, skill, damage, hitmode, isRange: true); } }
public void TargetHit(IBattleEntity target, TargetHitType hitType, Skill skill, short?skillEffect = null, short?mapX = null, short?mapY = null, ComboDTO skillCombo = null, bool showTargetAnimation = false, bool isPvp = false) { if (target == null || Entity == null) { return; } if (!target.IsTargetable(Entity.SessionType(), isPvp) || target.Faction == Entity.Faction && ServerManager.Instance.Act4Maps.Any(m => m == Entity.MapInstance)) { if (Session is Character cha) { cha.Session.SendPacket($"cancel 2 {target.GetId()}"); } return; } MapInstance mapInstance = target.MapInstance; int hitmode = 0; bool onyxWings = false; int damage = DamageHelper.Instance.GenerateDamage(this, target, skill, ref hitmode, ref onyxWings); if (skill != null && SkillHelper.Instance.NoDamageSkills != null) { if (SkillHelper.Instance.NoDamageSkills.Any(s => s == skill.SkillVNum)) { target.DealtDamage = 0; damage = 0; } } if (Session is Character charact && mapInstance != null && hitmode != 1) { target.RemoveBuff(548); if (onyxWings) { short onyxX = (short)(charact.PositionX + 2); short onyxY = (short)(charact.PositionY + 2); int onyxId = mapInstance.GetNextId(); var onyx = new MapMonster { MonsterVNum = 2371, MapX = onyxX, MapY = onyxY, MapMonsterId = onyxId, IsHostile = false, IsMoving = false, ShouldRespawn = false }; mapInstance.Broadcast($"guri 31 1 {charact.CharacterId} {onyxX} {onyxY}"); onyx.Initialize(mapInstance); mapInstance.AddMonster(onyx); mapInstance.Broadcast(onyx.GenerateIn()); target.GetDamage(target.DealtDamage / 2, Entity, false); Observable.Timer(TimeSpan.FromMilliseconds(350)).Subscribe(o => { mapInstance.Broadcast( $"su 3 {onyxId} {(target is Character ? "1" : "3")} {target.GetId()} -1 0 -1 {skill.Effect} -1 -1 1 {(int)(target.CurrentHp / (double)target.MaxHp * 100)} {(target.BattleEntity.IsReflecting ? 0 : target.DealtDamage) / 2} 0 0"); mapInstance.RemoveMonster(onyx); mapInstance.Broadcast(onyx.GenerateOut()); }); } if (target is Character tchar) { if (tchar.ReflectiveBuffs.Any()) { int?multiplier = 0; foreach (KeyValuePair <short, int?> entry in tchar.ReflectiveBuffs) { multiplier += entry.Value; } ushort damaged = (ushort)(damage > tchar.Level * multiplier ? tchar.Level * multiplier : damage); mapInstance.Broadcast( $"su 1 {tchar.GetId()} 1 {charact.GetId()} -1 0 -1 {skill.Effect} -1 -1 1 {(int)(tchar.Hp / (double)target.MaxHp * 100)} {damaged} 0 1"); charact.Hp = charact.Hp - damaged <= 0 ? 1 : charact.Hp - damaged; charact.Session.SendPacket(charact.GenerateStat()); target.DealtDamage = 0; } } else if (target is MapMonster tmon) { if (tmon.ReflectiveBuffs.Any()) { int?multiplier = 0; foreach (KeyValuePair <short, int?> entry in tmon.ReflectiveBuffs) { multiplier += entry.Value; } ushort damaged = (ushort)(damage > tmon.Monster.Level * multiplier ? tmon.Monster.Level * multiplier : damage); charact.Hp -= charact.Hp - damaged <= 0 ? 1 : charact.Hp - damaged; charact.Session.SendPacket(charact.GenerateStat()); mapInstance.Broadcast( $"su 3 {tmon.GetId()} 1 {charact.GetId()} -1 0 -1 {skill.Effect} -1 -1 1 {(int)(tmon.CurrentHp / (double)target.MaxHp * 100)} {damaged} 0 1"); target.DealtDamage = 0; } } } if (target.GetSession() is Character character) { damage = (ushort)(character.HasGodMode ? 0 : damage); target.DealtDamage = (ushort)(character.HasGodMode ? 0 : damage); if (character.IsSitting) { character.IsSitting = false; character.MapInstance.Broadcast(character.GenerateRest()); } } else if (target.GetSession() is Mate mate) { if (mate.IsSitting) { mate.IsSitting = false; mate.Owner.MapInstance.Broadcast(mate.GenerateRest()); } } int castTime = 0; if (skill != null && skill.CastEffect != 0) { Entity.MapInstance.Broadcast(Entity.GenerateEff(skill.CastEffect), Entity.GetPos().X, Entity.GetPos().Y); castTime = skill.CastTime * 100; } Observable.Timer(TimeSpan.FromMilliseconds(castTime)).Subscribe(o => TargetHit2(target, hitType, skill, damage, hitmode, skillEffect, mapX, mapY, skillCombo, showTargetAnimation, isPvp)); }
public void ApplyBCards(IBattleEntity session, IBattleEntity caster = null) { Mate mate; switch ((BCardType.CardType)Type) { case BCardType.CardType.Buff: if (ServerManager.Instance.RandomNumber() < FirstData) { session?.BattleEntity.AddBuff(new Buff(SecondData, caster?.BattleEntity.Level ?? session.BattleEntity.Level)); } break; case BCardType.CardType.Move: if (session.GetSession() is Character chara) { chara.LastSpeedChange = DateTime.Now; chara.LoadSpeed(); chara?.Session.SendPacket(chara.GenerateCond()); } break; case BCardType.CardType.Summons: NpcMonster npcMonster = session.GetSession() is MapMonster mob ? mob.Monster : session.GetSession() is MapNpc npc ? npc.Npc : null; ConcurrentBag <ToSummon> summonParameters = new ConcurrentBag <ToSummon>(); switch ((AdditionalTypes.Summons)SubType) { case AdditionalTypes.Summons.Summons: for (int i = 0; i < FirstData; i++) { MapCell cell = session.GetPos(); cell.Y += (short)ServerManager.Instance.RandomNumber(-3, 3); cell.X += (short)ServerManager.Instance.RandomNumber(-3, 3); summonParameters.Add(new ToSummon((short)SecondData, cell, null, true, (byte)Math.Abs(ThirdData))); } EventHelper.Instance.RunEvent(new EventContainer(session.MapInstance, EventActionType.SPAWNMONSTERS, summonParameters)); break; case AdditionalTypes.Summons.SummonTrainingDummy: if (npcMonster != null && session.BattleEntity.OnHitEvents.All(s => s?.EventActionType != EventActionType.SPAWNMONSTERS)) { summonParameters.Add(new ToSummon((short)SecondData, session.GetPos(), null, true, (byte)Math.Abs(ThirdData))); session.BattleEntity.OnHitEvents.Add(new EventContainer(session.MapInstance, EventActionType.SPAWNMONSTERS, summonParameters)); } break; case AdditionalTypes.Summons.SummonUponDeathChance: case AdditionalTypes.Summons.SummonUponDeath: if (npcMonster != null && session.BattleEntity.OnDeathEvents.All(s => s?.EventActionType != EventActionType.SPAWNMONSTERS)) { for (int i = 0; i < FirstData; i++) { MapCell cell = session.GetPos(); cell.Y += (short)i; summonParameters.Add(new ToSummon((short)SecondData, cell, null, true, (byte)Math.Abs(ThirdData))); } session.BattleEntity.OnDeathEvents.Add(new EventContainer(session.MapInstance, EventActionType.SPAWNMONSTERS, summonParameters)); } break; default: break; } break; case BCardType.CardType.SpecialAttack: break; case BCardType.CardType.SpecialDefence: break; case BCardType.CardType.AttackPower: break; case BCardType.CardType.Target: break; case BCardType.CardType.Critical: break; case BCardType.CardType.SpecialCritical: break; case BCardType.CardType.Element: break; case BCardType.CardType.IncreaseDamage: break; case BCardType.CardType.Defence: break; case BCardType.CardType.DodgeAndDefencePercent: break; case BCardType.CardType.Block: break; case BCardType.CardType.Absorption: break; case BCardType.CardType.ElementResistance: break; case BCardType.CardType.EnemyElementResistance: break; case BCardType.CardType.Damage: break; case BCardType.CardType.GuarantedDodgeRangedAttack: break; case BCardType.CardType.Morale: break; case BCardType.CardType.Casting: break; case BCardType.CardType.Reflection: break; case BCardType.CardType.DrainAndSteal: break; case BCardType.CardType.HealingBurningAndCasting: var subtype = (AdditionalTypes.HealingBurningAndCasting)SubType; Character sess; switch (subtype) { case AdditionalTypes.HealingBurningAndCasting.RestoreHP: case AdditionalTypes.HealingBurningAndCasting.RestoreHPWhenCasting: if (session.GetSession() is Character) { sess = (Character)session.GetSession(); int heal = FirstData; bool change = false; if (IsLevelScaled) { if (IsLevelDivided) { heal /= sess.Level; } else { heal *= sess.Level; } } if (sess.Hp + heal < sess.HpLoad()) { sess.Hp += heal; sess.Session?.CurrentMapInstance?.Broadcast(sess.GenerateRc(heal)); change = true; } else { if (sess.Hp != (int)sess.HpLoad()) { sess.Session?.CurrentMapInstance?.Broadcast(sess.GenerateRc((int)(sess.HpLoad() - sess.Hp))); change = true; } sess.Hp = (int)sess.HpLoad(); } if (change) { sess.Session?.SendPacket(sess.GenerateStat()); } } if (session.GetSession() is Mate) { mate = (Mate)session.GetSession(); int heal = FirstData; if (IsLevelScaled) { if (IsLevelDivided) { heal /= mate.Level; } else { heal *= mate.Level; } } if (mate.Hp + heal < mate.HpLoad()) { mate.Hp += heal; } else { mate.Hp = mate.HpLoad(); } } break; case AdditionalTypes.HealingBurningAndCasting.RestoreMP: if (session.GetSession() is Character) { sess = (Character)session.GetSession(); int heal = FirstData; bool change = false; if (IsLevelScaled) { if (IsLevelDivided) { heal /= sess.Level; } else { heal *= sess.Level; } } if (sess.Mp + heal < sess.MpLoad()) { sess.Mp += heal; change = true; } else { if (sess.Mp != (int)sess.MpLoad()) { change = true; } sess.Mp = (int)sess.MpLoad(); } if (change) { sess.Session?.SendPacket(sess.GenerateStat()); } } if (session.GetSession() is Mate) { mate = (Mate)session.GetSession(); int heal = FirstData; if (IsLevelScaled) { if (IsLevelDivided) { heal /= mate.Level; } else { heal *= mate.Level; } } if (mate.Mp + heal < mate.MpLoad()) { mate.Mp += heal; } else { mate.Mp = mate.MpLoad(); } } break; } break; case BCardType.CardType.HPMP: break; case BCardType.CardType.SpecialisationBuffResistance: break; case BCardType.CardType.SpecialEffects: break; case BCardType.CardType.Capture: if (session is MapMonster monsterToCapture && caster is Character hunter) { if (monsterToCapture.Monster.RaceType == 1 && (hunter.MapInstance.MapInstanceType == MapInstanceType.BaseMapInstance || hunter.MapInstance.MapInstanceType == MapInstanceType.TimeSpaceInstance)) { if (monsterToCapture.Monster.Level < hunter.Level) { if (monsterToCapture.CurrentHp < (monsterToCapture.Monster.MaxHP / 2)) { if (hunter.MaxMateCount > hunter.Mates.Count()) { // Algo int capturerate = 100 - (monsterToCapture.CurrentHp / monsterToCapture.Monster.MaxHP + 1) / 2; if (ServerManager.Instance.RandomNumber() <= capturerate) { if (hunter.Quests.Any(q => q.Quest.QuestType == (int)QuestType.Capture1 && q.Quest.QuestObjectives.Any(d => d.Data == monsterToCapture.MonsterVNum))) { hunter.IncrementQuests(QuestType.Capture1, monsterToCapture.MonsterVNum); return; } hunter.IncrementQuests(QuestType.Capture2, monsterToCapture.MonsterVNum); int level = monsterToCapture.Monster.Level - 15 < 1 ? 1 : monsterToCapture.Monster.Level - 15; Mate currentmate = hunter.Mates?.FirstOrDefault(m => m.IsTeamMember && m.MateType == MateType.Pet); if (currentmate != null) { currentmate.RemoveTeamMember(); // remove current pet hunter.MapInstance.Broadcast(currentmate.GenerateOut()); } monsterToCapture.MapInstance.DespawnMonster(monsterToCapture); NpcMonster mateNpc = ServerManager.Instance.GetNpc(monsterToCapture.MonsterVNum); mate = new Mate(hunter, mateNpc, (byte)level, MateType.Pet); hunter.Mates?.Add(mate); mate.RefreshStats(); hunter.Session.SendPacket($"ctl 2 {mate.PetId} 3"); hunter.MapInstance.Broadcast(mate.GenerateIn()); hunter.Session.SendPacket(hunter.GenerateSay(string.Format(Language.Instance.GetMessageFromKey("YOU_GET_PET"), mate.Name), 0)); hunter.Session.SendPacket(UserInterfaceHelper.Instance.GeneratePClear()); hunter.Session.SendPackets(hunter.GenerateScP()); hunter.Session.SendPackets(hunter.GenerateScN()); hunter.Session.SendPacket(hunter.GeneratePinit()); hunter.Session.SendPackets(hunter.Mates.Where(s => s.IsTeamMember) .OrderBy(s => s.MateType) .Select(s => s.GeneratePst())); } else { hunter.Session.SendPacket(UserInterfaceHelper.Instance.GenerateMsg(Language.Instance.GetMessageFromKey("CAPTURE_FAILED"), 0)); } } else { hunter.Session.SendPacket(UserInterfaceHelper.Instance.GenerateMsg(Language.Instance.GetMessageFromKey("MAX_MATES_COUNT"), 0)); } } else { hunter.Session.SendPacket(UserInterfaceHelper.Instance.GenerateMsg(Language.Instance.GetMessageFromKey("monsterToCapture_MUST_BE_LOW_HP"), 0)); } } else { hunter.Session.SendPacket(UserInterfaceHelper.Instance.GenerateMsg(Language.Instance.GetMessageFromKey("monsterToCapture_LVL_MUST_BE_LESS"), 0)); } } else { hunter.Session.SendPacket(UserInterfaceHelper.Instance.GenerateMsg(Language.Instance.GetMessageFromKey("monsterToCapture_CANNOT_BE_CAPTURED"), 0)); } } break; case BCardType.CardType.SpecialDamageAndExplosions: break; case BCardType.CardType.SpecialEffects2: break; case BCardType.CardType.CalculatingLevel: break; case BCardType.CardType.Recovery: break; case BCardType.CardType.MaxHPMP: break; case BCardType.CardType.MultAttack: break; case BCardType.CardType.MultDefence: break; case BCardType.CardType.TimeCircleSkills: break; case BCardType.CardType.RecoveryAndDamagePercent: break; case BCardType.CardType.Count: break; case BCardType.CardType.NoDefeatAndNoDamage: break; case BCardType.CardType.SpecialActions: if (session.GetSession() is Character charact) { if (SubType.Equals((byte)AdditionalTypes.SpecialActions.Hide)) { charact.Invisible = true; charact.Mates.Where(s => s.IsTeamMember).ToList().ForEach(s => charact.Session.CurrentMapInstance?.Broadcast(s.GenerateOut())); charact.Session.CurrentMapInstance?.Broadcast(charact.GenerateInvisible()); } } break; case BCardType.CardType.Mode: break; case BCardType.CardType.NoCharacteristicValue: break; case BCardType.CardType.LightAndShadow: break; case BCardType.CardType.Item: break; case BCardType.CardType.DebuffResistance: break; case BCardType.CardType.SpecialBehaviour: break; case BCardType.CardType.Quest: break; case BCardType.CardType.SecondSPCard: break; case BCardType.CardType.SPCardUpgrade: break; case BCardType.CardType.HugeSnowman: break; case BCardType.CardType.Drain: break; case BCardType.CardType.BossMonstersSkill: break; case BCardType.CardType.LordHatus: break; case BCardType.CardType.LordCalvinas: break; case BCardType.CardType.SESpecialist: break; case BCardType.CardType.FourthGlacernonFamilyRaid: break; case BCardType.CardType.SummonedMonsterAttack: break; case BCardType.CardType.BearSpirit: break; case BCardType.CardType.SummonSkill: break; case BCardType.CardType.InflictSkill: break; case BCardType.CardType.HideBarrelSkill: break; case BCardType.CardType.FocusEnemyAttentionSkill: break; case BCardType.CardType.TauntSkill: break; case BCardType.CardType.FireCannoneerRangeBuff: break; case BCardType.CardType.VulcanoElementBuff: break; case BCardType.CardType.DamageConvertingSkill: break; case BCardType.CardType.MeditationSkill: if (session.GetSession().GetType() == typeof(Character)) { if (SubType.Equals((byte)AdditionalTypes.MeditationSkill.CausingChance)) { if (ServerManager.Instance.RandomNumber() < FirstData) { if (!(session is Character character)) { break; } if (SkillVNum.HasValue) { character.LastSkillCombo = DateTime.Now; Skill skill = ServerManager.Instance.GetSkill(SkillVNum.Value); Skill newSkill = ServerManager.Instance.GetSkill((short)SecondData); Observable.Timer(TimeSpan.FromMilliseconds(100)).Subscribe(observer => { foreach (QuicklistEntryDTO qe in character.QuicklistEntries.Where(s => s.Pos.Equals(skill.CastId))) { character.Session.SendPacket( $"qset {qe.Q1} {qe.Q2} {qe.Type}.{qe.Slot}.{newSkill.CastId}.0"); } character.Session.SendPacket($"mslot {newSkill.CastId} -1"); }); if (skill.CastId > 10) { // HACK this way Observable.Timer(TimeSpan.FromMilliseconds(skill.Cooldown * 100 + 500)) .Subscribe(observer => { character.Session.SendPacket($"sr {skill.CastId}"); }); } } } } else { if (!(session is Character character)) { break; } switch (SubType) { case 21: character.MeditationDictionary[(short)SecondData] = DateTime.Now.AddSeconds(4); break; case 31: character.MeditationDictionary[(short)SecondData] = DateTime.Now.AddSeconds(8); break; case 41: character.MeditationDictionary[(short)SecondData] = DateTime.Now.AddSeconds(12); break; } } } break; case BCardType.CardType.FalconSkill: break; case BCardType.CardType.AbsorptionAndPowerSkill: break; case BCardType.CardType.LeonaPassiveSkill: break; case BCardType.CardType.FearSkill: break; case BCardType.CardType.SniperAttack: break; case BCardType.CardType.FrozenDebuff: break; case BCardType.CardType.JumpBackPush: break; case BCardType.CardType.FairyXPIncrease: break; case BCardType.CardType.SummonAndRecoverHP: break; case BCardType.CardType.TeamArenaBuff: break; case BCardType.CardType.ArenaCamera: break; case BCardType.CardType.DarkCloneSummon: break; case BCardType.CardType.AbsorbedSpirit: break; case BCardType.CardType.AngerSkill: break; case BCardType.CardType.MeteoriteTeleport: break; case BCardType.CardType.StealBuff: break; default: Logger.Error(new ArgumentOutOfRangeException($"Card Type {Type} not defined!")); //throw new ArgumentOutOfRangeException(); break; } }