Example #1
0
        public void Fire(Mobj actor)
        {
            var dest = actor.Tracer;

            if (dest == null)
            {
                return;
            }

            // Don't move it if the vile lost sight.
            if (!world.VisibilityCheck.CheckSight(actor.Target, dest))
            {
                return;
            }

            world.ThingMovement.UnsetThingPosition(actor);

            var angle = dest.Angle;

            actor.X = dest.X + Fixed.FromInt(24) * Trig.Cos(angle);
            actor.Y = dest.Y + Fixed.FromInt(24) * Trig.Sin(angle);
            actor.Z = dest.Z;

            world.ThingMovement.SetThingPosition(actor);
        }
Example #2
0
        /// <summary>
        /// Returns true if a straight line between the looker and target is unobstructed.
        /// </summary>
        public bool CheckSight(Mobj looker, Mobj target)
        {
            var map = world.Map;

            // First check for trivial rejection.
            // Check in REJECT table.
            if (map.Reject.Check(looker.Subsector.Sector, target.Subsector.Sector))
            {
                // Can't possibly be connected.
                return(false);
            }

            // An unobstructed LOS is possible.
            // Now look from eyes of t1 to any part of t2.

            sightZStart = looker.Z + looker.Height - (looker.Height >> 2);
            topSlope    = (target.Z + target.Height) - sightZStart;
            bottomSlope = (target.Z) - sightZStart;

            trace.X  = looker.X;
            trace.Y  = looker.Y;
            trace.Dx = target.X - looker.X;
            trace.Dy = target.Y - looker.Y;

            targetX = target.X;
            targetY = target.Y;

            // The head node is the last node output.
            return(CrossBspNode(map.Nodes.Length - 1, world.GetNewValidCount()));
        }
Example #3
0
        /// <summary>
        /// Remove the mobj from the level.
        /// </summary>
        public void RemoveMobj(Mobj mobj)
        {
            var tm = world.ThingMovement;

            if ((mobj.Flags & MobjFlags.Special) != 0 &&
                (mobj.Flags & MobjFlags.Dropped) == 0 &&
                (mobj.Type != MobjType.Inv) &&
                (mobj.Type != MobjType.Ins))
            {
                itemRespawnQue[itemQueHead]  = mobj.SpawnPoint;
                itemRespawnTime[itemQueHead] = world.LevelTime;
                itemQueHead = (itemQueHead + 1) & (itemQueSize - 1);

                // Lose one off the end?
                if (itemQueHead == itemQueTail)
                {
                    itemQueTail = (itemQueTail + 1) & (itemQueSize - 1);
                }
            }

            // Unlink from sector and block lists.
            tm.UnsetThingPosition(mobj);

            // Stop any playing sound.
            world.StopSound(mobj);

            // Free block.
            world.Thinkers.Remove(mobj);
        }
Example #4
0
        private bool StompThing(Mobj thing)
        {
            if ((thing.Flags & MobjFlags.Shootable) == 0)
            {
                return(true);
            }

            var blockDist = thing.Radius + currentThing.Radius;
            var dx        = Fixed.Abs(thing.X - currentX);
            var dy        = Fixed.Abs(thing.Y - currentY);

            if (dx >= blockDist || dy >= blockDist)
            {
                // Didn't hit it.
                return(true);
            }

            // Don't clip against self.
            if (thing == currentThing)
            {
                return(true);
            }

            // Monsters don't stomp things except on boss level.
            if (currentThing.Player == null && world.Options.Map != 30)
            {
                return(false);
            }

            world.ThingInteraction.DamageMobj(thing, currentThing, currentThing, 10000);

            return(true);
        }
Example #5
0
        public void VileAttack(Mobj actor)
        {
            if (actor.Target == null)
            {
                return;
            }

            FaceTarget(actor);

            if (!world.VisibilityCheck.CheckSight(actor, actor.Target))
            {
                return;
            }

            world.StartSound(actor, Sfx.BAREXP);
            world.ThingInteraction.DamageMobj(actor.Target, actor, actor, 20);
            actor.Target.MomZ = Fixed.FromInt(1000) / actor.Target.Info.Mass;

            var fire = actor.Tracer;

            if (fire == null)
            {
                return;
            }

            var angle = actor.Angle;

            // Move the fire between the vile and the player.
            fire.X = actor.Target.X - Fixed.FromInt(24) * Trig.Cos(angle);
            fire.Y = actor.Target.Y - Fixed.FromInt(24) * Trig.Sin(angle);
            world.ThingInteraction.RadiusAttack(fire, actor, 70);
        }
Example #6
0
        public void Clear()
        {
            mobj        = null;
            playerState = 0;
            cmd.Clear();

            viewZ           = Fixed.Zero;
            viewHeight      = Fixed.Zero;
            deltaViewHeight = Fixed.Zero;
            bob             = Fixed.Zero;

            health      = 0;
            armorPoints = 0;
            armorType   = 0;

            Array.Clear(powers, 0, powers.Length);
            Array.Clear(cards, 0, cards.Length);
            backpack = false;

            Array.Clear(frags, 0, frags.Length);

            readyWeapon   = 0;
            pendingWeapon = 0;

            Array.Clear(weaponOwned, 0, weaponOwned.Length);
            Array.Clear(ammo, 0, ammo.Length);
            Array.Clear(maxAmmo, 0, maxAmmo.Length);

            useDown    = false;
            attackDown = false;

            cheats = 0;

            refire = 0;

            killCount   = 0;
            itemCount   = 0;
            secretCount = 0;

            message     = null;
            messageTime = 0;

            damageCount = 0;
            bonusCount  = 0;

            attacker = null;

            extraLight = 0;

            fixedColorMap = 0;

            colorMap = 0;

            foreach (var psp in playerSprites)
            {
                psp.Clear();
            }

            didSecret = false;
        }
Example #7
0
        /// <summary>
        /// Find a target on the aiming line.
        /// Sets LineTaget when a target is aimed at.
        /// </summary>
        public Fixed AimLineAttack(Mobj shooter, Angle angle, Fixed range)
        {
            currentShooter  = shooter;
            currentShooterZ = shooter.Z + (shooter.Height >> 1) + Fixed.FromInt(8);
            currentRange    = range;

            var targetX = shooter.X + range.ToIntFloor() * Trig.Cos(angle);
            var targetY = shooter.Y + range.ToIntFloor() * Trig.Sin(angle);

            // Can't shoot outside view angles.
            topSlope    = Fixed.FromInt(100) / 160;
            bottomSlope = Fixed.FromInt(-100) / 160;

            lineTarget = null;

            world.PathTraversal.PathTraverse(
                shooter.X, shooter.Y,
                targetX, targetY,
                PathTraverseFlags.AddLines | PathTraverseFlags.AddThings,
                aimTraverseFunc);

            if (lineTarget != null)
            {
                return(currentAimSlope);
            }

            return(Fixed.Zero);
        }
Example #8
0
        public void SkullAttack(Mobj actor)
        {
            if (actor.Target == null)
            {
                return;
            }

            var dest = actor.Target;

            actor.Flags |= MobjFlags.SkullFly;

            world.StartSound(actor, actor.Info.AttackSound);

            FaceTarget(actor);

            var angle = actor.Angle;

            actor.MomX = skullSpeed * Trig.Cos(angle);
            actor.MomY = skullSpeed * Trig.Sin(angle);

            var dist = Geometry.AproxDistance(dest.X - actor.X, dest.Y - actor.Y);

            var num = (dest.Z + (dest.Height >> 1) - actor.Z).Data;
            var den = dist.Data / skullSpeed.Data;

            if (den < 1)
            {
                den = 1;
            }

            actor.MomZ = new Fixed(num / den);
        }
Example #9
0
        public static int GetMobjHash(Mobj mobj)
        {
            var hash = 0;

            hash = CombineHash(hash, mobj.X.Data);
            hash = CombineHash(hash, mobj.Y.Data);
            hash = CombineHash(hash, mobj.Z.Data);

            hash = CombineHash(hash, (int)mobj.Angle.Data);
            hash = CombineHash(hash, (int)mobj.Sprite);
            hash = CombineHash(hash, mobj.Frame);

            hash = CombineHash(hash, mobj.FloorZ.Data);
            hash = CombineHash(hash, mobj.CeilingZ.Data);

            hash = CombineHash(hash, mobj.Radius.Data);
            hash = CombineHash(hash, mobj.Height.Data);

            hash = CombineHash(hash, mobj.MomX.Data);
            hash = CombineHash(hash, mobj.MomY.Data);
            hash = CombineHash(hash, mobj.MomZ.Data);

            hash = CombineHash(hash, mobj.Tics);
            hash = CombineHash(hash, (int)mobj.Flags);
            hash = CombineHash(hash, mobj.Health);

            hash = CombineHash(hash, (int)mobj.MoveDir);
            hash = CombineHash(hash, mobj.MoveCount);

            hash = CombineHash(hash, mobj.ReactionTime);
            hash = CombineHash(hash, mobj.Threshold);

            return(hash);
        }
Example #10
0
 public void Pain(Mobj actor)
 {
     if (actor.Info.PainSound != 0)
     {
         world.StartSound(actor, actor.Info.PainSound);
     }
 }
Example #11
0
 private void StairStep(Mobj thing)
 {
     if (!TryMove(thing, thing.X, thing.Y + thing.MomY))
     {
         TryMove(thing, thing.X + thing.MomX, thing.Y);
     }
 }
Example #12
0
        private static string GetMobjCsv(Mobj mobj)
        {
            var sb = new StringBuilder();

            sb.Append(mobj.X.Data).Append(",");
            sb.Append(mobj.Y.Data).Append(",");
            sb.Append(mobj.Z.Data).Append(",");

            sb.Append((int)mobj.Angle.Data).Append(",");
            sb.Append((int)mobj.Sprite).Append(",");
            sb.Append(mobj.Frame).Append(",");

            sb.Append(mobj.FloorZ.Data).Append(",");
            sb.Append(mobj.CeilingZ.Data).Append(",");

            sb.Append(mobj.Radius.Data).Append(",");
            sb.Append(mobj.Height.Data).Append(",");

            sb.Append(mobj.MomX.Data).Append(",");
            sb.Append(mobj.MomY.Data).Append(",");
            sb.Append(mobj.MomZ.Data).Append(",");

            sb.Append((int)mobj.Tics).Append(",");
            sb.Append((int)mobj.Flags).Append(",");
            sb.Append(mobj.Health).Append(",");

            sb.Append((int)mobj.MoveDir).Append(",");
            sb.Append(mobj.MoveCount).Append(",");

            sb.Append(mobj.ReactionTime).Append(",");
            sb.Append(mobj.Threshold);

            return(sb.ToString());
        }
Example #13
0
        public void RemoveMobj(Mobj mobj)
        {
            var tm = world.ThingMovement;

            if ((mobj.Flags & MobjFlags.Special) != 0 &&
                (mobj.Flags & MobjFlags.Dropped) == 0 &&
                (mobj.Type != MobjType.Inv) &&
                (mobj.Type != MobjType.Ins))
            {
                //itemrespawnque[iquehead] = mobj->spawnpoint;
                //itemrespawntime[iquehead] = leveltime;
                //iquehead = (iquehead + 1) & (ITEMQUESIZE - 1);

                // lose one off the end?
                //if (iquehead == iquetail)
                //    iquetail = (iquetail + 1) & (ITEMQUESIZE - 1);
            }

            // Unlink from sector and block lists.
            tm.UnsetThingPosition(mobj);

            // Stop any playing sound.
            world.StopSound(mobj);

            // Free block.
            world.Thinkers.Remove(mobj);
        }
Example #14
0
        public FloorType HitFloor(Mobj thing)
        {
            if (thing.FloorZ != thing.Subsector.Sector.FloorHeight)
            {
                // don't splash if landing on the edge above water
                return(FloorType.Solid);
            }
            switch (world.ThingAllocation.GetThingFloorType(thing))
            {
            case FloorType.Water:
                world.ThingAllocation.SpawnMobj(thing.X, thing.Y, Mobj.OnFloorZ, MobjType.SplashBase);
                var mo = world.ThingAllocation.SpawnMobj(thing.X, thing.Y, Mobj.OnFloorZ, MobjType.Splash);
                mo.Target = thing;
                mo.MomX   = Fixed.FromInt((world.Random.Next() - world.Random.Next()) << 8);
                mo.MomY   = Fixed.FromInt((world.Random.Next() - world.Random.Next()) << 8);
                mo.MomZ   = Fixed.FromInt(2) * Fixed.One + (Fixed.FromInt(world.Random.Next()) << 8);
                world.StartSound(thing, Sfx.GLOOP, SfxType.Misc);
                return(FloorType.Water);

            case FloorType.Lava: break;

            case FloorType.Sludge: break;
            }

            return(FloorType.Solid);
        }
Example #15
0
        private bool LookForPlayers(Mobj actor, bool allAround)
        {
            var count = 0;

            var stop = (actor.LastLook - 1) & 3;

            for (; ; actor.LastLook = (actor.LastLook + 1) & 3)
            {
                if (!world.Players[actor.LastLook].InGame)
                {
                    continue;
                }

                if (count++ == 2 || actor.LastLook == stop)
                {
                    // Done looking.
                    return(false);
                }

                var player = world.Players[actor.LastLook];

                if (player.Health <= 0)
                {
                    // Player is dead.
                    continue;
                }

                if (!world.VisibilityCheck.CheckSight(actor, player.Mobj))
                {
                    // Out of sight.
                    continue;
                }

                if (!allAround)
                {
                    var angle = Geometry.PointToAngle(
                        actor.X, actor.Y,
                        player.Mobj.X, player.Mobj.Y) - actor.Angle;

                    if (angle > Angle.Ang90 && angle < Angle.Ang270)
                    {
                        var dist = Geometry.AproxDistance(
                            player.Mobj.X - actor.X,
                            player.Mobj.Y - actor.Y);

                        // If real close, react anyway.
                        if (dist > World.MELEERANGE)
                        {
                            // Behind back.
                            continue;
                        }
                    }
                }

                actor.Target = player.Mobj;

                return(true);
            }
        }
Example #16
0
        private void GroupLines()
        {
            var sectorLines = new List <LineDef>();
            var boundingBox = new Fixed[4];

            foreach (var line in lines)
            {
                if (line.Special != 0)
                {
                    var so = new Mobj(world);
                    so.X             = (line.Vertex1.X + line.Vertex2.X) / 2;
                    so.Y             = (line.Vertex1.Y + line.Vertex2.Y) / 2;
                    line.SoundOrigin = so;
                }
            }

            foreach (var sector in sectors)
            {
                sectorLines.Clear();
                Box.Clear(boundingBox);

                foreach (var line in lines)
                {
                    if (line.FrontSector == sector || line.BackSector == sector)
                    {
                        sectorLines.Add(line);
                        Box.AddPoint(boundingBox, line.Vertex1.X, line.Vertex1.Y);
                        Box.AddPoint(boundingBox, line.Vertex2.X, line.Vertex2.Y);
                    }
                }

                sector.Lines = sectorLines.ToArray();

                // Set the degenmobj_t to the middle of the bounding box.
                sector.SoundOrigin   = new Mobj(world);
                sector.SoundOrigin.X = (boundingBox[Box.Right] + boundingBox[Box.Left]) / 2;
                sector.SoundOrigin.Y = (boundingBox[Box.Top] + boundingBox[Box.Bottom]) / 2;

                sector.BlockBox = new int[4];
                int block;

                // Adjust bounding box to map blocks.
                block = (boundingBox[Box.Top] - blockMap.OriginY + GameConst.MaxThingRadius).Data >> BlockMap.FracToBlockShift;
                block = block >= blockMap.Height ? blockMap.Height - 1 : block;
                sector.BlockBox[Box.Top] = block;

                block = (boundingBox[Box.Bottom] - blockMap.OriginY - GameConst.MaxThingRadius).Data >> BlockMap.FracToBlockShift;
                block = block < 0 ? 0 : block;
                sector.BlockBox[Box.Bottom] = block;

                block = (boundingBox[Box.Right] - blockMap.OriginX + GameConst.MaxThingRadius).Data >> BlockMap.FracToBlockShift;
                block = block >= blockMap.Width ? blockMap.Width - 1 : block;
                sector.BlockBox[Box.Right] = block;

                block = (boundingBox[Box.Left] - blockMap.OriginX - GameConst.MaxThingRadius).Data >> BlockMap.FracToBlockShift;
                block = block < 0 ? 0 : block;
                sector.BlockBox[Box.Left] = block;
            }
        }
Example #17
0
 private void NoiseAlert(Mobj target, Mobj emmiter)
 {
     RecursiveSound(
         emmiter.Subsector.Sector,
         0,
         target,
         world.GetNewValidCount());
 }
Example #18
0
 public void Clear()
 {
     line        = null;
     position    = 0;
     texture     = 0;
     timer       = 0;
     soundOrigin = null;
 }
Example #19
0
 public void Clear()
 {
     Line        = null;
     Position    = 0;
     Texture     = 0;
     Timer       = 0;
     SoundOrigin = null;
 }
Example #20
0
        public void PainDie(Mobj actor)
        {
            Fall(actor);

            PainShootSkull(actor, actor.Angle + Angle.Ang90);
            PainShootSkull(actor, actor.Angle + Angle.Ang180);
            PainShootSkull(actor, actor.Angle + Angle.Ang270);
        }
Example #21
0
        public void StartSound(Mobj mobj, Sfx sfx)
        {
            if (audio == null)
            {
                return;
            }

            audio.StartSound(mobj, sfx);
        }
Example #22
0
        public void StopSound(Mobj mobj)
        {
            if (audio == null)
            {
                return;
            }

            audio.StopSound(mobj);
        }
Example #23
0
        private bool AddThingIntercepts(Mobj thing)
        {
            var tracePositive = (trace.Dx.Data ^ trace.Dy.Data) > 0;

            Fixed x1;
            Fixed y1;
            Fixed x2;
            Fixed y2;

            // Check a corner to corner crossection for hit.
            if (tracePositive)
            {
                x1 = thing.X - thing.Radius;
                y1 = thing.Y + thing.Radius;

                x2 = thing.X + thing.Radius;
                y2 = thing.Y - thing.Radius;
            }
            else
            {
                x1 = thing.X - thing.Radius;
                y1 = thing.Y - thing.Radius;

                x2 = thing.X + thing.Radius;
                y2 = thing.Y + thing.Radius;
            }

            var s1 = Geometry.PointOnDivLineSide(x1, y1, trace);
            var s2 = Geometry.PointOnDivLineSide(x2, y2, trace);

            if (s1 == s2)
            {
                // Line isn't crossed.
                return(true);
            }

            target.X  = x1;
            target.Y  = y1;
            target.Dx = x2 - x1;
            target.Dy = y2 - y1;

            var frac = InterceptVector(trace, target);

            if (frac < Fixed.Zero)
            {
                // Behind source.
                return(true);
            }

            intercepts[interceptCount].Frac  = frac;
            intercepts[interceptCount].Line  = null;
            intercepts[interceptCount].Thing = thing;
            interceptCount++;

            // Keep going.
            return(true);
        }
Example #24
0
        public bool TeleportMove(Mobj thing, Fixed x, Fixed y)
        {
            // Kill anything occupying the position.
            currentThing = thing;
            currentFlags = thing.Flags;

            currentX = x;
            currentY = y;

            currentBox[Box.Top]    = y + currentThing.Radius;
            currentBox[Box.Bottom] = y - currentThing.Radius;
            currentBox[Box.Right]  = x + currentThing.Radius;
            currentBox[Box.Left]   = x - currentThing.Radius;

            var ss = Geometry.PointInSubsector(x, y, world.Map);

            currentCeilingLine = null;

            // The base floor / ceiling is from the subsector that contains the point.
            // Any contacted lines the step closer together will adjust them.
            currentFloorZ   = currentDropoffZ = ss.Sector.FloorHeight;
            currentCeilingZ = ss.Sector.CeilingHeight;

            var validcount = world.GetNewValidCount();

            crossedSpecialCount = 0;

            // Stomp on any things contacted.
            var bm      = world.Map.BlockMap;
            var blockX1 = bm.GetBlockX(currentBox[Box.Left] - GameConst.MaxThingRadius);
            var blockX2 = bm.GetBlockX(currentBox[Box.Right] + GameConst.MaxThingRadius);
            var blockY1 = bm.GetBlockY(currentBox[Box.Bottom] - GameConst.MaxThingRadius);
            var blockY2 = bm.GetBlockY(currentBox[Box.Top] + GameConst.MaxThingRadius);

            for (var bx = blockX1; bx <= blockX2; bx++)
            {
                for (var by = blockY1; by <= blockY2; by++)
                {
                    if (!bm.IterateThings(bx, by, stompThingFunc))
                    {
                        return(false);
                    }
                }
            }

            // the move is ok, so link the thing into its new position
            UnsetThingPosition(thing);

            thing.FloorZ   = currentFloorZ;
            thing.CeilingZ = currentCeilingZ;
            thing.X        = x;
            thing.Y        = y;

            SetThingPosition(thing);

            return(true);
        }
Example #25
0
        ////////////////////////////////////////////////////////////
        // Thing spawn functions for the middle of a game
        ////////////////////////////////////////////////////////////

        /// <summary>
        /// Spawn a mobj at the given position as the given type.
        /// </summary>
        public Mobj SpawnMobj(Fixed x, Fixed y, Fixed z, MobjType type)
        {
            var mobj = new Mobj(world);

            var info = DoomInfo.MobjInfos[(int)type];

            mobj.Type   = type;
            mobj.Info   = info;
            mobj.X      = x;
            mobj.Y      = y;
            mobj.Radius = info.Radius;
            mobj.Height = info.Height;
            mobj.Flags  = info.Flags;
            mobj.Flags2 = info.Flags2;
            mobj.Health = info.SpawnHealth;

            if (world.Options.Skill != GameSkill.Nightmare)
            {
                mobj.ReactionTime = info.ReactionTime;
            }

            mobj.LastLook = world.Random.Next() % Player.MaxPlayerCount;

            // Do not set the state with P_SetMobjState,
            // because action routines can not be called yet.
            var st = DoomInfo.States[(int)info.SpawnState];

            mobj.State  = st;
            mobj.Tics   = st.Tics;
            mobj.Sprite = st.Sprite;
            mobj.Frame  = st.Frame;

            // Set subsector and/or block links.
            world.ThingMovement.SetThingPosition(mobj);

            mobj.FloorZ   = mobj.Subsector.Sector.FloorHeight;
            mobj.CeilingZ = mobj.Subsector.Sector.CeilingHeight;

            if (z == Mobj.OnFloorZ)
            {
                mobj.Z = mobj.FloorZ;
            }
            else if (z == Mobj.OnCeilingZ)
            {
                mobj.Z = mobj.CeilingZ - mobj.Info.Height;
            }
            else
            {
                mobj.Z = z;
            }

            world.Thinkers.Add(mobj);

            return(mobj);
        }
Example #26
0
        private void RecursiveSound(Sector sec, int soundblocks, Mobj soundtarget, int validCount)
        {
            // Wake up all monsters in this sector.
            if (sec.ValidCount == validCount && sec.SoundTraversed <= soundblocks + 1)
            {
                // Already flooded.
                return;
            }

            sec.ValidCount     = validCount;
            sec.SoundTraversed = soundblocks + 1;
            sec.SoundTarget    = soundtarget;

            var mc = world.MapCollision;

            for (var i = 0; i < sec.Lines.Length; i++)
            {
                var check = sec.Lines[i];
                if ((check.Flags & LineFlags.TwoSided) == 0)
                {
                    continue;
                }

                mc.LineOpening(check);

                if (mc.OpenRange <= Fixed.Zero)
                {
                    // Closed door.
                    continue;
                }

                Sector other;
                if (check.FrontSide.Sector == sec)
                {
                    other = check.BackSide.Sector;
                }
                else
                {
                    other = check.FrontSide.Sector;
                }

                if ((check.Flags & LineFlags.SoundBlock) != 0)
                {
                    if (soundblocks == 0)
                    {
                        RecursiveSound(other, 1, soundtarget, validCount);
                    }
                }
                else
                {
                    RecursiveSound(other, soundblocks, soundtarget, validCount);
                }
            }
        }
Example #27
0
        public void SkelWhoosh(Mobj actor)
        {
            if (actor.Target == null)
            {
                return;
            }

            FaceTarget(actor);

            world.StartSound(actor, Sfx.SKESWG);
        }
Example #28
0
        public void PainAttack(Mobj actor)
        {
            if (actor.Target == null)
            {
                return;
            }

            FaceTarget(actor);

            PainShootSkull(actor, actor.Angle);
        }
Example #29
0
        public void CyberAttack(Mobj actor)
        {
            if (actor.Target == null)
            {
                return;
            }

            FaceTarget(actor);

            world.ThingAllocation.SpawnMissile(actor, actor.Target, MobjType.Rocket);
        }
Example #30
0
        private bool TryWalk(Mobj actor)
        {
            if (!Move(actor))
            {
                return(false);
            }

            actor.MoveCount = world.Random.Next() & 15;

            return(true);
        }