예제 #1
0
        public SpAttackResult(Creature creature, int skillId, AttackResult atk)
        {
            Creature = creature;
            Target = atk.Target;

            SkillId = skillId;

            AttackUid = atk.AttackUid;
            AttackType = atk.AttackType.GetHashCode();
            Damage = atk.Damage;

            VisualEffect = atk.VisualEffect;

            if (VisualEffect != null)
                AttackType |= 1 << 24;
        }
예제 #2
0
        private static void ApplyPassivity(Player player, Condition condition, Passivity passivity, AttackResult result)
        {
            if(!CheckCondition(condition, passivity))
                return;

            if(passivity.Probability >= 0.001f && 1.0f - passivity.Probability > 0.001f)
                if(RandomUtilities.Random().Next(0, 100) > passivity.Probability*100)
                    return;

            switch (passivity.Type)
            {
                // Damage block
                case 109:
                    if (result.AttackType != AttackType.Normal || !result.Target.EffectsImpact.IsBlockFrontAttacks)
                        return;

                    if (result.AngleDif < 135 || passivity.Value < result.Damage)
                        return;

                    result.Damage = 0;
                    result.AttackType = AttackType.Block;
                    break;

                // Heal modifier
                case 168:
                case 169:
                    switch (passivity.Method)
                    {
                        case 2:
                            result.HpDiff += (int)passivity.Value;
                            break;
                        case 3:
                            result.HpDiff = (int)passivity.Value * result.HpDiff;
                            break;
                    }
                    break;

                // Do more damage when attack ...
                case 152:
                    if (passivity.MobSize != NpcSize.All)
                    {
                        if (result.Target is Player && passivity.MobSize != NpcSize.Player)
                            return;

                        if (result.Target is Npc && ((Npc)result.Target).NpcTemplate.Size != passivity.MobSize)
                            return;
                    }

                    switch (passivity.Method)
                    {
                        case 2:
                            result.Damage += (int)passivity.Value;
                            break;
                        case 3:
                            result.Damage = (int)(passivity.Value * result.Damage);
                            break;
                    }
                    break;

                // Chance to regenerate MP when combat starts.
                case 207:
                    Communication.Global.FeedbackService.MpChanged(player, (int)passivity.Value, player);
                    break;
            }
        }
예제 #3
0
 public static void OnHealed(Player player, AttackResult heal)
 {
     Apply(player, Condition.Healed, heal);
 }
예제 #4
0
 private static void Apply(Player player, Condition condition, AttackResult result = null)
 {
     foreach (var passivity in player.GameStats.Passivities)
         ApplyPassivity(player, condition, passivity, result);
 }
예제 #5
0
 public static void OnAttacked(Player player, AttackResult attack)
 {
     Apply(player, Condition.Attacked, attack);
 }
예제 #6
0
 public static void OnAttack(Player player, AttackResult attack)
 {
 }
예제 #7
0
        private async void ProcessArea(Creature creature, Skill skill, Targeting targeting, TargetingArea area,
                                       Projectile projectile = null)
        {
            try
            {
                bool isProjectileSkill = skill.Type == SkillType.Projectile || skill.Type == SkillType.Userslug;

                int skillId = creature.Attack.Args.SkillId;
                if (isProjectileSkill)
                    skillId += 20;

                if (targeting.Time > 0)
                    await Task.Delay((int) (targeting.Time/skill.TimeRate));
                int elapsed = targeting.Time;

                Player player = creature as Player;

                do
                {
                    try
                    {
                        if (creature.LifeStats.IsDead())
                            return;

                        if (area.DropItem != null)
                            creature.Instance.AddDrop(new Item
                                {
                                    Owner = player,

                                    ItemId = (int) area.DropItem,
                                    Count = 1,
                                    Position = Geom.ForwardPosition(creature.Position, 40),
                                    Instance = player.Instance,
                                });

                        Point3D center =
                            projectile != null
                                ? projectile.Position.ToPoint3D()
                                : Geom.GetNormal(creature.Position.Heading)
                                      .Multiple(area.OffsetDistance)
                                      .Add(creature.Position);

                        int count = 0;

                        List<Creature> targets =
                            creature.Attack.Args.Targets.Count > 0
                                ? creature.Attack.Args.Targets
                                : VisibleService.FindTargets(creature,
                                                             center,
                                                             projectile != null
                                                                 ? projectile.AttackDistance
                                                                 : area.MaxRadius,
                                                             area.Type);

                        foreach (Creature target in targets)
                        {
                            if (target != creature //Ignore checks for self-target
                                && !isProjectileSkill
                                && !creature.Attack.Args.IsItemSkill)
                            {
                                if (center.DistanceTo(target.Position) < area.MinRadius - 40)
                                    continue;

                                if (center.DistanceTo(target.Position) > area.MaxRadius)
                                    continue;

                                short diff = Geom.GetAngleDiff(creature.Attack.Args.StartPosition.Heading,
                                                               Geom.GetHeading(center, target.Position));

                                //diff from 0 to 180
                                //area.RangeAngel from 0 to 360
                                if (diff * 2 > (creature.Attack.Args.IsTargetAttack ? 90 : Math.Abs(area.RangeAngle) + 10))
                                    continue;
                            }

                            if (skill.TotalAtk > 0)
                            {
                                int damage = SeUtils.CalculateDamage(creature, target, skill.TotalAtk*area.Effect.Atk);

                                AttackResult result
                                    = new AttackResult
                                          {
                                              AttackType = AttackType.Normal,
                                              AttackUid = creature.Attack.UID,
                                              Damage = damage,
                                              Target = target,
                                          };

                                result.AngleDif = Geom.GetAngleDiff(creature.Attack.Args.StartPosition.Heading, result.Target.Position.Heading);
                                SeUtils.UpdateAttackResult(creature, result);

                                if (result.AttackType == AttackType.Block)
                                    VisibleService.Send(target, new SpAttackShowBlock(target, skillId));

                                VisibleService.Send(target, new SpAttackResult(creature, skillId, result));

                                AiLogic.OnAttack(creature, target);
                                AiLogic.OnAttacked(target, creature, result.Damage);

                                if (target is Player && ((Player)target).Duel != null && player != null &&
                                    ((Player)target).Duel.Equals(player.Duel) &&
                                    target.LifeStats.GetHpDiffResult(damage) < 1)
                                    DuelService.FinishDuel(player);
                                else
                                    CreatureLogic.HpChanged(target, target.LifeStats.MinusHp(result.Damage));
                            }

                            if (area.Effect.HpDiff > 0)
                            {
                                AttackResult result = new AttackResult {HpDiff = area.Effect.HpDiff, Target = target};

                                PassivityProcessor.OnHeal(player, result);
                                if(target is Player)
                                    PassivityProcessor.OnHealed((Player)target, result);

                                CreatureLogic.HpChanged(target, target.LifeStats.PlusHp(result.HpDiff),
                                                        creature);
                            }

                            if (area.Effect.MpDiff > 0)
                                CreatureLogic.MpChanged(target, target.LifeStats.PlusMp(area.Effect.MpDiff), creature);

                            if (area.Effect.AbnormalityOnCommon != null)
                                for (int i = 0; i < area.Effect.AbnormalityOnCommon.Count; i++)
                                    AbnormalityProcessor.AddAbnormality(target, area.Effect.AbnormalityOnCommon[i],
                                                                        creature);
                            if (player != null)
                            {
                                DuelService.ProcessDamage(player);

                                //MP regen on combo skill
                                if (skill.Id/10000 == 1 && player.GameStats.CombatMpRegen > 0)
                                {
                                    CreatureLogic.MpChanged(player, player.LifeStats.PlusMp(
                                        player.MaxMp*player.GameStats.CombatMpRegen/200));
                                }
                            }

                            if (++count == area.MaxCount) break;
                        }

                    }
                    catch (Exception ex)
                    {
                        Log.ErrorException("SkillEngine: ProcessAreaExc", ex);
                    }

                    if (targeting.Interval > 0)
                    {
                        await Task.Delay((int) (targeting.Interval/skill.TimeRate));
                        elapsed += targeting.Interval;
                    }

                } while (targeting.Interval > 0 && elapsed < targeting.Until);
            }
            catch (Exception ex)
            {
                Log.ErrorException("SkillEngine: ProcessArea", ex);
            }
        }
예제 #8
0
        private static void TrySetCrit(Creature attacker, AttackResult result)
        {
            int chance = (attacker is Player) ? 10 : 30;
            chance += attacker.GameStats.CritChanse - result.Target.GameStats.CritResist;
            if (chance < 0)
                chance = 2;

            if (Funcs.Random().Next(0, 100) > chance)
                return;

            result.Damage *= attacker.GameStats.CritPower;
            result.AttackType = AttackType.Critical;
        }
예제 #9
0
 public static void UpdateAttackResult(Creature attacker, AttackResult result)
 {
     if(attacker is Player)
         PassivityProcessor.OnAttack((Player)attacker, result);
     if(result.Target is Player)
         PassivityProcessor.OnAttacked((Player)result.Target, result);
     TrySetCrit(attacker, result);
 }