示例#1
0
        public override void Update()
        {
            if (Alive && Chatter.Count > 0 && DateTime.UtcNow > NextChatter)
            {
                int index = ChatterIndex % Chatter.Count;
                ChatterIndex++;
                Say(Chatter[index], 0);
                NextChatter = DateTime.UtcNow.AddSeconds(Program.Random(60, 90));
            }

            var statuses = new string[Statuses.Count];

            Statuses.Keys.CopyTo(statuses, 0);
            foreach (var status in statuses)
            {
                if (Statuses.ContainsKey(status))
                {
                    var s = Statuses[status];

                    if (s.RequiresCaster && s.Caster == null)
                    {
                        RemoveStatus(status);
                    }
                    else if (DateTime.UtcNow > s.NextTick)
                    {
                        if (s.Channeled)
                        {
                            Channel(s);
                        }
                        else if (Alive || !s.OnlyTickAlive)
                        {
                            s.OnTick(this);
                            if (s.SpellAnimation != 0 && !s.SingleAnimation)
                            {
                                SpellAnimation(s.SpellAnimation, 100);
                            }
                        }
                        if (--s.TimeLeft < 1)
                        {
                            RemoveStatus(status);
                        }
                        s.NextTick = DateTime.UtcNow.AddMilliseconds(s.Speed);
                    }
                }
            }

            var characters = new Character[ThreatMeter.Count];

            ThreatMeter.Keys.CopyTo(characters, 0);
            foreach (var c in characters)
            {
                if (c == null || c.Dead || !WithinRange(c, 12))
                {
                    ThreatMeter.Remove(c);
                }
            }

            var enemies = new Character[Enemies.Count];

            Enemies.CopyTo(enemies, 0);
            foreach (var e in enemies)
            {
                if (e == null || e.Dead || !WithinRange(e, 12))
                {
                    Enemies.Remove(e);
                }
                else
                {
                    foreach (var m in e.Group.Members)
                    {
                        this.Enemies.Add(m);
                        m.Enemies.Add(this);
                    }
                }
            }

            if (SpawnControl != null && SpawnControl.SpecificTime && SpawnControl.SpawnTime != GameServer.Time && !Dead)
            {
                LifeStatus = LifeStatus.Dead;
                Experience = 0;
            }

            if (CurrentHP <= 0 && Alive)
            {
                if (ShouldComa)
                {
                    CurrentHP = 1;
                    AddStatus("Spell_Coma", 1, 20, this);
                }
                else
                {
                    CurrentHP  = 0;
                    LifeStatus = LifeStatus.Dead;
                }
            }

            switch (LifeStatus)
            {
            case LifeStatus.Alive:
            {
                if (DateTime.UtcNow > NextTick)
                {
                    if (IsHostile && Target == null)
                    {
                        var targets = from t in
                                      from obj in Map.Objects
                                      where obj is Character && WithinRange(obj, HostileRange)
                                      select obj as Character
                                      where t.Alive && AllegianceTo(t) == Allegiance.Enemy && !t.Hidden && !t.Stealth
                                      orderby Point.DistanceFrom(t.Point) ascending
                                      select t;

                        if (targets.Count() > 0)
                        {
                            var target = targets.First();
                            Enemies.Add(target);
                            target.Enemies.Add(this);
                            target.Threaten(this, 1);
                        }
                    }

                    UpdateTarget();
                    if (IsCasting)
                    {
                        OnTickCasting();
                    }
                    else
                    {
                        OnTick();
                    }
                    TickCount++;
                    NextTick = DateTime.UtcNow.AddMilliseconds(TickSpeed);
                }
            } break;

            case LifeStatus.Coma:
            {
                if (DateTime.UtcNow > NextTick)
                {
                    OnTickComa();
                    TickCount++;
                    NextTick = DateTime.UtcNow.AddMilliseconds(TickSpeed);
                }
            } break;

            case LifeStatus.Dying:
            {
                if (DateTime.UtcNow > NextTick)
                {
                    OnTickDying();
                    TickCount++;
                    NextTick = DateTime.UtcNow.AddMilliseconds(TickSpeed);
                }
            } break;

            case LifeStatus.Dead:
            {
                #region Remove Statuses
                statuses = new string[Statuses.Count];
                Statuses.Keys.CopyTo(statuses, 0);
                foreach (var s in statuses)
                {
                    RemoveStatus(s);
                }
                #endregion

                #region Remove Threat
                characters = new Character[ThreatMeter.Count];
                ThreatMeter.Keys.CopyTo(characters, 0);
                foreach (var c in characters)
                {
                    ThreatMeter.Remove(c);
                }
                #endregion

                #region Remove Enemies
                enemies = new Character[Enemies.Count];
                Enemies.CopyTo(enemies, 0);
                foreach (var e in enemies)
                {
                    Enemies.Remove(e);
                    e.Enemies.Remove(this);
                }
                #endregion

                #region Give EXP / Quest Kill

                double highestGroupValue  = 0;
                double highestPlayerValue = 0;

                Group  highestGroup  = null;
                Player highestPlayer = null;

                var groups = new Dictionary <Group, double>();
                foreach (var attacker in Attackers)
                {
                    if (attacker.Key is Player)
                    {
                        var player = attacker.Key as Player;

                        if (groups.ContainsKey(player.Group))
                        {
                            groups[player.Group] += attacker.Value;
                        }
                        else
                        {
                            groups.Add(player.Group, attacker.Value);
                        }

                        if (groups[player.Group] > highestGroupValue)
                        {
                            highestGroup      = player.Group;
                            highestGroupValue = groups[player.Group];
                        }

                        if (attacker.Value > highestPlayerValue)
                        {
                            highestPlayer      = player;
                            highestPlayerValue = attacker.Value;
                        }
                    }
                }

                foreach (var group in groups)
                {
                    if (group.Value < MaximumHP * 0.15)
                    {
                        continue;
                    }

                    long averageLevel = 0;
                    var  players      = new List <Player>();

                    foreach (var p in group.Key.Members)
                    {
                        if (p.WithinRange(this, 12) && p is Player)
                        {
                            averageLevel += p.Level;
                            players.Add(p as Player);
                        }
                    }

                    if (players.Count > 0)
                    {
                        averageLevel /= players.Count;
                    }

                    foreach (var p in players)
                    {
                        var difference = Math.Abs(averageLevel - Level);

                        if (difference < 5)
                        {
                            var percent = 1.0 - difference * 0.125;
                            if (Program.Random(100) < p.ExperienceBonusChance)
                            {
                                percent *= p.ExperienceBonus;
                                p.SpellAnimation(341, 100);
                            }
                            p.RewardExperience((long)(Experience * percent));
                        }

                        foreach (var q in p.Quests)
                        {
                            var qs = q.Value.QuestStep;
                            foreach (var qo in qs.Objectives.Values)
                            {
                                if (qo.Type == QuestObjectiveType.Kill && qo.RequiredKilledTypes.Contains(GetType().Name))
                                {
                                    if (qo.GroupKill || p == highestPlayer)
                                    {
                                        p.AddQuestCount(q.Key, qo.Name);
                                    }
                                }
                            }
                        }
                    }
                }
                #endregion

                #region Close Dialogs
                foreach (Client c in GameServer.Clients)
                {
                    if (c.Player != null && c.Player.DialogSession.GameObject == this && c.Player.DialogSession.IsOpen)
                    {
                        c.Player.DialogSession.IsOpen     = false;
                        c.Player.DialogSession.Dialog     = null;
                        c.Player.DialogSession.GameObject = null;
                        c.Player.DialogSession.Map        = null;
                        c.Enqueue(Dialog.ExitPacket());
                    }
                }
                #endregion

                #region Loot
                if (SpawnControl != null || CanDropLootWithoutSpawn)
                {
                    var chest = new Chest();

                    foreach (Loot loot in Loot)
                    {
                        if (Program.Random(loot.MaximumValue) < loot.MinimumValue)
                        {
                            int  value;
                            int  index = Program.Random(loot.Items.Count);
                            var  item  = loot.Items[index];
                            Item drop  = null;

                            if (int.TryParse(item, out value))
                            {
                                drop = new Gold(value);
                                GameServer.InsertGameObject(drop);
                            }
                            else
                            {
                                drop = GameServer.CreateItem(item);
                            }

                            if (drop != null)
                            {
                                if (drop.LootRollLength > 0 || drop.BindType != BindType.None)
                                {
                                    var chestItem = new Chest.ChestItem();
                                    chestItem.Item = drop;
                                    chest.Items.Add(chestItem);
                                }
                                else
                                {
                                    if (highestGroup != null)
                                    {
                                        foreach (var member in highestGroup.Members)
                                        {
                                            drop.ProtectionOwners.Add(member.Name);
                                        }
                                        drop.ProtectionExpireTime = DateTime.UtcNow.AddSeconds(60);
                                    }
                                    Map.InsertCharacter(drop, Point);
                                }
                            }
                        }
                    }

                    if (chest.Items.Count > 0 && highestGroup != null)
                    {
                        foreach (var member in highestGroup.Members)
                        {
                            chest.GUIDs.Add(member.GUID);
                        }

                        chest.Direction = Direction.South;
                        GameServer.InsertGameObject(chest);
                        Map.InsertCharacter(chest, Point);
                    }
                }
                #endregion

                this.OnDeath();
                this.OnDeath(highestPlayer);

                Map.RemoveCharacter(this);
                GameServer.RemoveGameObject(this);
            } break;
            }

            if (DateTime.UtcNow.Subtract(LastHpRegen).TotalSeconds > 1)
            {
                if (Alive && CurrentHP < MaximumHP && Target == null)
                {
                    CurrentHP += (long)(MaximumHP * 0.10);
                    if (CurrentHP > MaximumHP)
                    {
                        CurrentHP = MaximumHP;
                    }
                }
                LastHpRegen = DateTime.UtcNow;
            }

            if (DateTime.UtcNow.Subtract(LastMpRegen).TotalSeconds > 1)
            {
                if (Alive && CurrentMP < MaximumMP && Target == null)
                {
                    CurrentMP += (long)(MaximumMP * 0.10);
                    if (CurrentMP > MaximumMP)
                    {
                        CurrentMP = MaximumMP;
                    }
                }
                LastMpRegen = DateTime.UtcNow;
            }
        }