Пример #1
0
        private void updateMaterial()
        {
            if (!this.main.EditorEnabled)
            {
                DynamicVoxel map = this.Entity.Get <DynamicVoxel>();
                if (map != null)
                {
                    bool active = this.Locked && (!this.Servo || (this.Servo && this.Goal.Value != this.Minimum.Value));

                    Voxel.State desired   = active ? Voxel.States.SliderPowered : Voxel.States.Slider;
                    Voxel.t     currentID = map[0, 0, 0].ID;
                    if (currentID != desired.ID & (currentID == Voxel.t.Slider || currentID == Voxel.t.SliderPowered))
                    {
                        List <Voxel.Coord> coords = map.GetContiguousByType(new[] { map.GetBox(0, 0, 0) }).SelectMany(x => x.GetCoords()).ToList();
                        map.Empty(coords, true, true, null, false);
                        foreach (Voxel.Coord c in coords)
                        {
                            map.Fill(c, desired);
                        }
                        map.Regenerate();
                    }
                    map.PhysicsEntity.ActivityInformation.Activate();
                }
            }
        }
Пример #2
0
 private static bool canConnect(Voxel.State state)
 {
     return(state == Voxel.States.Powered ||
            state == Voxel.States.HardPowered ||
            state == Voxel.States.PoweredSwitch ||
            state == Voxel.States.Blue ||
            state == Voxel.States.Neutral ||
            state == Voxel.States.Switch ||
            state == Voxel.States.Hard);
 }
Пример #3
0
 public override Voxel.State Apply(int x, int y, Voxel.State voxel)
 {
     x -= centerX;
     y -= centerY;
     if (x * x + y * y <= sqrRadius)
     {
         return(fillType);
     }
     return(voxel);
 }
Пример #4
0
 private bool canBuild(Voxel.State s)
 {
     return(s != Voxel.States.Blue &&
            s != Voxel.States.Powered &&
            s != Voxel.States.Infected &&
            s != Voxel.States.HardInfected &&
            s != Voxel.States.SliderPowered &&
            s != Voxel.States.Slider &&
            s != Voxel.States.SocketBlue &&
            s != Voxel.States.SocketWhite &&
            s != Voxel.States.SocketYellow);
 }
Пример #5
0
        public void Implode(Main main, Voxel v, Voxel.Coord coord, Voxel.State state, Vector3 target)
        {
            Entity       block        = this.CreateAndBind(main);
            ImplodeBlock implodeBlock = block.Get <ImplodeBlock>();

            state.ApplyToEffectBlock(block.Get <ModelInstance>());
            implodeBlock.Offset.Value = v.GetRelativePosition(coord);

            implodeBlock.StateId          = state.ID;
            implodeBlock.StartPosition    = v.GetAbsolutePosition(coord);
            implodeBlock.Type             = Rift.Style.In;
            implodeBlock.StartOrientation = Quaternion.CreateFromRotationMatrix(v.Transform);
            implodeBlock.EndOrientation   = Quaternion.CreateFromYawPitchRoll((float)this.random.NextDouble() * (float)Math.PI * 2.0f, (float)this.random.NextDouble() * (float)Math.PI * 2.0f, 0.0f);
            implodeBlock.EndPosition      = target;
            main.Add(block);
        }
Пример #6
0
        private void set()
        {
            Entity voxelEntity = this.AttachedVoxel.Value.Target;

            if (voxelEntity == null)
            {
                return;
            }

            Voxel map = voxelEntity.Get <Voxel>();

            if (map == null)
            {
                return;
            }

            Voxel.State state = Voxel.States.All[this.State];
            if (this.Contiguous)
            {
                lock (map.MutationLock)
                {
                    Voxel.Box b = map.GetBox(this.Coord);
                    if (b != null && b.Type != state)
                    {
                        List <Voxel.Coord> coords = map.GetContiguousByType(new[] { b }).SelectMany(x => x.GetCoords()).Select(x => x.WithData(state)).ToList();
                        map.Empty(coords, true, true, map);
                        map.Fill(coords, true, map);
                        map.Regenerate();
                    }
                }
            }
            else
            {
                lock (map.MutationLock)
                {
                    if (map[this.Coord] != state)
                    {
                        map.Empty(this.Coord, true, true, map);
                        map.Fill(this.Coord, state, true, map);
                        map.Regenerate();
                    }
                }
            }
            this.OnSet.Execute();
        }
Пример #7
0
        private bool determineShouldBuildFloor(Voxel v, Voxel.State floorState)
        {
            bool result = false;

            if (floorState == Voxel.States.Blue || floorState == Voxel.States.Powered)
            {
                // If we're standing on blue or powered, we need to check if we're close to a non-blue block before we can build a floor
                // This prevents the player from building a floor infinitely
                if (VoxelAStar.BroadphaseSearch(this.floorMap, this.floorCoordinate, 6, x => x.Type != Voxel.States.Blue && x.Type != Voxel.States.Powered) != null)
                {
                    result = true;
                }
            }
            else if (v == null || v.Entity.Type != "Bouncer")
            {
                result = true;
            }
            return(result);
        }
Пример #8
0
        public override void Awake()
        {
            base.Awake();

            this.Add(new CommandBinding(this.Set, delegate()
            {
                Entity voxelEntity = this.AttachedVoxel.Value.Target;
                if (voxelEntity == null)
                {
                    return;
                }

                Voxel map         = voxelEntity.Get <Voxel>();
                Voxel.State state = Voxel.States.All[this.State];
                if (this.Contiguous)
                {
                    Voxel.Box b = map.GetBox(this.Coord);
                    if (b != null && b.Type != state)
                    {
                        List <Voxel.Coord> coords = map.GetContiguousByType(new[] { b }).SelectMany(x => x.GetCoords()).Select(x => x.WithData(state)).ToList();
                        lock (map.MutationLock)
                        {
                            map.Empty(coords, true, true);
                            map.Fill(coords);
                        }
                        map.Regenerate();
                    }
                }
                else
                {
                    if (map[this.Coord] != state)
                    {
                        lock (map.MutationLock)
                        {
                            map.Empty(this.Coord, true, true);
                            map.Fill(this.Coord, state);
                        }
                        map.Regenerate();
                    }
                }
            }));
        }
Пример #9
0
        private static void explode(Main main, Voxel map, Voxel.Coord coord, Vector3 pos, int radius, float physicsRadius)
        {
            float distanceToCamera = (main.Camera.Position.Value - pos).Length();

            // Kaboom
            Sound.PostEvent(distanceToCamera < physicsRadius * 1.5f ? AK.EVENTS.PLAY_EXPLOSION_CLOSE : AK.EVENTS.PLAY_EXPLOSION, pos);

            Entity lightEntity = Factory.Get <PointLightFactory>().CreateAndBind(main);

            lightEntity.Serialize = false;
            PointLight light = lightEntity.Get <PointLight>();

            light.Color.Value       = new Vector3(1.3f, 1.1f, 0.9f);
            light.Attenuation.Value = 20.0f;
            light.Position.Value    = pos;
            lightEntity.Add(new Animation
                            (
                                new Animation.FloatMoveTo(light.Attenuation, 0.0f, 1.0f),
                                new Animation.Execute(light.Delete)
                            ));
            main.Add(lightEntity);

            SmokeFactory smokeFactory = Factory.Get <SmokeFactory>();

            for (int i = 0; i < 5; i++)
            {
                Entity smoke = smokeFactory.CreateAndBind(main);
                smoke.Get <Transform>().Position.Value = pos;
                main.Add(smoke);
            }

            ParticleEmitter.Emit(main, "Smoke", pos, physicsRadius * 0.4f, 250);

            Entity player = PlayerFactory.Instance;

            if (player != null && player.Active)
            {
                player.Get <CameraController>().Shake.Execute(pos, 50.0f);
            }

            const float physicsImpulse         = 70.0f;
            const float minPlayerDamage        = 0.1f;
            const float playerDamageMultiplier = 2.0f;

            // Remove the cells
            BlockFactory blockFactory = Factory.Get <BlockFactory>();

            foreach (Voxel m in Voxel.ActiveVoxels.ToList())
            {
                List <Voxel.Coord> removals = new List <Voxel.Coord>();

                Voxel.Coord c           = m.GetCoordinate(pos);
                Vector3     relativePos = m.GetRelativePosition(c);

                Quaternion quat = m.Entity.Get <Transform>().Quaternion;

                for (Voxel.Coord x = c.Move(Direction.NegativeX, radius - 1); x.X < c.X + radius; x.X++)
                {
                    for (Voxel.Coord y = x.Move(Direction.NegativeY, radius - 1); y.Y < c.Y + radius; y.Y++)
                    {
                        for (Voxel.Coord z = y.Move(Direction.NegativeZ, radius - 1); z.Z < c.Z + radius; z.Z++)
                        {
                            Voxel.State s = m[z];
                            if (s.ID == 0 || s.Permanent)
                            {
                                continue;
                            }

                            Vector3 cellPos = m.GetRelativePosition(z);
                            if ((cellPos - relativePos).Length() < radius - 1)
                            {
                                removals.Add(z);
                                if (random.NextDouble() > 0.5)
                                {
                                    Entity    block          = blockFactory.CreateAndBind(main);
                                    Transform blockTransform = block.Get <Transform>();
                                    blockTransform.Position.Value   = m.GetAbsolutePosition(cellPos);
                                    blockTransform.Quaternion.Value = Quaternion.CreateFromYawPitchRoll(((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI, ((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI, ((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI);
                                    s.ApplyToBlock(block);
                                    main.Add(block);
                                }
                            }
                        }
                    }
                }
                if (removals.Count > 0)
                {
                    m.Empty(removals);
                    m.Regenerate();
                }
            }

            // Damage the player
            if (player != null && player.Active)
            {
                Vector3 toPlayer = player.Get <Transform>().Position - pos;
                float   d        = toPlayer.Length();
                if (d < physicsRadius)
                {
                    float attenuation = 1.0f;
                    if (d > 0)
                    {
                        Voxel.GlobalRaycast(pos, toPlayer / d, d, delegate(int x, Voxel.t c)
                        {
                            Voxel.State s = Voxel.States.All[c];
                            if (s.Permanent)
                            {
                                attenuation = 0.0f;
                                return(true);
                            }
                            else if (s.Hard)
                            {
                                attenuation -= 0.6f;
                            }
                            else
                            {
                                attenuation -= 0.35f;
                            }
                            return(false);
                        });
                        attenuation = Math.Max(0, attenuation);
                    }
                    player.Get <Agent>().Damage.Execute(attenuation * (minPlayerDamage + (1.0f - (d / physicsRadius)) * playerDamageMultiplier));
                }
            }

            // Apply impulse to dynamic maps
            foreach (Voxel m in Voxel.ActiveVoxels)
            {
                DynamicVoxel dm = m as DynamicVoxel;
                if (dm == null)
                {
                    continue;
                }

                Vector3 toMap         = dm.Transform.Value.Translation - pos;
                float   distanceToMap = toMap.Length();
                toMap /= distanceToMap;

                toMap *= Math.Max(0.0f, 1.0f - (distanceToMap / physicsRadius)) * Math.Min(200.0f, dm.PhysicsEntity.Mass) * physicsImpulse;

                dm.PhysicsEntity.ApplyImpulse(dm.Transform.Value.Translation + new Vector3(((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f), toMap);
            }

            // Apply impulse to physics blocks
            foreach (Entity b in main.Get("Block"))
            {
                PhysicsBlock block         = b.Get <PhysicsBlock>();
                Vector3      fromExplosion = b.Get <Transform>().Position.Value - pos;
                float        distance      = fromExplosion.Length();
                if (distance > 0.0f && distance < physicsRadius)
                {
                    float blend = 1.0f - (distance / physicsRadius);
                    block.Box.LinearVelocity  += fromExplosion * blend * 10.0f / distance;
                    block.Box.AngularVelocity += new Vector3(((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f) * blend;
                }
            }
        }
Пример #10
0
        public bool Go()
        {
            if (this.main.TotalTime - this.LastJump < jumpCoolDown || this.Crouched)
            {
                return(false);
            }

            bool supported = this.IsSupported;

            WallRun.State wallRunState = this.WallRunState;

            Matrix  rotationMatrix = Matrix.CreateRotationY(this.Rotation);
            Vector3 forward        = -rotationMatrix.Forward;

            Vector2 jumpDirection = this.AbsoluteMovementDirection;

            Vector3 baseVelocity = Vector3.Zero;

            bool wallJumping = false;

            const float wallJumpHorizontalVelocityAmount = 0.75f;
            const float wallJumpDistance = 2.0f;

            Action <Voxel, Direction, Voxel.Coord> wallJump = delegate(Voxel wallJumpMap, Direction wallNormalDirection, Voxel.Coord wallCoordinate)
            {
                this.LastWallRunMap.Value    = wallJumpMap;
                this.LastWallDirection.Value = wallNormalDirection.GetReverse();
                this.LastWallJump.Value      = main.TotalTime;

                Voxel.State wallType = wallJumpMap[wallCoordinate];
                if (wallType == Voxel.States.Empty)                 // Empty. Must be a block possibility that hasn't been instantiated yet
                {
                    wallType = Voxel.States.Blue;
                }

                this.WalkedOn.Execute(wallJumpMap, wallCoordinate, wallNormalDirection.GetReverse());

                AkSoundEngine.PostEvent(AK.EVENTS.FOOTSTEP_PLAY, this.Entity);

                wallJumping = true;
                // Set up wall jump velocity
                Vector3 absoluteWallNormal = wallJumpMap.GetAbsoluteVector(wallNormalDirection.GetVector());
                Vector2 wallNormal2        = new Vector2(absoluteWallNormal.X, absoluteWallNormal.Z);
                wallNormal2.Normalize();

                bool wallRunningStraight = wallRunState == WallRun.State.Straight || wallRunState == WallRun.State.Down;
                if (wallRunningStraight)
                {
                    jumpDirection = new Vector2(main.Camera.Forward.Value.X, main.Camera.Forward.Value.Z);
                }
                else
                {
                    jumpDirection = new Vector2(forward.X, forward.Z);
                }

                jumpDirection.Normalize();

                float dot = Vector2.Dot(wallNormal2, jumpDirection);
                if (dot < 0)
                {
                    jumpDirection = jumpDirection - (2.0f * dot * wallNormal2);
                }
                jumpDirection *= wallJumpHorizontalVelocityAmount;

                if (!wallRunningStraight && Math.Abs(dot) < 0.5f)
                {
                    // If we're jumping perpendicular to the wall, add some velocity so we jump away from the wall a bit
                    jumpDirection += wallJumpHorizontalVelocityAmount * 0.75f * wallNormal2;
                }

                Vector3 supportLocation = this.FloorPosition;
                baseVelocity += wallJumpMap.LinearVelocity + Vector3.Cross(wallJumpMap.AngularVelocity, supportLocation - wallJumpMap.Transform.Value.Translation);
            };

            if (!supported && wallRunState == WallRun.State.None &&
                this.LinearVelocity.Value.Y > Lemma.Components.FallDamage.DamageVelocity * 1.5f)
            {
                // We're not doing our normal jump, and not wall-runnign
                // See if we can wall-jump
                Vector3 playerPos = this.Position;
                Voxel.GlobalRaycastResult?closestWallRaycastHit = null;
                Vector3 closestWallRaycastDirection             = Vector3.Zero;

                foreach (Vector3 dir in new[] { rotationMatrix.Left, rotationMatrix.Right, rotationMatrix.Backward, rotationMatrix.Forward })
                {
                    Voxel.GlobalRaycastResult hit = Voxel.GlobalRaycast(playerPos, dir, wallJumpDistance);
                    if (hit.Voxel != null && (!closestWallRaycastHit.HasValue || hit.Distance < closestWallRaycastHit.Value.Distance))
                    {
                        closestWallRaycastDirection = dir;
                        closestWallRaycastHit       = hit;
                    }
                }

                if (closestWallRaycastHit != null)
                {
                    Voxel m = closestWallRaycastHit.Value.Voxel;
                    wallJump(m, closestWallRaycastHit.Value.Normal, closestWallRaycastHit.Value.Coordinate.Value);
                }
            }

            // If we're wall-running, we can wall-jump
            // Add some velocity so we jump away from the wall a bit
            if (wallRunState != WallRun.State.None)
            {
                Vector3     pos       = this.FloorPosition + new Vector3(0, 0.5f, 0);
                Voxel.Coord wallCoord = this.WallRunMap.Value.GetCoordinate(pos).Move(this.WallDirection, 2);
                wallJump(this.WallRunMap, this.WallDirection.Value.GetReverse(), wallCoord);
            }

            bool go = supported || wallJumping;

            BlockPredictor.Possibility instantiatedBlockPossibility = null;
            Voxel.Coord instantiatedBlockPossibilityCoord           = default(Voxel.Coord);

            if (!go)
            {
                // Check block possibilities beneath us
                Vector3 jumpPos = this.FloorPosition + new Vector3(0, -1.0f, 0);
                foreach (BlockPredictor.Possibility possibility in this.Predictor.AllPossibilities)
                {
                    Voxel.Coord possibilityCoord = possibility.Map.GetCoordinate(jumpPos);
                    if (possibilityCoord.Between(possibility.StartCoord, possibility.EndCoord) &&
                        !possibility.Map.GetCoordinate(jumpPos + new Vector3(2.0f)).Between(possibility.StartCoord, possibility.EndCoord))
                    {
                        this.Predictor.InstantiatePossibility(possibility);
                        go = true;
                        instantiatedBlockPossibility      = possibility;
                        instantiatedBlockPossibilityCoord = possibilityCoord;
                        break;
                    }
                }
            }

            if (!go)
            {
                // Check block possibilities for wall jumping
                Vector3   playerPos          = this.Position;
                Vector3[] wallJumpDirections = new[] { rotationMatrix.Left, rotationMatrix.Right, rotationMatrix.Forward };
                foreach (BlockPredictor.Possibility possibility in this.Predictor.AllPossibilities)
                {
                    foreach (Vector3 dir in wallJumpDirections)
                    {
                        foreach (Voxel.Coord coord in possibility.Map.Rasterize(playerPos, playerPos + (dir * wallJumpDistance)))
                        {
                            if (coord.Between(possibility.StartCoord, possibility.EndCoord))
                            {
                                this.Predictor.InstantiatePossibility(possibility);
                                instantiatedBlockPossibility      = possibility;
                                instantiatedBlockPossibilityCoord = coord;
                                wallJump(possibility.Map, possibility.Map.GetRelativeDirection(dir).GetReverse(), coord);
                                wallJumping = true;
                                go          = true;
                                break;
                            }
                        }
                        if (wallJumping)
                        {
                            break;
                        }
                    }
                    if (wallJumping)
                    {
                        break;
                    }
                }
            }

            if (go)
            {
                float totalMultiplier = 1.0f;

                bool grunted = false;

                if (wallJumping)
                {
                    if (this.wallJumpCount == 0)
                    {
                        this.wallJumpChainStart = this.Position;
                    }
                    else
                    {
                        Vector3 chainDistance = this.Position - this.wallJumpChainStart;
                        chainDistance.Y = 0.0f;
                        if (chainDistance.Length() > 6.0f)
                        {
                            this.wallJumpCount      = 0;
                            this.wallJumpChainStart = this.Position;
                        }
                    }

                    if (this.wallJumpCount > 3)
                    {
                        return(false);
                    }
                    totalMultiplier = 1.0f - Math.Min(1.0f, this.wallJumpCount / 8.0f);
                    this.wallJumpCount++;
                }
                else
                {
                    // Regular jump
                    // Take base velocity into account
                    baseVelocity += this.SupportVelocity;

                    grunted = this.FallDamage.ApplyJump();
                    if (!this.Active)                     // We got killed by fall damage
                    {
                        return(false);
                    }
                    if (instantiatedBlockPossibility != null)
                    {
                        this.WalkedOn.Execute(instantiatedBlockPossibility.Map, instantiatedBlockPossibilityCoord, instantiatedBlockPossibility.Map.GetRelativeDirection(Direction.NegativeY));
                    }

                    // Also manually reset our ability to kick and wall-jump
                    this.CanKick.Value = true;
                    this.wallJumpCount = 0;
                }

                Vector3 velocity             = this.LinearVelocity - baseVelocity;
                float   currentVerticalSpeed = velocity.Y;
                velocity.Y = 0.0f;
                float jumpSpeed = jumpDirection.Length();
                if (jumpSpeed > 0)
                {
                    jumpDirection *= (wallJumping ? Math.Max(this.MaxSpeed, Vector3.Dot(forward, velocity)) : velocity.Length()) / jumpSpeed;
                }

                if (main.TotalTime - this.LastRollKickEnded < 0.3f)
                {
                    totalMultiplier *= 1.2f;
                }

                float verticalJumpSpeed = this.JumpSpeed;

                // If we're not instantiating a block possibility beneath us or we're not currently falling, incorporate some of our existing vertical velocity in our jump
                if (instantiatedBlockPossibility == null || wallJumping || currentVerticalSpeed > 0.0f)
                {
                    verticalJumpSpeed += currentVerticalSpeed * 0.5f;
                }

                this.LinearVelocity.Value = baseVelocity + new Vector3(jumpDirection.X, verticalJumpSpeed, jumpDirection.Y) * totalMultiplier;

                velocity   = this.LinearVelocity;
                velocity.Y = 0.0f;
                this.LastSupportedSpeed.Value = velocity.Length();

                if (supported && this.SupportEntity.Value != null)
                {
                    Vector3 impulsePosition = this.FloorPosition;
                    Vector3 impulse         = this.LinearVelocity.Value * this.Mass * -1.0f;
                    this.SupportEntity.Value.ApplyImpulse(ref impulsePosition, ref impulse);
                }

                Session.Recorder.Event(main, "Jump");

                this.IsSupported.Value   = false;
                this.SupportEntity.Value = null;
                this.HasTraction.Value   = false;

                AkSoundEngine.PostEvent(AK.EVENTS.PLAY_PLAYER_JUMP, this.Entity);
                if (!grunted && (float)this.random.NextDouble() < 0.15f)
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_PLAYER_LAND, this.Entity);                     // Grunt
                }
                this.model.Stop
                (
                    "Vault",
                    "Mantle",
                    "TopOut",
                    "Jump",
                    "Jump02",
                    "Jump03",
                    "JumpLeft",
                    "JumpRight",
                    "JumpBackward"
                );

                velocity   = -Vector3.TransformNormal(this.LinearVelocity, Matrix.CreateRotationY(-this.Rotation));
                velocity.Y = 0.0f;
                if (wallRunState == WallRun.State.Left || wallRunState == WallRun.State.Right)
                {
                    velocity.Z = 0.0f;
                }
                else if (wallJumping)
                {
                    velocity.Z *= 0.5f;
                }
                else
                {
                    velocity.X = 0.0f;
                }
                Direction direction = DirectionExtensions.GetDirectionFromVector(velocity);
                string    animation;
                switch (direction)
                {
                case Direction.NegativeX:
                    animation = "JumpLeft";
                    break;

                case Direction.PositiveX:
                    animation = "JumpRight";
                    break;

                case Direction.PositiveZ:
                    animation = wallJumping ? "JumpBackward" : this.randomJumpAnimation();
                    break;

                default:
                    animation = this.randomJumpAnimation();
                    break;
                }
                this.model.StartClip(animation, 4, false);
                this.model[animation].CurrentTime = TimeSpan.FromSeconds(0.2);

                // Deactivate any wall-running we're doing
                this.DeactivateWallRun.Execute();

                // Play a footstep sound since we're jumping off the ground
                AkSoundEngine.PostEvent(AK.EVENTS.FOOTSTEP_PLAY, this.Entity);

                this.LastJump.Value = this.main.TotalTime;
                return(true);
            }

            return(false);
        }
Пример #11
0
 public virtual void Initialize(Voxel.State fillType, int radius)
 {
     this.fillType = fillType;
     this.radius = radius;
 }
Пример #12
0
        public bool BreakWalls(Vector3 forward, Vector3 right)
        {
            BlockFactory blockFactory = Factory.Get <BlockFactory>();
            Vector3      basePos      = this.Position + new Vector3(0, 0.2f + (this.Height * -0.5f) - this.SupportHeight, 0) + forward * -1.0f;
            bool         broke        = false;

            foreach (Voxel map in Voxel.ActivePhysicsVoxels.ToList())
            {
                List <Voxel.Coord> removals      = new List <Voxel.Coord>();
                Quaternion         mapQuaternion = Quaternion.CreateFromRotationMatrix(map.Transform);
                Voxel.Coord        top           = map.GetCoordinate(basePos + new Vector3(0, this.Height + this.SupportHeight + 0.5f, 0));
                Direction          upDir         = map.GetRelativeDirection(Vector3.Up);
                Direction          rightDir      = map.GetRelativeDirection(right);
                Direction          forwardDir    = map.GetRelativeDirection(forward);
                Voxel.Coord        center        = map.GetCoordinate(basePos);
                for (Voxel.Coord y = center.Clone(); y.GetComponent(upDir) <= top.GetComponent(upDir); y = y.Move(upDir))
                {
                    int minZ = center.GetComponent(rightDir) - 10;
                    int maxZ = minZ + 20;
                    foreach (Voxel.Coord x in this.spreadFromCenter(y, rightDir))
                    {
                        Voxel.Coord z = x.Clone();
                        for (int i = 0; i < 4; i++)
                        {
                            Voxel.State state           = map[z];
                            int         zRightDimension = z.GetComponent(rightDir);
                            if (zRightDimension > minZ && zRightDimension < maxZ && state.ID != 0 && !removals.Contains(z))
                            {
                                if (state.Permanent || state.Hard)
                                {
                                    if (zRightDimension >= center.GetComponent(rightDir))
                                    {
                                        maxZ = zRightDimension;
                                    }
                                    else
                                    {
                                        minZ = zRightDimension;
                                    }
                                    break;
                                }
                                else
                                {
                                    broke = true;
                                    removals.Add(z);
                                    Vector3   cellPos        = map.GetAbsolutePosition(z);
                                    Vector3   toCell         = cellPos - basePos;
                                    Entity    block          = blockFactory.CreateAndBind(this.main);
                                    Transform blockTransform = block.Get <Transform>();
                                    blockTransform.Position.Value   = cellPos;
                                    blockTransform.Quaternion.Value = mapQuaternion;
                                    state.ApplyToBlock(block);
                                    toCell += forward * 4.0f;
                                    toCell.Normalize();
                                    PhysicsBlock physicsBlock = block.Get <PhysicsBlock>();
                                    physicsBlock.LinearVelocity.Value  = toCell * 15.0f;
                                    physicsBlock.AngularVelocity.Value = new Vector3(((float)this.random.NextDouble() - 0.5f) * 2.0f, ((float)this.random.NextDouble() - 0.5f) * 2.0f, ((float)this.random.NextDouble() - 0.5f) * 2.0f);
                                    main.Add(block);
                                }
                            }
                            z = z.Move(forwardDir);
                        }
                    }
                }

                if (removals.Count > 0)
                {
                    map.Empty(removals);
                    map.Regenerate();
                }
            }
            return(broke);
        }
Пример #13
0
        public static bool Go(Voxel voxel, Voxel.Coord center, int radius, Action <List <DynamicVoxel> > callback = null)
        {
            if (!voxel[center].Permanent)
            {
                // Break off a chunk of this voxel into a new DynamicMap.

                List <Voxel.Coord> edges = new List <Voxel.Coord>();

                Voxel.Coord ripStart = center.Move(-radius, -radius, -radius);
                Voxel.Coord ripEnd   = center.Move(radius, radius, radius);

                Dictionary <Voxel.Box, bool> permanentBoxes = new Dictionary <Voxel.Box, bool>();
                foreach (Voxel.Coord c in ripStart.CoordinatesBetween(ripEnd))
                {
                    Voxel.Box box = voxel.GetBox(c);
                    if (box != null && box.Type.Permanent)
                    {
                        permanentBoxes[box] = true;
                    }
                }

                foreach (Voxel.Box b in permanentBoxes.Keys)
                {
                    // Top and bottom
                    for (int x = b.X - 1; x <= b.X + b.Width; x++)
                    {
                        for (int z = b.Z - 1; z <= b.Z + b.Depth; z++)
                        {
                            Voxel.Coord coord = new Voxel.Coord {
                                X = x, Y = b.Y + b.Height, Z = z
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }

                            coord = new Voxel.Coord {
                                X = x, Y = b.Y - 1, Z = z
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }
                        }
                    }

                    // Outer shell
                    for (int y = b.Y; y < b.Y + b.Height; y++)
                    {
                        // Left and right
                        for (int z = b.Z - 1; z <= b.Z + b.Depth; z++)
                        {
                            Voxel.Coord coord = new Voxel.Coord {
                                X = b.X - 1, Y = y, Z = z
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }

                            coord = new Voxel.Coord {
                                X = b.X + b.Width, Y = y, Z = z
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }
                        }

                        // Backward and forward
                        for (int x = b.X; x < b.X + b.Width; x++)
                        {
                            Voxel.Coord coord = new Voxel.Coord {
                                X = x, Y = y, Z = b.Z - 1
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }

                            coord = new Voxel.Coord {
                                X = x, Y = y, Z = b.Z + b.Depth
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }
                        }
                    }
                }

                if (edges.Contains(center))
                {
                    return(false);
                }

                // Top and bottom
                for (int x = ripStart.X; x <= ripEnd.X; x++)
                {
                    for (int z = ripStart.Z; z <= ripEnd.Z; z++)
                    {
                        Voxel.Coord c = new Voxel.Coord {
                            X = x, Y = ripStart.Y, Z = z
                        };
                        Voxel.State s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                        c = new Voxel.Coord {
                            X = x, Y = ripEnd.Y, Z = z
                        };
                        s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                    }
                }

                // Sides
                for (int y = ripStart.Y + 1; y <= ripEnd.Y - 1; y++)
                {
                    // Left and right
                    for (int z = ripStart.Z; z <= ripEnd.Z; z++)
                    {
                        Voxel.Coord c = new Voxel.Coord {
                            X = ripStart.X, Y = y, Z = z
                        };
                        Voxel.State s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                        c = new Voxel.Coord {
                            X = ripEnd.X, Y = y, Z = z
                        };
                        s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                    }

                    // Backward and forward
                    for (int x = ripStart.X; x <= ripEnd.X; x++)
                    {
                        Voxel.Coord c = new Voxel.Coord {
                            X = x, Y = y, Z = ripStart.Z
                        };
                        Voxel.State s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                        c = new Voxel.Coord {
                            X = x, Y = y, Z = ripEnd.Z
                        };
                        s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                    }
                }

                Propagator p = WorldFactory.Instance.Get <Propagator>();
                foreach (Voxel.Coord c in edges)
                {
                    p.SparksLowPriority(voxel.GetAbsolutePosition(c), Propagator.Spark.Dangerous);
                }

                voxel.Empty(edges);

                voxel.Regenerate(callback);
                return(true);
            }
            return(false);
        }
Пример #14
0
        // Function for finding a platform to build for the player
        public Possibility FindPlatform(Vector3 position)
        {
            int       shortestDistance = searchDistance;
            Direction relativeShortestDirection = Direction.None, absoluteShortestDirection = Direction.None;

            Voxel.Coord shortestCoordinate = new Voxel.Coord();
            Voxel       shortestMap        = null;

            EffectBlockFactory blockFactory = Factory.Get <EffectBlockFactory>();

            foreach (Voxel map in Voxel.ActivePhysicsVoxels)
            {
                if (!ignoreTypes.Contains(map.Entity.Type))
                {
                    List <Matrix> results             = new List <Matrix>();
                    Voxel.Coord   absolutePlayerCoord = map.GetCoordinate(position);
                    bool          inMap = map.GetChunk(absolutePlayerCoord, false) != null;
                    foreach (Direction absoluteDir in platformBuildableDirections)
                    {
                        Voxel.Coord playerCoord = absoluteDir == Direction.NegativeY ? absolutePlayerCoord : map.GetCoordinate(position + new Vector3(0, platformSize / -2.0f, 0));
                        Direction   relativeDir = map.GetRelativeDirection(absoluteDir);
                        if (!inMap && map.GetChunk(playerCoord.Move(relativeDir, searchDistance), false) == null)
                        {
                            continue;
                        }

                        for (int i = 1; i < shortestDistance; i++)
                        {
                            Voxel.Coord coord = playerCoord.Move(relativeDir, i);
                            Voxel.State state = map[coord];

                            if (state == Voxel.States.Empty)
                            {
                                continue;
                            }

                            if (this.canBuild(state) && this.canBuild(map.GetAbsolutePosition(coord)))
                            {
                                shortestDistance          = i;
                                relativeShortestDirection = relativeDir;
                                absoluteShortestDirection = absoluteDir;
                                shortestCoordinate        = playerCoord;
                                shortestMap = map;
                            }
                            break;
                        }
                    }
                }
            }

            if (shortestMap != null && shortestDistance > 1)
            {
                Direction yDir = relativeShortestDirection.IsParallel(Direction.PositiveY) ? Direction.PositiveX : Direction.PositiveY;
                Direction zDir = relativeShortestDirection.Cross(yDir);

                int         initialOffset = absoluteShortestDirection == Direction.NegativeY ? 0 : -2;
                Voxel.Coord startCoord    = shortestCoordinate.Move(relativeShortestDirection, initialOffset).Move(yDir, platformSize / -2).Move(zDir, platformSize / -2);
                Voxel.Coord endCoord      = startCoord.Move(relativeShortestDirection, -initialOffset + shortestDistance).Move(yDir, platformSize).Move(zDir, platformSize);

                return(new Possibility
                {
                    Map = shortestMap,
                    StartCoord = new Voxel.Coord {
                        X = Math.Min(startCoord.X, endCoord.X), Y = Math.Min(startCoord.Y, endCoord.Y), Z = Math.Min(startCoord.Z, endCoord.Z)
                    },
                    EndCoord = new Voxel.Coord {
                        X = Math.Max(startCoord.X, endCoord.X), Y = Math.Max(startCoord.Y, endCoord.Y), Z = Math.Max(startCoord.Z, endCoord.Z)
                    },
                });
            }
            return(null);
        }
Пример #15
0
        public override void Awake()
        {
            base.Awake();

            Switch.all.Add(this);

            this.Add(new NotifyBinding(delegate()
            {
                if (this.On)
                {
                    this.OnPowerOn.Execute();
                }
                else
                {
                    this.OnPowerOff.Execute();
                }
            }, this.On));

            this.Add(new CommandBinding(this.OnPowerOff, delegate()
            {
                AkSoundEngine.PostEvent(AK.EVENTS.PLAY_SWITCH_OFF, this.Entity);
            }));

            this.Add(new CommandBinding(this.OnPowerOn, delegate()
            {
                AkSoundEngine.PostEvent(AK.EVENTS.PLAY_SWITCH_ON, this.Entity);
                Voxel map = this.AttachedVoxel.Value.Target.Get <Voxel>();
                List <Voxel.Coord> changes = new List <Voxel.Coord>();
                Stack <Voxel.Box> path     = new Stack <Voxel.Box>();
                Queue <Voxel.Coord> queue  = new Queue <Voxel.Coord>();
                foreach (Switch s in Switch.all)
                {
                    if (s.On && s != this && s.AttachedVoxel.Value.Target == this.AttachedVoxel.Value.Target &&
                        VoxelAStar.Broadphase(map, map.GetBox(this.Coord), s.Coord, canConnect, path, 2000))
                    {
                        Voxel.Coord start = s.Coord;
                        start.Data        = map[start];
                        queue.Enqueue(start);
                        while (queue.Count > 0)
                        {
                            Voxel.Coord c = queue.Dequeue();

                            c.Data = null;                             // Ensure the visited dictionary works correctly
                            Voxel.CoordDictionaryCache[c] = true;

                            Voxel.Coord change = c.Clone();
                            change.Data        = Voxel.States.Switch;
                            changes.Add(change);

                            foreach (Direction adjacentDirection in DirectionExtensions.Directions)
                            {
                                Voxel.Coord adjacentCoord = c.Move(adjacentDirection);
                                if (!Voxel.CoordDictionaryCache.ContainsKey(adjacentCoord))
                                {
                                    Voxel.State adjacentState = map[adjacentCoord];
                                    if (adjacentState == Voxel.States.PoweredSwitch)
                                    {
                                        queue.Enqueue(adjacentCoord);
                                    }
                                    else if ((adjacentState == Voxel.States.Blue || adjacentState == Voxel.States.Powered) &&
                                             path.Contains(map.GetBox(adjacentCoord)))
                                    {
                                        adjacentCoord.Data = Voxel.States.Neutral;
                                        changes.Add(adjacentCoord);
                                    }
                                }
                            }
                        }
                    }
                    path.Clear();
                    queue.Clear();
                }
                Voxel.CoordDictionaryCache.Clear();
                if (changes.Count > 0)
                {
                    lock (map.MutationLock)
                    {
                        map.Empty(changes, true, true, map);
                        map.Fill(changes);
                    }
                    map.Regenerate();
                }
            }));
        }
Пример #16
0
 private static bool canConnect(Voxel.State state)
 {
     return(state == Voxel.States.Powered ||
            state == Voxel.States.HardPowered ||
            state == Voxel.States.PoweredSwitch);
 }
Пример #17
0
        public override void Awake()
        {
            base.Awake();

            Switch.all.Add(this);

            this.Add(new NotifyBinding(delegate()
            {
                if (this.On)
                {
                    this.OnPowerOn.Execute();
                }
                else
                {
                    this.OnPowerOff.Execute();
                }
            }, this.On));

            this.Add(new CommandBinding(this.OnPowerOff, delegate()
            {
                if (this.main.TotalTime > 0.1f)
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_SWITCH_OFF, this.Entity);
                }
            }));

            this.Add(new CommandBinding(this.OnPowerOn, delegate()
            {
                if (this.main.TotalTime > 0.1f && this.PowerOnCue != 0)
                {
                    AkSoundEngine.PostEvent(this.PowerOnCue, this.Entity);
                }
                Voxel map = this.AttachedVoxel.Value.Target.Get <Voxel>();

                Switch closestConnectedSwitch          = null;
                Stack <Voxel.Box> closestConnectedPath = null;

                foreach (Switch s in Switch.all)
                {
                    Stack <Voxel.Box> path = new Stack <Voxel.Box>();
                    if (s.On && s != this && s.AttachedVoxel.Value.Target == this.AttachedVoxel.Value.Target &&
                        VoxelAStar.Broadphase(map, map.GetBox(this.Coord), s.Coord, canConnect, path, 2000))
                    {
                        if (closestConnectedPath == null || path.Count < closestConnectedPath.Count)
                        {
                            closestConnectedSwitch = s;
                            closestConnectedPath   = path;
                        }
                    }
                }
                if (closestConnectedSwitch != null)
                {
                    List <Voxel.Coord> changes = new List <Voxel.Coord>();
                    Queue <Voxel.Coord> queue  = new Queue <Voxel.Coord>();
                    Voxel.Coord start          = closestConnectedSwitch.Coord;
                    start.Data = null;
                    queue.Enqueue(start);
                    Voxel.CoordSetCache.Add(start);

                    start.Data = Voxel.States.Switch;
                    changes.Add(start);
                    while (queue.Count > 0)
                    {
                        Voxel.Coord c = queue.Dequeue();

                        foreach (Direction adjacentDirection in DirectionExtensions.Directions)
                        {
                            Voxel.Coord adjacentCoord = c.Move(adjacentDirection);
                            if (!Voxel.CoordSetCache.Contains(adjacentCoord))
                            {
                                Voxel.CoordSetCache.Add(adjacentCoord);
                                Voxel.State adjacentState = map[adjacentCoord];
                                if (adjacentState == Voxel.States.PoweredSwitch)
                                {
                                    queue.Enqueue(adjacentCoord);

                                    adjacentCoord.Data = Voxel.States.Switch;
                                    changes.Add(adjacentCoord);
                                }
                                else if (adjacentState == Voxel.States.Hard)
                                {
                                    queue.Enqueue(adjacentCoord);
                                }
                                else if (adjacentState == Voxel.States.HardPowered)
                                {
                                    queue.Enqueue(adjacentCoord);

                                    adjacentCoord.Data = Voxel.States.Hard;
                                    changes.Add(adjacentCoord);
                                }
                                else if ((adjacentState == Voxel.States.Blue || adjacentState == Voxel.States.Powered) &&
                                         closestConnectedPath.Contains(map.GetBox(adjacentCoord)))
                                {
                                    adjacentCoord.Data = Voxel.States.Neutral;
                                    changes.Add(adjacentCoord);
                                    adjacentCoord.Data = null;
                                }
                            }
                        }
                    }
                    Voxel.CoordSetCache.Clear();
                    if (changes.Count > 0)
                    {
                        lock (map.MutationLock)
                        {
                            map.Empty(changes, true, true, map);
                            map.Fill(changes);
                        }
                        map.Regenerate();
                    }
                }
            }));
        }
Пример #18
0
        private bool determineShouldBuildFloor(Voxel.State floorState)
        {
            bool result = false;

            if (floorState == Voxel.States.Blue || floorState == Voxel.States.Powered)
            {
                // If we're standing on blue or powered, we need to check if we're close to a non-blue block before we can build a floor
                // This prevents the player from building a floor infinitely
                Queue <Voxel.Box>           queue   = new Queue <Voxel.Box>();
                Dictionary <Voxel.Box, int> visited = new Dictionary <Voxel.Box, int>();
                Voxel.Box floorBox = this.floorMap.GetBox(this.floorCoordinate);
                queue.Enqueue(floorBox);
                visited[floorBox] = 0;
                const int radius      = 6;
                const int maxSearch   = radius * radius * radius;
                int       searchIndex = 0;
                while (queue.Count > 0 && searchIndex < maxSearch)
                {
                    searchIndex++;
                    Voxel.Box b = queue.Dequeue();
                    lock (b.Adjacent)
                    {
                        int parentGScore = visited[b];
                        for (int i = 0; i < b.Adjacent.Count; i++)
                        {
                            Voxel.Box adjacent        = b.Adjacent[i];
                            int       tentativeGScore = parentGScore + adjacent.Width * adjacent.Height * adjacent.Depth;
                            int       previousGScore;
                            if (!visited.TryGetValue(adjacent, out previousGScore) || tentativeGScore < previousGScore)
                            {
                                visited[adjacent] = tentativeGScore;

                                if (parentGScore < radius * radius &&
                                    this.floorCoordinate.X >= adjacent.X - radius && this.floorCoordinate.X < adjacent.X + adjacent.Width + radius &&
                                    this.floorCoordinate.Y >= adjacent.Y - radius && this.floorCoordinate.Y < adjacent.Y + adjacent.Height + radius &&
                                    this.floorCoordinate.Z >= adjacent.Z - radius && this.floorCoordinate.Z < adjacent.Z + adjacent.Depth + radius)
                                {
                                    if (adjacent.Type != Voxel.States.Blue && adjacent.Type != Voxel.States.Powered)
                                    {
                                        // Non-blue block. It's close enough, we can build a floor
                                        result = true;
                                        break;
                                    }
                                    else
                                    {
                                        queue.Enqueue(adjacent);
                                    }
                                }
                            }
                        }
                    }
                    if (result)
                    {
                        break;
                    }
                }
            }
            else
            {
                result = true;
            }
            return(result);
        }
Пример #19
0
 private static bool filter(Voxel.State state)
 {
     return(state != Components.Voxel.States.Empty && !state.Hard);
 }
Пример #20
0
        public override void Bind(Entity entity, Main main, bool creating = false)
        {
            SpotLight light = entity.Create <SpotLight>();

            light.Enabled.Value = !main.EditorEnabled;

            light.FieldOfView.Value = 1.0f;
            light.Attenuation.Value = 75.0f;

            Transform transform = entity.GetOrCreate <Transform>("Transform");

            light.Add(new Binding <Vector3>(light.Position, transform.Position));

            Turret turret = entity.GetOrCreate <Turret>("Turret");

            Command die = new Command
            {
                Action = delegate()
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_TURRET_DEATH, entity);
                    ParticleSystem shatter = ParticleSystem.Get(main, "InfectedShatter");
                    Random         random  = new Random();
                    for (int i = 0; i < 50; i++)
                    {
                        Vector3 offset = new Vector3((float)random.NextDouble() - 0.5f, (float)random.NextDouble() - 0.5f, (float)random.NextDouble() - 0.5f);
                        shatter.AddParticle(transform.Position + offset, offset);
                    }
                    entity.Delete.Execute();
                }
            };
            VoxelAttachable attachable = VoxelAttachable.MakeAttachable(entity, main, true, true, die);

            attachable.Enabled.Value = true;
            attachable.Offset.Value  = 2;

            PointLight pointLight = entity.GetOrCreate <PointLight>();

            pointLight.Serialize = false;
            pointLight.Add(new Binding <Vector3>(pointLight.Position, transform.Position));

            LineDrawer laser = new LineDrawer {
                Serialize = false
            };

            entity.Add(laser);
            laser.DrawOrder.Value = 0;

            AI ai = entity.GetOrCreate <AI>("AI");

            ModelAlpha model = entity.Create <ModelAlpha>();

            model.Add(new Binding <Matrix>(model.Transform, transform.Matrix));
            model.Filename.Value = "AlphaModels\\pyramid";

            const float defaultModelScale = 0.75f;

            model.Scale.Value = new Vector3(defaultModelScale);

            const float sightDistance     = 80.0f;
            const float hearingDistance   = 0.0f;
            const float operationalRadius = 100.0f;

            model.Add(new Binding <Vector3, string>(model.Color, delegate(string state)
            {
                switch (state)
                {
                case "Alert":
                    return(new Vector3(1.0f, 1.0f, 0.25f));

                case "Aggressive":
                    return(new Vector3(1.0f, 0.5f, 0.25f));

                case "Firing":
                    return(new Vector3(1.0f, 0.0f, 0.0f));

                case "Disabled":
                    return(new Vector3(0.0f, 0.0f, 0.0f));

                default:
                    return(new Vector3(1.0f, 1.0f, 1.0f));
                }
            }, ai.CurrentState));
            laser.Add(new Binding <bool, string>(laser.Enabled, x => x != "Disabled" && x != "Suspended", ai.CurrentState));

            light.Add(new Binding <Vector3>(light.Color, model.Color));
            pointLight.Add(new Binding <Vector3>(pointLight.Color, model.Color));

            Voxel.GlobalRaycastResult rayHit = new Voxel.GlobalRaycastResult();
            Vector3 toReticle = Vector3.Zero;

            AI.Task checkOperationalRadius = new AI.Task
            {
                Interval = 2.0f,
                Action   = delegate()
                {
                    bool shouldBeActive = (transform.Position.Value - main.Camera.Position).Length() < operationalRadius && Water.Get(transform.Position) == null;
                    if (shouldBeActive && ai.CurrentState == "Suspended")
                    {
                        ai.CurrentState.Value = "Idle";
                    }
                    else if (!shouldBeActive && ai.CurrentState != "Suspended")
                    {
                        ai.CurrentState.Value = "Suspended";
                    }
                },
            };

            turret.Add(new CommandBinding(turret.PowerOn, delegate()
            {
                if (ai.CurrentState == "Disabled")
                {
                    ai.CurrentState.Value = "Suspended";
                    checkOperationalRadius.Action();
                }
            }));

            turret.Add(new CommandBinding(turret.PowerOff, delegate()
            {
                ai.CurrentState.Value = "Disabled";
            }));

            light.Add(new Binding <Quaternion>(light.Orientation, delegate()
            {
                return(Quaternion.CreateFromYawPitchRoll(-(float)Math.Atan2(toReticle.Z, toReticle.X) - (float)Math.PI * 0.5f, (float)Math.Asin(toReticle.Y), 0));
            }, transform.Position, turret.Reticle));

            AI.Task updateRay = new AI.Task
            {
                Action = delegate()
                {
                    toReticle = Vector3.Normalize(turret.Reticle.Value - transform.Position.Value);
                    rayHit    = Voxel.GlobalRaycast(transform.Position, toReticle, operationalRadius);
                    laser.Lines.Clear();

                    Microsoft.Xna.Framework.Color color = new Microsoft.Xna.Framework.Color(model.Color);
                    laser.Lines.Add(new LineDrawer.Line
                    {
                        A = new Microsoft.Xna.Framework.Graphics.VertexPositionColor(transform.Position, color),
                        B = new Microsoft.Xna.Framework.Graphics.VertexPositionColor(rayHit.Position, color),
                    });
                }
            };

            ai.Add(new AI.AIState
            {
                Name  = "Disabled",
                Tasks = new AI.Task[] { },
            });

            ai.Add(new AI.AIState
            {
                Name  = "Suspended",
                Tasks = new[] { checkOperationalRadius, },
            });

            ai.Add(new AI.AIState
            {
                Name  = "Idle",
                Tasks = new[]
                {
                    checkOperationalRadius,
                    updateRay,
                    new AI.Task
                    {
                        Interval = 1.0f,
                        Action   = delegate()
                        {
                            Agent a = Agent.Query(transform.Position, sightDistance, hearingDistance, x => x.Entity.Type == "Player");
                            if (a != null)
                            {
                                ai.CurrentState.Value = "Alert";
                            }
                        },
                    },
                },
            });

            ai.Add(new AI.AIState
            {
                Name  = "Alert",
                Tasks = new[]
                {
                    checkOperationalRadius,
                    updateRay,
                    new AI.Task
                    {
                        Interval = 1.0f,
                        Action   = delegate()
                        {
                            if (ai.TimeInCurrentState > 3.0f)
                            {
                                ai.CurrentState.Value = "Idle";
                            }
                            else
                            {
                                Agent a = Agent.Query(transform.Position, sightDistance, hearingDistance, x => x.Entity.Type == "Player");
                                if (a != null)
                                {
                                    ai.TargetAgent.Value  = a.Entity;
                                    ai.CurrentState.Value = "Aggressive";
                                }
                            }
                        },
                    },
                },
            });

            AI.Task checkTargetAgent = new AI.Task
            {
                Action = delegate()
                {
                    Entity target = ai.TargetAgent.Value.Target;
                    if (target == null || !target.Active)
                    {
                        ai.TargetAgent.Value  = null;
                        ai.CurrentState.Value = "Idle";
                    }
                },
            };

            float lastSpotted = 0.0f;

            ai.Add(new AI.AIState
            {
                Name  = "Aggressive",
                Tasks = new[]
                {
                    checkTargetAgent,
                    updateRay,
                    new AI.Task
                    {
                        Action = delegate()
                        {
                            Entity target         = ai.TargetAgent.Value.Target;
                            turret.Reticle.Value += (target.Get <Transform>().Position - turret.Reticle.Value) * Math.Min(3.0f * main.ElapsedTime, 1.0f);
                        }
                    },
                    new AI.Task
                    {
                        Interval = 0.1f,
                        Action   = delegate()
                        {
                            if (Agent.Query(transform.Position, sightDistance, hearingDistance, ai.TargetAgent.Value.Target.Get <Agent>()))
                            {
                                lastSpotted = main.TotalTime;
                            }

                            if (ai.TimeInCurrentState.Value > 1.5f)
                            {
                                if (lastSpotted < main.TotalTime - 2.0f)
                                {
                                    ai.CurrentState.Value = "Alert";
                                }
                                else
                                {
                                    Vector3 targetPos = ai.TargetAgent.Value.Target.Get <Transform>().Position.Value;
                                    Vector3 toTarget  = Vector3.Normalize(targetPos - transform.Position.Value);
                                    if (Vector3.Dot(toReticle, toTarget) > 0.95f)
                                    {
                                        ai.CurrentState.Value = "Firing";
                                    }
                                }
                            }
                        }
                    },
                }
            });

            ai.Add(new AI.AIState
            {
                Name  = "Firing",
                Enter = delegate(AI.AIState last)
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_TURRET_CHARGE, entity);
                },
                Exit = delegate(AI.AIState next)
                {
                    Voxel.State attachedState = attachable.AttachedVoxel.Value.Target.Get <Voxel>()[attachable.Coord];
                    if (!attachedState.Permanent && rayHit.Voxel != null && (rayHit.Position - transform.Position).Length() < 8.0f)
                    {
                        return;                         // Danger close, cease fire!
                    }
                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_TURRET_FIRE, entity);

                    bool hitVoxel = true;

                    Entity target = ai.TargetAgent.Value.Target;
                    if (target != null && target.Active)
                    {
                        Vector3 targetPos = target.Get <Transform>().Position;
                        Vector3 toTarget  = targetPos - transform.Position.Value;
                        if (Vector3.Dot(toReticle, Vector3.Normalize(toTarget)) > 0.2f)
                        {
                            float distance = toTarget.Length();
                            if (distance < rayHit.Distance)
                            {
                                Sound.PostEvent(AK.EVENTS.PLAY_TURRET_MISS, transform.Position + toReticle * distance);
                            }
                        }

                        BEPUutilities.RayHit physicsHit;
                        if (target.Get <Player>().Character.Body.CollisionInformation.RayCast(new Ray(transform.Position, toReticle), rayHit.Voxel == null ? float.MaxValue : rayHit.Distance, out physicsHit))
                        {
                            Explosion.Explode(main, targetPos, 6, 8.0f);
                            hitVoxel = false;
                        }
                    }

                    if (hitVoxel && rayHit.Voxel != null)
                    {
                        Explosion.Explode(main, rayHit.Position + rayHit.Voxel.GetAbsoluteVector(rayHit.Normal.GetVector()) * 0.5f, 6, 8.0f);
                    }

                    Vector3 splashPos;
                    Water w = Water.Raycast(transform.Position, toReticle, rayHit.Distance, out splashPos);
                    if (w != null)
                    {
                        Sound.PostEvent(AK.EVENTS.PLAY_WATER_SPLASH, splashPos);
                        Water.SplashParticles(main, splashPos, 3.0f);
                    }
                },
                Tasks = new[]
                {
                    checkTargetAgent,
                    updateRay,
                    new AI.Task
                    {
                        Action = delegate()
                        {
                            if (ai.TimeInCurrentState.Value > 0.75f)
                            {
                                ai.CurrentState.Value = "Aggressive";                                 // This actually fires (in the Exit function)
                            }
                        }
                    }
                }
            });

            this.SetMain(entity, main);

            entity.Add("On", turret.On);
            entity.Add("PowerOn", turret.PowerOn);
            entity.Add("PowerOff", turret.PowerOff);
        }
Пример #21
0
        public void InternalBind(Entity entity, Main main, bool creating = false, Transform transform = null, bool dataOnly = false)
        {
            if (transform == null)
            {
                transform = entity.GetOrCreate <Transform>("Transform");
            }

            entity.CannotSuspend = false;

            Voxel map = entity.Get <Voxel>();

            // Apply the position and orientation components to the map
            if (main.EditorEnabled || map.Scale.Value != 1.0f)
            {
                map.Add(new TwoWayBinding <Matrix, Matrix>
                        (
                            transform.Matrix,
                            x => x * Matrix.CreateScale(1.0f / map.Scale),
                            new IProperty[] { map.Scale },
                            map.Transform,
                            x => Matrix.CreateScale(map.Scale) * x,
                            new IProperty[] { map.Scale }
                        ));
            }
            else
            {
                map.Add(new TwoWayBinding <Matrix>(transform.Matrix, map.Transform));
            }

            map.Add(new CommandBinding(map.CompletelyEmptied, delegate()
            {
                if (!main.EditorEnabled)
                {
                    entity.Delete.Execute();
                }
            }));

            Entity world = main.Get("World").FirstOrDefault();

            if (dataOnly && !main.EditorEnabled)
            {
                map.EnablePhysics.Value = false;
            }
            else
            {
                map.CreateModel = delegate(Vector3 min, Vector3 max, Voxel.State state)
                {
                    if (state.Invisible && !main.EditorEnabled)
                    {
                        return(null);
                    }

                    DynamicModel <Voxel.Vertex> model = new DynamicModel <Voxel.Vertex>(Voxel.Vertex.VertexDeclaration);
                    model.EffectFile.Value = "Effects\\Environment";
                    model.Lock             = new object();
                    state.ApplyTo(model);

                    if (state.Invisible)
                    {
                        model.Add(new Binding <bool>(model.Enabled, Editor.EditorModelsVisible));
                    }

                    /*
                     * ModelAlpha debug = new ModelAlpha { Serialize = false };
                     * debug.Alpha.Value = 0.01f;
                     * debug.DrawOrder.Value = 11; // In front of water
                     * debug.Color.Value = new Vector3(1.0f, 0.8f, 0.6f);
                     * debug.Filename.Value = "AlphaModels\\box";
                     * debug.CullBoundingBox.Value = false;
                     * debug.DisableCulling.Value = true;
                     * debug.Add(new Binding<Matrix>(debug.Transform, delegate()
                     * {
                     *      BoundingBox box = model.BoundingBox;
                     *      return Matrix.CreateScale(box.Max - box.Min) * Matrix.CreateTranslation((box.Max + box.Min) * 0.5f) * transform.Matrix;
                     * }, transform.Matrix, model.BoundingBox));
                     * result.Add(debug);
                     */

                    if (main.EditorEnabled || map.Scale.Value != 1.0f)
                    {
                        model.Add(new Binding <Matrix>(model.Transform, () => Matrix.CreateScale(map.Scale) * transform.Matrix, transform.Matrix, map.Scale));
                    }
                    else
                    {
                        model.Add(new Binding <Matrix>(model.Transform, transform.Matrix));
                    }

                    model.Add(new Binding <Vector3>(model.GetVector3Parameter("Offset"), map.Offset));

                    Voxel.State s = state;

                    model.Add(new Binding <Matrix>(model.GetMatrixParameter("UVScaleRotation"), delegate()
                    {
                        Matrix m    = Matrix.CreateRotationZ(map.UVRotation * (float)Math.PI / 180.0f);
                        float scale = 0.075f * s.Tiling;
                        m.M11      *= scale;
                        m.M12      *= scale;
                        m.M21      *= scale;
                        m.M22      *= scale;
                        return(m);
                    }, map.UVRotation));

                    model.Add(new Binding <Vector2>(model.GetVector2Parameter("UVOffset"), x => x * 0.075f * s.Tiling, map.UVOffset));

                    if (!s.ShadowCast)
                    {
                        model.UnsupportedTechniques.Add(Technique.Shadow);
                    }

                    entity.Add(model);

                    // We have to create this binding after adding the model to the entity
                    // Because when the model loads, it automatically calculates a bounding box for it.
                    model.Add(new Binding <BoundingBox, Vector3>(model.BoundingBox, x => new BoundingBox(min - x, max - x), map.Offset));
                    model.CullBoundingBox.Value = true;

                    return(model);
                };
            }

            this.SetMain(entity, main);
            map.Offset.Changed();
        }
Пример #22
0
 public virtual Voxel.State Apply(int x, int y, Voxel.State voxel)
 {
     return(fillType);
 }
Пример #23
0
        public void Update(float dt)
        {
            // Spawn an editor or a player if needed
            if (this.main.EditorEnabled)
            {
                this.main.Renderer.InternalGamma.Value = 0.0f;
                this.main.Renderer.Brightness.Value    = 0.0f;
                if (this.editor == null || !this.editor.Active)
                {
                    this.editor = Factory.Get <EditorFactory>().CreateAndBind(this.main);
                    FPSInput.RecenterMouse();
                    this.editor.Get <Editor>().Position.Value = this.lastEditorPosition;
                    this.editor.Get <FPSInput>().Mouse.Value  = this.lastEditorMouse;
                    this.StartSpawnPoint.Value     = this.lastEditorSpawnPoint;
                    this.StartSpawnPointGUID.Value = this.lastEditorSpawnPointGUID;
                    this.main.Add(this.editor);
                }
                else
                {
                    this.lastEditorPosition = this.editor.Get <Editor>().Position;
                    this.lastEditorMouse    = this.editor.Get <FPSInput>().Mouse;
                }
            }
            else
            {
                if (this.main.MapFile.Value == null || !this.CanSpawn || CameraStop.CinematicActive)
                {
                    return;
                }

                this.editor = null;

                bool createPlayer = PlayerFactory.Instance == null;

                if (this.mapJustLoaded)
                {
                    if (!createPlayer)
                    {
                        // We just loaded a save game
                        this.main.Renderer.InternalGamma.Value = 0.0f;
                        this.main.Renderer.Brightness.Value    = 0.0f;
                        this.PlayerSpawned.Execute();
                        this.respawnTimer = 0;
                    }
                }
                else if (createPlayer)
                {
                    if (this.respawnTimer == 0)
                    {
                        this.main.AddComponent(new Animation(this.FlashAnimation()));
                    }

                    if (this.respawnTimer > this.RespawnInterval)
                    {
                        bool spawnFound = false;

                        RespawnLocation foundSpawnLocation         = default(RespawnLocation);
                        Vector3         foundSpawnAbsolutePosition = Vector3.Zero;

                        if (string.IsNullOrEmpty(this.StartSpawnPoint) && this.StartSpawnPointGUID == 0)
                        {
                            // Look for an autosaved spawn point
                            Entity playerData = PlayerDataFactory.Instance;
                            if (playerData != null)
                            {
                                ListProperty <RespawnLocation> respawnLocations = playerData.Get <PlayerData>().RespawnLocations;
                                int   supportedLocations = 0;
                                float lowerLimit         = Factory.Get <LowerLimitFactory>().GetLowerLimit();
                                while (respawnLocations.Length > 0)
                                {
                                    RespawnLocation respawnLocation  = respawnLocations[respawnLocations.Length - 1];
                                    Entity          respawnMapEntity = respawnLocation.Map.Target;
                                    if (respawnMapEntity != null && respawnMapEntity.Active)
                                    {
                                        Voxel   respawnMap  = respawnMapEntity.Get <Voxel>();
                                        Vector3 absolutePos = respawnMap.GetAbsolutePosition(respawnLocation.Coordinate);
                                        if (respawnMap.Active &&
                                            absolutePos.Y > lowerLimit &&
                                            respawnMap.GetAbsoluteVector(respawnMap.GetRelativeDirection(Direction.PositiveY).GetVector()).Y > 0.5f &&
                                            Agent.Query(absolutePos, 0.0f, 20.0f) == null &&
                                            Rift.Query(absolutePos) == null &&
                                            Zone.CanSpawnAt(absolutePos))
                                        {
                                            Voxel.State state = respawnMap[respawnLocation.Coordinate];
                                            if (state != Voxel.States.Empty && state != Voxel.States.Infected && state != Voxel.States.HardInfected && state != Voxel.States.Floater)
                                            {
                                                supportedLocations++;
                                                DynamicVoxel dynamicMap = respawnMap as DynamicVoxel;
                                                if (dynamicMap == null || absolutePos.Y > respawnLocation.OriginalPosition.Y - 1.0f)
                                                {
                                                    Voxel.GlobalRaycastResult hit = Voxel.GlobalRaycast(absolutePos + new Vector3(0, 1, 0), Vector3.Up, 2);
                                                    if (hit.Voxel == null)
                                                    {
                                                        // We can spawn here
                                                        spawnFound                 = true;
                                                        foundSpawnLocation         = respawnLocation;
                                                        foundSpawnAbsolutePosition = absolutePos;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    if (supportedLocations >= 40 || (spawnFound && (foundSpawnAbsolutePosition - this.lastPlayerPosition).Length() > this.RespawnDistance))
                                    {
                                        if (supportedLocations > 3)                                         // We should try to spawn the player back at least a few steps
                                        {
                                            break;
                                        }
                                    }

                                    respawnLocations.RemoveAt(respawnLocations.Length - 1);
                                }
                            }
                        }

                        if (spawnFound)
                        {
                            // Spawn at an autosaved location
                            if (createPlayer)
                            {
                                this.spawn();
                            }
                            Vector3 absolutePos = foundSpawnLocation.Map.Target.Get <Voxel>().GetAbsolutePosition(foundSpawnLocation.Coordinate);
                            PlayerFactory.Instance.Get <Transform>().Position.Value = this.main.Camera.Position.Value = absolutePos + new Vector3(0, spawnHeightOffset, 0);

                            FPSInput.RecenterMouse();
                            PlayerFactory.Instance.Get <FPSInput>().Mouse.Value = new Vector2(foundSpawnLocation.Rotation, 0);
                        }
                        else
                        {
                            // Spawn at a spawn point
                            PlayerSpawn spawn       = null;
                            Entity      spawnEntity = null;
                            if (this.StartSpawnPointGUID != 0)
                            {
                                spawnEntity = this.main.GetByGUID(this.StartSpawnPointGUID);
                                if (spawnEntity != null)
                                {
                                    spawn = spawnEntity.Get <PlayerSpawn>();
                                }
                                this.lastEditorSpawnPointGUID  = this.StartSpawnPointGUID;
                                this.StartSpawnPointGUID.Value = 0;
                            }
                            else if (!string.IsNullOrEmpty(this.StartSpawnPoint.Value))
                            {
                                spawnEntity = this.main.GetByID(this.StartSpawnPoint);
                                if (spawnEntity != null)
                                {
                                    spawn = spawnEntity.Get <PlayerSpawn>();
                                }
                                this.lastEditorSpawnPoint  = this.StartSpawnPoint;
                                this.StartSpawnPoint.Value = null;
                            }

                            if (spawnEntity == null)
                            {
                                spawn       = PlayerSpawn.FirstActive();
                                spawnEntity = spawn == null ? null : spawn.Entity;
                            }

                            if (spawnEntity != null)
                            {
                                Vector3 pos = spawnEntity.Get <Transform>().Position;
                                main.Camera.Position.Value = pos;
                                WorldFactory.Instance.Get <World>().UpdateZones();
                                Voxel.GlobalRaycastResult hit = Voxel.GlobalRaycast(pos + new Vector3(0, 2, 0), Vector3.Down, 8, null, false, true);
                                if (hit.Voxel == null)
                                {
                                    // There is nowhere to spawn. Reload the map.
                                    this.respawnTimer = 0;
                                    IO.MapLoader.Load(this.main, this.main.MapFile);
                                    return;
                                }
                                else
                                {
                                    if (createPlayer)
                                    {
                                        this.spawn();
                                    }
                                    pos = hit.Position + new Vector3(0, spawnHeightOffset, 0);
                                    PlayerFactory.Instance.Get <Transform>().Position.Value = this.main.Camera.Position.Value = pos;

                                    if (spawn != null)
                                    {
                                        spawn.IsActivated.Value = true;
                                        FPSInput.RecenterMouse();
                                        PlayerFactory.Instance.Get <FPSInput>().Mouse.Value = new Vector2(spawn.Rotation, 0);
                                        spawn.OnSpawn.Execute();
                                    }
                                }
                            }
                        }

                        // When the player teleports to a new map, show the number of orbs and notes on that map
                        // If mapJustLoaded is true, we just loaded a save game
                        if (this.main.TotalTime < Spawner.DefaultRespawnInterval * 2 && !this.mapJustLoaded)
                        {
                            WorldFactory.Instance.Add(new Animation
                                                      (
                                                          new Animation.Delay(1.5f),
                                                          new Animation.Execute(delegate()
                            {
                                int notes = Note.UncollectedCount;
                                if (notes > 0)
                                {
                                    this.main.Menu.HideMessage(WorldFactory.Instance, this.main.Menu.ShowMessageFormat(WorldFactory.Instance, notes == 1 ? "\\one note" : "\\note count", notes), 3.0f);
                                }

                                int orbs = Collectible.ActiveCount;
                                if (orbs > 0)
                                {
                                    this.main.Menu.HideMessage(WorldFactory.Instance, this.main.Menu.ShowMessageFormat(WorldFactory.Instance, orbs == 1 ? "\\one orb" : "\\orb count", orbs), 3.0f);
                                }
                            })
                                                      ));
                        }

                        WorldFactory.Instance.Add(new Animation(this.EndFlashAnimation()));
                        this.respawnTimer = 0;

                        this.PlayerSpawned.Execute();

                        this.RespawnInterval = Spawner.DefaultRespawnInterval;
                        this.RespawnDistance = Spawner.DefaultRespawnDistance;
                    }
                    else
                    {
                        this.respawnTimer += dt;
                    }
                }
                else
                {
                    this.lastPlayerPosition = PlayerFactory.Instance.Get <Transform>().Position;
                }
            }
            this.mapJustLoaded = false;
        }
Пример #24
0
        public override void Awake()
        {
            base.Awake();
            this.EnabledWhenPaused = false;
            this.Serialize         = false;

            this.Footstep.Action = delegate()
            {
                if (this.SoundEnabled && this.main.TotalTime - this.lastFootstepSound > footstepSoundInterval)
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.FOOTSTEP_PLAY, this.Entity);
                    this.lastFootstepSound = this.main.TotalTime;
                }
            };

            this.Add(new CommandBinding <Voxel, Voxel.Coord, Direction>(this.WalkedOn, delegate(Voxel map, Voxel.Coord coord, Direction dir)
            {
                Voxel.State state = map[coord];

                if (state != Voxel.States.Empty)
                {
                    AkSoundEngine.SetSwitch(AK.SWITCHES.FOOTSTEP_MATERIAL.GROUP, state.FootstepSwitch, this.Entity);

                    if (this.WallRunState.Value == WallRun.State.None)
                    {
                        if (map.GetAbsoluteDirection(dir) == Direction.NegativeY && !this.IsSwimming)
                        {
                            this.walkedOnCount++;
                            if (this.walkedOnCount >= 2)
                            {
                                // Every few tiles, save off the location for the auto-respawn system
                                coord.Data = null;
                                this.RespawnLocations.Add(new RespawnLocation
                                {
                                    Coordinate       = coord,
                                    Map              = map.Entity,
                                    Rotation         = this.Rotation,
                                    OriginalPosition = map.GetAbsolutePosition(coord),
                                });
                                while (this.RespawnLocations.Length > Spawner.RespawnMemoryLength)
                                {
                                    this.RespawnLocations.RemoveAt(0);
                                }
                                this.walkedOnCount = 0;
                            }
                        }
                    }
                }

                Voxel.t id = state.ID;
                if (id == Voxel.t.Neutral)
                {
                    map.Empty(coord, false, true, map);
                    bool isPowered = false;
                    for (int i = 0; i < 6; i++)
                    {
                        Voxel.Coord adjacentCoord = coord.Move(DirectionExtensions.Directions[i]);
                        Voxel.t adjacentId        = map[coord].ID;
                        if (adjacentId == Voxel.t.Powered || adjacentId == Voxel.t.PermanentPowered || adjacentId == Voxel.t.PoweredSwitch || adjacentId == Voxel.t.HardPowered)
                        {
                            isPowered = true;
                            break;
                        }
                    }
                    map.Fill(coord, isPowered ? Voxel.States.Powered : Voxel.States.Blue);
                    map.Regenerate();
                    WorldFactory.Instance.Get <Propagator>().Sparks(map.GetAbsolutePosition(coord), Propagator.Spark.Normal);
                }
                else if (id == Voxel.t.Reset)
                {
                    bool regenerate = false;

                    Queue <Voxel.Coord> queue = new Queue <Voxel.Coord>();
                    queue.Enqueue(coord);
                    Voxel.CoordSetCache.Add(coord);
                    while (queue.Count > 0)
                    {
                        Voxel.Coord c = queue.Dequeue();
                        for (int i = 0; i < 6; i++)
                        {
                            Voxel.Coord adjacentCoord = c.Move(DirectionExtensions.Directions[i]);
                            if (!Voxel.CoordSetCache.Contains(adjacentCoord))
                            {
                                Voxel.CoordSetCache.Add(adjacentCoord);
                                Voxel.t adjacentID = map[adjacentCoord].ID;
                                if (adjacentID == Voxel.t.Reset || adjacentID == Voxel.t.Hard)
                                {
                                    queue.Enqueue(adjacentCoord);
                                }
                                else if (adjacentID == Voxel.t.Infected || adjacentID == Voxel.t.Blue || adjacentID == Voxel.t.Powered)
                                {
                                    map.Empty(adjacentCoord, false, true, map);
                                    map.Fill(adjacentCoord, Voxel.States.Neutral);
                                    regenerate = true;
                                }
                                else if (adjacentID == Voxel.t.HardPowered || adjacentID == Voxel.t.HardInfected)
                                {
                                    map.Empty(adjacentCoord, false, true, map);
                                    map.Fill(adjacentCoord, Voxel.States.Hard);
                                    regenerate = true;
                                }
                            }
                        }
                    }
                    Voxel.CoordSetCache.Clear();
                    if (regenerate)
                    {
                        map.Regenerate();
                    }
                }

                // Lava. Damage the player character if it steps on lava.
                bool isInfected = id == Voxel.t.Infected || id == Voxel.t.HardInfected;
                if (isInfected)
                {
                    this.Damage.Execute(0.2f);
                }
                else if (id == Voxel.t.Floater)
                {
                    // Floater. Delete the block after a delay.
                    Vector3 pos = map.GetAbsolutePosition(coord);
                    ParticleEmitter.Emit(main, "Smoke", pos, 1.0f, 10);
                    Sound.PostEvent(AK.EVENTS.PLAY_CRUMBLE, pos);
                    WorldFactory.Instance.Add(new Animation
                                              (
                                                  new Animation.Delay(0.5f),
                                                  new Animation.Execute(delegate()
                    {
                        if (map[coord].ID == Voxel.t.Floater)
                        {
                            map.Empty(coord);
                            map.Regenerate();
                        }
                    })
                                              ));
                }

                this.infectedDamage = isInfected;
            }));
        }
Пример #25
0
 public virtual void Initialize(Voxel.State fillType, int radius)
 {
     this.fillType = fillType;
     this.radius   = radius;
 }
Пример #26
0
        // Function for finding a wall to build for the player
        public Possibility FindWall(Vector3 position, Vector2 direction)
        {
            Voxel shortestMap = null;

            Voxel.Coord shortestPlayerCoord    = new Voxel.Coord();
            Direction   shortestWallDirection  = Direction.None;
            Direction   shortestBuildDirection = Direction.None;
            int         shortestDistance       = searchDistance;

            EffectBlockFactory blockFactory = Factory.Get <EffectBlockFactory>();

            foreach (Voxel map in Voxel.ActivePhysicsVoxels)
            {
                if (!ignoreTypes.Contains(map.Entity.Type))
                {
                    foreach (Direction absoluteWallDir in DirectionExtensions.HorizontalDirections)
                    {
                        Direction relativeWallDir = map.GetRelativeDirection(absoluteWallDir);
                        Vector3   wallVector      = map.GetAbsoluteVector(relativeWallDir.GetVector());
                        float     dot             = Vector2.Dot(direction, Vector2.Normalize(new Vector2(wallVector.X, wallVector.Z)));
                        if (dot > -0.25f && dot < 0.8f)
                        {
                            Voxel.Coord coord = map.GetCoordinate(position).Move(relativeWallDir, 2);
                            foreach (Direction dir in DirectionExtensions.Directions.Where(x => x.IsPerpendicular(relativeWallDir)))
                            {
                                for (int i = 0; i < shortestDistance; i++)
                                {
                                    Voxel.Coord c     = coord.Move(dir, i);
                                    Voxel.State state = map[c];

                                    if (state == Voxel.States.Empty)
                                    {
                                        continue;
                                    }

                                    if (this.canBuild(state) && this.canBuild(map.GetAbsolutePosition(c)))
                                    {
                                        shortestMap            = map;
                                        shortestBuildDirection = dir;
                                        shortestWallDirection  = relativeWallDir;
                                        shortestDistance       = i;
                                        shortestPlayerCoord    = coord;
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            if (shortestMap != null)
            {
                // Found something to build a wall on.
                Direction   dirU       = shortestBuildDirection;
                Direction   dirV       = dirU.Cross(shortestWallDirection);
                Voxel.Coord startCoord = shortestPlayerCoord.Move(dirU, shortestDistance).Move(dirV, additionalWallDistance);
                Voxel.Coord endCoord   = shortestPlayerCoord.Move(dirU, -additionalWallDistance).Move(dirV, -additionalWallDistance).Move(shortestWallDirection);
                return(new Possibility
                {
                    Map = shortestMap,
                    StartCoord = new Voxel.Coord {
                        X = Math.Min(startCoord.X, endCoord.X), Y = Math.Min(startCoord.Y, endCoord.Y), Z = Math.Min(startCoord.Z, endCoord.Z)
                    },
                    EndCoord = new Voxel.Coord {
                        X = Math.Max(startCoord.X, endCoord.X), Y = Math.Max(startCoord.Y, endCoord.Y), Z = Math.Max(startCoord.Z, endCoord.Z)
                    },
                });
            }

            return(null);
        }
Пример #27
0
        public void Update(float dt)
        {
            State wallRunState = this.CurrentState;

            if (wallRunState != State.None)
            {
                this.Vault.Execute();                      // Try to vault up
                if (this.CurrentState.Value == State.None) // We vaulted
                {
                    return;
                }

                if (!this.WallRunVoxel.Value.Active || this.IsSupported)
                {
                    this.Deactivate();
                    return;
                }

                Voxel voxel = this.WallRunVoxel.Value;
                if (voxel == null || !voxel.Active)
                {
                    this.Deactivate();
                    return;
                }

                Vector3 wallRunVector = voxel.GetAbsoluteVector(this.WallRunDirection.Value.GetVector());
                Vector3 baseVelocity  = voxel.LinearVelocity + Vector3.Cross(voxel.AngularVelocity, this.Position - voxel.Transform.Value.Translation);
                float   wallRunSpeed  = Vector3.Dot(this.LinearVelocity.Value - baseVelocity, wallRunVector);
                Vector3 pos           = this.Position + new Vector3(0, this.Height * -0.5f, 0);

                if (wallRunState == State.Straight)
                {
                    if (wallRunSpeed < 0.0f)
                    {
                        // Start sliding down
                        this.CurrentState.Value = wallRunState = State.Down;
                        AkSoundEngine.PostEvent(AK.EVENTS.PLAY_PLAYER_SLIDE_LOOP, this.Entity);
                    }
                }
                else if (wallRunState == State.Left || wallRunState == State.Right)
                {
                    if (this.IsSupported || wallRunSpeed < minWallRunSpeed)
                    {
                        // We landed on the ground or we're going too slow to continue wall-running
                        this.Deactivate();
                        return;
                    }
                    else
                    {
                        // Check if we should switch to another wall
                        Vector3 wallVector = voxel.GetAbsoluteVector(this.WallDirection.Value.GetVector());
                        Voxel.GlobalRaycastResult result = Voxel.GlobalRaycast(pos, wallRunVector + wallVector, 2.0f);
                        if (result.Voxel != null && result.Voxel != voxel)
                        {
                            float dot = Vector3.Dot(result.Voxel.GetAbsoluteVector(result.Normal.GetReverse().GetVector()), wallVector);
                            if (dot > 0.7f)
                            {
                                Matrix  matrix        = Matrix.CreateRotationY(this.Rotation);
                                Vector3 forwardVector = -matrix.Forward;
                                this.setup(result.Voxel, result.Normal.GetReverse(), wallRunState, forwardVector, false, true);
                            }
                        }
                    }
                }

                Voxel.Coord coord     = voxel.GetCoordinate(pos);
                Voxel.Coord wallCoord = coord.Move(this.WallDirection, 2);
                Voxel.State wallType  = voxel[wallCoord];

                if (!wallCoord.Equivalent(this.lastWallRunCoord))
                {
                    this.lastWallRunCoord = wallCoord;
                    this.WalkedOn.Execute(voxel, wallCoord, this.WallDirection);
                }

                if (this.EnableEnhancedWallRun &&
                    (wallRunState == State.Left || wallRunState == State.Right) &&
                    Zone.CanBuild(this.Position) &&
                    voxel.Entity.Type != "Bouncer")
                {
                    Direction up = voxel.GetRelativeDirection(Direction.PositiveY);
                    if (up.IsPerpendicular(this.WallDirection))
                    {
                        Direction right = this.WallDirection.Value.Cross(up);

                        List <EffectBlockFactory.BlockBuildOrder> buildCoords = new List <EffectBlockFactory.BlockBuildOrder>();

                        const int radius       = 5;
                        int       upwardRadius = wallRunState == State.Down ? 0 : radius;
                        for (Voxel.Coord x = wallCoord.Move(right, -radius); x.GetComponent(right) < wallCoord.GetComponent(right) + radius; x = x.Move(right))
                        {
                            int dx = x.GetComponent(right) - wallCoord.GetComponent(right);
                            for (Voxel.Coord y = x.Move(up, -radius); y.GetComponent(up) < wallCoord.GetComponent(up) + upwardRadius; y = y.Move(up))
                            {
                                int dy = y.GetComponent(up) - wallCoord.GetComponent(up);
                                if ((float)Math.Sqrt(dx * dx + dy * dy) < radius && voxel[y].ID == 0)
                                {
                                    buildCoords.Add(new EffectBlockFactory.BlockBuildOrder
                                    {
                                        Voxel      = voxel,
                                        Coordinate = y,
                                        State      = Voxel.States.Blue,
                                    });
                                }
                            }
                        }
                        Factory.Get <EffectBlockFactory>().Build(main, buildCoords, this.Position);
                    }
                    else
                    {
                        this.Deactivate();
                        return;
                    }
                }
                else if (wallType.ID == 0 && wallInstantiationTimer == 0.0f)                 // We ran out of wall to walk on
                {
                    this.Deactivate();
                    return;
                }

                wallInstantiationTimer = Math.Max(0.0f, wallInstantiationTimer - dt);

                Vector3 coordPos = voxel.GetAbsolutePosition(coord);

                Vector3 normal = voxel.GetAbsoluteVector(this.WallDirection.Value.GetVector());
                // Equation of a plane
                // normal (dot) point = d
                float d = Vector3.Dot(normal, coordPos) + (wallRunState == State.Down ? 0.3f : 0.4f);

                // Distance along the normal to keep the player glued to the wall
                float snapDistance = d - Vector3.Dot(pos, normal);

                this.Position.Value += normal * snapDistance;

                Vector3 velocity = this.LinearVelocity;

                // Also fix the velocity so we don't jitter away from the wall
                velocity -= Vector3.Dot(velocity, normal) * normal;

                // Slow our descent
                velocity += new Vector3(0, (wallRunState == State.Straight ? 3.0f : 10.0f) * dt, 0);

                this.LinearVelocity.Value = velocity;
            }
        }
Пример #28
0
        public void Update(float dt)
        {
            if (this.TargetVoxel.Target == null || !this.TargetVoxel.Target.Active)
            {
                this.Delete.Execute();
                return;
            }

            this.Lifetime += dt;

            if (this.Lifetime < this.Delay)
            {
                return;
            }

            float blend = (this.Lifetime - this.Delay) / this.TotalLifetime;

            Voxel m = this.TargetVoxel.Target.Get <Voxel>();

            Matrix finalOrientation = m.Transform;

            finalOrientation.Translation = Vector3.Zero;
            Quaternion finalQuat = Quaternion.CreateFromRotationMatrix(finalOrientation);

            Vector3 finalPosition = m.GetAbsolutePosition(this.Coord);

            if (blend > 1.0f)
            {
                if (this.StateId != Voxel.t.Empty)
                {
                    Voxel.Coord c = this.Coord;

                    bool blue = this.StateId == Voxel.t.Blue;
                    bool foundAdjacentCell = false;
                    bool foundConflict     = false;
                    if (this.CheckAdjacent)
                    {
                        foreach (Direction dir in DirectionExtensions.Directions)
                        {
                            Voxel.Coord adjacent   = c.Move(dir);
                            Voxel.t     adjacentID = m[adjacent].ID;
                            if (adjacentID != Voxel.t.Empty)
                            {
                                if (blue && (adjacentID == Voxel.t.Infected || adjacentID == Voxel.t.HardInfected || adjacentID == Voxel.t.Slider || adjacentID == Voxel.t.SliderPowered || adjacentID == Voxel.t.SocketWhite || adjacentID == Voxel.t.SocketBlue || adjacentID == Voxel.t.SocketYellow))
                                {
                                    foundConflict = true;
                                }
                                else
                                {
                                    foundAdjacentCell = true;
                                    if (blue)
                                    {
                                        if (adjacentID == Voxel.t.Reset)
                                        {
                                            this.StateId = Voxel.t.Neutral;
                                            break;
                                        }
                                        else if (adjacentID == Voxel.t.Powered || adjacentID == Voxel.t.PermanentPowered || adjacentID == Voxel.t.PoweredSwitch || adjacentID == Voxel.t.HardPowered)
                                        {
                                            this.StateId = Voxel.t.Powered;
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        foundAdjacentCell = true;
                    }

                    if (foundAdjacentCell)
                    {
                        Vector3 absolutePos = m.GetAbsolutePosition(c);

                        if (blue && !Zone.CanBuild(absolutePos))
                        {
                            foundConflict = true;
                        }

                        if (!foundConflict)
                        {
                            bool isDynamic = m.GetType() == typeof(DynamicVoxel);
                            foreach (Voxel m2 in Voxel.ActivePhysicsVoxels)
                            {
                                bool atLeastOneDynamic = isDynamic || m2.GetType() == typeof(DynamicVoxel);
                                if (m2 != m && atLeastOneDynamic && m2[absolutePos].ID != 0)
                                {
                                    foundConflict = true;
                                    break;
                                }
                            }
                        }

                        if (!foundConflict)
                        {
                            Voxel.State state = m[this.Coord];
                            if (state.Permanent || state.Hard || state.ID == this.StateId || (blue && state == Voxel.States.Powered))
                            {
                                foundConflict = true;
                            }
                            else
                            {
                                if (state.ID != 0)
                                {
                                    m.Empty(this.Coord);
                                }
                                m.Fill(this.Coord, Voxel.States.All[this.StateId]);
                                m.Regenerate();
                                if (EffectBlock.random.Next(0, 4) == 0)
                                {
                                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_BLOCK_BUILD, this.Entity);
                                }
                                this.Entity.Delete.Execute();
                                return;
                            }
                        }
                    }

                    // For one reason or another, we can't fill the cell
                    // Animate nicely into oblivion
                    this.StateId = Voxel.t.Empty;
                }
                else
                {
                    // For one reason or another, we can't fill the cell
                    // Animate nicely into oblivion
                    if (blend > 2.0f)
                    {
                        this.Delete.Execute();
                    }
                    else
                    {
                        Matrix result = Matrix.CreateFromQuaternion(finalQuat);
                        float  scale  = 2.0f - blend;
                        result.Right        *= scale;
                        result.Up           *= scale;
                        result.Forward      *= scale;
                        result.Translation   = finalPosition;
                        this.Transform.Value = result;
                    }
                }
            }
            else
            {
                float scale;
                if (this.DoScale)
                {
                    scale = blend;
                }
                else
                {
                    scale = 1.0f;
                }

                float distance = (finalPosition - this.StartPosition).Length() * 0.1f * Math.Max(0.0f, 0.5f - Math.Abs(blend - 0.5f));

                Matrix result = Matrix.CreateFromQuaternion(Quaternion.Lerp(this.StartOrientation, finalQuat, blend));
                result.Right        *= scale;
                result.Up           *= scale;
                result.Forward      *= scale;
                result.Translation   = Vector3.Lerp(this.StartPosition, finalPosition, blend) + new Vector3((float)Math.Sin(blend * Math.PI) * distance);
                this.Transform.Value = result;
            }
        }
Пример #29
0
        public void Go(bool overrideCooldown = false)
        {
            if (this.Rolling || this.Kicking || (main.TotalTime - this.LastRollKickEnded < coolDown && !overrideCooldown))
            {
                return;
            }

            Matrix rotationMatrix = Matrix.CreateRotationY(this.Rotation);

            this.forward          = -rotationMatrix.Forward;
            this.right            = rotationMatrix.Right;
            this.shouldBuildFloor = false;

            bool instantiatedBlockPossibility = false;

            if (this.EnableCrouch && this.EnableRoll && !this.IsSwimming &&
                (!this.EnableKick || !this.IsSupported || (this.LinearVelocity.Value - this.SupportVelocity.Value).Length() < 4.0f))
            {
                // Try to roll
                Vector3 playerPos = this.FloorPosition + new Vector3(0, 0.5f, 0);

                Voxel.GlobalRaycastResult floorRaycast = this.raycastFloor();

                bool nearGround = this.LinearVelocity.Value.Y < this.SupportVelocity.Value.Y + 0.1f && floorRaycast.Voxel != null;

                this.floorCoordinate = new Voxel.Coord();
                this.floorMap        = null;

                if (nearGround)
                {
                    this.floorMap        = floorRaycast.Voxel;
                    this.floorCoordinate = floorRaycast.Coordinate.Value;
                }
                else
                {
                    // Check for block possibilities
                    foreach (BlockPredictor.Possibility block in this.Predictor.AllPossibilities)
                    {
                        bool first = true;
                        foreach (Voxel.Coord coord in block.Map.Rasterize(playerPos + Vector3.Up * 2.0f, playerPos + (Vector3.Down * (this.Height + 3.0f))))
                        {
                            if (coord.Between(block.StartCoord, block.EndCoord))
                            {
                                if (first)
                                {
                                    break;                                     // If the top coord is intersecting the possible block, we're too far down into the block. Need to be at the top.
                                }
                                this.Predictor.InstantiatePossibility(block);
                                instantiatedBlockPossibility = true;
                                this.floorMap         = block.Map;
                                this.floorCoordinate  = coord;
                                this.Position.Value  += new Vector3(0, this.floorMap.GetAbsolutePosition(coord).Y + 2 - this.FloorPosition.Value.Y, 0);
                                this.shouldBuildFloor = true;
                                nearGround            = true;
                                break;
                            }
                            first = false;
                        }
                        if (nearGround)
                        {
                            break;
                        }
                    }
                }

                if (nearGround)
                {
                    // We're rolling.
                    this.Rolling.Value = true;

                    Session.Recorder.Event(main, "Roll");

                    this.DeactivateWallRun.Execute();

                    this.EnableWalking.Value = false;
                    this.LockRotation.Execute();

                    this.Footstep.Execute();                     // We just landed; play a footstep sound
                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_PLAYER_ROLL, this.Entity);

                    this.model.StartClip("Roll", 5, false, AnimatedModel.DefaultBlendTime);

                    Voxel.State floorState = floorRaycast.Voxel == null ? Voxel.States.Empty : floorRaycast.Coordinate.Value.Data;
                    if (this.EnableEnhancedRollSlide && (instantiatedBlockPossibility || (this.IsSupported && floorState != Voxel.States.Slider && floorState != Voxel.States.SliderPowered)))
                    {
                        this.shouldBuildFloor |= this.determineShouldBuildFloor(floorRaycast.Voxel, floorState);
                    }

                    // If the player is not yet supported, that means they're just about to land.
                    // So give them a little speed boost for having such good timing.
                    this.velocity             = this.SupportVelocity + this.forward * this.MaxSpeed * (this.IsSupported ? 0.75f : 1.25f);
                    this.LinearVelocity.Value = new Vector3(this.velocity.X, instantiatedBlockPossibility ? 0.0f : this.LinearVelocity.Value.Y, this.velocity.Z);

                    // Crouch
                    this.Crouched.Value      = true;
                    this.AllowUncrouch.Value = false;

                    this.rightDir   = this.floorMap.GetRelativeDirection(this.right);
                    this.forwardDir = this.floorMap.GetRelativeDirection(this.forward);

                    this.rollKickTime          = 0.0f;
                    this.firstTimeBreak        = true;
                    this.LastRollStarted.Value = this.main.TotalTime;
                }
            }

            if (!this.Rolling && this.EnableCrouch && this.EnableKick && this.CanKick && !this.Kicking && !this.IsSwimming && Vector3.Dot(this.LinearVelocity.Value - this.SupportVelocity, this.forward) > 0.05f)
            {
                // Kick
                this.Kicking.Value = true;
                this.CanKick.Value = false;

                Session.Recorder.Event(main, "Kick");

                this.DeactivateWallRun.Execute();

                this.EnableWalking.Value = false;
                this.LockRotation.Execute();

                this.Crouched.Value      = true;
                this.AllowUncrouch.Value = false;

                Vector3 playerPos = this.FloorPosition + new Vector3(0, 0.5f, 0);

                this.sliding = false;

                Voxel.GlobalRaycastResult floorRaycast = this.raycastFloor();
                this.floorMap = floorRaycast.Voxel;

                if (instantiatedBlockPossibility)
                {
                    this.sliding          = true;
                    this.shouldBuildFloor = true;
                }
                else if (this.floorMap == null)
                {
                    this.shouldBuildFloor = false;
                    this.sliding          = false;
                    this.floorCoordinate  = new Voxel.Coord();
                }
                else if (this.LinearVelocity.Value.Y - this.SupportVelocity.Value.Y < 1.0f)
                {
                    this.floorCoordinate = floorRaycast.Coordinate.Value;
                    if (this.EnableEnhancedRollSlide)
                    {
                        this.shouldBuildFloor |= this.determineShouldBuildFloor(floorRaycast.Voxel, floorRaycast.Coordinate.Value.Data);
                    }
                    this.sliding = true;
                }

                float forwardSpeed = Vector3.Dot(this.forward, this.LinearVelocity.Value - this.SupportVelocity);
                if (forwardSpeed < this.MaxSpeed * 1.1f)
                {
                    if (this.sliding)
                    {
                        this.velocity = this.LinearVelocity.Value + this.forward * (this.MaxSpeed - forwardSpeed);
                    }
                    else
                    {
                        this.velocity = this.LinearVelocity.Value + this.forward * Math.Max(4.0f, forwardSpeed * 0.4f) + new Vector3(0, this.JumpSpeed * 0.2f, 0);
                    }
                }
                else
                {
                    this.velocity = this.LinearVelocity;
                }

                if (this.sliding)
                {
                    this.velocity.Y = 0.0f;
                }

                this.LinearVelocity.Value = this.velocity;

                this.model.StartClip(this.sliding ? "Slide" : "Kick", 5, false, AnimatedModel.DefaultBlendTime);
                AkSoundEngine.PostEvent(AK.EVENTS.PLAY_PLAYER_SLIDE, this.Entity);
                if (this.sliding)                 // We're sliding on the floor
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_PLAYER_SLIDE_LOOP, this.Entity);
                }

                this.forwardDir = Direction.None;
                this.rightDir   = Direction.None;

                if (this.floorMap != null)
                {
                    this.forwardDir = this.floorMap.GetRelativeDirection(this.forward);
                    this.rightDir   = this.floorMap.GetRelativeDirection(this.right);
                }

                this.rollKickTime   = 0.0f;
                this.firstTimeBreak = true;
            }
        }
Пример #30
0
 public override void Initialize(Voxel.State fillType, int radius)
 {
     base.Initialize(fillType, radius);
     sqrRadius = radius * radius;
 }