Inheritance: OpenNos.Data.SkillDTO
Example #1
0
        public ushort GenerateDamage(MapMonster monsterToAttack, Skill skill, ref int hitmode)
        {
            #region Definitions

            if (monsterToAttack == null)
            {
                return 0;
            }
            if (Inventory == null)
            {
                return 0;
            }

            Random random = new Random();

            // int miss_chance = 20;
            int monsterDefence = 0;
            int monsterDodge = 0;

            short mainUpgrade = 0;
            int mainCritChance = 0;
            int mainCritHit = 0;
            int mainMinDmg = 0;
            int mainMaxDmg = 0;
            int mainHitRate = 0;

            short secUpgrade = 0;
            int secCritChance = 0;
            int secCritHit = 0;
            int secMinDmg = 0;
            int secMaxDmg = 0;
            int secHitRate = 0;

            // int CritChance = 4; int CritHit = 70; int MinDmg = 0; int MaxDmg = 0; int HitRate = 0;
            // sbyte Upgrade = 0;
            #endregion

            #region Get Weapon Stats

            WearableInstance weapon = Inventory.LoadBySlotAndType<WearableInstance>((byte)EquipmentType.MainWeapon, InventoryType.Wear);
            if (weapon != null)
            {
                mainUpgrade = weapon.Upgrade;
            }

            mainMinDmg += MinHit;
            mainMaxDmg += MaxHit;
            mainHitRate += HitRate;
            mainCritChance += HitCriticalRate;
            mainCritHit += HitCritical;

            WearableInstance weapon2 = Inventory.LoadBySlotAndType<WearableInstance>((byte)EquipmentType.SecondaryWeapon, InventoryType.Wear);
            if (weapon2 != null)
            {
                secUpgrade = weapon2.Upgrade;
            }

            secMinDmg += MinDistance;
            secMaxDmg += MaxDistance;
            secHitRate += DistanceRate;
            secCritChance += DistanceCriticalRate;
            secCritHit += DistanceCritical;

            #endregion

            #region Switch skill.Type

            switch (skill.Type)
            {
                case 0:
                    monsterDefence = monsterToAttack.Monster.CloseDefence;
                    monsterDodge = monsterToAttack.Monster.DefenceDodge;
                    if (Class == ClassType.Archer)
                    {
                        mainCritHit = secCritHit;
                        mainCritChance = secCritChance;
                        mainHitRate = secHitRate;
                        mainMaxDmg = secMaxDmg;
                        mainMinDmg = secMinDmg;
                        mainUpgrade = secUpgrade;
                    }
                    break;

                case 1:
                    monsterDefence = monsterToAttack.Monster.DistanceDefence;
                    monsterDodge = monsterToAttack.Monster.DistanceDefenceDodge;
                    if (Class == ClassType.Swordman || Class == ClassType.Adventurer || Class == ClassType.Magician)
                    {
                        mainCritHit = secCritHit;
                        mainCritChance = secCritChance;
                        mainHitRate = secHitRate;
                        mainMaxDmg = secMaxDmg;
                        mainMinDmg = secMinDmg;
                        mainUpgrade = secUpgrade;
                    }
                    break;

                case 2:
                    monsterDefence = monsterToAttack.Monster.MagicDefence;
                    break;

                case 3:
                    switch (Class)
                    {
                        case ClassType.Swordman:
                            monsterDefence = monsterToAttack.Monster.CloseDefence;
                            break;

                        case ClassType.Archer:
                            monsterDefence = monsterToAttack.Monster.DistanceDefence;
                            break;

                        case ClassType.Magician:
                            monsterDefence = monsterToAttack.Monster.MagicDefence;
                            break;

                        case ClassType.Adventurer:
                            monsterDefence = monsterToAttack.Monster.CloseDefence;
                            break;
                    }
                    break;

                case 5:
                    monsterDefence = monsterToAttack.Monster.CloseDefence;
                    monsterDodge = monsterToAttack.Monster.DefenceDodge;
                    if (Class == ClassType.Archer)
                    {
                        mainCritHit = secCritHit;
                        mainCritChance = secCritChance;
                        mainHitRate = secHitRate;
                        mainMaxDmg = secMaxDmg;
                        mainMinDmg = secMinDmg;
                        mainUpgrade = secUpgrade;
                    }
                    break;
            }

            #endregion

            #region Basic Damage Data Calculation

            #warning TODO: Implement BCard damage boosts, see Issue

            mainUpgrade -= monsterToAttack.Monster.DefenceUpgrade;
            if (mainUpgrade < -10)
            {
                mainUpgrade = -10;
            }
            else if (mainUpgrade > 10)
            {
                mainUpgrade = 10;
            }

            #endregion

            #region Detailed Calculation

            #region Dodge

            if (Class != ClassType.Magician)
            {
                double multiplier = monsterDodge / (mainHitRate + 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 ((skill.Type == 0 || skill.Type == 1) && !HasGodMode)
                {
                    if (random.Next(0, 100) <= chance)
                    {
                        hitmode = 1;
                        return 0;
                    }
                }
            }

            #endregion

            #region Base Damage

            int baseDamage = new Random().Next(mainMinDmg, mainMaxDmg + 1);
            baseDamage += (skill.Damage / 4);
            baseDamage += Level - monsterToAttack.Monster.Level; //Morale
            if (Class == ClassType.Adventurer)
            {
                //HACK: Damage is ~10 lower in OpenNos than in official. Fix this...
                baseDamage += 20;
            }
            int elementalDamage = 0; // placeholder for BCard etc...
            elementalDamage += (skill.ElementalDamage / 4);
            switch (mainUpgrade)
            {
                case -10:
                    monsterDefence += monsterDefence * 2;
                    break;

                case -9:
                    monsterDefence += (int)(monsterDefence * 1.2);
                    break;

                case -8:
                    monsterDefence += (int)(monsterDefence * 0.9);
                    break;

                case -7:
                    monsterDefence += (int)(monsterDefence * 0.65);
                    break;

                case -6:
                    monsterDefence += (int)(monsterDefence * 0.54);
                    break;

                case -5:
                    monsterDefence += (int)(monsterDefence * 0.43);
                    break;

                case -4:
                    monsterDefence += (int)(monsterDefence * 0.32);
                    break;

                case -3:
                    monsterDefence += (int)(monsterDefence * 0.22);
                    break;

                case -2:
                    monsterDefence += (int)(monsterDefence * 0.15);
                    break;

                case -1:
                    monsterDefence += (int)(monsterDefence * 0.1);
                    break;

                case 0:
                    break;

                case 1:
                    baseDamage += (int)(baseDamage * 0.1);
                    break;

                case 2:
                    baseDamage += (int)(baseDamage * 0.15);
                    break;

                case 3:
                    baseDamage += (int)(baseDamage * 0.22);
                    break;

                case 4:
                    baseDamage += (int)(baseDamage * 0.32);
                    break;

                case 5:
                    baseDamage += (int)(baseDamage * 0.43);
                    break;

                case 6:
                    baseDamage += (int)(baseDamage * 0.54);
                    break;

                case 7:
                    baseDamage += (int)(baseDamage * 0.65);
                    break;

                case 8:
                    baseDamage += (int)(baseDamage * 0.9);
                    break;

                case 9:
                    baseDamage += (int)(baseDamage * 1.2);
                    break;

                case 10:
                    baseDamage += baseDamage * 2;
                    break;
            }
            if (skill.Type == 1)
            {
                if (Math.Abs(monsterToAttack.MapX - MapX) < 4 && Math.Abs(monsterToAttack.MapY - MapY) < 4)
                    baseDamage = (int)(baseDamage * 0.7);
            }

            #endregion

            #region Elementary Damage

            #region Calculate Elemental Boost + Rate

            double elementalBoost = 0;
            short monsterResistance = 0;
            switch (Element)
            {
                case 0:
                    break;

                case 1:
                    monsterResistance = monsterToAttack.Monster.FireResistance;
                    switch (monsterToAttack.Monster.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:
                    monsterResistance = monsterToAttack.Monster.WaterResistance;
                    switch (monsterToAttack.Monster.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:
                    monsterResistance = monsterToAttack.Monster.LightResistance;
                    switch (monsterToAttack.Monster.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:
                    monsterResistance = monsterToAttack.Monster.DarkResistance;
                    switch (monsterToAttack.Monster.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)
            {
                if (elementalBoost == 0.5)
                {
                    elementalBoost = 0;
                }
                else if (elementalBoost == 1)
                {
                    elementalBoost = 0.05;
                }
                else if (elementalBoost == 1.3)
                {
                    elementalBoost = 0.15;
                }
                else if (elementalBoost == 1.5)
                {
                    elementalBoost = 0.15;
                }
                else if (elementalBoost == 2)
                {
                    elementalBoost = 0.2;
                }
                else if (elementalBoost == 3)
                {
                    elementalBoost = 0.2;
                }
            }
            else if (skill.Element != Element)
            {
                elementalBoost = 0;
            }

            elementalDamage = (int)((elementalDamage + ((elementalDamage + baseDamage) * ((ElementRate + ElementRateSP) / 100D))) * elementalBoost);
            elementalDamage = elementalDamage / 100 * (100 - monsterResistance);

            #endregion

            #region Critical Damage

            baseDamage -= monsterDefence;

            if (random.Next(100) <= mainCritChance)
            {
                if (skill.Type == 2)
                {
                }
                else if (skill.Type == 3 && Class != ClassType.Magician)
                {
                    double multiplier = (mainCritHit / 100D);
                    if (multiplier > 3)
                        multiplier = 3;
                    baseDamage += (int)(baseDamage * multiplier);
                    hitmode = 3;
                }
                else
                {
                    double multiplier = (mainCritHit / 100D);
                    if (multiplier > 3)
                        multiplier = 3;
                    baseDamage += (int)(baseDamage * multiplier);
                    hitmode = 3;
                }
            }

            #endregion

            #region Total Damage

            int totalDamage = baseDamage + elementalDamage;
            if (totalDamage < 5)
            {
                totalDamage = random.Next(1, 6);
            }

            #endregion

            #endregion

            if (monsterToAttack.DamageList.ContainsKey(CharacterId))
            {
                monsterToAttack.DamageList[CharacterId] += totalDamage;
            }
            else
            {
                monsterToAttack.DamageList.Add(CharacterId, totalDamage);
            }
            if (monsterToAttack.CurrentHp <= totalDamage)
            {
                monsterToAttack.IsAlive = false;
                monsterToAttack.CurrentHp = 0;
                monsterToAttack.CurrentMp = 0;
                monsterToAttack.Death = DateTime.Now;
                monsterToAttack.LastMove = DateTime.Now;
            }
            else
            {
                monsterToAttack.CurrentHp -= totalDamage;
            }

            while (totalDamage > ushort.MaxValue)
            {
                totalDamage -= ushort.MaxValue;
            }
            // only set the hit delay if we become the monsters target with this hit
            if (monsterToAttack.Target != CharacterId)
            {
                monsterToAttack.LastEffect = DateTime.Now;
            }
            ushort damage = Convert.ToUInt16(totalDamage);
            if (monsterToAttack.IsMoving)
            {
                monsterToAttack.Target = CharacterId;
            }
            return damage;
        }
Example #2
0
        /// <summary>
        /// Generate the Monster -&gt; Character Damage
        /// </summary>
        /// <param name="targetCharacter"></param>
        /// <param name="skill"></param>
        /// <param name="hitmode"></param>
        /// <returns></returns>
        private int GenerateDamage(Character targetCharacter, Skill skill, ref int hitmode)
        {
            //Warning: This code contains a huge amount of copypasta!

            #region Definitions

            if (targetCharacter == null)
            {
                return(0);
            }

            int  playerDefense        = targetCharacter.Buff.Get(Type.Defense, SubType.Increase, false)[0];
            byte playerDefenseUpgrade = (byte)targetCharacter.Buff.Get(Type.Defense, SubType.IncreaseLevel, false)[0];
            int  playerDodge          = targetCharacter.Buff.Get(Type.Dodge, SubType.Increase, false)[0];

            WearableInstance playerArmor = targetCharacter.Inventory.LoadBySlotAndType <WearableInstance>((byte)EquipmentType.Armor, InventoryType.Wear);
            if (playerArmor != null)
            {
                playerDefenseUpgrade += playerArmor.Upgrade;
            }

            short mainUpgrade    = Monster.AttackUpgrade;
            int   mainCritChance = Monster.CriticalChance;
            int   mainCritHit    = Monster.CriticalRate - 30;
            int   mainMinDmg     = Monster.DamageMinimum;
            int   mainMaxDmg     = Monster.DamageMaximum;
            int   mainHitRate    = Monster.Concentrate; //probably missnamed, check later
            if (mainMaxDmg == 0)
            {
                mainMinDmg     = Monster.Level * 8;
                mainMaxDmg     = Monster.Level * 12;
                mainCritChance = 10;
                mainCritHit    = 120;
                mainHitRate    = Monster.Level / 2 + 1;
            }

            #endregion

            #region Get Player defense

            int boostpercentage;
            switch (Monster.AttackClass)
            {
            case 0:
                playerDefense += targetCharacter.Defence
                                 + targetCharacter.Buff.Get(Type.Defense, SubType.IncreaseMelee, false)[0];
                playerDodge += targetCharacter.DefenceRate
                               + targetCharacter.Buff.Get(Type.Dodge, SubType.IncreaseDistance, false)[0];
                boostpercentage = targetCharacter.Buff.Get(Type.Defense, SubType.IncreaseMeleePercentage, false)[0];
                playerDefense   = (int)(playerDefense * (1 + boostpercentage / 100D));
                boostpercentage = targetCharacter.Buff.Get(Type.Dodge, SubType.IncreaseMeleePercentage, false)[0];
                playerDodge     = (int)(playerDodge * (1 + boostpercentage / 100D));
                break;

            case 1:
                playerDefense += targetCharacter.DistanceDefence
                                 + targetCharacter.Buff.Get(Type.Defense, SubType.IncreaseDistance, false)[0];
                playerDodge += targetCharacter.DistanceDefenceRate
                               + targetCharacter.Buff.Get(Type.Dodge, SubType.IncreaseDistance, false)[0];
                boostpercentage = targetCharacter.Buff.Get(Type.Defense, SubType.IncreaseDistancePercentage, false)[0];
                playerDefense   = (int)(playerDefense * (1 + boostpercentage / 100D));
                boostpercentage = targetCharacter.Buff.Get(Type.Dodge, SubType.IncreaseDistancePercentage, false)[0];
                playerDodge     = (int)(playerDodge * (1 + boostpercentage / 100D));
                break;

            case 2:
                playerDefense += targetCharacter.MagicalDefence
                                 + targetCharacter.Buff.Get(Type.Defense, SubType.IncreaseMagic, false)[0];
                boostpercentage = targetCharacter.Buff.Get(Type.Defense, SubType.IncreaseMagicPercentage, false)[0];
                playerDefense   = (int)(playerDefense * (1 + boostpercentage / 100D));
                break;

            default:
                throw new Exception($"Monster.AttackClass {Monster.AttackClass} not implemented");
            }

            #endregion

            #region Basic Damage Data Calculation

            mainCritChance += targetCharacter.Buff.Get(Type.Defense, SubType.IncreaseCriticalChance, false)[0];
            mainCritChance -= targetCharacter.Buff.Get(Type.Defense, SubType.DecreaseCriticalChance, false)[0];
            mainCritHit    += targetCharacter.Buff.Get(Type.Defense, SubType.IncreaseCriticalDamage, false)[0];
            mainCritHit    -= targetCharacter.Buff.Get(Type.Defense, SubType.DecreaseCriticalDamage, false)[0];
            mainUpgrade    -= playerDefenseUpgrade;
            if (mainUpgrade < -10)
            {
                mainUpgrade = -10;
            }
            else if (mainUpgrade > 10)
            {
                mainUpgrade = 10;
            }

            #endregion

            #region Detailed Calculation

            #region Dodge

            double multiplier = playerDodge / (double)mainHitRate;
            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 (Monster.AttackClass == 0 || Monster.AttackClass == 1)
            {
                if (ServerManager.Instance.RandomNumber() <= chance)
                {
                    hitmode = 1;
                    return(0);
                }
            }

            #endregion

            #region Base Damage

            int baseDamage = ServerManager.Instance.RandomNumber(mainMinDmg, mainMaxDmg + 1);
            baseDamage += Monster.Level - targetCharacter.Level;
            int elementalDamage = 0; // placeholder for BCard etc...

            if (skill != null)
            {
                baseDamage      += skill.Damage / 4;
                elementalDamage += skill.ElementalDamage / 4;
            }

            switch (mainUpgrade)
            {
            case -10:
                playerDefense += playerDefense * 2;
                break;

            case -9:
                playerDefense += (int)(playerDefense * 1.2);
                break;

            case -8:
                playerDefense += (int)(playerDefense * 0.9);
                break;

            case -7:
                playerDefense += (int)(playerDefense * 0.65);
                break;

            case -6:
                playerDefense += (int)(playerDefense * 0.54);
                break;

            case -5:
                playerDefense += (int)(playerDefense * 0.43);
                break;

            case -4:
                playerDefense += (int)(playerDefense * 0.32);
                break;

            case -3:
                playerDefense += (int)(playerDefense * 0.22);
                break;

            case -2:
                playerDefense += (int)(playerDefense * 0.15);
                break;

            case -1:
                playerDefense += (int)(playerDefense * 0.1);
                break;

            case 0:
                break;

            case 1:
                baseDamage += (int)(baseDamage * 0.1);
                break;

            case 2:
                baseDamage += (int)(baseDamage * 0.15);
                break;

            case 3:
                baseDamage += (int)(baseDamage * 0.22);
                break;

            case 4:
                baseDamage += (int)(baseDamage * 0.32);
                break;

            case 5:
                baseDamage += (int)(baseDamage * 0.43);
                break;

            case 6:
                baseDamage += (int)(baseDamage * 0.54);
                break;

            case 7:
                baseDamage += (int)(baseDamage * 0.65);
                break;

            case 8:
                baseDamage += (int)(baseDamage * 0.9);
                break;

            case 9:
                baseDamage += (int)(baseDamage * 1.2);
                break;

            case 10:
                baseDamage += baseDamage * 2;
                break;
            }

            #endregion

            #region Elementary Damage

            int bonusrez = targetCharacter.Buff.Get(Type.Resistance, SubType.Increase, false)[0];

            #region Calculate Elemental Boost + Rate

            double elementalBoost    = 0;
            int    playerRessistance = 0;
            switch (Monster.Element)
            {
            case 0:
                break;

            case 1:
                bonusrez         += targetCharacter.Buff.Get(Type.Resistance, SubType.IncreaseFire, false)[0];
                playerRessistance = targetCharacter.FireResistance;
                switch (targetCharacter.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         += targetCharacter.Buff.Get(Type.Resistance, SubType.IncreaseWater, false)[0];
                playerRessistance = targetCharacter.WaterResistance;
                switch (targetCharacter.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         += targetCharacter.Buff.Get(Type.Resistance, SubType.IncreaseLight, false)[0];
                playerRessistance = targetCharacter.LightResistance;
                switch (targetCharacter.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         += targetCharacter.Buff.Get(Type.Resistance, SubType.IncreaseShadow, false)[0];
                playerRessistance = targetCharacter.DarkResistance;
                switch (targetCharacter.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 (Monster.Element == 0)
            {
                if (elementalBoost == 0.5)
                {
                    elementalBoost = 0;
                }
                else if (elementalBoost == 1)
                {
                    elementalBoost = 0.05;
                }
                else if (elementalBoost == 1.3)
                {
                    elementalBoost = 0;
                }
                else if (elementalBoost == 1.5)
                {
                    elementalBoost = 0.15;
                }
                else if (elementalBoost == 2)
                {
                    elementalBoost = 0.2;
                }
                else if (elementalBoost == 3)
                {
                    elementalBoost = 0.2;
                }
            }
            elementalDamage = (int)((elementalDamage + (elementalDamage + baseDamage) * (Monster.ElementRate / 100D)) * elementalBoost);
            elementalDamage = elementalDamage / 100 * (100 - playerRessistance - bonusrez);
            if (elementalDamage < 0)
            {
                elementalDamage = 0;
            }

            #endregion

            #region Critical Damage

            if (ServerManager.Instance.RandomNumber() <= mainCritChance)
            {
                if (Monster.AttackClass == 2)
                {
                }
                else
                {
                    baseDamage += (int)(baseDamage * (mainCritHit / 100D));
                    hitmode     = 3;
                }
            }

            #endregion

            #region Total Damage

            int totalDamage = baseDamage + elementalDamage - playerDefense;
            if (totalDamage < 5)
            {
                totalDamage = ServerManager.Instance.RandomNumber(1, 6);
            }

            #endregion

            #endregion

            #region Minimum damage

            if (Monster.Level < 45)
            {
                //no minimum damage
            }
            else if (Monster.Level < 55)
            {
                totalDamage += Monster.Level;
            }
            else if (Monster.Level < 60)
            {
                totalDamage += Monster.Level * 2;
            }
            else if (Monster.Level < 65)
            {
                totalDamage += Monster.Level * 3;
            }
            else if (Monster.Level < 70)
            {
                totalDamage += Monster.Level * 4;
            }
            else
            {
                totalDamage += Monster.Level * 5;
            }

            #endregion

            return(totalDamage);
        }
Example #3
0
        /// <summary>
        /// Generate the Monster -&gt; Character Damage
        /// </summary>
        /// <param name="targetCharacter"></param>
        /// <param name="skill"></param>
        /// <param name="hitmode"></param>
        /// <returns></returns>
        internal int GenerateDamage(Character targetCharacter, Skill skill, ref int hitmode)
        {
            //Warning: This code contains a huge amount of copypasta!
            #region Definitions

            if (targetCharacter == null)
            {
                return 0;
            }

            short distanceX = (short)(MapX - targetCharacter.MapX);
            short distanceY = (short)(MapY - targetCharacter.MapY);
            Random random = new Random();
            int generated = random.Next(0, 100);

            int playerDefense = 0;
            byte playerDefenseUpgrade = 0;
            int playerDodge = 0;

            WearableInstance playerArmor = targetCharacter.Inventory.LoadBySlotAndType<WearableInstance>((byte)Domain.EquipmentType.Armor, Domain.InventoryType.Wear);
            if (playerArmor != null)
            {
                playerDefenseUpgrade = playerArmor.Upgrade;
            }

            short mainUpgrade = Monster.AttackUpgrade;
            int mainCritChance = Monster.CriticalChance;
            int mainCritHit = Monster.CriticalRate;
            int mainMinDmg = Monster.DamageMinimum;
            int mainMaxDmg = Monster.DamageMaximum;
            int mainHitRate = Monster.Concentrate; //probably missnamed, check later
            if (mainMaxDmg == 0)
            {
                mainMinDmg = Monster.Level * 8;
                mainMaxDmg = Monster.Level * 12;
                mainCritChance = 10;
                mainCritHit = 120;
                mainHitRate = (Monster.Level / 2) + 1;
            }

            #endregion

            #region Get Player defense

            switch (Monster.AttackClass)
            {
                case 0:
                    playerDefense = targetCharacter.Defence;
                    playerDodge = targetCharacter.DefenceRate;
                    break;

                case 1:
                    playerDefense = targetCharacter.DistanceDefence;
                    playerDodge = targetCharacter.DistanceDefenceRate;
                    break;

                case 2:
                    playerDefense = targetCharacter.MagicalDefence;
                    break;

                default:
                    throw new Exception(String.Format("Monster.AttackClass {0} not implemented", Monster.AttackClass));
            }

            #endregion

            #region Basic Damage Data Calculation

            #warning TODO: Implement BCard damage boosts, see Issue

            mainUpgrade -= playerDefenseUpgrade;
            if (mainUpgrade < -10)
            {
                mainUpgrade = -10;
            }
            else if (mainUpgrade > 10)
            {
                mainUpgrade = 10;
            }

            #endregion

            #region Detailed Calculation

            #region Dodge

            double multiplier = playerDodge / mainHitRate;
            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 (Monster.AttackClass == 0 || Monster.AttackClass == 1)
            {
                if (random.Next(0, 100) <= chance)
                {
                    hitmode = 1;
                    return 0;
                }
            }

            #endregion

            #region Base Damage

            int baseDamage = new Random().Next(mainMinDmg, mainMaxDmg + 1);
            baseDamage += Monster.Level - targetCharacter.Level;
            int elementalDamage = 0; // placeholder for BCard etc...

            if (skill != null)
            {
                baseDamage += (skill.Damage / 4);
                elementalDamage += (skill.ElementalDamage / 4);
            }

            switch (mainUpgrade)
            {
                case -10:
                    playerDefense += (int)(playerDefense * 2);
                    break;

                case -9:
                    playerDefense += (int)(playerDefense * 1.2);
                    break;

                case -8:
                    playerDefense += (int)(playerDefense * 0.9);
                    break;

                case -7:
                    playerDefense += (int)(playerDefense * 0.65);
                    break;

                case -6:
                    playerDefense += (int)(playerDefense * 0.54);
                    break;

                case -5:
                    playerDefense += (int)(playerDefense * 0.43);
                    break;

                case -4:
                    playerDefense += (int)(playerDefense * 0.32);
                    break;

                case -3:
                    playerDefense += (int)(playerDefense * 0.22);
                    break;

                case -2:
                    playerDefense += (int)(playerDefense * 0.15);
                    break;

                case -1:
                    playerDefense += (int)(playerDefense * 0.1);
                    break;

                case 0:
                    break;

                case 1:
                    baseDamage += (int)(baseDamage * 0.1);
                    break;

                case 2:
                    baseDamage += (int)(baseDamage * 0.15);
                    break;

                case 3:
                    baseDamage += (int)(baseDamage * 0.22);
                    break;

                case 4:
                    baseDamage += (int)(baseDamage * 0.32);
                    break;

                case 5:
                    baseDamage += (int)(baseDamage * 0.43);
                    break;

                case 6:
                    baseDamage += (int)(baseDamage * 0.54);
                    break;

                case 7:
                    baseDamage += (int)(baseDamage * 0.65);
                    break;

                case 8:
                    baseDamage += (int)(baseDamage * 0.9);
                    break;

                case 9:
                    baseDamage += (int)(baseDamage * 1.2);
                    break;

                case 10:
                    baseDamage += (int)(baseDamage * 2);
                    break;
            }

            #endregion

            #region Elementary Damage

            #region Calculate Elemental Boost + Rate

            double elementalBoost = 0;
            int playerRessistance = 0;
            switch (Monster.Element)
            {
                case 0:
                    break;

                case 1:
                    playerRessistance = targetCharacter.FireResistance;
                    switch (targetCharacter.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:
                    playerRessistance = targetCharacter.WaterResistance;
                    switch (targetCharacter.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:
                    playerRessistance = targetCharacter.LightResistance;
                    switch (targetCharacter.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:
                    playerRessistance = targetCharacter.DarkResistance;
                    switch (targetCharacter.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 (Monster.Element == 0)
            {
                if (elementalBoost == 0.5)
                {
                    elementalBoost = 0;
                }
                else if (elementalBoost == 1)
                {
                    elementalBoost = 0.05;
                }
                else if (elementalBoost == 1.3)
                {
                    elementalBoost = 0;
                }
                else if (elementalBoost == 1.5)
                {
                    elementalBoost = 0.15;
                }
                else if (elementalBoost == 2)
                {
                    elementalBoost = 0.2;
                }
                else if (elementalBoost == 3)
                {
                    elementalBoost = 0.2;
                }
            }

            elementalDamage = (int)((elementalDamage + ((elementalDamage + baseDamage) * ((Monster.ElementRate) / 100D))) * elementalBoost);
            elementalDamage = elementalDamage / 100 * (100 - playerRessistance);

            #endregion

            #region Critical Damage

            if (random.Next(100) <= mainCritChance)
            {
                if (Monster.AttackClass == 2)
                {
                }
                else
                {
                    baseDamage += (int)(baseDamage * ((mainCritHit / 100D)));
                    hitmode = 3;
                }
            }

            #endregion

            #region Total Damage

            int totalDamage = baseDamage + elementalDamage - playerDefense;
            if (totalDamage < 5)
            {
                totalDamage = random.Next(1, 6);
            }

            #endregion

            #endregion

            #region Minimum damage
            if (Monster.Level < 45)
            {
                //no minimum damage
            }
            else if (Monster.Level < 55)
            {
                totalDamage += Monster.Level;
            }
            else if (Monster.Level < 60)
            {
                totalDamage += Monster.Level * 2;
            }
            else if (Monster.Level < 65)
            {
                totalDamage += Monster.Level * 3;
            }
            else if (Monster.Level < 70)
            {
                totalDamage += Monster.Level * 4;
            }
            else
            {
                totalDamage += Monster.Level * 5;
            }

            #endregion

            return totalDamage;
        }
Example #4
0
        public void Initialize()
        {
            // parse rates
            XPRate       = int.Parse(System.Configuration.ConfigurationManager.AppSettings["RateXp"]);
            DropRate     = int.Parse(System.Configuration.ConfigurationManager.AppSettings["RateDrop"]);
            GoldDropRate = int.Parse(System.Configuration.ConfigurationManager.AppSettings["GoldRateDrop"]);
            GoldRate     = int.Parse(System.Configuration.ConfigurationManager.AppSettings["RateGold"]);
            FairyXpRate  = int.Parse(System.Configuration.ConfigurationManager.AppSettings["RateFairyXp"]);

            Mails = DAOFactory.MailDAO.LoadAll().ToList();

            // load explicite type of ItemDTO
            foreach (ItemDTO itemDTO in DAOFactory.ItemDAO.LoadAll())
            {
                Item ItemGO = null;

                switch (itemDTO.ItemType)
                {
                case ItemType.Ammo:
                    ItemGO = new NoFunctionItem(itemDTO);
                    break;

                case ItemType.Armor:
                    ItemGO = new WearableItem(itemDTO);
                    break;

                case ItemType.Box:
                    ItemGO = new BoxItem(itemDTO);
                    break;

                case ItemType.Event:
                    ItemGO = new MagicalItem(itemDTO);
                    break;

                case ItemType.Fashion:
                    ItemGO = new WearableItem(itemDTO);
                    break;

                case ItemType.Food:
                    ItemGO = new FoodItem(itemDTO);
                    break;

                case ItemType.Jewelery:
                    ItemGO = new WearableItem(itemDTO);
                    break;

                case ItemType.Magical:
                    ItemGO = new MagicalItem(itemDTO);
                    break;

                case ItemType.Main:
                    ItemGO = new NoFunctionItem(itemDTO);
                    break;

                case ItemType.Map:
                    ItemGO = new NoFunctionItem(itemDTO);
                    break;

                case ItemType.Part:
                    ItemGO = new NoFunctionItem(itemDTO);
                    break;

                case ItemType.Potion:
                    ItemGO = new PotionItem(itemDTO);
                    break;

                case ItemType.Production:
                    ItemGO = new ProduceItem(itemDTO);
                    break;

                case ItemType.Quest1:
                    ItemGO = new NoFunctionItem(itemDTO);
                    break;

                case ItemType.Quest2:
                    ItemGO = new NoFunctionItem(itemDTO);
                    break;

                case ItemType.Sell:
                    ItemGO = new NoFunctionItem(itemDTO);
                    break;

                case ItemType.Shell:
                    ItemGO = new MagicalItem(itemDTO);
                    break;

                case ItemType.Snack:
                    ItemGO = new SnackItem(itemDTO);
                    break;

                case ItemType.Special:
                    ItemGO = new SpecialItem(itemDTO);
                    break;

                case ItemType.Specialist:
                    ItemGO = new WearableItem(itemDTO);
                    break;

                case ItemType.Teacher:
                    ItemGO = new TeacherItem(itemDTO);
                    break;

                case ItemType.Upgrade:
                    ItemGO = new UpgradeItem(itemDTO);
                    break;

                case ItemType.Weapon:
                    ItemGO = new WearableItem(itemDTO);
                    break;

                default:
                    ItemGO = new NoFunctionItem(itemDTO);
                    break;
                }
                _items.Add(ItemGO);
            }
            Logger.Log.Info(String.Format(Language.Instance.GetMessageFromKey("ITEMS_LOADED"), _items.Count()));

            // intialize monsterdrops
            _monsterDrops = new ThreadSafeSortedList <short, List <DropDTO> >();
            foreach (var monsterDropGrouping in DAOFactory.DropDAO.LoadAll().GroupBy(d => d.MonsterVNum))
            {
                if (monsterDropGrouping.Key.HasValue)
                {
                    _monsterDrops[monsterDropGrouping.Key.Value] = monsterDropGrouping.OrderBy(d => d.DropChance).ToList();
                }
                else
                {
                    _generalDrops = monsterDropGrouping.ToList();
                }
            }
            Logger.Log.Info(String.Format(Language.Instance.GetMessageFromKey("DROPS_LOADED"), _monsterDrops.GetAllItems().Sum(i => i.Count())));

            // initialiize monsterskills
            _monsterSkills = new ThreadSafeSortedList <short, List <NpcMonsterSkill> >();
            foreach (var monsterSkillGrouping in DAOFactory.NpcMonsterSkillDAO.LoadAll().GroupBy(n => n.NpcMonsterVNum))
            {
                _monsterSkills[monsterSkillGrouping.Key] = monsterSkillGrouping.Select(n => n as NpcMonsterSkill).ToList();
            }
            Logger.Log.Info(String.Format(Language.Instance.GetMessageFromKey("MONSTERSKILLS_LOADED"), _monsterSkills.GetAllItems().Sum(i => i.Count())));

            // initialize npcmonsters
            foreach (NpcMonsterDTO npcmonsterDTO in DAOFactory.NpcMonsterDAO.LoadAll())
            {
                _npcs.Add(npcmonsterDTO as NpcMonster);
            }
            Logger.Log.Info(String.Format(Language.Instance.GetMessageFromKey("NPCMONSTERS_LOADED"), _npcs.Count()));

            // intialize receipes
            _recipes = new ThreadSafeSortedList <int, List <Recipe> >();
            foreach (var recipeGrouping in DAOFactory.RecipeDAO.LoadAll().GroupBy(r => r.MapNpcId))
            {
                _recipes[recipeGrouping.Key] = recipeGrouping.Select(r => r as Recipe).ToList();
            }
            Logger.Log.Info(String.Format(Language.Instance.GetMessageFromKey("RECIPES_LOADED"), _recipes.GetAllItems().Sum(i => i.Count())));

            // initialize shopitems
            _shopItems = new ThreadSafeSortedList <int, List <ShopItemDTO> >();
            foreach (var shopItemGrouping in DAOFactory.ShopItemDAO.LoadAll().GroupBy(s => s.ShopId))
            {
                _shopItems[shopItemGrouping.Key] = shopItemGrouping.ToList();
            }
            Logger.Log.Info(String.Format(Language.Instance.GetMessageFromKey("SHOPITEMS_LOADED"), _shopItems.GetAllItems().Sum(i => i.Count())));

            // initialize shopskills
            _shopSkills = new ThreadSafeSortedList <int, List <ShopSkillDTO> >();
            foreach (var shopSkillGrouping in DAOFactory.ShopSkillDAO.LoadAll().GroupBy(s => s.ShopId))
            {
                _shopSkills[shopSkillGrouping.Key] = shopSkillGrouping.ToList();
            }
            Logger.Log.Info(String.Format(Language.Instance.GetMessageFromKey("SHOPSKILLS_LOADED"), _shopSkills.GetAllItems().Sum(i => i.Count())));

            // initialize shops
            _shops = new ThreadSafeSortedList <int, Shop>();
            foreach (var shopGrouping in DAOFactory.ShopDAO.LoadAll())
            {
                _shops[shopGrouping.MapNpcId] = shopGrouping as Shop;
            }
            Logger.Log.Info(String.Format(Language.Instance.GetMessageFromKey("SHOPS_LOADED"), _shops.GetAllItems().Count()));

            // initialize teleporters
            _teleporters = new ThreadSafeSortedList <int, List <TeleporterDTO> >();
            foreach (var teleporterGrouping in DAOFactory.TeleporterDAO.LoadAll().GroupBy(t => t.MapNpcId))
            {
                _teleporters[teleporterGrouping.Key] = teleporterGrouping.Select(t => t).ToList();
            }
            Logger.Log.Info(String.Format(Language.Instance.GetMessageFromKey("TELEPORTERS_LOADED"), _teleporters.GetAllItems().Sum(i => i.Count())));

            // initialize skills
            foreach (SkillDTO skillDTO in DAOFactory.SkillDAO.LoadAll())
            {
                Skill skill = skillDTO as Skill;
                skill.Combos.AddRange(DAOFactory.ComboDAO.LoadBySkillVnum(skill.SkillVNum).ToList());
                _skills.Add(skill);
            }
            Logger.Log.Info(String.Format(Language.Instance.GetMessageFromKey("SKILLS_LOADED"), _skills.Count()));

            // intialize mapnpcs
            _mapNpcs = new ThreadSafeSortedList <short, List <MapNpc> >();
            foreach (var mapNpcGrouping in DAOFactory.MapNpcDAO.LoadAll().GroupBy(t => t.MapId))
            {
                _mapNpcs[mapNpcGrouping.Key] = mapNpcGrouping.Select(t => t as MapNpc).ToList();
            }
            Logger.Log.Info(String.Format(Language.Instance.GetMessageFromKey("MAPNPCS_LOADED"), _mapNpcs.GetAllItems().Sum(i => i.Count())));

            try
            {
                int i            = 0;
                int monstercount = 0;

                foreach (MapDTO map in DAOFactory.MapDAO.LoadAll())
                {
                    Guid guid   = Guid.NewGuid();
                    Map  newMap = new Map(map.MapId, guid, map.Data);
                    newMap.Music       = map.Music;
                    newMap.ShopAllowed = map.ShopAllowed;

                    // register for broadcast
                    _maps.TryAdd(guid, newMap);
                    newMap.SetMapMapMonsterReference();
                    newMap.SetMapMapNpcReference();
                    i++;

                    newMap.LoadMonsters();
                    foreach (MapMonster mapMonster in newMap.Monsters)
                    {
                        mapMonster.Map = newMap;
                        newMap.AddMonster(mapMonster);
                    }
                    monstercount += newMap.Monsters.Count();
                }
                if (i != 0)
                {
                    Logger.Log.Info(String.Format(Language.Instance.GetMessageFromKey("MAPS_LOADED"), i));
                }
                else
                {
                    Logger.Log.Error(Language.Instance.GetMessageFromKey("NO_MAP"));
                }
                Logger.Log.Info(String.Format(Language.Instance.GetMessageFromKey("MAPMONSTERS_LOADED"), monstercount));
            }
            catch (Exception ex)
            {
                Logger.Log.Error("General Error", ex);
            }
            LaunchEvents();
        }