Example #1
0
        public static void AddDamage(IPlayerEntity player, string[] parameters)
        {
            if (parameters.Length < 1)
            {
                WorldPacketFactory.SendWorldMsg(player, "Syntax: .ad <atkFlag> <damage>");
                return;
            }

            if (player.Interaction.TargetEntity == null)
            {
                WorldPacketFactory.SendWorldMsg(player, "Select target entity first.");
                return;
            }

            Logger.LogDebug("Player {0} wants to execute AddDamage with effect to entity {1}.", player.Object.Name, player.Interaction.TargetEntity.Object.Name);

            if (!(player.Interaction.TargetEntity is ILivingEntity livingEntity))
            {
                WorldPacketFactory.SendWorldMsg(player, "Target is not a living entity.");
                return;
            }

            var atkFlag = AttackFlags.AF_GENERIC;
            var damage  = 0;

            if (parameters.Length == 2)
            {
                if (!Enum.TryParse(parameters[0], out atkFlag) || !int.TryParse(parameters[1], out damage))
                {
                    WorldPacketFactory.SendWorldMsg(player, "Invalid atkFlags or damage parameter.");
                    return;
                }
            }
            else
            {
                if (!int.TryParse(parameters[0], out damage))
                {
                    WorldPacketFactory.SendWorldMsg(player, "Invalid damage parameter.");
                    return;
                }
            }

            WorldPacketFactory.SendAddDamage(livingEntity, player, atkFlag, damage);
        }
Example #2
0
        /// <summary>
        /// Process the melee attack algorithm.
        /// </summary>
        /// <param name="attacker">Attacker</param>
        /// <param name="e">Melee attack event arguments</param>
        private void ProcessMeleeAttack(ILivingEntity attacker, MeleeAttackEventArgs e)
        {
            ILivingEntity defender = e.Target;

            if (defender.Health.IsDead)
            {
                Logger.LogError($"{attacker.Object.Name} cannot attack {defender.Object.Name} because target is already dead.");
                this.ClearBattleTargets(defender);
                this.ClearBattleTargets(attacker);
                return;
            }

            attacker.Battle.Target = defender;
            defender.Battle.Target = attacker;

            AttackResult meleeAttackResult = new MeleeAttackArbiter(attacker, defender).OnDamage();

            Logger.LogDebug($"{attacker.Object.Name} inflicted {meleeAttackResult.Damages} to {defender.Object.Name}");

            if (meleeAttackResult.Flags.HasFlag(AttackFlags.AF_FLYING))
            {
                BattleHelper.KnockbackEntity(defender);
            }

            WorldPacketFactory.SendAddDamage(defender, attacker, meleeAttackResult.Flags, meleeAttackResult.Damages);
            WorldPacketFactory.SendMeleeAttack(attacker, e.AttackType, defender.Id, e.UnknownParameter, meleeAttackResult.Flags);

            defender.Health.Hp -= meleeAttackResult.Damages;

            if (defender.Health.IsDead)
            {
                Logger.LogDebug($"{attacker.Object.Name} killed {defender.Object.Name}.");
                defender.Health.Hp = 0;
                this.ClearBattleTargets(defender);
                this.ClearBattleTargets(attacker);
                WorldPacketFactory.SendDie(attacker as IPlayerEntity, defender, attacker, e.AttackType);

                if (defender is IMonsterEntity deadMonster)
                {
                    var worldServerConfiguration = DependencyContainer.Instance.Resolve <WorldConfiguration>();
                    var itemsData = DependencyContainer.Instance.Resolve <ItemLoader>();
                    var expTable  = DependencyContainer.Instance.Resolve <ExpTableLoader>();

                    deadMonster.Timers.DespawnTime = Time.TimeInSeconds() + 5;

                    // Drop items
                    int itemCount = 0;
                    foreach (DropItemData dropItem in deadMonster.Data.DropItems)
                    {
                        if (itemCount >= deadMonster.Data.MaxDropItem)
                        {
                            break;
                        }

                        long dropChance = RandomHelper.LongRandom(0, DropSystem.MaxDropChance);

                        if (dropItem.Probability * worldServerConfiguration.Rates.Drop >= dropChance)
                        {
                            var item = new Item(dropItem.ItemId, 1, -1, -1, -1, (byte)RandomHelper.Random(0, dropItem.ItemMaxRefine));

                            deadMonster.NotifySystem <DropSystem>(new DropItemEventArgs(item, attacker));
                            itemCount++;
                        }
                    }

                    // Drop item kinds
                    foreach (DropItemKindData dropItemKind in deadMonster.Data.DropItemsKind)
                    {
                        var itemsDataByItemKind = itemsData.GetItems(x => x.ItemKind3 == dropItemKind.ItemKind && x.Rare >= dropItemKind.UniqueMin && x.Rare <= dropItemKind.UniqueMax);

                        if (!itemsDataByItemKind.Any())
                        {
                            continue;
                        }

                        var itemData = itemsDataByItemKind.ElementAt(RandomHelper.Random(0, itemsDataByItemKind.Count() - 1));

                        int itemRefine = RandomHelper.Random(0, 10);

                        for (int i = itemRefine; i >= 0; i--)
                        {
                            long itemDropProbability = (long)(expTable.GetDropLuck(itemData.Level > 120 ? 119 : itemData.Level, itemRefine) * (deadMonster.Data.CorrectionValue / 100f));
                            long dropChance          = RandomHelper.LongRandom(0, DropSystem.MaxDropChance);

                            if (dropChance < itemDropProbability * worldServerConfiguration.Rates.Drop)
                            {
                                var item = new Item(itemData.Id, 1, -1, -1, -1, (byte)itemRefine);

                                deadMonster.NotifySystem <DropSystem>(new DropItemEventArgs(item, attacker));
                                break;
                            }
                        }
                    }

                    // Drop gold
                    int goldDropped = RandomHelper.Random(deadMonster.Data.DropGoldMin, deadMonster.Data.DropGoldMax);
                    deadMonster.NotifySystem <DropSystem>(new DropGoldEventArgs(goldDropped, attacker));

                    // TODO: give exp
                }
            }
        }