Пример #1
0
        public IEnumerable <Status> PerformStep(MoveAction Step)
        {
            var actionSpeed = GetAgentSpeed(Step.MoveType);

            switch (Step.MoveType)
            {
                #region Ride Elevator
            case MoveType.RideElevator:

                CleanupMinecart();
                var shafts = Step.DestinationState.Tag as Elevators.ElevatorMoveState;
                if (shafts == null || shafts.Entrance == null || shafts.Entrance.IsDead || shafts.Exit == null || shafts.Exit.IsDead)
                {
                    yield return(Status.Fail);
                }

                var shaft = shafts.Entrance.Shaft;
                if (shaft == null || shaft.Invalid)
                {
                    yield return(Status.Fail);
                }

                if (!shaft.EnqueuDwarf(Agent, shafts))
                {
                    yield return(Status.Fail);
                }

                while (!shaft.ReadyToBoard(Agent))
                {
                    if (DeltaTime > 30.0f)
                    {
                        yield return(Status.Fail);    // We waited too long.
                    }
                    if (shaft.Invalid)
                    {
                        yield return(Status.Fail);
                    }

                    SetCharacterMode(CharacterMode.Idle);

                    if (Debugger.Switches.DebugElevators)
                    {
                        Drawer3D.DrawBox(shafts.Entrance.GetBoundingBox(), Color.Red, 0.1f, false);
                        Drawer3D.DrawBox(shafts.Exit.GetBoundingBox(), Color.Red, 0.1f, false);
                        Drawer3D.DrawBox(Step.DestinationVoxel.GetBoundingBox(), Color.Red, 0.1f, false);
                    }

                    yield return(Status.Running);
                }

                DeltaTime = 0;
                foreach (var bit in Translate(Agent.Position, GetPathPoint(shafts.Entrance.GetContainingVoxel()), actionSpeed))
                {
                    if (shaft.Invalid)
                    {
                        yield return(Status.Fail);
                    }

                    shaft.WaitForMe(Agent);

                    SetCharacterMode(CharacterMode.Walking);

                    if (Debugger.Switches.DebugElevators)
                    {
                        Drawer3D.DrawBox(shafts.Entrance.GetBoundingBox(), Color.Green, 0.1f, false);
                        Drawer3D.DrawBox(shafts.Exit.GetBoundingBox(), Color.Green, 0.1f, false);
                        Drawer3D.DrawBox(Step.DestinationVoxel.GetBoundingBox(), Color.Green, 0.1f, false);
                    }
                    yield return(Status.Running);
                }

                shaft.StartMotion(Agent);

                var grav = Creature.Physics.Gravity;
                //Creature.Physics.Gravity = Vector3.Zero;
                while (!shaft.AtDestination(Agent))
                {
                    if (shaft.Invalid)
                    {
                        yield return(Status.Fail);
                    }

                    SetCharacterMode(CharacterMode.Idle);

                    if (Debugger.Switches.DebugElevators)
                    {
                        Drawer3D.DrawBox(shafts.Entrance.GetBoundingBox(), Color.Red, 0.1f, false);
                        Drawer3D.DrawBox(shafts.Exit.GetBoundingBox(), Color.Red, 0.1f, false);
                        Drawer3D.DrawBox(Step.DestinationVoxel.GetBoundingBox(), Color.Red, 0.1f, false);
                    }

                    yield return(Status.Running);
                }

                DeltaTime = 0;
                foreach (var bit in Translate(Agent.Physics.LocalPosition, GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    if (shaft.Invalid)
                    {
                        yield return(Status.Fail);
                    }

                    shaft.WaitForMe(Agent);

                    SetCharacterMode(CharacterMode.Walking);

                    if (Debugger.Switches.DebugElevators)
                    {
                        Drawer3D.DrawBox(shafts.Entrance.GetBoundingBox(), Color.Green, 0.1f, false);
                        Drawer3D.DrawBox(shafts.Exit.GetBoundingBox(), Color.Green, 0.1f, false);
                        Drawer3D.DrawBox(Step.DestinationVoxel.GetBoundingBox(), Color.Green, 0.1f, false);
                    }

                    yield return(Status.Running);
                }
                Creature.Physics.Gravity = grav;

                shaft.Done(Agent);

                break;

                #endregion
            case MoveType.EnterVehicle:

                Creature.NoiseMaker.MakeNoise("Jump", Agent.Position, false);

                foreach (var bit in Jump(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), Step.DestinationVoxel.Center - Step.SourceVoxel.Center, actionSpeed, 1.5f))
                {
                    SetCharacterMode(Creature.Physics.Velocity.Y > 0 ? CharacterMode.Jumping : CharacterMode.Falling);
                    yield return(Status.Running);
                }

                DeltaTime = 0.0f;
                SetupMinecart();

                break;

            case MoveType.ExitVehicle:

                CleanupMinecart();
                SetAgentTranslation(GetPathPoint(Step.DestinationVoxel));
                break;

            case MoveType.RideVehicle:

                SetupMinecart();
                var rail = Step.SourceState.Rail;
                if (rail == null)
                {
                    yield return(Status.Fail);
                }

                var rideTime = 1.0f / actionSpeed;
                while (DeltaTime < rideTime)
                {
                    var pos = rail.InterpolateSpline(DeltaTime / rideTime, Step.SourceVoxel.WorldPosition, Step.DestinationVoxel.WorldPosition);

                    var transform = Agent.Physics.LocalTransform;
                    transform.Translation        = pos + Vector3.Up * 0.5f;
                    Agent.Physics.LocalTransform = transform;
                    Agent.Physics.Velocity       = GetPathPoint(Step.DestinationVoxel) - GetPathPoint(Step.SourceVoxel);

                    SetCharacterMode(CharacterMode.Minecart);

                    transform.Translation = pos + Vector3.Up * -0.1f;

                    if (Minecart != null)
                    {
                        Minecart.LocalTransform = transform;
                    }

                    yield return(Status.Running);
                }

                DeltaTime -= rideTime;

                break;

            case MoveType.Walk:

                // Todo: Fail if distance is too great.

                CleanupMinecart();

                foreach (var bit in Translate(Agent.Position, GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    SetCharacterMode(CharacterMode.Walking);
                    yield return(Status.Running);
                }
                break;

            case MoveType.Swim:

                CleanupMinecart();

                foreach (var bit in Translate(Agent.Position, GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    Creature.NoiseMaker.MakeNoise("Swim", Agent.Position, true);
                    SetCharacterMode(CharacterMode.Swimming);
                    yield return(Status.Running);
                }

                break;

            case MoveType.Jump:
            {
                CleanupMinecart();
                Creature.NoiseMaker.MakeNoise("Jump", Agent.Position, false);

                var dest  = GetPathPoint(Step.DestinationVoxel);
                var above = VoxelHelpers.GetVoxelAbove(Step.SourceVoxel);
                if (above.IsValid && !above.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                foreach (var bit in Jump(Agent.Position, dest, dest - Agent.Position, actionSpeed / 2.0f, 0.0f))
                {
                    Creature.Physics.CollisionType = CollisionType.None;
                    Creature.OverrideCharacterMode = false;
                    SetCharacterMode(Creature.Physics.Velocity.Y > 0 ? CharacterMode.Jumping : CharacterMode.Falling);
                    yield return(Status.Running);
                }

                SetAgentTranslation(dest);

                break;
            }

            case MoveType.HighJump:
            {
                CleanupMinecart();
                Creature.NoiseMaker.MakeNoise("Jump", Agent.Position, false);

                var dest  = GetPathPoint(Step.DestinationVoxel);
                var above = VoxelHelpers.GetVoxelAbove(Step.SourceVoxel);
                if (above.IsValid && !above.IsEmpty)
                {
                    yield return(Status.Fail);
                }

                foreach (var bit in Jump(Agent.Position, dest, dest - Agent.Position, actionSpeed / 2.0f, 1.5f))
                {
                    Creature.Physics.CollisionType = CollisionType.None;
                    Creature.OverrideCharacterMode = false;
                    SetCharacterMode(Creature.Physics.Velocity.Y > 0 ? CharacterMode.Jumping : CharacterMode.Falling);
                    yield return(Status.Running);
                }

                SetAgentTranslation(dest);

                break;
            }

            case MoveType.Fall:

                CleanupMinecart();

                foreach (var bit in Translate(Agent.Position, GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    SetCharacterMode(CharacterMode.Falling);
                    yield return(Status.Running);
                }

                break;

            case MoveType.Climb:

                CleanupMinecart();

                DeltaTime = 0.0f;
                foreach (var bit in Translate(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    if (Step.InteractObject == null || Step.InteractObject.IsDead)
                    {
                        yield return(Status.Fail);
                    }

                    if (DeltaTime - LastNoiseTime > 1.0f)
                    {
                        Creature.NoiseMaker.MakeNoise("Climb", Agent.Position, false);
                        LastNoiseTime = DeltaTime;
                    }

                    SetCharacterMode(CharacterMode.Climbing);
                    yield return(Status.Running);
                }

                break;

            case MoveType.ClimbWalls:

                CleanupMinecart();

                DeltaTime = 0.0f;
                foreach (var bit in Translate(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    if (DeltaTime - LastNoiseTime > 1.0f)
                    {
                        Creature.NoiseMaker.MakeNoise("Climb", Agent.Position, false);
                        LastNoiseTime = DeltaTime;
                    }

                    SetCharacterMode(CharacterMode.Climbing);

                    if (Step.ActionVoxel.IsValid)
                    {
                        var voxelVector = new Vector3(Step.ActionVoxel.Coordinate.X + 0.5f, Agent.Physics.Position.Y, Step.ActionVoxel.Coordinate.Z + 0.5f);
                        Agent.Physics.Velocity = Vector3.Normalize(voxelVector - Agent.Physics.Position) * actionSpeed;
                    }

                    yield return(Status.Running);
                }

                break;

            case MoveType.Fly:

                CleanupMinecart();

                DeltaTime = 0.0f;
                foreach (var bit in Translate(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), actionSpeed))
                {
                    if ((int)(DeltaTime * 100) % 2 == 0)
                    {
                        Creature.NoiseMaker.MakeNoise("Flap", Agent.Position, false);
                    }
                    SetCharacterMode(CharacterMode.Flying);

                    yield return(Status.Running);
                }

                break;

            case MoveType.Dig:

                CleanupMinecart();

                var destroy = new DigAct(Creature.AI, new KillVoxelTask(Step.DestinationVoxel))
                {
                    CheckOwnership = false
                };
                destroy.Initialize();
                foreach (var status in destroy.Run())
                {
                    if (status == Act.Status.Fail)
                    {
                        yield return(Act.Status.Fail);
                    }
                    yield return(Act.Status.Running);
                }
                yield return(Act.Status.Fail);    // Abort the path so that they stop digging if a path has opened.

                break;

            case MoveType.DestroyObject:

                CleanupMinecart();

                var melee = new AttackAct(Creature.AI, (GameComponent)Step.InteractObject);
                melee.Initialize();
                foreach (var status in melee.Run())
                {
                    if (status == Act.Status.Fail)
                    {
                        yield return(Act.Status.Fail);
                    }
                    yield return(Act.Status.Running);
                }
                yield return(Act.Status.Fail);    // Abort the path so that they stop destroying things if a path has opened.

                break;

            case MoveType.Teleport:

                CleanupMinecart();

                if (Step.InteractObject == null || Step.InteractObject.IsDead)
                {
                    yield return(Status.Fail);
                }

                if (Step.InteractObject.GetComponent <MagicalObject>().HasValue(out var teleporter))
                {
                    teleporter.CurrentCharges--;
                }

                SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_ic_dwarf_magic_research, Agent.Position, true, 1.0f);
                Agent.World.ParticleManager.Trigger("green_flame", (Step.InteractObject as GameComponent).Position, Color.White, 1);
                //Agent.GetRoot().SetFlagRecursive(GameComponent.Flag.Visible, false);

                {
                    var source = GetPathPoint(Step.SourceVoxel);
                    var dest   = GetPathPoint(Step.DestinationVoxel);
                    var delta  = dest - source;
                    var steps  = delta.Length() * 2.0f;
                    delta.Normalize();
                    delta *= 0.5f;

                    for (var i = 0; i <= steps; ++i)
                    {
                        Agent.World.ParticleManager.Trigger("star_particle", source, Color.White, 1);
                        source += delta;
                    }
                }

                //foreach (var bit in Translate(GetPathPoint(Step.SourceVoxel), GetPathPoint(Step.DestinationVoxel), actionSpeed))
                //{
                //    Agent.World.ParticleManager.Trigger("star_particle", Agent.Position, Color.White, 1);
                //    yield return Status.Running;
                //}

                SetAgentTranslation(GetPathPoint(Step.DestinationVoxel));
                //Agent.GetRoot().SetFlagRecursive(GameComponent.Flag.Visible, true);
                yield return(Status.Running);

                break;
            }
        }
Пример #2
0
        public IEnumerable <Status> PerformCurrentAction()
        {
            MoveAction action       = Path.First();
            float      t            = 0;
            int        currentIndex = 0;

            if (!GetCurrentAction(ref action, ref t, ref currentIndex))
            {
                CleanupMinecart();
                yield break;
            }
            //Trace.Assert(t >= 0);
            Trace.Assert(action.SourceVoxel.IsValid);
            int     nextID        = currentIndex + 1;
            bool    hasNextAction = false;
            Vector3 half          = GetBoundingBoxOffset();
            Vector3 nextPosition  = Vector3.Zero;
            Vector3 currPosition  = action.SourceVoxel.WorldPosition + half;

            currPosition += RandomPositionOffsets[currentIndex];
            if (nextID < Path.Count)
            {
                hasNextAction = true;
                nextPosition  = Path[nextID].SourceVoxel.WorldPosition;
                nextPosition += RandomPositionOffsets[nextID] + half;
            }
            else
            {
                hasNextAction = true;
                nextPosition  = action.DestinationVoxel.WorldPosition + half;
            }

            Matrix  transform = Agent.Physics.LocalTransform;
            Vector3 diff      = (nextPosition - currPosition);

            Agent.GetRoot().SetFlag(GameComponent.Flag.Visible, true);
            switch (action.MoveType)
            {
            case MoveType.EnterVehicle:
                if (t < 0.5f)
                {
                    Creature.NoiseMaker.MakeNoise("Jump", Agent.Position, false);
                }
                Creature.OverrideCharacterMode = false;
                Creature.CurrentCharacterMode  = Creature.Physics.Velocity.Y > 0
                        ? CharacterMode.Jumping
                        : CharacterMode.Falling;
                if (hasNextAction)
                {
                    float   z     = Easing.Ballistic(t, 1.0f, 1.0f);
                    Vector3 start = currPosition;
                    Vector3 end   = nextPosition + Vector3.Up * 0.5f;
                    Vector3 dx    = (end - start) * t + start;
                    dx.Y = start.Y * (1 - t) + end.Y * (t) + z;
                    transform.Translation  = dx;
                    Agent.Physics.Velocity = new Vector3(diff.X, (dx.Y - Agent.Physics.Position.Y), diff.Z);
                }
                else
                {
                    transform.Translation = currPosition;
                }
                if (t > 0.9f)
                {
                    SetupMinecart();
                }

                break;

            case MoveType.ExitVehicle:
                CleanupMinecart();
                transform.Translation = currPosition;
                break;

            case MoveType.RideVehicle:
                SetupMinecart();
                Creature.CurrentCharacterMode = CharacterMode.Minecart;
                var rail = action.SourceState.VehicleState.Rail;
                if (rail == null)
                {
                    if (hasNextAction)
                    {
                        transform.Translation  = diff * t + currPosition;
                        Agent.Physics.Velocity = diff;
                    }
                    else
                    {
                        transform.Translation = currPosition;
                    }
                }
                else
                {
                    //Drawer3D.DrawBox(rail.GetContainingVoxel().GetBoundingBox(), Color.Green, 0.1f, true);
                    var pos = rail.InterpolateSpline(t, action.SourceVoxel.WorldPosition + Vector3.One * 0.5f, action.DestinationVoxel.WorldPosition + Vector3.One * 0.5f);
                    transform.Translation  = pos + Vector3.Up * 0.5f;
                    Agent.Physics.Velocity = diff;
                }
                break;

            case MoveType.Walk:
                CleanupMinecart();
                Creature.OverrideCharacterMode = false;
                Creature.CurrentCharacterMode  = CharacterMode.Walking;
                if (hasNextAction)
                {
                    transform.Translation  = diff * t + currPosition;
                    Agent.Physics.Velocity = diff;
                }
                else
                {
                    transform.Translation = currPosition;
                }
                break;

            case MoveType.Swim:
                CleanupMinecart();
                Creature.NoiseMaker.MakeNoise("Swim", Agent.Position, true);
                Creature.OverrideCharacterMode = false;
                Creature.CurrentCharacterMode  = CharacterMode.Swimming;
                if (hasNextAction)
                {
                    transform.Translation  = diff * t + currPosition;
                    Agent.Physics.Velocity = diff;
                }
                else
                {
                    transform.Translation = currPosition;
                }
                break;

            case MoveType.Jump:
                CleanupMinecart();
                if (t < 0.5f)
                {
                    Creature.NoiseMaker.MakeNoise("Jump", Agent.Position, false);
                }
                Creature.OverrideCharacterMode = false;
                Creature.CurrentCharacterMode  = Creature.Physics.Velocity.Y > 0
                        ? CharacterMode.Jumping
                        : CharacterMode.Falling;
                if (hasNextAction)
                {
                    float   z     = Easing.Ballistic(t, 1.0f, 1.0f);
                    Vector3 start = currPosition;
                    Vector3 end   = nextPosition;
                    Vector3 dx    = (end - start) * t + start;
                    dx.Y = start.Y * (1 - t) + end.Y * (t) + z;
                    transform.Translation  = dx;
                    Agent.Physics.Velocity = new Vector3(diff.X, (dx.Y - Agent.Physics.Position.Y), diff.Z);
                }
                else
                {
                    transform.Translation = currPosition;
                }
                break;

            case MoveType.Fall:
                CleanupMinecart();
                Creature.OverrideCharacterMode = false;
                Creature.CurrentCharacterMode  = CharacterMode.Falling;
                if (hasNextAction)
                {
                    transform.Translation  = diff * t + currPosition;
                    Agent.Physics.Velocity = diff;
                }
                else
                {
                    transform.Translation = currPosition;
                }
                break;

            case MoveType.Climb:
            case MoveType.ClimbWalls:
                CleanupMinecart();
                if (((int)((t + 1) * 100)) % 50 == 0)
                {
                    Creature.NoiseMaker.MakeNoise("Climb", Agent.Position, false);
                }
                Creature.OverrideCharacterMode = false;
                Creature.CurrentCharacterMode  = CharacterMode.Climbing;
                Creature.OverrideCharacterMode = true;
                if (hasNextAction)
                {
                    if (action.MoveType == MoveType.ClimbWalls && action.ActionVoxel.IsValid)
                    {
                        Agent.Physics.Velocity = (action.DestinationVoxel.WorldPosition + Vector3.One * 0.5f) - currPosition;
                        transform.Translation  = diff * t + currPosition;
                    }
                    else if (action.MoveType == MoveType.Climb && action.InteractObject != null)
                    {
                        var ladderPosition = action.InteractObject.GetRoot().GetComponent <Body>().Position;
                        transform.Translation  = diff * t + currPosition;
                        Agent.Physics.Velocity = ladderPosition - currPosition;
                    }
                }
                else
                {
                    transform.Translation = currPosition;
                }
                break;

            case MoveType.Fly:
                CleanupMinecart();
                if (((int)((t + 1) * 100)) % 2 == 0)
                {
                    Creature.NoiseMaker.MakeNoise("Flap", Agent.Position, false);
                }
                Creature.OverrideCharacterMode = false;
                Creature.CurrentCharacterMode  = CharacterMode.Flying;
                Creature.OverrideCharacterMode = true;
                if (hasNextAction)
                {
                    transform.Translation  = diff * t + currPosition;
                    Agent.Physics.Velocity = diff;
                }
                else
                {
                    transform.Translation = currPosition;
                }
                break;

            case MoveType.Dig:
                CleanupMinecart();
                var destroy = new DigAct(Creature.AI, new KillVoxelTask(action.DestinationVoxel))
                {
                    CheckOwnership = false
                };
                destroy.Initialize();
                foreach (var status in destroy.Run())
                {
                    if (status == Act.Status.Fail)
                    {
                        yield return(Act.Status.Fail);
                    }
                    yield return(Act.Status.Running);
                }
                yield return(Act.Status.Fail);

                yield break;

            case MoveType.DestroyObject:
                CleanupMinecart();
                var melee = new MeleeAct(Creature.AI, (Body)action.InteractObject);
                melee.Initialize();
                foreach (var status in melee.Run())
                {
                    if (status == Act.Status.Fail)
                    {
                        yield return(Act.Status.Fail);
                    }
                    yield return(Act.Status.Running);
                }
                yield return(Act.Status.Success);

                yield break;

            case MoveType.Teleport:
                if (lastMovement != MoveType.Teleport)
                {
                    if (action.InteractObject != null)
                    {
                        var teleporter = action.InteractObject.GetComponent <MagicalObject>();
                        if (teleporter != null)
                        {
                            teleporter.CurrentCharges--;
                        }
                    }
                    SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_ic_dwarf_magic_research, currPosition, true, 1.0f);
                }
                Agent.GetRoot().SetFlagRecursive(GameComponent.Flag.Visible, false);
                Agent.World.ParticleManager.Trigger("star_particle", diff * t + currPosition, Color.White, 1);
                if (action.InteractObject != null)
                {
                    Agent.World.ParticleManager.Trigger("green_flame", (action.InteractObject as Body).Position, Color.White, 1);
                }
                transform.Translation = action.DestinationVoxel.WorldPosition + Vector3.One * 0.5f;
                break;
            }

            Agent.Physics.LocalTransform = transform;
            lastMovement = action.MoveType;
        }