public void UseAbility(RealmTime time, int abilitySlot, Position target)
 {
     if (Ability[abilitySlot] == null)
         return;
     var ability = Ability[abilitySlot];
     if (MP < ability.MpCost || AbilityCooldown[abilitySlot] != 0)
         return;
     MP -= ability.MpCost;
     AbilityCooldown[abilitySlot] = ability.Cooldown;
     foreach (ActivateEffect eff in ability.ActivateEffects)
     {
         switch (eff.Effect)
         {
             case ActivateEffects.BulletNova:
                 {
                     ProjectileDesc prjDesc = ability.Projectiles[0]; //Assume only one
                     var batch = new Packet[21];
                     uint s = Random.CurrentSeed;
                     Random.CurrentSeed = (uint)(s * time.tickTimes);
                     for (int i = 0; i < 20; i++)
                     {
                         Projectile proj = CreateProjectile(prjDesc, ability.AbilityType,
                             (int)statsMgr.GetAttackDamage(prjDesc.MinDamage, prjDesc.MaxDamage),
                             time.tickTimes, target, (float)(i * (Math.PI * 2) / 20));
                         Owner.EnterWorld(proj);
                         fames.Shoot(proj);
                         batch[i] = new ShootPacket
                         {
                             BulletId = proj.ProjectileId,
                             OwnerId = Id,
                             ContainerType = ability.AbilityType,
                             Position = target,
                             Angle = proj.Angle,
                             Damage = (short)proj.Damage,
                             FromAbility = true
                         };
                     }
                     Random.CurrentSeed = s;
                     batch[20] = new ShowEffectPacket
                     {
                         EffectType = EffectType.Trail,
                         PosA = target,
                         TargetId = Id,
                         Color = new ARGB(0xFFFF00AA)
                     };
                     BroadcastSync(batch, p => this.Dist(p) < 25);
                 } break;
             case ActivateEffects.Shoot:
                 {
                     ActivateAbilityShoot(time, ability, target);
                 } break;
         }
     }
     UpdateCount++;
 }
        private bool Activate(RealmTime time, Item item, ItemData data, int itemSlot, Position target)
        {
            if (MP < item.MpCost)
                return false;
            MP -= item.MpCost;
            bool success = true;
            foreach (ActivateEffect eff in item.ActivateEffects)
            {
                switch (eff.Effect)
                {
                    case ActivateEffects.BulletNova:
                    {
                        ProjectileDesc prjDesc = item.Projectiles[0]; //Assume only one
                        var batch = new Packet[21];
                        uint s = Random.CurrentSeed;
                        Random.CurrentSeed = (uint) (s*time.tickTimes);
                        for (int i = 0; i < 20; i++)
                        {
                            Projectile proj = CreateProjectile(prjDesc, item.ObjectType,
                                (int) statsMgr.GetAttackDamage(prjDesc.MinDamage, prjDesc.MaxDamage),
                                time.tickTimes, target, (float) (i*(Math.PI*2)/20));
                            Owner.EnterWorld(proj);
                            fames.Shoot(proj);
                            batch[i] = new ShootPacket
                            {
                                BulletId = proj.ProjectileId,
                                OwnerId = Id,
                                ContainerType = item.ObjectType,
                                Position = target,
                                Angle = proj.Angle,
                                Damage = (short) proj.Damage,
                                FromAbility = false
                            };
                        }
                        Random.CurrentSeed = s;
                        batch[20] = new ShowEffectPacket
                        {
                            EffectType = EffectType.Trail,
                            PosA = target,
                            TargetId = Id,
                            Color = new ARGB(0xFFFF00AA)
                        };
                        BroadcastSync(batch, p => this.Dist(p) < 25);
                    }
                        break;
                    case ActivateEffects.Shoot:
                    {
                        ActivateShoot(time, item, target);
                    }
                        break;
                    case ActivateEffects.StatBoostSelf:
                    {
                        var idx = -1;
                        switch ((StatsType) eff.Stats)
                        {
                            case StatsType.MaximumHP: idx = 0; break;
                            case StatsType.MaximumMP: idx = 1; break;
                            case StatsType.Attack: idx = 2; break;
                            case StatsType.Defense: idx = 3; break;
                            case StatsType.Speed: idx = 4; break;
                            case StatsType.Vitality: idx = 5; break;
                            case StatsType.Wisdom: idx = 6; break;
                            case StatsType.Dexterity: idx = 7; break;
                        }
                        var s = eff.Amount;
                        ActivateBoost[idx].Push(s);
                        CalculateBoost();
                        (this as Player).UpdateCount++;
                        Owner.Timers.Add(new WorldTimer(eff.DurationMS, (world, t) =>
                        {
                            ActivateBoost[idx].Pop(s);
                            CalculateBoost();
                            (this as Player).UpdateCount++;
                        }));
                        BroadcastSync(new ShowEffectPacket
                        {
                            EffectType = EffectType.Potion,
                            TargetId = Id,
                            Color = new ARGB(0xffffffff)
                        }, p => this.Dist(p) < 25);
                    }
                        break;
                    case ActivateEffects.StatBoostAura:
                    {
                        int idx = -1;
                        switch ((StatsType) eff.Stats)
                        {
                            case StatsType.MaximumHP: idx = 0; break;
                            case StatsType.MaximumMP: idx = 1; break;
                            case StatsType.Attack: idx = 2; break;
                            case StatsType.Defense: idx = 3; break;
                            case StatsType.Speed: idx = 4; break;
                            case StatsType.Vitality: idx = 5; break;
                            case StatsType.Wisdom: idx = 6; break;
                            case StatsType.Dexterity: idx = 7; break;
                        }
                        int s = eff.Amount;
                        this.AOE(eff.Range, true, player =>
                        {
                            var plr = (player as Player);
                            if (PvP && (plr.Team == 0 || plr.Team != Team) && plr != this)
                                return;
                            ActivateBoost[idx].Push(s);
                            CalculateBoost();
                            player.UpdateCount++;
                            Owner.Timers.Add(new WorldTimer(eff.DurationMS, (world, t) =>
                            {
                                ActivateBoost[idx].Pop(s);
                                CalculateBoost();
                                player.UpdateCount++;
                            }));
                        });
                        BroadcastSync(new ShowEffectPacket
                        {
                            EffectType = EffectType.AreaBlast,
                            TargetId = Id,
                            Color = new ARGB(0xffffffff),
                            PosA = new Position {X = eff.Range}
                        }, p => this.Dist(p) < 25);
                    }
                        break;
                    case ActivateEffects.ConditionEffectSelf:
                    {
                        ApplyConditionEffect(new ConditionEffect
                        {
                            Effect = eff.ConditionEffect.Value,
                            DurationMS = eff.DurationMS
                        });
                        BroadcastSync(new ShowEffectPacket
                        {
                            EffectType = EffectType.AreaBlast,
                            TargetId = Id,
                            Color = new ARGB(0xffffffff),
                            PosA = new Position {X = 1}
                        }, p => this.Dist(p) < 25);
                    }
                        break;
                    case ActivateEffects.ConditionEffectAura:
                    {
                        this.AOE(eff.Range, true, player =>
                        {
                            var plr = (player as Player);
                            if (PvP && (plr.Team == 0 || plr.Team != Team) && plr != this)
                                return;
                            player.ApplyConditionEffect(new ConditionEffect
                            {
                                Effect = eff.ConditionEffect.Value,
                                DurationMS = eff.DurationMS
                            });
                        });
                        uint color = 0xffffffff;
                        if (eff.ConditionEffect.Value == ConditionEffectIndex.Damaging)
                            color = 0xffff0000;
                        BroadcastSync(new ShowEffectPacket
                        {
                            EffectType = EffectType.AreaBlast,
                            TargetId = Id,
                            Color = new ARGB(color),
                            PosA = new Position {X = eff.Range}
                        }, p => this.Dist(p) < 25);
                    }
                        break;
                    case ActivateEffects.Heal:
                    {
                        var pkts = new List<Packet>();
                        ActivateHealHp(this, this, eff.Amount, pkts);
                        BroadcastSync(pkts, p => this.Dist(p) < 25);
                    }
                        break;
                    case ActivateEffects.HealNova:
                    {
                        var pkts = new List<Packet>();
                        this.AOE(eff.Range, true,
                            player => { ActivateHealHp(player as Player, this, eff.Amount, pkts); });
                        pkts.Add(new ShowEffectPacket
                        {
                            EffectType = EffectType.AreaBlast,
                            TargetId = Id,
                            Color = new ARGB(0xffffffff),
                            PosA = new Position {X = eff.Range}
                        });
                        BroadcastSync(pkts, p => this.Dist(p) < 25);
                    }
                        break;
                    case ActivateEffects.Magic:
                    {
                        var pkts = new List<Packet>();
                        ActivateHealMp(this, this, eff.Amount, pkts);
                        BroadcastSync(pkts, p => this.Dist(p) < 25);
                    }
                        break;
                    case ActivateEffects.MagicNova:
                    {
                        var pkts = new List<Packet>();
                        this.AOE(eff.Range, true,
                            player => { ActivateHealMp(player as Player, this, eff.Amount, pkts); });
                        pkts.Add(new ShowEffectPacket
                        {
                            EffectType = EffectType.AreaBlast,
                            TargetId = Id,
                            Color = new ARGB(0xffffffff),
                            PosA = new Position {X = eff.Range}
                        });
                        BroadcastSync(pkts, p => this.Dist(p) < 25);
                    }
                        break;
                    case ActivateEffects.Teleport:
                    {
                        if (!Owner.AllowAbilityTeleport)
                        {
                            SendError("Teleporting is disabled.");
                            break;
                        }
                        Move(target.X, target.Y);
                        UpdateCount++;
                        Owner.BroadcastPacket(new GotoPacket
                        {
                            ObjectId = Id,
                            Position = new Position
                            {
                                X = X,
                                Y = Y
                            }
                        }, null);
                        foreach (Player i in Owner.Players.Values)
                            if (this.Dist(i) < 25)
                                if ((PvP && i.Team != 0 && i.Team == Team) || !PvP)
                                    i.Client.SendPackets(new Packet[]
                                    {
                                        new ShowEffectPacket
                                        {
                                            EffectType = EffectType.Teleport,
                                            TargetId = Id,
                                            PosA = new Position
                                            {
                                                X = X,
                                                Y = Y
                                            },
                                            Color = new ARGB(0xFFFFFFFF)
                                        }
                                    });
                    }
                        break;
                    case ActivateEffects.VampireBlast:
                    {
                        var pkts = new List<Packet>();
                        pkts.Add(new ShowEffectPacket
                        {
                            EffectType = EffectType.Trail,
                            TargetId = Id,
                            PosA = target,
                            Color = new ARGB(0xFFFF0000)
                        });
                        pkts.Add(new ShowEffectPacket
                        {
                            EffectType = EffectType.Diffuse,
                            TargetId = Id,
                            PosA = target,
                            PosB = new Position {X = target.X + eff.Radius, Y = target.Y},
                            Color = new ARGB(0xFFFF0000)
                        });
                        BroadcastSync(pkts, p => this.Dist(p) < 25);

                        pkts = new List<Packet>();

                        int totalDmg = 0;
                        var enemies = new List<Entity>();
                        var targets = new List<Player>();
                        Owner.AOE(target, eff.Radius, false, enemy =>
                        {
                            enemies.Add(enemy);
                            totalDmg += (enemy as Enemy).Damage(this, time, eff.TotalDamage, false, false, null);
                            pkts.Add(new DamagePacket
                            {
                                BulletId = 0,
                                ObjectId = Id,
                                TargetId = enemy.Id,
                                Effects = 0,
                                Damage = (ushort) eff.TotalDamage,
                                Killed = (enemy as Enemy).HP <= 0
                            });
                        });
                        if (PvP)
                        {
                            Owner.AOE(target, eff.Radius, true, enemy =>
                            {
                                var plr = (enemy as Player);
                                if (!plr.PvP || (plr.PvP && plr.Team != 0 && plr.Team == Team) || plr == this)
                                    return;
                                enemies.Add(enemy);
                                (enemy as Player).Damage(eff.TotalDamage, enemy as Character, false, true, 0.20f);
                                totalDmg +=
                                    (int)
                                        Math.Max(1, (enemy as Player).statsMgr.GetDefenseDamage(eff.TotalDamage, false) * 0.20);
                            });
                        }
                        var players = new List<Player>();

                        this.AOE(eff.Radius, true, player =>
                        {
                            var plr = (player as Player);
                            if (PvP && (plr.Team == 0 || plr.Team != Team) && plr != this)
                                return;
                            players.Add(player as Player);
                            ActivateHealHp(player as Player, this, totalDmg, pkts);
                        });

                        var rand = new Random();
                        for (int i = 0; i < 5; i++)
                        {
                            Entity a = enemies[rand.Next(0, enemies.Count)];
                            Player b = players[rand.Next(0, players.Count)];
                            pkts.Add(new ShowEffectPacket
                            {
                                EffectType = EffectType.Flow,
                                TargetId = b.Id,
                                PosA = new Position {X = a.X, Y = a.Y},
                                Color = new ARGB(0xffffffff)
                            });
                        }

                        BroadcastSync(pkts, p => this.Dist(p) < 25);
                    }
                        break;
                    case ActivateEffects.Trap:
                    {
                        BroadcastSync(new ShowEffectPacket
                        {
                            EffectType = EffectType.Throw,
                            Color = new ARGB(0xff9000ff),
                            TargetId = Id,
                            PosA = target
                        }, p => this.Dist(p) < 25);
                        Owner.Timers.Add(new WorldTimer(1500, (world, t) =>
                        {
                            var trap = new Trap(
                                this,
                                eff.Radius,
                                eff.TotalDamage,
                                eff.ConditionEffect ?? ConditionEffectIndex.Slowed,
                                eff.EffectDuration);
                            trap.Move(target.X, target.Y);
                            world.EnterWorld(trap);
                        }));
                    }
                        break;
                    case ActivateEffects.StasisBlast:
                    {
                        var pkts = new List<Packet>();

                        pkts.Add(new ShowEffectPacket
                        {
                            EffectType = EffectType.Concentrate,
                            TargetId = Id,
                            PosA = target,
                            PosB = new Position {X = target.X + 3, Y = target.Y},
                            Color = new ARGB(0xffffffff)
                        });
                        Owner.AOE(target, 3, false, enemy =>
                        {
                            if (enemy.HasConditionEffect(ConditionEffects.StasisImmune))
                            {
                                pkts.Add(new NotificationPacket
                                {
                                    ObjectId = enemy.Id,
                                    Color = new ARGB(0xff00ff00),
                                    Text = "Immune"
                                });
                            }
                            else if (!enemy.HasConditionEffect(ConditionEffects.Stasis))
                            {
                                enemy.ApplyConditionEffect(
                                    new ConditionEffect
                                    {
                                        Effect = ConditionEffectIndex.Stasis,
                                        DurationMS = eff.DurationMS
                                    },
                                    new ConditionEffect
                                    {
                                        Effect = ConditionEffectIndex.Paused,
                                        DurationMS = eff.DurationMS
                                    },
                                    new ConditionEffect
                                    {
                                        Effect = ConditionEffectIndex.Confused,
                                        DurationMS = eff.DurationMS
                                    }
                                    );
                            }
                            Owner.Timers.Add(new WorldTimer(eff.DurationMS, (world, t) => enemy.ApplyConditionEffect(new ConditionEffect
                            {
                                Effect = ConditionEffectIndex.StasisImmune,
                                DurationMS = 3000
                            })));
                            pkts.Add(new NotificationPacket
                            {
                                ObjectId = enemy.Id,
                                Color = new ARGB(0xffff0000),
                                Text = "Stasis"
                            });
                        });
                        if (PvP)
                        {
                            Owner.AOE(target, 3, true, enemy =>
                            {
                                var plr = (enemy as Player);
                                if (!plr.PvP || (plr.PvP && plr.Team != 0 && plr.Team == Team) || plr == this)
                                    return;
                                if (enemy.HasConditionEffect(ConditionEffects.StasisImmune))
                                {
                                    pkts.Add(new NotificationPacket
                                    {
                                        ObjectId = enemy.Id,
                                        Color = new ARGB(0xff00ff00),
                                        Text = "Immune"
                                    });
                                }
                                else if (!enemy.HasConditionEffect(ConditionEffects.Stasis))
                                {
                                    if (enemy is Player && Owner.PvP)
                                    {
                                        if (enemy.Id == Id)
                                            return;
                                        enemy.ApplyConditionEffect(
                                            new ConditionEffect
                                            {
                                                Effect = ConditionEffectIndex.Stasis,
                                                DurationMS = eff.DurationMS
                                            },
                                            new ConditionEffect
                                            {
                                                Effect = ConditionEffectIndex.Paused,
                                                DurationMS = eff.DurationMS
                                            },
                                            new ConditionEffect
                                            {
                                                Effect = ConditionEffectIndex.Confused,
                                                DurationMS = eff.DurationMS
                                            }
                                            );
                                    }
                                    Owner.Timers.Add(new WorldTimer(eff.DurationMS, (world, t) => enemy.ApplyConditionEffect(new ConditionEffect
                                    {
                                        Effect = ConditionEffectIndex.StasisImmune,
                                        DurationMS = 3000
                                    })));
                                    pkts.Add(new NotificationPacket
                                    {
                                        ObjectId = enemy.Id,
                                        Color = new ARGB(0xffff0000),
                                        Text = "Stasis"
                                    });
                                }
                            });
                        }
                        BroadcastSync(pkts, p => this.Dist(p) < 25);
                    }
                        break;
                    case ActivateEffects.Decoy:
                    {
                        var decoy = new Decoy(this, eff.DurationMS, statsMgr.GetSpeed());
                        decoy.Move(X, Y);
                        Owner.EnterWorld(decoy);
                    }
                        break;
                    case ActivateEffects.Lightning:
                    {
                        if (!PvP)
                        {
                            Enemy start = null;
                            double angle = Math.Atan2(target.Y - Y, target.X - X);
                            double diff = Math.PI/3;
                            Owner.AOE(target, 6, false, enemy =>
                            {
                                if (!(enemy is Enemy)) return;
                                double x = Math.Atan2(enemy.Y - Y, enemy.X - X);
                                if (Math.Abs(angle - x) < diff)
                                {
                                    start = enemy as Enemy;
                                    diff = Math.Abs(angle - x);
                                }
                            });
                            if (start == null)
                                break;

                            Enemy current = start;
                            var targets = new Enemy[eff.MaxTargets];
                            for (int i = 0; i < targets.Length; i++)
                            {
                                targets[i] = current;
                                var next = current.GetNearestEntity(8, false,
                                    enemy =>
                                        enemy is Enemy &&
                                        Array.IndexOf(targets, enemy) == -1 &&
                                        this.Dist(enemy) <= 6) as Enemy;

                                if (next == null) break;
                                current = next;
                            }

                            var pkts = new List<Packet>();
                            for (int i = 0; i < targets.Length; i++)
                            {
                                if (targets[i] == null) break;
                                Entity prev = i == 0 ? (Entity) this : targets[i - 1];
                                targets[i].Damage(this, time, eff.TotalDamage, false, false, null);
                                if (eff.ConditionEffect != null)
                                    targets[i].ApplyConditionEffect(new ConditionEffect
                                    {
                                        Effect = eff.ConditionEffect.Value,
                                        DurationMS = (int) (eff.EffectDuration*1000)
                                    });
                                pkts.Add(new ShowEffectPacket
                                {
                                    EffectType = EffectType.Lightning,
                                    TargetId = prev.Id,
                                    Color = new ARGB(0xffff0088),
                                    PosA = new Position
                                    {
                                        X = targets[i].X,
                                        Y = targets[i].Y
                                    },
                                    PosB = new Position {X = 350}
                                });
                            }
                            BroadcastSync(pkts, p => this.Dist(p) < 25);
                        }
                        if (PvP)
                        {
                            Player start = null;
                            double angle = Math.Atan2(target.Y - Y, target.X - X);
                            double diff = Math.PI/3;
                            Owner.AOE(target, 6, true, enemy =>
                            {
                                //if (!(enemy is Player)) return;
                                var plr = (enemy as Player);
                                if (!plr.PvP || (plr.PvP && plr.Team != 0 && plr.Team == Team) || plr == this)
                                    return;
                                double x = Math.Atan2(enemy.Y - Y, enemy.X - X);
                                if (Math.Abs(angle - x) < diff)
                                {
                                    start = enemy as Player;
                                    diff = Math.Abs(angle - x);
                                }
                            });
                            if (start == null)
                                break;

                            Player current = start;
                            var targets = new Player[eff.MaxTargets];
                            for (int i = 0; i < targets.Length; i++)
                            {
                                targets[i] = current;
                                var next = current.GetNearestEntity(8, true,
                                    enemy =>
                                        enemy is Player && enemy.Id != Id &&
                                        Array.IndexOf(targets, enemy) == -1 &&
                                        (enemy as Player).PvP &&
                                        ((enemy as Player).Team == 0 || (enemy as Player).Team != Team) &&
                                        this.Dist(enemy) <= 6) as Player;

                                if (next == null) break;
                                current = next;
                            }

                            var pkts = new List<Packet>();
                            for (int i = 0; i < targets.Length; i++)
                            {
                                if (targets[i] == null) break;
                                Entity prev = i == 0 ? this : targets[i - 1];
                                targets[i].Damage(eff.TotalDamage, targets[i], false, true, 0.20f);
                                if (eff.ConditionEffect != null)
                                    targets[i].ApplyConditionEffect(new ConditionEffect
                                    {
                                        Effect = eff.ConditionEffect.Value,
                                        DurationMS = (int) (eff.EffectDuration*1000)
                                    });
                                pkts.Add(new ShowEffectPacket
                                {
                                    EffectType = EffectType.Lightning,
                                    TargetId = prev.Id,
                                    Color = new ARGB(0xffff0088),
                                    PosA = new Position
                                    {
                                        X = targets[i].X,
                                        Y = targets[i].Y
                                    },
                                    PosB = new Position {X = 350}
                                });
                            }
                            BroadcastSync(pkts, p => this.Dist(p) < 25);
                        }
                    }
                        break;
                    case ActivateEffects.PoisonGrenade:
                    {
                        BroadcastSync(new ShowEffectPacket
                        {
                            EffectType = EffectType.Throw,
                            Color = new ARGB(0xffddff00),
                            TargetId = Id,
                            PosA = target
                        }, p => this.Dist(p) < 25);
                        var x = new Placeholder(Manager, 1500);
                        x.Move(target.X, target.Y);
                        Owner.EnterWorld(x);
                        Owner.Timers.Add(new WorldTimer(1500, (world, t) =>
                        {
                            if (Owner != null)
                            {
                                Owner.BroadcastPacket(new ShowEffectPacket
                                {
                                    EffectType = EffectType.AreaBlast,
                                    TargetId = x.Id,
                                    Color = new ARGB(0xffddff00),
                                    PosA = new Position { X = eff.Radius }
                                }, null);
                                if (PvP)
                                {
                                    var players = new List<Player>();
                                    Owner.AOE(target, eff.Radius, true,
                                        enemy =>
                                        {
                                            var plr = (enemy as Player);
                                            if (!plr.PvP || (plr.PvP && plr.Team != 0 && plr.Team == Team) || plr == this)
                                                return;
                                            players.Add(enemy as Player);
                                            foreach (Player i in players)
                                                if (i.Id != Id)
                                                    PoisonPlayer(i, eff);
                                        });
                                }
                                var enemies = new List<Enemy>();
                                Owner.AOE(target, eff.Radius, false,
                                    enemy => PoisonEnemy(enemy as Enemy, eff));
                            }
                        }));
                    }
                        break;
                    case ActivateEffects.RemoveNegativeConditions:
                    {
                        this.AOE(eff.Range, true, player =>
                        {
                            var plr = (player as Player);
                            if (PvP && (plr.Team == 0 || plr.Team != Team) && plr != this)
                                return;
                            ApplyConditionEffect(NegativeEffs);
                        });
                        BroadcastSync(new ShowEffectPacket
                        {
                            EffectType = EffectType.AreaBlast,
                            TargetId = Id,
                            Color = new ARGB(0xffffffff),
                            PosA = new Position {X = eff.Range}
                        }, p => this.Dist(p) < 25);
                    }
                        break;
                    case ActivateEffects.RemoveNegativeConditionsSelf:
                    {
                        ApplyConditionEffect(NegativeEffs);
                        BroadcastSync(new ShowEffectPacket
                        {
                            EffectType = EffectType.AreaBlast,
                            TargetId = Id,
                            Color = new ARGB(0xffffffff),
                            PosA = new Position {X = 1}
                        }, p => this.Dist(p) < 25);
                    }
                        break;
                    case ActivateEffects.IncrementStat:
                    {
                        int idx = -1;
                        switch ((StatsType) eff.Stats)
                        {
                            case StatsType.MaximumHP:
                                idx = 0;
                                break;
                            case StatsType.MaximumMP:
                                idx = 1;
                                break;
                            case StatsType.Attack:
                                idx = 2;
                                break;
                            case StatsType.Defense:
                                idx = 3;
                                break;
                            case StatsType.Speed:
                                idx = 4;
                                break;
                            case StatsType.Vitality:
                                idx = 5;
                                break;
                            case StatsType.Wisdom:
                                idx = 6;
                                break;
                            case StatsType.Dexterity:
                                idx = 7;
                                break;
                        }
                        if (eff.Amount > 0)
                            Stats[idx] += eff.Amount;
                        else
                            Stats[idx] -= eff.Amount;
                        int limit =
                            int.Parse(
                                Manager.GameData.ObjectTypeToElement[ObjectType].Element(
                                    StatsManager.StatsIndexToName(idx)).Attribute("max").Value);
                        if (Stats[idx] > limit)
                            Stats[idx] = limit;
                        UpdateCount++;
                    }
                        break;
                    case ActivateEffects.Create: //this is a portal
                    {
                        ushort objType;
                        if (!Manager.GameData.IdToObjectType.TryGetValue(eff.Id, out objType) ||
                            !Manager.GameData.Portals.ContainsKey(objType))
                            break; // object not found, ignore
                        Entity entity = Resolve(Manager, objType);
                        entity.Move(X, Y);
                        int TimeoutTime = Manager.GameData.Portals[objType].TimeoutTime;
                        string DungeonName = Manager.GameData.Portals[objType].DungeonName;

                        Owner.EnterWorld(entity);
                        World w = Manager.GetWorld(Owner.Id); //can't use Owner here, as it goes out of scope

                        Client.SendPacket(new NotificationPacket
                        {
                            Color = new ARGB(0xff00ff00),
                            Text = "Opened by " + Client.Account.Name,
                            ObjectId = Client.Player.Id,
                        });
                        w.BroadcastPacket(new TextPacket
                        {
                            BubbleTime = 0,
                            Stars = -1,
                            Name = "",
                            Text = DungeonName + " opened by " + Client.Account.Name
                        }, null);

                        w.Timers.Add(new WorldTimer(TimeoutTime*1000, (world, t) => //default portal close time * 1000
                        {
                            try
                            {
                                w.LeaveWorld(entity);
                            }
                            catch
                                //couldn't remove portal, Owner became null. Should be fixed with RealmManager implementation
                            {
                                Console.WriteLine("Couldn't despawn portal.");
                            }
                        }));
                    }
                        break;
                    case ActivateEffects.PermaPet:
                        client.Character.Pet = Manager.GameData.IdToObjectType[eff.ObjectId];
                        GivePet(Manager.GameData.IdToObjectType[eff.ObjectId]);
                        UpdateCount++;
                        break;
                    case ActivateEffects.UnlockPortal:
                        break;
                    case ActivateEffects.Dye:
                        if (item.Texture1 != 0)
                        {
                            Texture1 = item.Texture1;
                        }
                        if (item.Texture2 != 0)
                        {
                            Texture2 = item.Texture2;
                        }
                        SaveToCharacter();
                        break;
                    case ActivateEffects.UnlockSkin:
                        if (Manager.GameData.Skins.ContainsKey((ushort) eff.SkinType))
                        {
                            SkinDesc skin = Manager.GameData.Skins[(ushort) eff.SkinType];
                            if (skin.PlayerClassType == -1 || skin.PlayerClassType == ObjectType)
                            {
                                Skin = eff.SkinType;
                                PermaSkin = !item.Consumable || (data != null ? data.MultiUse : false);
                                if (data != null && data.Effect != "")
                                {
                                    Effect = (data.FullEffect == "" ? UnusualEffects.Save(data.Effect) : data.FullEffect);
                                }
                                else
                                {
                                    Effect = "";
                                }
                                SendInfo("Successfully changed skin.");
                            }
                            else
                            {
                                success = false;
                                SendError("Your class cannot use this skin.");
                            }
                        }
                        else
                        {
                            success = false;
                            SendError("Invalid skin type.");
                        }
                        break;
                    case ActivateEffects.ShurikenAbility:
                    {
                        usingShuriken = !usingShuriken;
                        if (usingShuriken)
                        {
                            ApplyConditionEffect(new ConditionEffect
                            {
                                Effect = ConditionEffectIndex.Speedy,
                                DurationMS = -1
                            });
                        }
                        else
                        {
                            ApplyConditionEffect(new ConditionEffect
                            {
                                Effect = ConditionEffectIndex.Speedy,
                                DurationMS = 0
                            });
                            if (MP >= item.MpEndCost)
                            {
                                MP -= item.MpEndCost;
                                ActivateShoot(time, item, target);
                            }
                        }
                    }
                        break;
                    case ActivateEffects.SwitchMusic:
                        {
                            Client.SendPacket(new SwitchMusicPacket
                            {
                                Music = eff.Id
                            });
                        } break;
                    case ActivateEffects.OpenCrate:
                        {
                            success = false;
                            try
                            {
                                this.ItemSelect((_item, _data) =>
                                {
                                    return _item.IsCrate;
                                }, _slot =>
                                {
                                    bool succeeded = false;
                                    for (int i = 0; i < Inventory.Length; i++)
                                    {
                                        if (Inventory[i] == null) continue;
                                        if (Inventory[i].ObjectId == "Supply Crate Key")
                                        {
                                            Inventory[i] = null;
                                            Inventory.Data[i] = null;
                                            succeeded = true;
                                            break;
                                        }
                                    }
                                    if (succeeded)
                                    {
                                        Item originalItem = Inventory[_slot];
                                        Random rand1 = new Random();

                                        int choice = rand1.Next(1, 101);
                                        if (choice > 20 && !originalItem.UnusualCrate)
                                        {
                                            if (rand1.Next(0,5) != 0)
                                            {
                                                int[] types = new int[] { 1, 2, 3, 8, 17, 24 };
                                                List<Item> candidates = Manager.GameData.Items
                                                    .Where(_item => Array.IndexOf(types, _item.Value.SlotType) != -1)
                                                    .Where(_item => _item.Value.Tier == rand1.Next(8, 11 + 1))
                                                    .Select(_item => _item.Value)
                                                    .ToList();

                                                candidates.Shuffle();

                                                Inventory[_slot] = Manager.GameData.Items[Manager.GameData.IdToObjectType["Strangifier"]];
                                                Inventory.Data[_slot] = new ItemData
                                                {
                                                    NamePrefix = candidates[0].ObjectId,
                                                    NameColor = 0xFF5A28
                                                };
                                            }
                                            else
                                            {
                                                List<string> Parts = new List<string>(){
                                                    "God Kills",
                                                    "Quest Kills",
                                                    "Oryx Kills",
                                                    "Kills While Cloaked",
                                                    "Kills Near Death"
                                                };
                                                Parts.Shuffle();

                                                Inventory[_slot] = Manager.GameData.Items[Manager.GameData.IdToObjectType["Strange Part"]];
                                                Inventory.Data[_slot] = new ItemData
                                                {
                                                    NamePrefix = Parts[0]
                                                };
                                            }
                                        }
                                        else
                                        {
                                            List<Item> candidates = Manager.GameData.Items
                                                .Where(_item =>
                                                {
                                                    foreach (var activEff in _item.Value.ActivateEffects)
                                                        if (activEff.Effect == ActivateEffects.UnlockSkin)
                                                            return true;
                                                    return false;
                                                })
                                                .Where(_item =>
                                                {
                                                    if (originalItem.Premium && !_item.Value.Premium)
                                                        return false;
                                                    if (!originalItem.Premium && _item.Value.Premium)
                                                        return false;
                                                    return true;
                                                })
                                                .Select(_item => _item.Value)
                                                .ToList();

                                            candidates.Shuffle();

                                            Inventory[_slot] = candidates[0];
                                            Inventory.Data[_slot] = null;

                                            if (rand1.Next(0, 6) == 0 || originalItem.UnusualCrate)
                                            {
                                                List<string> effects = new List<string>();
                                                if (originalItem.Crate != 0)
                                                    effects = UnusualEffects.Series[originalItem.Crate];
                                                else if (!this.Client.Account.Admin)
                                                {
                                                    foreach (var i in UnusualEffects.Series)
                                                        if (i.Key > 0 && i.Key <= UnusualEffects.CurrentSeries)
                                                            effects.AddRange(i.Value);
                                                }
                                                else
                                                {
                                                    foreach (var i in UnusualEffects.Series)
                                                        if (i.Key != 0)
                                                            effects.AddRange(i.Value);
                                                }
                                                Inventory.Data[_slot] = new ItemData
                                                {
                                                    NamePrefix = "Unusual",
                                                    NameColor = 0x8000FF,
                                                    Effect = effects.RandomElement(rand1),
                                                };
                                                Inventory.Data[_slot].FullEffect = UnusualEffects.Save(Inventory.Data[_slot].Effect);
                                            }
                                        }

                                        client.SendPacket(new ItemResultPacket
                                        {
                                            ItemID = Inventory[_slot].ObjectType,
                                            Data = Inventory.Data[_slot] != null ? Inventory.Data[_slot].GetJson() : "{}"
                                        });

                                        string msg = "{c}" + this.GetNameColor() + "{/c}" + Name + "{c}0xFFFFFF{/c} has unboxed: {c}" +
                                                    ((Inventory.Data[_slot] != null && Inventory.Data[_slot].NameColor != 0xFFFFFF) ? Inventory.Data[_slot].NameColor.ToString() : "0xFFFF00") + "{/c}" +
                                                    ((Inventory.Data[_slot] != null && Inventory.Data[_slot].NamePrefix != "") ? Inventory.Data[_slot].NamePrefix + " " : "") +
                                                    ((Inventory.Data[_slot] != null && Inventory.Data[_slot].Name != "") ?
                                                        Inventory.Data[_slot].Name :
                                                        Inventory[_slot].DisplayId ?? Inventory[_slot].ObjectId);

                                        Owner.BroadcastPacket(new TextPacket
                                        {
                                            BubbleTime = 0,
                                            Stars = -1,
                                            Name = "",
                                            Text = msg
                                        }, null);

                                        UpdateCount++;
                                    }
                                });
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e);
                            }
                        } break;
                    case ActivateEffects.RenameItem:
                        {
                            success = false;
                            this.ItemSelect((_item, _data) =>
                                {
                                    return _item != item;
                                }, _slot =>
                                {
                                    client.SendPacket(new GetTextInputPacket
                                    {
                                        Name = "Choose a new item name",
                                        Action = "renameSlot" + _slot.ToString()
                                    });
                                });
                        } break;
                    case ActivateEffects.RemoveSkin:
                        {
                            success = false;
                            if (Skin == -1)
                            {
                                SendError("No skin equipped");
                                break;
                            }
                            if (Manager.GameData.SkinToItem.ContainsKey((ushort)Skin) && !PermaSkin)
                            {
                                Inventory[itemSlot] = Manager.GameData.SkinToItem[(ushort)Skin];
                                Inventory.Data[itemSlot] = null;
                                if (Effect != "")
                                {
                                    string effId = Utils.FromCommaSepString(Effect)[0];
                                    Inventory.Data[itemSlot] = new ItemData()
                                    {
                                        NamePrefix = "Unusual",
                                        NameColor = 0x8000FF,
                                        Effect = effId,
                                        FullEffect = Effect
                                    };
                                }
                            }
                            Damage((int)Math.Ceiling((double)HP / 2), this, true, true, 1.0f);
                            Skin = -1;
                            PermaSkin = false;
                            Effect = "";
                            UpdateCount++;
                        } break;
                    case ActivateEffects.BindSkin:
                        {
                            success = false;
                            this.ItemSelect((_item, _data) =>
                            {
                                foreach (var activEff in _item.ActivateEffects)
                                    if (activEff.Effect == ActivateEffects.UnlockSkin)
                                        return (_data != null) ? !_data.Soulbound : true;
                                return false;
                            }, _slot =>
                            {
                                if(Inventory[_slot] == null)
                                {
                                    SendError("Item no longer exists");
                                    return;
                                }
                                bool isSkin = false;
                                foreach (var activEff in Inventory[_slot].ActivateEffects)
                                    if (activEff.Effect == ActivateEffects.UnlockSkin)
                                        isSkin = (Inventory.Data[_slot] != null) ? !Inventory.Data[_slot].Soulbound : true;
                                if (!isSkin)
                                {
                                    SendError("Item is not a valid skin");
                                    return;
                                }
                                if (Inventory[itemSlot] == null)
                                {
                                    SendError("Skin keeper no longer exists");
                                    return;
                                }
                                bool succeeded = false;
                                foreach (var activEff in Inventory[itemSlot].ActivateEffects)
                                    if (activEff.Effect == ActivateEffects.BindSkin)
                                        succeeded = true;
                                if (!succeeded)
                                {
                                    SendError("Invalid skin keeper");
                                    return;
                                }
                                if (Inventory.Data[_slot] == null)
                                    Inventory.Data[_slot] = new ItemData();
                                Inventory.Data[_slot].Soulbound = true;
                                Inventory.Data[_slot].MultiUse = true;

                                Inventory[itemSlot] = null;
                                Inventory.Data[itemSlot] = null;

                                UpdateCount++;
                            });
                        } break;
                    case ActivateEffects.StrangePart:
                        {
                            success = false;
                            this.ItemSelect((_item, _data) =>
                            {
                                return _item != null && _data != null && _data.Strange && !data.StrangeParts.ContainsKey(data.NamePrefix);
                            }, _slot =>
                            {
                                if (Inventory[_slot] == null || Inventory.Data[_slot] == null)
                                {
                                    SendError("Item no longer exists");
                                    return;
                                }
                                if (Inventory[itemSlot] == null || Inventory.Data[itemSlot] == null)
                                {
                                    SendError("Strange part no longer exists");
                                    return;
                                }
                                bool succeeded = false;
                                foreach (var activEff in Inventory[itemSlot].ActivateEffects)
                                    if (activEff.Effect == ActivateEffects.StrangePart)
                                        succeeded = true;
                                if (!succeeded || Inventory.Data[itemSlot].NamePrefix == "")
                                {
                                    SendError("Invalid strange part");
                                    return;
                                }
                                Inventory.Data[_slot].StrangeParts.TryAdd(Inventory.Data[itemSlot].NamePrefix, 0);
                                Inventory[itemSlot] = null;
                                Inventory.Data[itemSlot] = null;

                                UpdateCount++;
                            });
                        } break;
                    case ActivateEffects.Strangify:
                        {
                            success = false;
                            if(data.NamePrefix == "")
                                break;
                            this.ItemSelect((_item, _data) =>
                            {
                                return _item != null && _item.ObjectId == data.NamePrefix && ((_data != null && !_data.Strange) || (_data == null));
                            }, _slot =>
                            {
                                if (Inventory[_slot] == null)
                                {
                                    SendError("Item no longer exists");
                                    return;
                                }
                                if (Inventory[itemSlot] == null || Inventory.Data[itemSlot] == null)
                                {
                                    SendError("Strangifier no longer exists");
                                    return;
                                }
                                bool succeeded = false;
                                foreach (var activEff in Inventory[itemSlot].ActivateEffects)
                                    if (activEff.Effect == ActivateEffects.Strangify)
                                        succeeded = true;
                                if (!succeeded || Inventory.Data[itemSlot].NamePrefix != Inventory[_slot].ObjectId)
                                {
                                    SendError("Invalid strangifier");
                                    return;
                                }
                                if (Inventory.Data[_slot] == null)
                                    Inventory.Data[_slot] = new ItemData();
                                Inventory.Data[_slot].Strange = true;
                                Inventory.Data[_slot].NamePrefix = "Strange";
                                Inventory.Data[_slot].NameColor = 0xFF5A28;
                                Inventory[itemSlot] = null;
                                Inventory.Data[itemSlot] = null;

                                UpdateCount++;
                            });
                        } break;
                    case ActivateEffects.UnbindSkin:
                        {
                            success = false;
                            if (Skin != -1)
                            {
                                SendError("You cannot wear a skin while unbinding a skin item.");
                                break;
                            }
                            this.ItemSelect((_item, _data) =>
                            {
                                foreach (var activEff in _item.ActivateEffects)
                                    if (activEff.Effect == ActivateEffects.UnlockSkin)
                                        return _data != null && _data.Soulbound && _data.MultiUse;
                                return false;
                            }, _slot =>
                            {
                                if (Skin != -1)
                                {
                                    SendError("You cannot wear a skin while unbinding a skin item.");
                                    return;
                                }
                                if (Inventory[_slot] == null)
                                {
                                    SendError("Item no longer exists");
                                    return;
                                }
                                bool isSkin = false;
                                foreach (var activEff in Inventory[_slot].ActivateEffects)
                                    if (activEff.Effect == ActivateEffects.UnlockSkin)
                                        isSkin = Inventory.Data[_slot] != null && Inventory.Data[_slot].Soulbound && Inventory.Data[_slot].MultiUse;
                                if (!isSkin)
                                {
                                    SendError("Item is not a valid skin");
                                    return;
                                }
                                if (Inventory[itemSlot] == null)
                                {
                                    SendError("Skin disowner no longer exists");
                                    return;
                                }
                                bool succeeded = false;
                                foreach (var activEff in Inventory[itemSlot].ActivateEffects)
                                    if (activEff.Effect == ActivateEffects.UnbindSkin)
                                        succeeded = true;
                                if (!succeeded)
                                {
                                    SendError("Invalid skin disowner");
                                    return;
                                }
                                if (Inventory.Data[_slot] != null)
                                {
                                    Inventory.Data[_slot].Soulbound = false;
                                    Inventory.Data[_slot].MultiUse = false;
                                }

                                Inventory[itemSlot] = null;
                                Inventory.Data[itemSlot] = null;

                                UpdateCount++;
                            });
                        } break;
                }
            }
            UpdateCount++;
            return success;
        }
Esempio n. 3
0
        void Activate(RealmTime time, Item item, Position target)
        {
            MP -= item.MpCost;
            foreach (var eff in item.ActivateEffects)
            {
                switch (eff.Effect)
                {
                    case ActivateEffects.BulletNova:
                        {
                            var prjDesc = item.Projectiles[0]; //Assume only one
                            Packet[] batch = new Packet[21];
                            uint s = Random.CurrentSeed;
                            Random.CurrentSeed = (uint)(s * time.tickTimes);
                            for (int i = 0; i < 20; i++)
                            {
                                Projectile proj = CreateProjectile(prjDesc, item.ObjectType,
                                    (int)statsMgr.GetAttackDamage(prjDesc.MinDamage, prjDesc.MaxDamage),
                                    time.tickTimes, target, (float)(i * (Math.PI * 2) / 20));
                                Owner.EnterWorld(proj);
                                fames.Shoot(proj);
                                batch[i] = new ShootPacket()
                                {
                                    BulletId = proj.ProjectileId,
                                    OwnerId = Id,
                                    ContainerType = item.ObjectType,
                                    Position = target,
                                    Angle = proj.Angle,
                                    Damage = (short)proj.Damage
                                };
                            }
                            Random.CurrentSeed = s;
                            batch[20] = new ShowEffectPacket()
                            {
                                EffectType = EffectType.Trail,
                                PosA = target,
                                TargetId = Id,
                                Color = new ARGB(0xFFFF00AA)
                            };
                            BroadcastSync(batch, p => this.Dist(p) < 25);
                        } break;
                    case ActivateEffects.Shoot:
                        {
                            ActivateShoot(time, item, target);
                        } break;
                    case ActivateEffects.StatBoostSelf:
                        {
                            int idx = -1;
                            switch ((StatsType)eff.Stats)
                            {
                                case StatsType.MaximumHP: idx = 0; break;
                                case StatsType.MaximumMP: idx = 1; break;
                                case StatsType.Attack: idx = 2; break;
                                case StatsType.Defense: idx = 3; break;
                                case StatsType.Speed: idx = 4; break;
                                case StatsType.Vitality: idx = 5; break;
                                case StatsType.Wisdom: idx = 6; break;
                                case StatsType.Dexterity: idx = 7; break;
                            }
                            int s = eff.Amount;
                            Boost[idx] += s;
                            UpdateCount++;
                            Owner.Timers.Add(new WorldTimer(eff.DurationMS, (world, t) =>
                            {
                                Boost[idx] -= s;
                                UpdateCount++;
                            }));
                            BroadcastSync(new ShowEffectPacket()
                            {
                                EffectType = EffectType.Potion,
                                TargetId = Id,
                                Color = new ARGB(0xffffffff)
                            }, null);
                        } break;
                    case ActivateEffects.StatBoostAura:
                        {
                            int idx = -1;
                            switch ((StatsType)eff.Stats)
                            {
                                case StatsType.MaximumHP: idx = 0; break;
                                case StatsType.MaximumMP: idx = 1; break;
                                case StatsType.Attack: idx = 2; break;
                                case StatsType.Defense: idx = 3; break;
                                case StatsType.Speed: idx = 4; break;
                                case StatsType.Vitality: idx = 5; break;
                                case StatsType.Wisdom: idx = 6; break;
                                case StatsType.Dexterity: idx = 7; break;
                            }
                            int s = eff.Amount;
                            this.AOE(eff.Range / 2, true, player =>
                            {
                                (player as Player).Boost[idx] += s;
                                player.UpdateCount++;
                                Owner.Timers.Add(new WorldTimer(eff.DurationMS, (world, t) =>
                                {
                                    (player as Player).Boost[idx] -= s;
                                    player.UpdateCount++;
                                }));
                            });
                            BroadcastSync(new ShowEffectPacket()
                            {
                                EffectType = EffectType.AreaBlast,
                                TargetId = Id,
                                Color = new ARGB(0xffffffff),
                                PosA = new Position() { X = eff.Range / 2 }
                            }, p => this.Dist(p) < 25);
                        } break;
                    case ActivateEffects.ConditionEffectSelf:
                        {
                            ApplyConditionEffect(new ConditionEffect()
                            {
                                Effect = eff.ConditionEffect.Value,
                                DurationMS = eff.DurationMS
                            });
                            BroadcastSync(new ShowEffectPacket()
                            {
                                EffectType = EffectType.AreaBlast,
                                TargetId = Id,
                                Color = new ARGB(0xffffffff),
                                PosA = new Position() { X = 1 }
                            }, p => this.Dist(p) < 25);
                        } break;
                    case ActivateEffects.ConditionEffectAura:
                        {
                            this.AOE(eff.Range / 2, true, player =>
                            {
                                player.ApplyConditionEffect(new ConditionEffect()
                                {
                                    Effect = eff.ConditionEffect.Value,
                                    DurationMS = eff.DurationMS
                                });
                            });
                            uint color = 0xffffffff;
                            if (eff.ConditionEffect.Value == ConditionEffectIndex.Damaging)
                                color = 0xffff0000;
                            BroadcastSync(new ShowEffectPacket()
                            {
                                EffectType = EffectType.AreaBlast,
                                TargetId = Id,
                                Color = new ARGB(color),
                                PosA = new Position() { X = eff.Range / 2 }
                            }, p => this.Dist(p) < 25);
                        } break;
                    case ActivateEffects.Heal:
                        {
                            List<Packet> pkts = new List<Packet>();
                            ActivateHealHp(this, eff.Amount, pkts);
                            BroadcastSync(pkts, p => this.Dist(p) < 25);
                        } break;
                    case ActivateEffects.HealNova:
                        {
                            List<Packet> pkts = new List<Packet>();
                            this.AOE(eff.Range / 2, true, player =>
                            {
                                ActivateHealHp(player as Player, eff.Amount, pkts);
                            });
                            pkts.Add(new ShowEffectPacket()
                            {
                                EffectType = EffectType.AreaBlast,
                                TargetId = Id,
                                Color = new ARGB(0xffffffff),
                                PosA = new Position() { X = eff.Range / 2 }
                            });
                            BroadcastSync(pkts, p => this.Dist(p) < 25);
                        } break;
                    case ActivateEffects.Magic:
                        {
                            List<Packet> pkts = new List<Packet>();
                            ActivateHealMp(this, eff.Amount, pkts);
                            BroadcastSync(pkts, p => this.Dist(p) < 25);
                        } break;
                    case ActivateEffects.MagicNova:
                        {
                            List<Packet> pkts = new List<Packet>();
                            this.AOE(eff.Range / 2, true, player =>
                            {
                                ActivateHealMp(player as Player, eff.Amount, pkts);
                            });
                            pkts.Add(new ShowEffectPacket()
                            {
                                EffectType = EffectType.AreaBlast,
                                TargetId = Id,
                                Color = new ARGB(0xffffffff),
                                PosA = new Position() { X = eff.Range / 2 }
                            });
                            BroadcastSync(pkts, p => this.Dist(p) < 25);
                        } break;
                    case ActivateEffects.Teleport:
                        {
                            Move(target.X, target.Y);
                            UpdateCount++;
                            BroadcastSync(new Packet[]
                            {
                                new GotoPacket()
                                {
                                    ObjectId = Id,
                                    Position = new Position()
                                    {
                                        X = X,
                                        Y = Y
                                    }
                                },
                                new ShowEffectPacket()
                                {
                                    EffectType = EffectType.Teleport,
                                    TargetId = Id,
                                    PosA = new Position()
                                    {
                                        X = X,
                                        Y = Y
                                    },
                                    Color = new ARGB(0xFFFFFFFF)
                                }
                            }, p => this.Dist(p) < 25);
                        } break;
                    case ActivateEffects.VampireBlast:
                        {
                            List<Packet> pkts = new List<Packet>();
                            pkts.Add(new ShowEffectPacket()
                            {
                                EffectType = EffectType.Trail,
                                TargetId = Id,
                                PosA = target,
                                Color = new ARGB(0xFFFF0000)
                            });
                            pkts.Add(new AOEPacket()
                            {
                                Position = target,
                                Radius = eff.Radius,
                                Damage = (ushort)eff.TotalDamage,
                                EffectDuration = 0,
                                Effects = 0,
                                OriginType = item.ObjectType
                            });

                            int totalDmg = 0;
                            var enemies = new List<Enemy>();
                            Owner.AOE(target, eff.Radius, false, enemy =>
                            {
                                enemies.Add(enemy as Enemy);
                                totalDmg += (enemy as Enemy).Damage(this, time, eff.TotalDamage, false);
                            });
                            var players = new List<Player>();
                            this.AOE(eff.Radius, true, player =>
                            {
                                players.Add(player as Player);
                                ActivateHealHp(player as Player, totalDmg, pkts);
                            });

                            Random rand = new System.Random();
                            for (int i = 0; i < 5; i++)
                            {
                                Enemy a = enemies[rand.Next(0, enemies.Count)];
                                Player b = players[rand.Next(0, players.Count)];
                                pkts.Add(new ShowEffectPacket()
                                {
                                    EffectType = EffectType.Flow,
                                    TargetId = b.Id,
                                    PosA = new Position() { X = a.X, Y = a.Y },
                                    Color = new ARGB(0xffffffff)
                                });
                            }

                            BroadcastSync(pkts, p => this.Dist(p) < 25);
                        } break;
                    case ActivateEffects.Trap:
                        {
                            BroadcastSync(new ShowEffectPacket()
                            {
                                EffectType = EffectType.Throw,
                                Color = new ARGB(0xff9000ff),
                                TargetId = Id,
                                PosA = target
                            }, p => this.Dist(p) < 25);
                            Owner.Timers.Add(new WorldTimer(1500, (world, t) =>
                            {
                                Trap trap = new Trap(
                                    this,
                                    eff.Radius,
                                    eff.TotalDamage,
                                    eff.ConditionEffect ?? ConditionEffectIndex.Slowed,
                                    eff.EffectDuration);
                                trap.Move(target.X, target.Y);
                                world.EnterWorld(trap);
                            }));
                        } break;
                    case ActivateEffects.StasisBlast:
                        {
                            List<Packet> pkts = new List<Packet>();

                            pkts.Add(new ShowEffectPacket()
                            {
                                EffectType = EffectType.Concentrate,
                                TargetId = Id,
                                PosA = target,
                                PosB = new Position() { X = target.X + 3, Y = target.Y },
                                Color = new ARGB(0xffffffff)
                            });
                            Owner.AOE(target, 3, false, enemy =>
                            {
                                if (enemy.HasConditionEffect(ConditionEffects.StasisImmune))
                                {
                                    pkts.Add(new NotificationPacket()
                                    {
                                        ObjectId = enemy.Id,
                                        Color = new ARGB(0xff00ff00),
                                        Text = "Immune"
                                    });
                                }
                                else if (!enemy.HasConditionEffect(ConditionEffects.Stasis))
                                {
                                    enemy.ApplyConditionEffect(
                                        new ConditionEffect()
                                        {
                                            Effect = ConditionEffectIndex.Stasis,
                                            DurationMS = eff.DurationMS
                                        },
                                        new ConditionEffect()
                                        {
                                            Effect = ConditionEffectIndex.Confused,
                                            DurationMS = eff.DurationMS
                                        }
                                    );
                                    Owner.Timers.Add(new WorldTimer(eff.DurationMS, (world, t) =>
                                    {
                                        enemy.ApplyConditionEffect(new ConditionEffect()
                                            {
                                                Effect = ConditionEffectIndex.StasisImmune,
                                                DurationMS = 3000
                                            }
                                        );
                                    }
                                    ));
                                    pkts.Add(new NotificationPacket()
                                    {
                                        ObjectId = enemy.Id,
                                        Color = new ARGB(0xffff0000),
                                        Text = "Stasis"
                                    });
                                }
                            });
                            BroadcastSync(pkts, p => this.Dist(p) < 25);
                        } break;
                    case ActivateEffects.Decoy:
                        {
                            var decoy = new Decoy(this, eff.DurationMS, statsMgr.GetSpeed());
                            decoy.Move(X, Y);
                            Owner.EnterWorld(decoy);
                        } break;
                    case ActivateEffects.Lightning:
                        {
                            Enemy start = null;
                            double angle = Math.Atan2(target.Y - Y, target.X - X);
                            double diff = Math.PI / 3;
                            Owner.AOE(target, 6, false, enemy =>
                            {
                                if (!(enemy is Enemy)) return;
                                var x = Math.Atan2(enemy.Y - Y, enemy.X - X);
                                if (Math.Abs(angle - x) < diff)
                                {
                                    start = enemy as Enemy;
                                    diff = Math.Abs(angle - x);
                                }
                            });
                            if (start == null)
                                break;

                            Enemy current = start;
                            Enemy[] targets = new Enemy[eff.MaxTargets];
                            for (int i = 0; i < targets.Length; i++)
                            {
                                targets[i] = current;
                                Enemy next = current.GetNearestEntity(8, false,
                                    enemy =>
                                        enemy is Enemy &&
                                        Array.IndexOf(targets, enemy) == -1 &&
                                        this.Dist(enemy) <= 6) as Enemy;

                                if (next == null) break;
                                else current = next;
                            }

                            List<Packet> pkts = new List<Packet>();
                            for (int i = 0; i < targets.Length; i++)
                            {
                                if (targets[i] == null) break;
                                Entity prev = i == 0 ? (Entity)this : targets[i - 1];
                                targets[i].Damage(this, time, eff.TotalDamage, false);
                                if (eff.ConditionEffect != null)
                                    targets[i].ApplyConditionEffect(new ConditionEffect()
                                    {
                                        Effect = eff.ConditionEffect.Value,
                                        DurationMS = (int)(eff.EffectDuration * 1000)
                                    });
                                pkts.Add(new ShowEffectPacket()
                                {
                                    EffectType = EffectType.Lightning,
                                    TargetId = prev.Id,
                                    Color = new ARGB(0xffff0088),
                                    PosA = new Position()
                                    {
                                        X = targets[i].X,
                                        Y = targets[i].Y
                                    },
                                    PosB = new Position() { X = 350 }
                                });
                            }
                            BroadcastSync(pkts, p => this.Dist(p) < 25);
                        } break;
                    case ActivateEffects.PoisonGrenade:
                        {
                            BroadcastSync(new ShowEffectPacket()
                            {
                                EffectType = EffectType.Throw,
                                Color = new ARGB(0xffddff00),
                                TargetId = Id,
                                PosA = target
                            }, p => this.Dist(p) < 25);
                            Placeholder x = new Placeholder(Manager, 1500);
                            x.Move(target.X, target.Y);
                            Owner.EnterWorld(x);
                            Owner.Timers.Add(new WorldTimer(1500, (world, t) =>
                            {
                                Owner.BroadcastPacket(new ShowEffectPacket()
                                {
                                    EffectType = EffectType.AreaBlast,
                                    Color = new ARGB(0xffddff00),
                                    TargetId = x.Id,
                                    PosA = new Position() { X = eff.Radius }
                                }, null);
                                List<Enemy> enemies = new List<Enemy>();
                                Owner.AOE(target, eff.Radius, false,
                                    enemy => PoisonEnemy(enemy as Enemy, eff));
                            }));
                        } break;
                    case ActivateEffects.RemoveNegativeConditions:
                        {
                            this.AOE(eff.Range / 2, true, player =>
                            {
                                ApplyConditionEffect(NegativeEffs);
                            });
                            BroadcastSync(new ShowEffectPacket()
                            {
                                EffectType = EffectType.AreaBlast,
                                TargetId = Id,
                                Color = new ARGB(0xffffffff),
                                PosA = new Position() { X = eff.Range / 2 }
                            }, p => this.Dist(p) < 25);
                        } break;
                    case ActivateEffects.RemoveNegativeConditionsSelf:
                        {
                            ApplyConditionEffect(NegativeEffs);
                            BroadcastSync(new ShowEffectPacket()
                            {
                                EffectType = EffectType.AreaBlast,
                                TargetId = Id,
                                Color = new ARGB(0xffffffff),
                                PosA = new Position() { X = 1 }
                            }, p => this.Dist(p) < 25);
                        } break;
                    case ActivateEffects.IncrementStat:
                        {
                            int idx = -1;
                            switch ((StatsType)eff.Stats)
                            {
                                case StatsType.MaximumHP: idx = 0; break;
                                case StatsType.MaximumMP: idx = 1; break;
                                case StatsType.Attack: idx = 2; break;
                                case StatsType.Defense: idx = 3; break;
                                case StatsType.Speed: idx = 4; break;
                                case StatsType.Vitality: idx = 5; break;
                                case StatsType.Wisdom: idx = 6; break;
                                case StatsType.Dexterity: idx = 7; break;
                            }
                            Stats[idx] += eff.Amount;
                            int limit = int.Parse(Manager.GameData.ObjectTypeToElement[ObjectType].Element(StatsManager.StatsIndexToName(idx)).Attribute("max").Value);
                            if (Stats[idx] > limit)
                                Stats[idx] = limit;
                            UpdateCount++;
                        } break;
                    case ActivateEffects.Create: //this is a portal
                        {
                            ushort objType;
                            if (!Manager.GameData.IdToObjectType.TryGetValue(eff.Id, out objType) ||
                                !Manager.GameData.Portals.ContainsKey(objType))
                                break;// object not found, ignore
                            var entity = Entity.Resolve(Manager, objType);
                            entity.Move(X, Y);
                            int TimeoutTime = Manager.GameData.Portals[objType].TimeoutTime;

                            Owner.EnterWorld(entity);
                            World w = Manager.GetWorld(Owner.Id); //can't use Owner here, as it goes out of scope
                            w.Timers.Add(new WorldTimer(TimeoutTime * 1000, (world, t) => //default portal close time * 1000
                            {
                                try
                                {
                                    w.LeaveWorld(entity);
                                }
                                catch //couldn't remove portal, Owner became null. Should be fixed with RealmManager implementation
                                {
                                    Console.WriteLine("Couldn't despawn portal.");
                                }
                            }));
                        } break;
                    case ActivateEffects.Pet:
                    case ActivateEffects.UnlockPortal:
                        break;
                }
            }
            UpdateCount++;
        }
        private void ActivateAbilityShoot(RealmTime time, Ability ability, Position target)
        {
            double arcGap = ability.ArcGap * Math.PI / 180;
            double startAngle = Math.Atan2(target.Y - Y, target.X - X) - (ability.NumProjectiles - 1) / 2 * arcGap;
            ProjectileDesc prjDesc = ability.Projectiles[0]; //Assume only one

            var batch = new Packet[ability.NumProjectiles];
            for (int i = 0; i < ability.NumProjectiles; i++)
            {
                Projectile proj = CreateProjectile(prjDesc, ObjectDesc.ObjectType,
                    (int)statsMgr.GetAttackDamage(prjDesc.MinDamage, prjDesc.MaxDamage),
                    time.tickTimes, new Position { X = X, Y = Y }, (float)(startAngle + arcGap * i), 1);
                Owner.EnterWorld(proj);
                fames.Shoot(proj);
                batch[i] = new ShootPacket
                {
                    BulletId = proj.ProjectileId,
                    OwnerId = Id,
                    ContainerType = ability.AbilityType,
                    Position = new Position { X = X, Y = Y },
                    Angle = proj.Angle,
                    Damage = (short)proj.Damage,
                    FromAbility = true
                };
            }
            BroadcastSync(batch, p => this.Dist(p) < 25);
        }