Exemple #1
0
        protected override bool TickCore(RealmTime time)
        {
            var chr = Host as Character;
            Position target = new Position()
            {
                X = Host.Self.X,
                Y = Host.Self.Y
            };
            target.X += (float)Math.Cos(angle) * range;
            target.Y += (float)Math.Sin(angle) * range;
            chr.Owner.BroadcastPacket(new ShowEffectPacket()
            {
                EffectType = EffectType.Throw,
                Color = new ARGB(0xffffbf00),
                TargetId = Host.Self.Id,
                PosA = target
            }, null);
            chr.Owner.Timers.Add(new WorldTimer(1500, (world, t) =>
            {
                Entity entity = Entity.Resolve(objType);
                entity.Move(target.X, target.Y);
                (entity as Enemy).Terrain = (chr as Enemy).Terrain;
                world.EnterWorld(entity);
            }));

            return true;
        }
        protected override bool TickCore(RealmTime time)
        {
            int remainingTick;
            object o;
            if (!Host.StateStorage.TryGetValue(Key, out o))
                remainingTick = 0;
            else
                remainingTick = (int)o;

            remainingTick -= time.thisTickTimes;
            bool ret;
            if (remainingTick <= 0)
            {
                if (CountEntity(radius, objType) < maxCount)
                {
                    Entity entity = Entity.Resolve(objType);
                    entity.Move(Host.Self.X, Host.Self.Y);
                    (entity as Enemy).Terrain = (Host as Enemy).Terrain;
                    Host.Self.Owner.EnterWorld(entity);
                }

                remainingTick = rand.Next(minTick, maxTick);
                ret = true;
            }
            else
                ret = false;
            Host.StateStorage[Key] = remainingTick;
            return ret;
        }
Exemple #3
0
        protected override bool TickCore(RealmTime time)
        {
            if (Host.Self.HasConditionEffect(ConditionEffects.Paralyzed)) return true;
            var speed = this.speed * GetSpeedMultiplier(Host.Self);

            float d;
            object o;
            if (!Host.StateStorage.TryGetValue(Key, out o))
                Host.StateStorage[Key] = d = dist;
            else
            {
                d = (float)o;

                float dd = (speed / 1.5f) * (time.thisTickTimes / 1000f);
                d -= dd;
                ValidateAndMove(Host.Self.X + (float)Math.Cos(angle) * dd, Host.Self.Y + (float)Math.Sin(angle) * dd);
                Host.Self.UpdateCount++;
            }

            bool ret;
            if (d <= 0)
            {
                d = dist;
                ret = true;
            }
            else
                ret = false;
            Host.StateStorage[Key] = d;
            return ret;
        }
Exemple #4
0
        protected override bool TickCore(RealmTime time)
        {
            if (Host.Self.HasConditionEffect(ConditionEffects.Paralyzed)) return true;
            var speed = this.speed * GetSpeedMultiplier(Host.Self);

            float dist = radius;
            Entity entity = GetNearestEntity(ref dist, objType);
            Character chr = Host as Character;
            if (entity != null && chr.HP < threshold)
            {
                var x = Host.Self.X;
                var y = Host.Self.Y;
                Vector2 vect = new Vector2(entity.X, entity.Y) - new Vector2(Host.Self.X, Host.Self.Y);
                vect.Normalize();
                vect *= -1 * (speed / 1.5f) * (time.thisTickTimes / 1000f);
                ValidateAndMove(Host.Self.X + vect.X, Host.Self.Y + vect.Y);
                Host.Self.UpdateCount++;

                if (!Host.StateStorage.ContainsKey(Key))
                {
                    chr.Owner.BroadcastPacket(new ShowEffectPacket()
                    {
                        EffectType = EffectType.Flashing,
                        PosA = new Position() { X = 1, Y = 1000000 },
                        TargetId = chr.Id,
                        Color = new ARGB(0xff303030)
                    }, null);
                    Host.StateStorage[Key] = true;
                }

                return true;
            }
            else return false;
        }
        protected override bool TickCore(RealmTime time)
        {
            if (Host.Self.HasConditionEffect(ConditionEffects.Paralyzed)) return true;
            var speed = this.speed * GetSpeedMultiplier(Host.Self);

            WanderingState state;
            object o;
            if (!Host.StateStorage.TryGetValue(Key, out o))
                Host.StateStorage[Key] = state = new WanderingState();
            else
            {
                state = (WanderingState)o;

                float dist = (speed / 1.5f) * (time.thisTickTimes / 1000f);
                state.remainingDist -= dist;
                ValidateAndMove(Host.Self.X + state.x * dist, Host.Self.Y + state.y * dist);
                Host.Self.UpdateCount++;
            }

            bool ret;
            if (state.remainingDist <= 0)
            {
                state.x = rand.Next(-1, 2);
                state.y = rand.Next(-1, 2);
                state.remainingDist = dist + dist * (float)(rand.NextDouble() * 0.1 - 0.05);
                ret = true;
            }
            else
                ret = false;
            return ret;
        }
        protected override bool TickCore(RealmTime time)
        {
            float dist = 8;
            var entity = GetNearestEntityByGroup(ref dist, "Golem");
            if (entity != null && dist > 4)
            {
                ValidateAndMove(entity.X, entity.Y);
                Host.StateStorage[Key] = 30 * 1000;
                return true;
            }
            else if (entity == null)
            {
                int remainingTick;
                object obj;
                if (!Host.StateStorage.TryGetValue(Key, out obj))
                    remainingTick = 30 * 1000;
                else
                    remainingTick = (int)obj;

                remainingTick -= time.thisTickTimes;
                if (remainingTick <= 0)
                    Host.Self.Owner.LeaveWorld(Host.Self);
                Host.StateStorage[Key] = remainingTick;
                return false;
            }
            else
            {
                Host.StateStorage[Key] = 30 * 1000;
                return true;
            }
        }
Exemple #7
0
        protected override bool TickCore(RealmTime time)
        {
            object obj;
            int t;
            if (Host.StateStorage.TryGetValue(Key, out obj))
                t = (int)obj;
            else
                t = this.time;

            bool ret;
            if (t == this.time)
            {
                Host.Self.Owner.BroadcastPacket(new ShowEffectPacket()
                {
                    EffectType = EffectType.Flashing,
                    PosA = new Position() { X = this.time / 1000f, Y = 1 },
                    TargetId = Host.Self.Id,
                    Color = new ARGB(color)
                }, null);
                ret = false;
                t -= time.thisTickTimes;
            }
            else if (t < 0)
            {
                ret = true;
                t = this.time;
            }
            else
            {
                ret = false;
                t -= time.thisTickTimes;
            }
            Host.StateStorage[Key] = t;
            return ret;
        }
        protected override bool TickCore(RealmTime time)
        {
            if (Host.Self.HasConditionEffect(ConditionEffects.Stunned)) return false;

            var chr = Host as Character;
            var startAngle = angle - projAngle * (numShot - 1) / 2;
            var desc = chr.ObjectDesc.Projectiles[projectileIndex];

            byte prjId = 0;
            Position prjPos = new Position() { X = chr.X, Y = chr.Y };
            var dmg = chr.Random.Next(desc.MinDamage, desc.MaxDamage);
            for (int i = 0; i < numShot; i++)
            {
                var prj = chr.CreateProjectile(
                    desc, chr.ObjectType, dmg, time.tickTimes,
                    prjPos, (float)(startAngle + projAngle * i));
                chr.Owner.EnterWorld(prj);
                if (i == 0)
                    prjId = prj.ProjectileId;
            }
            chr.Owner.BroadcastPacket(new MultiShootPacket()
            {
                BulletId = prjId,
                OwnerId = Host.Self.Id,
                BulletType = (byte)desc.BulletType,
                Position = prjPos,
                Angle = (float)startAngle,
                Damage = (short)dmg,
                NumShots = (byte)numShot,
                AngleIncrement = (float)projAngle,
            }, null);
            return true;
        }
 protected override bool TickCore(RealmTime time)
 {
     Host.Self.ApplyConditionEffect(new ConditionEffect()
     {
         Effect = eff,
         DurationMS = this.time
     });
     return true;
 }
 protected override bool TickCore(RealmTime time)
 {
     if ((Host.Self as Enemy).AltTextureIndex != index)
     {
         (Host.Self as Enemy).AltTextureIndex = index;
         Host.Self.UpdateCount++;
     }
     return true;
 }
 protected override void BehaveCore(BehaviorCondition cond, RealmTime? time, object state)
 {
     if (Host.Self.State == name)
     {
         foreach (var i in behave)
         {
             i.Tick(Host, (RealmTime)time);
         }
     }
 }
Exemple #12
0
 public bool Tick(World world, RealmTime time)
 {
     remain -= time.thisTickTimes;
     if (remain < 1)
     {
         cb(world, time);
         return true;
     }
     return false;
 }
Exemple #13
0
        protected override bool TickCore(RealmTime time)
        {
            if (Host.Self.HasConditionEffect(ConditionEffects.Paralyzed)) return true;

            float dist = radius;
            Entity entity = GetNearestEntity(ref dist, objType);
            if (entity != null)
                ValidateAndMove(entity.X, entity.Y);
            return true;
        }
Exemple #14
0
 protected override bool TickCore(RealmTime time)
 {
     if (Host.Self.Size < target)
     {
         Host.Self.Size += rate / 2;
         Host.Self.UpdateCount++;
         return true;
     }
     else
         return false;
 }
Exemple #15
0
 protected override bool TickCore(RealmTime time)
 {
     var x = GetNearestEntities(radius, objType);
     bool ret = false;
     foreach (var i in x)
     {
         ret = true;
         behav.Tick(i, time);
     }
     return ret;
 }
 protected override bool TickCore(RealmTime time)
 {
     int count = rand.Next(minCount, maxCount + 1);
     for (int i = 0; i < count; i++)
     {
         Entity entity = Entity.Resolve(objType);
         entity.Move(Host.Self.X + (float)(rand.NextDouble() * 2 - 1) * radius, Host.Self.Y + (float)(rand.NextDouble() * 2 - 1) * radius);
         (entity as Enemy).Terrain = (Host as Enemy).Terrain;
         Host.Self.Owner.EnterWorld(entity);
     }
     return true;
 }
 protected override bool TickCore(RealmTime time)
 {
     if (Host.Self.State != name)
     {
         foreach (var i in behave)
         {
             i.Tick(Host, time);
         }
         return true;
     }
     return false;
 }
Exemple #18
0
        protected override bool TickCore(RealmTime time)
        {
            if (Host.Self.HasConditionEffect(ConditionEffects.Paralyzed)) return true;
            var speed = this.speed * GetSpeedMultiplier(Host.Self);

            Vector2 velo = GetVelocity();
            if (velo != Vector2.Zero)
                velo.Normalize();
            float dist = (speed / 1.5f) * (time.thisTickTimes / 1000f);
            ValidateAndMove(Host.Self.X + velo.X * dist, Host.Self.Y + velo.Y * dist);
            Host.Self.UpdateCount++;
            return true;
        }
Exemple #19
0
 protected override bool TickCore(RealmTime time)
 {
     int c = rand.Next(minCount, maxCount + 1);
     Entity parent = Host as Entity;
     for (int i = 0; i < c; i++)
     {
         Entity entity = Entity.Resolve(objType);
         entity.Move(parent.X, parent.Y);
         (entity as Enemy).Terrain = (Host as Enemy).Terrain;
         parent.Owner.EnterWorld(entity);
     }
     parent.Owner.LeaveWorld(parent);
     return true;
 }
 //Debugger error begins here
 public void TickLoop()
 {
     Stopwatch watch = new Stopwatch();
     long dt = 0; //Down Time
     long count = 0;
     watch.Start();
     RealmTime t = new RealmTime();
     long xa = 0;
     do
     {
         long times = dt / MsPT;
         dt -= times * MsPT;
         times++;
         long b = watch.ElapsedMilliseconds;
         count += times;
         if (times > 3)
         {
             Console.ForegroundColor = ConsoleColor.Cyan;
             Console.WriteLine("Pinged! times pinged:" + times + " dt:" + dt + " count:" + count + " time:" + b + " tps:" + count / (b / 1000.0));
             Console.ForegroundColor = ConsoleColor.White;
         }
         t.tickTimes = b;
         t.tickCount = count;
         t.thisTickCounts = (int)times;
         t.thisTickTimes = (int)(times * MsPT);
         xa += t.thisTickTimes;
         foreach (var i in pendings)
         {
             Action<RealmTime> callback;
             while (i.TryDequeue(out callback))
             {
                 try
                 {
                     callback(t);
                 }
                 catch (Exception ex)
                 {
                     Console.ForegroundColor = ConsoleColor.Red;
                     Console.Out.WriteLine("Error syncing the server, check LogicTicker.cs");
                     log.Error(ex);
                     Console.ForegroundColor = ConsoleColor.White;
                 }
             }
         }
         TickWorlds1(t);
         Thread.Sleep(MsPT);
         dt += Math.Max(0, watch.ElapsedMilliseconds - b - MsPT);
     } while (true);
 }
Exemple #21
0
        protected override bool TickCore(RealmTime time)
        {
            int remainingTick;
            object o;
            if (!Host.StateStorage.TryGetValue(Key, out o))
                remainingTick = rand.Next(min, max);
            else
                remainingTick = (int)o;

            remainingTick -= time.thisTickTimes;
            bool ret;
            if (remainingTick <= 0)
            {
                if (CountEntity(radius, objType) < maxCount)
                {
                    Entity entity = Entity.Resolve(objType);

                    double targetX = Host.Self.X;
                    double targetY = Host.Self.Y;
                    if (radius != 5)
                    {
                        int i = 0;
                        do
                        {
                            var angle = rand.NextDouble() * 2 * Math.PI;
                            targetX = Host.Self.X + radius * 0.5 * Math.Cos(angle);
                            targetY = Host.Self.Y + radius * 0.5 * Math.Sin(angle);
                            i++;
                        } while (targetX < Host.Self.Owner.Map.Width &&
                                 targetY < Host.Self.Owner.Map.Height &&
                                 targetX > 0 && targetY > 0 &&
                                 Host.Self.Owner.Map[(int)targetX, (int)targetY].Terrain !=
                                 Host.Self.Owner.Map[(int)Host.Self.X, (int)Host.Self.Y].Terrain &&
                            i < 10);
                    }

                    entity.Move((float)targetX, (float)targetY);
                    (entity as Enemy).Terrain = (Host as Enemy).Terrain;
                    Host.Self.Owner.EnterWorld(entity);
                }

                remainingTick = rand.Next(min, max);
                ret = true;
            }
            else
                ret = false;
            Host.StateStorage[Key] = remainingTick;
            return ret;
        }
Exemple #22
0
        protected override bool TickCore(RealmTime time)
        {
            if (Host.Self.HasConditionEffect(ConditionEffects.Paralyzed)) return true;
            var speed = this.speed * GetSpeedMultiplier(Host.Self);

            CirclingState state;
            object o;
            if (!Host.StateStorage.TryGetValue(Key, out o))
            {
                float dist = sight;
                Host.StateStorage[Key] = state = new CirclingState()
                {
                    target = WeakReference<Entity>.Create(GetNearestEntity(ref dist, objType)),
                    angle = (float)(2 * Math.PI * rand.NextDouble())
                };
            }
            else
            {
                state = (CirclingState)o;

                state.angle += angularSpeed * (time.thisTickTimes / 1000f);
                if (!state.target.IsAlive)
                {
                    Host.StateStorage.Remove(Key);
                    return false;
                }
                var target = state.target.Target;
                if (target == null || target.Owner == null)
                {
                    Host.StateStorage.Remove(Key);
                    return false;
                }

                double x = target.X + Math.Cos(state.angle) * radius;
                double y = target.Y + Math.Sin(state.angle) * radius;
                if (x != Host.Self.X || y != Host.Self.Y)
                {
                    Vector2 vect = new Vector2((float)x, (float)y) - new Vector2(Host.Self.X, Host.Self.Y);
                    vect.Normalize();
                    vect *= (speed / 1.5f) * (time.thisTickTimes / 1000f);
                    ValidateAndMove(Host.Self.X + vect.X, Host.Self.Y + vect.Y);
                    Host.Self.UpdateCount++;
                }
            }

            if (state.angle >= Math.PI * 2)
                state.angle -= (float)(Math.PI * 2);
            return true;
        }
        protected override bool TickCore(RealmTime time)
        {
            int remainingTick;
            object o;
            if (!Host.StateStorage.TryGetValue(Key, out o))
                remainingTick = 0;
            else
                remainingTick = (int)o;

            remainingTick -= time.thisTickTimes;
            bool ret;
            if (remainingTick <= 0)
            {
                double angle = 0;
                switch (Host.Self.ObjectType)
                {
                    case 0x0802: angle = Math.PI / 2; break;
                    case 0x0803: angle = Math.PI * 3 / 2; break;
                    case 0x0804: angle = 0; break;
                    case 0x0805: angle = Math.PI; break;
                }

                ProjectileDesc desc = Host.Self.ObjectDesc.Projectiles[0];
                Projectile proj = Host.Self.CreateProjectile(desc, Host.Self.ObjectType,
                    5, time.tickTimes, new Position() { X = Host.Self.X, Y = Host.Self.Y },
                    (float)angle);
                Host.Self.Owner.EnterWorld(proj);
                Host.Self.Owner.BroadcastPacket(new ShootPacket()
                {
                    BulletId = proj.ProjectileId,
                    OwnerId = Host.Self.Id,
                    ContainerType = Host.Self.ObjectType,
                    Position = proj.BeginPos,
                    Angle = proj.Angle,
                    Damage = (short)proj.Damage
                }, null);

                remainingTick = rand.Next(2000, 3500);
                ret = true;
            }
            else
                ret = false;
            Host.StateStorage[Key] = remainingTick;
            return ret;
        }
        protected override bool TickCore(RealmTime time)
        {
            if (Host.Self.HasConditionEffect(ConditionEffects.Stunned)) return false;
            float dist = radius;
            Entity entity = radius == 0 ? null : GetNearestEntity(ref dist, null);
            if (entity != null || radius == 0)
            {
                var chr = Host as Character;
                if (chr.Owner == null) return false;
                var desc = chr.ObjectDesc.Projectiles[projectileIndex];
                var angle = entity == null ? 0 : Math.Atan2(entity.Y - chr.Y, entity.X - chr.X);
                angle = Predict(entity, desc);
                var angleInc = (2 * Math.PI) / this.count;

                var count = this.count;
                if (Host.Self.HasConditionEffect(ConditionEffects.Dazed))
                    count = Math.Max(1, count / 2);

                byte prjId = 0;
                Position prjPos = new Position() { X = chr.X, Y = chr.Y };
                var dmg = chr.Random.Next(desc.MinDamage, desc.MaxDamage);
                for (int i = 0; i < count; i++)
                {
                    var prj = chr.CreateProjectile(
                        desc, chr.ObjectType, dmg, time.tickTimes,
                        prjPos, (float)(angle + angleInc * i));
                    chr.Owner.EnterWorld(prj);
                    if (i == 0)
                        prjId = prj.ProjectileId;
                }
                chr.Owner.BroadcastPacket(new MultiShootPacket()
                {
                    BulletId = prjId,
                    OwnerId = Host.Self.Id,
                    BulletType = (byte)desc.BulletType,
                    Position = prjPos,
                    Angle = (float)angle,
                    Damage = (short)dmg,
                    NumShots = (byte)count,
                    AngleIncrement = (float)angleInc,
                }, null);
                return true;
            }
            return false;
        }
        protected override bool TickCore(RealmTime time)
        {
            if (Host.Self.HasConditionEffect(ConditionEffects.Stunned)) return false;
            var numShot = this.numShot;
            if (Host.Self.HasConditionEffect(ConditionEffects.Dazed))
                numShot = Math.Max(1, numShot / 2);

            float dist = radius;
            Entity player = GetNearestEntity(ref dist, null);
            if (player != null)
            {
                var chr = Host as Character;
                var startAngle = Math.Atan2(player.Y - chr.Y, player.X - chr.X)
                    - angle * (numShot - 1) / 2
                    + offset;
                var desc = chr.ObjectDesc.Projectiles[projectileIndex];

                byte prjId = 0;
                Position prjPos = new Position() { X = chr.X, Y = chr.Y };
                var dmg = chr.Random.Next(desc.MinDamage, desc.MaxDamage);
                for (int i = 0; i < numShot; i++)
                {
                    var prj = chr.CreateProjectile(
                        desc, chr.ObjectType, dmg, time.tickTimes,
                        prjPos, (float)(startAngle + angle * i));
                    chr.Owner.EnterWorld(prj);
                    if (i == 0)
                        prjId = prj.ProjectileId;
                }
                chr.Owner.BroadcastPacket(new MultiShootPacket()
                {
                    BulletId = prjId,
                    OwnerId = Host.Self.Id,
                    BulletType = (byte)desc.BulletType,
                    Position = prjPos,
                    Angle = (float)startAngle,
                    Damage = (short)dmg,
                    NumShots = (byte)numShot,
                    AngleIncrement = (float)angle,
                }, null);
                return true;
            }
            return false;
        }
        protected override bool TickCore(RealmTime time)
        {
            float dist = 4;
            var entity = GetNearestEntityByGroup(ref dist, "Golem Satellites");
            if (entity == null)
            {
                entity = Entity.Resolve((short)(0x6d2 + rand.Next(0, 3)));
                entity.Move(Host.Self.X, Host.Self.Y);
                Host.Self.Owner.EnterWorld(entity);

                for (int i = 0; i < 3; i++)
                {
                    entity = Entity.Resolve((short)(0x6d5 + i));
                    entity.Move(Host.Self.X, Host.Self.Y);
                    Host.Self.Owner.EnterWorld(entity);
                }
                return true;
            }
            return false;
        }
        protected override bool TickCore(RealmTime time)
        {
            if (Host.Self.HasConditionEffect(ConditionEffects.Stunned)) return false;
            float dist = sightRadius;
            Entity player = GetNearestEntity(ref dist, null);
            if (player != null)
            {
                var chr = Host as Character;
                Position target = new Position()
                {
                    X = player.X,
                    Y = player.Y
                };
                chr.Owner.BroadcastPacket(new ShowEffectPacket()
                {
                    EffectType = EffectType.Throw,
                    Color = new ARGB(0xffff0000), //was 0xffff0000
                    TargetId = Host.Self.Id,
                    PosA = target
                }, null);
                chr.Owner.Timers.Add(new WorldTimer(1500, (world, t) =>
                {
                    world.BroadcastPacket(new AOEPacket()
                    {
                        Position = target,
                        Radius = bombRadius,
                        Damage = (ushort)damage,
                        EffectDuration = 0,
                        Effects = 0,
                        OriginType = Host.Self.ObjectType
                    }, null);
                    AOE(world, target, bombRadius, true, p =>
                    {
                        (p as IPlayer).Damage(damage, Host.Self as Character);
                    });
                }));

                return true;
            }
            return false;
        }
        protected override bool TickCore(RealmTime time)
        {
            if (Host.Self.HasConditionEffect(ConditionEffects.Stunned)) return false;
            float dist = radius;
            Entity player = GetNearestEntity(ref dist, null);
            if (player != null)
            {
                var chr = Host as Character;
                var angle = Math.Atan2(player.Y - chr.Y, player.X - chr.X);
                var desc = chr.ObjectDesc.Projectiles[projectileIndex];

                var prj = chr.CreateProjectile(
                    desc, chr.ObjectType, chr.Random.Next(desc.MinDamage, desc.MaxDamage),
                    time.tickTimes, new Position() { X = chr.X, Y = chr.Y }, (float)angle);
                chr.Owner.EnterWorld(prj);
                if (projectileIndex == 0) //(false)
                    chr.Owner.BroadcastPacket(new ShootPacket()
                    {
                        BulletId = prj.ProjectileId,
                        OwnerId = Host.Self.Id,
                        ContainerType = Host.Self.ObjectType,
                        Position = prj.BeginPos,
                        Angle = prj.Angle,
                        Damage = (short)prj.Damage
                    }, null);
                else
                    chr.Owner.BroadcastPacket(new MultiShootPacket()
                    {
                        BulletId = prj.ProjectileId,
                        OwnerId = Host.Self.Id,
                        Position = prj.BeginPos,
                        Angle = prj.Angle,
                        Damage = (short)prj.Damage,
                        BulletType = (byte)(desc.BulletType),
                        AngleIncrement = 0,
                        NumShots = 1,
                    }, null);
                return true;
            }
            return false;
        }
        protected override bool TickCore(RealmTime time)
        {
            if (Host.Self.HasConditionEffect(ConditionEffects.Paralyzed)) return true;
            var speed = this.speed * GetSpeedMultiplier(Host.Self);

            WanderingState state;
            object o;
            if (!Host.StateStorage.TryGetValue(Key, out o))
                Host.StateStorage[Key] = state = new WanderingState() { beginPos = new Position() { X = Host.Self.X, Y = Host.Self.Y } };
            else
            {
                state = (WanderingState)o;

                double dist = (speed / 1.5f) * (time.thisTickTimes / 1000.0);
                double x = Math.Cos(state.angle) * dist;
                double y = Math.Sin(state.angle) * dist;
                state.remainingDist -= (float)dist;
                ValidateAndMove(Host.Self.X + (float)x, Host.Self.Y + (float)y);
                Host.Self.UpdateCount++;
            }

            bool ret;
            if (state.remainingDist <= 0)
            {
                double randAngle = Math.PI * 2 * rand.NextDouble();
                double randRadius = radius * rand.NextDouble();
                Position newPos = new Position()
                {
                    X = (float)(Math.Cos(randAngle) * randRadius) + state.beginPos.X,
                    Y = (float)(Math.Sin(randAngle) * randRadius) + state.beginPos.Y,
                };
                var dx = newPos.X - Host.Self.X;
                var dy = newPos.Y - Host.Self.Y;
                state.angle = (float)Math.Atan2(dy, dx);
                state.remainingDist = (float)Math.Sqrt(dx * dx + dy * dy);
                ret = true;
            }
            else
                ret = false;
            return ret;
        }
        protected override bool TickCore(RealmTime time)
        {
            if (Host.Self.HasConditionEffect(ConditionEffects.Paralyzed)) return true;
            var speed = this.speed * GetSpeedMultiplier(Host.Self);

            Position pos = (Host as Enemy).SpawnPoint;
            var tx = pos.X;
            var ty = pos.Y;
            if (Math.Abs(tx - Host.Self.X) > 1 || Math.Abs(ty - Host.Self.Y) > 1)
            {
                var x = Host.Self.X;
                var y = Host.Self.Y;
                Vector2 vect = new Vector2(tx, ty) - new Vector2(Host.Self.X, Host.Self.Y);
                vect.Normalize();
                vect *= (speed / 1.5f) * (time.thisTickTimes / 1000f);
                ValidateAndMove(Host.Self.X + vect.X, Host.Self.Y + vect.Y);
                Host.Self.UpdateCount++;
                return true;
            }
            return false;
        }