public void AddBuff(short buffId, BattleEntity sender = null) { if (sender?.EntityType == EntityType.Player && sender.Session?.Character is Character senderCharacter) { Buff buff = new Buff(buffId, senderCharacter.Level, senderCharacter); switch (EntityType) { case EntityType.Player: Session.Character.AddBuff(buff); break; case EntityType.Monster: MapMonster?.AddBuff(buff); break; } } }
public Mate(Character owner, NpcMonster npcMonster, byte level, MateType matetype) { Owner = owner; NpcMonsterVNum = npcMonster.NpcMonsterVNum; Monster = npcMonster; Level = level; BattleEntity = new BattleEntity(this); Name = npcMonster.Name; MateType = matetype; Loyalty = 1000; PositionY = (short)(owner.PositionY + 1); PositionX = (short)(owner.PositionX + 1); MapX = (short)(owner.PositionX + 1); MapY = (short)(owner.PositionY + 1); Direction = 2; CharacterId = owner.CharacterId; AddTeamMember(); GenerateMateTransportId(); StartLife(); }
public override void Initialize() { Monster = ServerManager.Instance.GetNpc(NpcMonsterVNum); Owner = ServerManager.Instance.GetSessionByCharacterId(CharacterId)?.Character; if (Monster == null || Owner == null) { return; } Life = null; BattleEntity = new BattleEntity(this); byte type = (byte)(Monster.AttackClass == 2 ? 1 : 0); Concentrate = (short)(MateHelper.Instance.Concentrate[type, Level] + (Monster.Concentrate - MateHelper.Instance.Concentrate[type, Monster.Level])); DamageMinimum = (short)(MateHelper.Instance.MinDamageData[type, Level] + (Monster.DamageMinimum - MateHelper.Instance.MinDamageData[type, Monster.Level])); DamageMaximum = (short)(MateHelper.Instance.MaxDamageData[type, Level] + (Monster.DamageMaximum - MateHelper.Instance.MaxDamageData[type, Monster.Level])); IsAlive = true; Hp = MaxHp; if (IsTeamMember) { AddTeamMember(); } }
public MonsterToSummon(short vnum, MapCell spawnCell, BattleEntity target, bool move, bool isTarget = false, bool isBonus = false, bool isHostile = true, bool isBoss = false, BattleEntity owner = null, int aliveTime = 0, int aliveTimeMp = 0, byte noticeRange = 0, short hasDelay = 0, int maxHp = 0, int maxMp = 0) { VNum = vnum; SpawnCell = spawnCell; Target = target; IsMoving = move; IsTarget = isTarget; IsBonus = isBonus; IsBoss = isBoss; IsHostile = isHostile; DeathEvents = new List <EventContainer>(); NoticingEvents = new List <EventContainer>(); UseSkillOnDamage = new List <UseSkillOnDamage>(); SpawnEvents = new List <EventContainer>(); AfterSpawnEvents = new List <EventContainer>(); Owner = owner; AliveTime = aliveTime; AliveTimeMp = aliveTimeMp; NoticeRange = noticeRange; HasDelay = hasDelay; MaxHp = maxHp; MaxMp = maxMp; }
public bool HasBuff(CardType type, byte subtype, bool removeWeaponEffects = false) => BattleEntity.HasBuff(type, subtype, removeWeaponEffects);
public int[] GetBuff(CardType type, byte subtype) => BattleEntity.GetBuff(type, subtype);
public void Initialize() { if (MapInstance.MapInstanceType == MapInstanceType.BaseMapInstance && ServerManager.Instance.MapBossVNums.Contains(NpcVNum)) { MapCell randomCell = MapInstance.Map.GetRandomPosition(); if (randomCell != null) { if (MapInstance.Portals.Any(s => Map.GetDistance(new MapCell { X = s.SourceX, Y = s.SourceY }, new MapCell { X = randomCell.X, Y = randomCell.Y }) < 5)) { randomCell = MapInstance.Map.GetRandomPosition(); } MapX = randomCell.X; MapY = randomCell.Y; } } _random = new Random(MapNpcId); Npc = ServerManager.GetNpcMonster(NpcVNum); MaxHp = Npc.MaxHP; MaxMp = Npc.MaxMP; if (MapInstance?.MapInstanceType == MapInstanceType.TimeSpaceInstance) { if (IsProtected) { MaxHp *= 8; MaxMp *= 8; } } IsAlive = true; CurrentHp = MaxHp; CurrentMp = MaxMp; LastEffect = DateTime.Now; LastProtectedEffect = DateTime.Now; LastMove = DateTime.Now; LastSkill = DateTime.Now; IsHostile = Npc.IsHostile; ShouldRespawn = ShouldRespawn ?? true; FirstX = MapX; FirstY = MapY; EffectActivated = true; _movetime = ServerManager.RandomNumber(500, 3000); Path = new List <Node>(); Recipes = ServerManager.Instance.GetRecipesByMapNpcId(MapNpcId); Target = -1; Teleporters = ServerManager.Instance.GetTeleportersByNpcVNum(MapNpcId); Shop shop = ServerManager.Instance.GetShopByMapNpcId(MapNpcId); if (shop != null) { shop.Initialize(); Shop = shop; } Skills = new List <NpcMonsterSkill>(); foreach (NpcMonsterSkill ski in Npc.Skills) { Skills.Add(new NpcMonsterSkill { SkillVNum = ski.SkillVNum, Rate = ski.Rate }); } BattleEntity = new BattleEntity(this); if (AliveTime > 0) { Thread AliveTimeThread = new Thread(() => AliveTimeCheck()); AliveTimeThread.Start(); } if (NpcVNum == 1408) { OnDeathEvents.Add(new EventContainer(MapInstance, EventActionType.SPAWNMONSTER, new MonsterToSummon(621, new MapCell { X = MapX, Y = MapY }, null, move: true))); } if (NpcVNum == 1409) { OnDeathEvents.Add(new EventContainer(MapInstance, EventActionType.SPAWNMONSTER, new MonsterToSummon(622, new MapCell { X = MapX, Y = MapY }, null, move: true))); } if (NpcVNum == 1410) { OnDeathEvents.Add(new EventContainer(MapInstance, EventActionType.SPAWNMONSTER, new MonsterToSummon(623, new MapCell { X = MapX, Y = MapY }, null, move: true))); } if (OnSpawnEvents.Any()) { OnSpawnEvents.ToList().ForEach(e => { EventHelper.Instance.RunEvent(e, npc: this); }); OnSpawnEvents.Clear(); } }
public void AddBuff(Buff indicator, BattleEntity battleEntity) => BattleEntity.AddBuff(indicator, battleEntity);
/// <summary> /// Handle any kind of Monster interaction /// </summary> private void monsterLife() { if (Monster == null) { return; } if ((DateTime.Now - LastEffect).TotalSeconds >= 5) { LastEffect = DateTime.Now; if (IsTarget) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Monster, MapMonsterId, 824)); } if (IsBonus) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Monster, MapMonsterId, 826)); } } if (IsBoss && IsAlive) { MapInstance.Broadcast(GenerateBoss()); } // handle hit queue while (HitQueue.TryDequeue(out HitRequest hitRequest)) { if (IsAlive && hitRequest.Session.Character.Hp > 0 && (ServerManager.Instance.ChannelId != 51 || MonsterVNum - (byte)hitRequest.Session.Character.Faction != 678)) { int hitmode = 0; bool isCaptureSkill = hitRequest.Skill.BCards.Any(s => s.Type.Equals((byte)CardType.Capture)); // calculate damage bool onyxWings = false; BattleEntity battleEntity = new BattleEntity(hitRequest.Session.Character, hitRequest.Skill); int damage = DamageHelper.Instance.CalculateDamage(battleEntity, new BattleEntity(this), hitRequest.Skill, ref hitmode, ref onyxWings); if (onyxWings) { short onyxX = (short)(hitRequest.Session.Character.PositionX + 2); short onyxY = (short)(hitRequest.Session.Character.PositionY + 2); int onyxId = MapInstance.GetNextMonsterId(); MapMonster onyx = new MapMonster() { MonsterVNum = 2371, MapX = onyxX, MapY = onyxY, MapMonsterId = onyxId, IsHostile = false, IsMoving = false, ShouldRespawn = false }; MapInstance.Broadcast(UserInterfaceHelper.Instance.GenerateGuri(31, 1, hitRequest.Session.Character.CharacterId, onyxX, onyxY)); onyx.Initialize(MapInstance); MapInstance.AddMonster(onyx); MapInstance.Broadcast(onyx.GenerateIn()); CurrentHp -= damage / 2; Observable.Timer(TimeSpan.FromMilliseconds(350)).Subscribe(o => { MapInstance.Broadcast(StaticPacketHelper.SkillUsed(UserType.Monster, onyxId, 3, MapMonsterId, -1, 0, -1, hitRequest.Skill.Effect, -1, -1, true, 92, damage / 2, 0, 0)); MapInstance.RemoveMonster(onyx); MapInstance.Broadcast(StaticPacketHelper.Out(UserType.Monster, onyx.MapMonsterId)); }); } if (hitmode != 1) { hitRequest.Skill.BCards.Where(s => s.Type.Equals((byte)CardType.Buff)).ToList().ForEach(s => s.ApplyBCards(this, hitRequest.Session)); hitRequest.Skill.BCards.Where(s => s.Type.Equals((byte)CardType.Capture)).ToList().ForEach(s => s.ApplyBCards(this, hitRequest.Session)); if (battleEntity?.ShellWeaponEffects != null) { foreach (ShellEffectDTO shell in battleEntity.ShellWeaponEffects) { switch (shell.Effect) { case (byte)ShellWeaponEffectType.Blackout: { Buff buff = new Buff(7, battleEntity.Level); if (ServerManager.Instance.RandomNumber() < shell.Value) { AddBuff(buff); } break; } case (byte)ShellWeaponEffectType.DeadlyBlackout: { Buff buff = new Buff(66, battleEntity.Level); if (ServerManager.Instance.RandomNumber() < shell.Value) { AddBuff(buff); } break; } case (byte)ShellWeaponEffectType.MinorBleeding: { Buff buff = new Buff(1, battleEntity.Level); if (ServerManager.Instance.RandomNumber() < shell.Value) { AddBuff(buff); } break; } case (byte)ShellWeaponEffectType.Bleeding: { Buff buff = new Buff(21, battleEntity.Level); if (ServerManager.Instance.RandomNumber() < shell.Value) { AddBuff(buff); } break; } case (byte)ShellWeaponEffectType.HeavyBleeding: { Buff buff = new Buff(42, battleEntity.Level); if (ServerManager.Instance.RandomNumber() < shell.Value) { AddBuff(buff); } break; } case (byte)ShellWeaponEffectType.Freeze: { Buff buff = new Buff(27, battleEntity.Level); if (ServerManager.Instance.RandomNumber() < shell.Value) { AddBuff(buff); } break; } } } } } if (DamageList.ContainsKey(hitRequest.Session.Character.CharacterId)) { DamageList[hitRequest.Session.Character.CharacterId] += damage; } else { DamageList.Add(hitRequest.Session.Character.CharacterId, damage); } if (isCaptureSkill) { damage = 0; } if (CurrentHp <= damage) { SetDeathStatement(); } else { CurrentHp -= damage; } // only set the hit delay if we become the monsters target with this hit if (Target == -1) { LastSkill = DateTime.Now; } int nearestDistance = 100; foreach (KeyValuePair <long, long> kvp in DamageList) { ClientSession session = MapInstance.GetSessionByCharacterId(kvp.Key); if (session != null) { int distance = Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = session.Character.PositionX, Y = session.Character.PositionY }); if (distance < nearestDistance) { nearestDistance = distance; Target = session.Character.CharacterId; } } } switch (hitRequest.TargetHitType) { case TargetHitType.SingleTargetHit: if (!isCaptureSkill) { MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1))); } break; case TargetHitType.SingleTargetHitCombo: MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.SkillCombo.Animation, hitRequest.SkillCombo.Effect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1))); break; case TargetHitType.SingleAOETargetHit: switch (hitmode) { case 1: hitmode = 4; break; case 3: hitmode = 6; break; default: hitmode = 5; break; } if (hitRequest.ShowTargetHitAnimation) { MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1))); } else { MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, 0, 0, 0, 0, 0, 0, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1))); } break; case TargetHitType.AOETargetHit: switch (hitmode) { case 1: hitmode = 4; break; case 3: hitmode = 6; break; default: hitmode = 5; break; } MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1))); break; case TargetHitType.ZoneHit: MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.MapX, hitRequest.MapY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, 5, (byte)(hitRequest.Skill.SkillType - 1))); break; case TargetHitType.SpecialZoneHit: MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1))); break; } if (CurrentHp <= 0 && !isCaptureSkill) { // generate the kill bonus hitRequest.Session.Character.GenerateKillBonus(this); } } else { // monster already has been killed, send cancel hitRequest.Session.SendPacket(StaticPacketHelper.Cancel(2, MapMonsterId)); } if (IsBoss) { MapInstance.Broadcast(GenerateBoss()); } } // Respawn if (!IsAlive && ShouldRespawn != null && !ShouldRespawn.Value) { MapInstance.RemoveMonster(this); } if (!IsAlive && ShouldRespawn != null && ShouldRespawn.Value) { double timeDeath = (DateTime.Now - Death).TotalSeconds; if (timeDeath >= Monster.RespawnTime / 10d) { respawn(); } } // normal movement else if (Target == -1) { move(); } // target following else if (MapInstance != null) { GetNearestOponent(); HostilityTarget(); ClientSession targetSession = MapInstance.GetSessionByCharacterId(Target); // remove target in some situations if (targetSession == null || targetSession.Character.Invisible || targetSession.Character.Hp <= 0 || CurrentHp <= 0) { RemoveTarget(); return; } NpcMonsterSkill npcMonsterSkill = null; if (Skills != null && ServerManager.Instance.RandomNumber(0, 10) > 8) { npcMonsterSkill = Skills.Where(s => (DateTime.Now - s.LastSkillUse).TotalMilliseconds >= 100 * s.Skill?.Cooldown)?.OrderBy(rnd => _random.Next())?.FirstOrDefault(); } if (npcMonsterSkill?.Skill.TargetType == 1 && npcMonsterSkill?.Skill.HitType == 0) { targetHit(targetSession, npcMonsterSkill); } // check if target is in range if (!targetSession.Character.InvisibleGm && !targetSession.Character.Invisible && targetSession.Character.Hp > 0) { if (npcMonsterSkill != null && CurrentMp >= npcMonsterSkill.Skill.MpCost && Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = targetSession.Character.PositionX, Y = targetSession.Character.PositionY }) < npcMonsterSkill.Skill.Range) { targetHit(targetSession, npcMonsterSkill); } else if (Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = targetSession.Character.PositionX, Y = targetSession.Character.PositionY }) <= Monster.BasicRange) { targetHit(targetSession, npcMonsterSkill); } else { followTarget(targetSession); } } else { followTarget(targetSession); } } }
/// <summary> /// Calculates the damage attacker inflicts defender /// </summary> /// <param name="attacker">The attacking Entity</param> /// <param name="defender">The defending Entity</param> /// <param name="skill">The used Skill</param> /// <param name="hitMode">reference to HitMode</param> /// <param name="onyxWings"></param> /// <returns>Damage</returns> public int CalculateDamage(BattleEntity attacker, BattleEntity defender, Skill skill, ref int hitMode, ref bool onyxWings) { int[] GetAttackerBenefitingBuffs(CardType type, byte subtype) { int value1 = 0; int value2 = 0; int value3 = 0; int[] tmp; int temp = 0; tmp = getBuff(attacker.Level, attacker.Buffs, attacker.BCards, type, subtype, BuffType.Good, ref temp); value1 += tmp[0]; value2 += tmp[1]; value3 += tmp[2]; tmp = getBuff(attacker.Level, attacker.Buffs, attacker.BCards, type, subtype, BuffType.Neutral, ref temp); value1 += tmp[0]; value2 += tmp[1]; value3 += tmp[2]; tmp = getBuff(defender.Level, defender.Buffs, defender.BCards, type, subtype, BuffType.Bad, ref temp); value1 += tmp[0]; value2 += tmp[1]; value3 += tmp[2]; return(new int[] { value1, value2, value3, temp }); } int[] GetDefenderBenefitingBuffs(CardType type, byte subtype) { int value1 = 0; int value2 = 0; int value3 = 0; int[] tmp; int temp = 0; tmp = getBuff(defender.Level, defender.Buffs, defender.BCards, type, subtype, BuffType.Good, ref temp); value1 += tmp[0]; value2 += tmp[1]; value3 += tmp[2]; tmp = getBuff(defender.Level, defender.Buffs, defender.BCards, type, subtype, BuffType.Neutral, ref temp); value1 += tmp[0]; value2 += tmp[1]; value3 += tmp[2]; tmp = getBuff(attacker.Level, attacker.Buffs, attacker.BCards, type, subtype, BuffType.Bad, ref temp); value1 += tmp[0]; value2 += tmp[1]; value3 += tmp[2]; return(new int[] { value1, value2, value3, temp }); } int GetShellWeaponEffectValue(ShellWeaponEffectType effectType) { return(attacker.ShellWeaponEffects?.Where(s => s.Effect == (byte)effectType)?.FirstOrDefault()?.Value ?? 0); } int GetShellArmorEffectValue(ShellArmorEffectType effectType) { return(defender.ShellArmorEffects?.Where(s => s.Effect == (byte)effectType)?.FirstOrDefault()?.Value ?? 0); } if (skill != null) { attacker.BCards.AddRange(skill.BCards); } #region Basic Buff Initialisation attacker.Morale += GetAttackerBenefitingBuffs(CardType.Morale, (byte)AdditionalTypes.Morale.MoraleIncreased)[0]; attacker.Morale += GetDefenderBenefitingBuffs(CardType.Morale, (byte)AdditionalTypes.Morale.MoraleDecreased)[0]; defender.Morale += GetDefenderBenefitingBuffs(CardType.Morale, (byte)AdditionalTypes.Morale.MoraleIncreased)[0]; defender.Morale += GetAttackerBenefitingBuffs(CardType.Morale, (byte)AdditionalTypes.Morale.MoraleDecreased)[0]; attacker.AttackUpgrade += (short)GetAttackerBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.AttackLevelIncreased)[0]; attacker.AttackUpgrade += (short)GetDefenderBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.AttackLevelDecreased)[0]; defender.DefenseUpgrade += (short)GetDefenderBenefitingBuffs(CardType.Defence, (byte)AdditionalTypes.Defence.DefenceLevelIncreased)[0]; defender.DefenseUpgrade += (short)GetAttackerBenefitingBuffs(CardType.Defence, (byte)AdditionalTypes.Defence.DefenceLevelDecreased)[0]; int[] attackerpercentdamage = GetDefenderBenefitingBuffs(CardType.RecoveryAndDamagePercent, 11); int[] defenderpercentdefense = GetDefenderBenefitingBuffs(CardType.RecoveryAndDamagePercent, 2); if (attackerpercentdamage[3] != 0) { return(defender.HPMax / 100 * attackerpercentdamage[2]); } if (defenderpercentdefense[3] != 0) { return(defender.HPMax / 100 * Math.Abs(defenderpercentdefense[2])); } /* * * Percentage Boost categories: * 1.: Adds to Total Damage * 2.: Adds to Normal Damage * 3.: Adds to Base Damage * 4.: Adds to Defense * 5.: Adds to Element * * Buff Effects get added, whereas * Shell Effects get multiplied afterwards. * * Simplified Example on Defense (Same for Attack): * - 1k Defense * - Costume(+5% Defense) * - Defense Potion(+20% Defense) * - S-Defense Shell with 20% Boost * * Calculation: * 1000 * 1.25 * 1.2 = 1500 * Def Buff Shell Total * * Keep in Mind that after each step, one has * to round the current value down if necessary * * Static Boost categories: * 1.: Adds to Total Damage * 2.: Adds to Normal Damage * 3.: Adds to Base Damage * 4.: Adds to Defense * 5.: Adds to Element * */ #region Definitions double boostCategory1 = 1; double boostCategory2 = 1; double boostCategory3 = 1; double boostCategory4 = 1; double boostCategory5 = 1; double shellBoostCategory1 = 1; double shellBoostCategory2 = 1; double shellBoostCategory3 = 1; double shellBoostCategory4 = 1; double shellBoostCategory5 = 1; int staticBoostCategory1 = 0; int staticBoostCategory2 = 0; int staticBoostCategory3 = 0; int staticBoostCategory4 = 0; int staticBoostCategory5 = 0; #endregion #region Type 1 #region Static // None for now #endregion #region Boost boostCategory1 += GetAttackerBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.DamageIncreased)[0] / 100D; boostCategory1 += GetAttackerBenefitingBuffs(CardType.Item, (byte)AdditionalTypes.Item.AttackIncreased)[0] / 100D; boostCategory1 += GetDefenderBenefitingBuffs(CardType.Item, (byte)AdditionalTypes.Item.DefenceIncreased)[0] / 100D; shellBoostCategory1 += GetShellWeaponEffectValue(ShellWeaponEffectType.PercentageTotalDamage) / 100D; if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate)) { boostCategory1 += GetAttackerBenefitingBuffs(CardType.SpecialisationBuffResistance, (byte)AdditionalTypes.SpecialisationBuffResistance.IncreaseDamageInPVP)[0] / 100D; boostCategory1 += GetAttackerBenefitingBuffs(CardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.AttackIncreasedInPVP)[0] / 100D; shellBoostCategory1 += GetShellWeaponEffectValue(ShellWeaponEffectType.PercentageDamageInPVP) / 100D; } #endregion #endregion #region Type 2 #region Static // None for now #endregion #region Boost boostCategory2 += GetDefenderBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.DamageDecreased)[0] / 100D; if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate)) { boostCategory2 += GetDefenderBenefitingBuffs(CardType.SpecialisationBuffResistance, (byte)AdditionalTypes.SpecialisationBuffResistance.DecreaseDamageInPVP)[0] / 100D; boostCategory2 += GetDefenderBenefitingBuffs(CardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.AttackDecreasedInPVP)[0] / 100D; } #endregion #endregion #region Type 3 #region Static staticBoostCategory3 += GetAttackerBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.AllAttacksIncreased)[0]; staticBoostCategory3 += GetDefenderBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.AllAttacksDecreased)[0]; staticBoostCategory3 += GetShellWeaponEffectValue(ShellWeaponEffectType.DamageImproved); #endregion #region Soft-Damage int[] soft = GetAttackerBenefitingBuffs(CardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.IncreasingPropability); int[] skin = GetAttackerBenefitingBuffs(CardType.EffectSummon, (byte)AdditionalTypes.EffectSummon.DamageBoostOnHigherLvl); if (attacker.Level < defender.Level) { soft[0] += skin[0]; soft[1] += skin[1]; } if (ServerManager.Instance.RandomNumber() < soft[0]) { boostCategory3 += soft[1] / 100D; if (attacker.EntityType.Equals(EntityType.Player) && attacker.Session != null) { attacker.Session.CurrentMapInstance?.Broadcast(StaticPacketHelper.GenerateEff(UserType.Player, attacker.Session.Character.CharacterId, 15)); } } #endregion #endregion #region Type 4 #region Static staticBoostCategory4 += GetDefenderBenefitingBuffs(CardType.Defence, (byte)AdditionalTypes.Defence.AllIncreased)[0]; staticBoostCategory4 += GetAttackerBenefitingBuffs(CardType.Defence, (byte)AdditionalTypes.Defence.AllDecreased)[0]; #endregion #region Boost boostCategory4 += GetDefenderBenefitingBuffs(CardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DefenceIncreased)[0] / 100D; boostCategory4 += GetAttackerBenefitingBuffs(CardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DefenceReduced)[0] / 100D; shellBoostCategory4 += GetShellArmorEffectValue(ShellArmorEffectType.PercentageTotalDefence) / 100D; if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate)) { boostCategory4 += GetDefenderBenefitingBuffs(CardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.DefenceIncreasedInPVP)[0] / 100D; boostCategory4 += GetAttackerBenefitingBuffs(CardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.DefenceDecreasedInPVP)[0] / 100D; shellBoostCategory4 -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesPercentageEnemyDefenceInPVP) / 100D; shellBoostCategory4 += GetShellArmorEffectValue(ShellArmorEffectType.PercentageAllPVPDefence) / 100D; } int[] def = GetAttackerBenefitingBuffs(CardType.Block, (byte)AdditionalTypes.Block.ChanceAllIncreased); if (ServerManager.Instance.RandomNumber() < def[0]) { boostCategory3 += def[1] / 100D; } #endregion #endregion #region Type 5 #region Static staticBoostCategory5 += GetAttackerBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.AllIncreased)[0]; staticBoostCategory5 += GetDefenderBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.AllDecreased)[0]; staticBoostCategory5 += GetShellWeaponEffectValue(ShellWeaponEffectType.IncreasedElementalProperties); #endregion #region Boost // Nothing for now #endregion #endregion #region All Type Class Dependant int[] def2 = null; switch (attacker.AttackType) { case AttackType.Melee: def2 = GetAttackerBenefitingBuffs(CardType.Block, (byte)AdditionalTypes.Block.ChanceMeleeIncreased); boostCategory1 += GetAttackerBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.MeleeIncreased)[0] / 100D; boostCategory1 += GetDefenderBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.MeleeDecreased)[0] / 100D; staticBoostCategory3 += GetAttackerBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksIncreased)[0]; staticBoostCategory3 += GetDefenderBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksDecreased)[0]; staticBoostCategory4 += GetShellArmorEffectValue(ShellArmorEffectType.CloseDefence); break; case AttackType.Range: def2 = GetAttackerBenefitingBuffs(CardType.Block, (byte)AdditionalTypes.Block.ChanceRangedIncreased); boostCategory1 += GetAttackerBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.RangedIncreased)[0] / 100D; boostCategory1 += GetDefenderBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.RangedDecreased)[0] / 100D; staticBoostCategory3 += GetAttackerBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksIncreased)[0]; staticBoostCategory3 += GetDefenderBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksDecreased)[0]; staticBoostCategory4 += GetShellArmorEffectValue(ShellArmorEffectType.DistanceDefence); break; case AttackType.Magical: def2 = GetAttackerBenefitingBuffs(CardType.Block, (byte)AdditionalTypes.Block.ChanceRangedIncreased); boostCategory1 += GetAttackerBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.MagicalIncreased)[0] / 100D; boostCategory1 += GetDefenderBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.MagicalDecreased)[0] / 100D; staticBoostCategory3 += GetAttackerBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksIncreased)[0]; staticBoostCategory3 += GetDefenderBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksDecreased)[0]; staticBoostCategory4 += GetShellArmorEffectValue(ShellArmorEffectType.MagicDefence); break; } def[0] += def2[0]; def[1] += def2[1]; #endregion #region Softdef finishing if (ServerManager.Instance.RandomNumber() < def[0]) { boostCategory3 += def[1] / 100D; } #endregion #region Element Dependant switch (attacker.Element) { case 1: defender.FireResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllIncreased)[0]; defender.FireResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllDecreased)[0]; defender.FireResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.FireIncreased)[0]; defender.FireResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.FireDecreased)[0]; defender.FireResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllIncreased)[0]; defender.FireResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllDecreased)[0]; defender.FireResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.FireIncreased)[0]; defender.FireResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.FireDecreased)[0]; if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate)) { defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyFireResistanceInPVP); defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyAllResistancesInPVP); } defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedFireResistence); defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedAllResistence); staticBoostCategory5 += GetShellWeaponEffectValue(ShellWeaponEffectType.IncreasedFireProperties); boostCategory5 += GetAttackerBenefitingBuffs(CardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.FireIncreased)[0] / 100D; staticBoostCategory5 += GetAttackerBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.FireIncreased)[0]; staticBoostCategory5 += GetDefenderBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.FireDecreased)[0]; break; case 2: defender.WaterResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllIncreased)[0]; defender.WaterResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllDecreased)[0]; defender.WaterResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.WaterIncreased)[0]; defender.WaterResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.WaterDecreased)[0]; defender.WaterResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllIncreased)[0]; defender.WaterResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllDecreased)[0]; defender.WaterResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.WaterIncreased)[0]; defender.WaterResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.WaterDecreased)[0]; if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate)) { defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyWaterResistanceInPVP); defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyAllResistancesInPVP); } defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedWaterResistence); defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedAllResistence); staticBoostCategory5 += GetShellWeaponEffectValue(ShellWeaponEffectType.IncreasedWaterProperties); boostCategory5 += GetAttackerBenefitingBuffs(CardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.WaterIncreased)[0] / 100D; staticBoostCategory5 += GetAttackerBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.WaterIncreased)[0]; staticBoostCategory5 += GetDefenderBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.WaterDecreased)[0]; break; case 3: defender.LightResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllIncreased)[0]; defender.LightResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllDecreased)[0]; defender.LightResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.LightIncreased)[0]; defender.LightResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.LightDecreased)[0]; defender.LightResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllIncreased)[0]; defender.LightResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllDecreased)[0]; defender.LightResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.LightIncreased)[0]; defender.LightResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.LightDecreased)[0]; if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate)) { defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyLightResistanceInPVP); defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyAllResistancesInPVP); } defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedLightResistence); defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedAllResistence); staticBoostCategory5 += GetShellWeaponEffectValue(ShellWeaponEffectType.IncreasedLightProperties); boostCategory5 += GetAttackerBenefitingBuffs(CardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.LightIncreased)[0] / 100D; staticBoostCategory5 += GetAttackerBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.LightIncreased)[0]; staticBoostCategory5 += GetDefenderBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.Light5Decreased)[0]; break; case 4: defender.ShadowResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllIncreased)[0]; defender.ShadowResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllDecreased)[0]; defender.ShadowResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.DarkIncreased)[0]; defender.ShadowResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.DarkDecreased)[0]; defender.ShadowResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllIncreased)[0]; defender.ShadowResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllDecreased)[0]; defender.ShadowResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.DarkIncreased)[0]; defender.ShadowResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.DarkDecreased)[0]; if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate)) { defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyDarkResistanceInPVP); defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyAllResistancesInPVP); } defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedDarkResistence); defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedAllResistence); staticBoostCategory5 += GetShellWeaponEffectValue(ShellWeaponEffectType.IncreasedDarkProperties); boostCategory5 += GetAttackerBenefitingBuffs(CardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.DarkIncreased)[0] / 100D; staticBoostCategory5 += GetAttackerBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.DarkIncreased)[0]; staticBoostCategory5 += GetDefenderBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.DarkDecreased)[0]; break; } #endregion #endregion #region Attack Type Related Variables switch (attacker.AttackType) { case AttackType.Melee: defender.Defense = defender.MeleeDefense; defender.ArmorDefense = defender.ArmorMeleeDefense; defender.Dodge = defender.MeleeDefenseDodge; break; case AttackType.Range: defender.Defense = defender.RangeDefense; defender.ArmorDefense = defender.ArmorRangeDefense; defender.Dodge = defender.RangeDefenseDodge; break; case AttackType.Magical: defender.Defense = defender.MagicalDefense; defender.ArmorDefense = defender.ArmorMagicalDefense; break; } #endregion #region Too Near Range Attack Penalty (boostCategory2) if (attacker.AttackType == AttackType.Range && Map.GetDistance(new MapCell { X = attacker.PositionX, Y = attacker.PositionY }, new MapCell { X = defender.PositionX, Y = defender.PositionY }) < 4) { boostCategory2 -= 0.3; } #endregion #region Morale and Dodge attacker.Morale -= defender.Morale; double chance = 0; if (attacker.AttackType != AttackType.Magical) { int hitrate = attacker.Hitrate + attacker.Morale; double multiplier = defender.Dodge / (hitrate > 1 ? hitrate : 1); if (multiplier > 5) { multiplier = 5; } 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.Buff, (byte)AdditionalTypes.DodgeAndDefencePercent.)[0] != 0) TODO: Eagle Eyes AND Other Fixed Hitrates //{ // chance = 10; //} } int bonus = 0; if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate)) { switch (attacker.AttackType) { case AttackType.Melee: bonus += GetShellArmorEffectValue(ShellArmorEffectType.CloseDefenceDodgeInPVP); break; case AttackType.Range: bonus += GetShellArmorEffectValue(ShellArmorEffectType.DistanceDefenceDodgeInPVP); break; case AttackType.Magical: bonus += GetShellArmorEffectValue(ShellArmorEffectType.IgnoreMagicDamage); break; } bonus += GetShellArmorEffectValue(ShellArmorEffectType.DodgeAllAttacksInPVP); } if (!defender.Invincible && ServerManager.Instance.RandomNumber() - bonus < chance) { hitMode = 1; return(0); } #endregion #region Base Damage int baseDamage = ServerManager.Instance.RandomNumber(attacker.DamageMinimum, attacker.DamageMaximum + 1); int weaponDamage = ServerManager.Instance.RandomNumber(attacker.WeaponDamageMinimum, attacker.WeaponDamageMaximum + 1); #region Attack Level Calculation int[] atklvlfix = GetDefenderBenefitingBuffs(CardType.CalculatingLevel, (byte)AdditionalTypes.CalculatingLevel.CalculatedAttackLevel); int[] deflvlfix = GetAttackerBenefitingBuffs(CardType.CalculatingLevel, (byte)AdditionalTypes.CalculatingLevel.CalculatedDefenceLevel); if (atklvlfix[3] != 0) { attacker.AttackUpgrade = (short)atklvlfix[0]; } if (deflvlfix[3] != 0) { attacker.DefenseUpgrade = (short)deflvlfix[0]; } attacker.AttackUpgrade -= defender.DefenseUpgrade; if (attacker.AttackUpgrade < -10) { attacker.AttackUpgrade = -10; } else if (attacker.AttackUpgrade > ServerManager.Instance.Configuration.MaxUpgrade) { attacker.AttackUpgrade = ServerManager.Instance.Configuration.MaxUpgrade; } switch (attacker.AttackUpgrade) { case 0: weaponDamage += 0; break; case 1: weaponDamage += (int)(weaponDamage * 0.1); break; case 2: weaponDamage += (int)(weaponDamage * 0.15); break; case 3: weaponDamage += (int)(weaponDamage * 0.22); break; case 4: weaponDamage += (int)(weaponDamage * 0.32); break; case 5: weaponDamage += (int)(weaponDamage * 0.43); break; case 6: weaponDamage += (int)(weaponDamage * 0.54); break; case 7: weaponDamage += (int)(weaponDamage * 0.65); break; case 8: weaponDamage += (int)(weaponDamage * 0.9); break; case 9: weaponDamage += (int)(weaponDamage * 1.2); break; case 10: weaponDamage += (int)(weaponDamage * 2); break; default: if (attacker.AttackUpgrade > 0) { weaponDamage *= attacker.AttackUpgrade / 5; } break; } #endregion baseDamage = (int)((int)((baseDamage + staticBoostCategory3 + weaponDamage + 15) * boostCategory3) * shellBoostCategory3); #endregion #region Defense switch (attacker.AttackUpgrade) { default: if (attacker.AttackUpgrade < 0) { defender.ArmorDefense += defender.ArmorDefense / 5; } break; case -10: defender.ArmorDefense += (int)(defender.ArmorDefense * 2); break; case -9: defender.ArmorDefense += (int)(defender.ArmorDefense * 1.2); break; case -8: defender.ArmorDefense += (int)(defender.ArmorDefense * 0.9); break; case -7: defender.ArmorDefense += (int)(defender.ArmorDefense * 0.65); break; case -6: defender.ArmorDefense += (int)(defender.ArmorDefense * 0.54); break; case -5: defender.ArmorDefense += (int)(defender.ArmorDefense * 0.43); break; case -4: defender.ArmorDefense += (int)(defender.ArmorDefense * 0.32); break; case -3: defender.ArmorDefense += (int)(defender.ArmorDefense * 0.22); break; case -2: defender.ArmorDefense += (int)(defender.ArmorDefense * 0.15); break; case -1: defender.ArmorDefense += (int)(defender.ArmorDefense * 0.1); break; case 0: defender.ArmorDefense += 0; break; } int defense = (int)((int)((defender.Defense + defender.ArmorDefense + staticBoostCategory4) * boostCategory4) * shellBoostCategory4); if (GetAttackerBenefitingBuffs(CardType.SpecialDefence, (byte)AdditionalTypes.SpecialDefence.AllDefenceNullified)[3] != 0 || (GetAttackerBenefitingBuffs(CardType.SpecialDefence, (byte)AdditionalTypes.SpecialDefence.MeleeDefenceNullified)[3] != 0 && attacker.AttackType.Equals(AttackType.Melee)) || (GetAttackerBenefitingBuffs(CardType.SpecialDefence, (byte)AdditionalTypes.SpecialDefence.RangedDefenceNullified)[3] != 0 && attacker.AttackType.Equals(AttackType.Range)) || (GetAttackerBenefitingBuffs(CardType.SpecialDefence, (byte)AdditionalTypes.SpecialDefence.MagicDefenceNullified)[3] != 0 && attacker.AttackType.Equals(AttackType.Magical))) { defense = 0; } #endregion #region Normal Damage int normalDamage = (int)((int)((baseDamage + staticBoostCategory2 - defense) * boostCategory2) * shellBoostCategory2); if (normalDamage < 0) { normalDamage = 0; } #endregion #region Crit Damage attacker.CritChance += GetShellWeaponEffectValue(ShellWeaponEffectType.CriticalChance); attacker.CritChance -= GetShellArmorEffectValue(ShellArmorEffectType.ReducedCritChanceRecive); attacker.CritRate += GetShellWeaponEffectValue(ShellWeaponEffectType.CriticalDamage); if (defender.CellonOptions != null) { attacker.CritRate -= defender.CellonOptions.Where(s => s.Type == CellonOptionType.CritReduce).Sum(s => s.Value); } if (ServerManager.Instance.RandomNumber() < attacker.CritChance && attacker.AttackType != AttackType.Magical) { double multiplier = attacker.CritRate / 100D; if (multiplier > 3) { multiplier = 3; } normalDamage += (int)(normalDamage * multiplier); hitMode = 3; } #endregion #region Fairy Damage int fairyDamage = (int)((baseDamage + 100) * attacker.ElementRate / 100D); #endregion #region Elemental Damage Advantage double elementalBoost = 0; switch (attacker.Element) { case 0: break; case 1: defender.Resistance = defender.FireResistance; switch (defender.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: defender.Resistance = defender.WaterResistance; switch (defender.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: defender.Resistance = defender.LightResistance; switch (defender.Element) { case 0: elementalBoost = 1.3; break; case 1: elementalBoost = 1.5; break; case 2: case 3: elementalBoost = 1; break; case 4: elementalBoost = 3; break; } break; case 4: defender.Resistance = defender.ShadowResistance; switch (defender.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; } if (skill?.Element == 0 || (skill?.Element != attacker.Element && attacker.EntityType == EntityType.Player)) { elementalBoost = 0; } #endregion #region Elemental Damage int elementalDamage = (int)((int)((int)((int)((staticBoostCategory5 + fairyDamage) * elementalBoost) * (1 - (defender.Resistance / 100D))) * boostCategory5) * shellBoostCategory5); if (elementalDamage < 0) { elementalDamage = 0; } #endregion #region Total Damage int totalDamage = (int)((int)((normalDamage + elementalDamage + attacker.Morale + staticBoostCategory1) * boostCategory1) * shellBoostCategory1); if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate)) { totalDamage /= 2; } if (defender.EntityType == EntityType.Monster || defender.EntityType == EntityType.NPC) { totalDamage -= getMonsterDamageBonus(defender.Level); } if (totalDamage < 5) { totalDamage = ServerManager.Instance.RandomNumber(1, 6); } if (attacker.EntityType == EntityType.Monster || attacker.EntityType == EntityType.NPC) { totalDamage += getMonsterDamageBonus(attacker.Level); } #endregion #region Onyx Wings int[] onyxBuff = GetAttackerBenefitingBuffs(CardType.StealBuff, (byte)AdditionalTypes.StealBuff.ChanceSummonOnyxDragon); if (onyxBuff[0] > ServerManager.Instance.RandomNumber()) { onyxWings = true; } #endregion return(totalDamage); }
public void AddBuff(Buff.Buff indicator) => BattleEntity.AddBuff(indicator);