Beispiel #1
0
        public override void Bind(Entity entity, Main main, bool creating = false)
        {
            BlockCloud blockCloud = entity.GetOrCreate <BlockCloud>("BlockCloud");

            blockCloud.Add(new CommandBinding(blockCloud.Delete, entity.Delete));
            blockCloud.Add(new CommandBinding <Collidable, ContactCollection>(blockCloud.Collided, delegate(Collidable other, ContactCollection contacts)
            {
                if (other.Tag != null && other.Tag.GetType() == typeof(Character))
                {
                    // Damage the player
                    Entity p = PlayerFactory.Instance;
                    if (p != null && p.Active)
                    {
                        p.Get <Agent>().Damage.Execute(0.1f);
                    }
                }
            }));
            blockCloud.Type.Value = Voxel.t.Black;

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

            Sound.AttachTracker(entity);

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

            if (!main.EditorEnabled)
            {
                entity.Add(new PostInitialization(delegate()
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_EVIL_CUBES, entity);
                    AkSoundEngine.PostEvent(ai.CurrentState == "Chase" ? AK.EVENTS.EVIL_CUBES_CHASE : AK.EVENTS.EVIL_CUBES_IDLE, entity);
                }));

                SoundKiller.Add(entity, AK.EVENTS.STOP_EVIL_CUBES);
            }

            Agent agent = entity.GetOrCreate <Agent>();

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

            RaycastAI raycastAI = entity.GetOrCreate <RaycastAI>("RaycastAI");

            raycastAI.BlendTime.Value = 1.0f;
            raycastAI.Add(new TwoWayBinding <Vector3>(transform.Position, raycastAI.Position));
            raycastAI.Add(new Binding <Quaternion>(transform.Quaternion, raycastAI.Orientation));

            RaycastAIMovement movement = entity.GetOrCreate <RaycastAIMovement>("Movement");

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

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

            AI.Task updatePosition = new AI.Task
            {
                Action = delegate()
                {
                    raycastAI.Update();
                },
            };

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

            const float sightDistance   = 25.0f;
            const float hearingDistance = 0.0f;

            ai.Add(new AI.AIState
            {
                Name  = "Idle",
                Tasks = new[]
                {
                    checkOperationalRadius,
                    updatePosition,
                    new AI.Task
                    {
                        Interval = 1.0f,
                        Action   = delegate()
                        {
                            raycastAI.Move(new Vector3(((float)this.random.NextDouble() * 2.0f) - 1.0f, ((float)this.random.NextDouble() * 2.0f) - 1.0f, ((float)this.random.NextDouble() * 2.0f) - 1.0f));
                        }
                    },
                    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,
                    updatePosition,
                    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 = "Chase";
                                }
                            }
                        },
                    },
                },
            });

            AI.Task checkTargetAgent = new AI.Task
            {
                Action = delegate()
                {
                    Entity target = ai.TargetAgent.Value.Target;
                    if (target == null || !target.Active || (target.Get <Transform>().Position.Value - transform.Position.Value).Length() > sightDistance * 1.25f)
                    {
                        ai.TargetAgent.Value  = null;
                        ai.CurrentState.Value = "Alert";
                    }
                },
            };

            Action findNextPosition = delegate()
            {
                movement.LastPosition.Value = transform.Position.Value;
                float   radius = 5.0f;
                Vector3 center = ai.TargetAgent.Value.Target.Get <Transform>().Position;
                Vector3 candidate;
                do
                {
                    candidate = center + new Vector3((float)this.random.NextDouble() - 0.5f, (float)this.random.NextDouble(), (float)this.random.NextDouble() - 0.5f) * radius;
                    radius   += 1.0f;
                }while (!RaycastAI.DefaultPositionFilter(candidate));

                Vector3     toCandidate         = candidate - movement.LastPosition;
                float       distance            = toCandidate.Length();
                const float maxMovementDistance = 9.0f;
                if (distance > maxMovementDistance)
                {
                    toCandidate *= maxMovementDistance / distance;
                }

                movement.NextPosition.Value  = movement.LastPosition.Value + toCandidate;
                movement.PositionBlend.Value = 0.0f;
            };

            // Chase AI state

            ai.Add(new AI.AIState
            {
                Name  = "Chase",
                Enter = delegate(AI.AIState previous)
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.EVIL_CUBES_CHASE, entity);
                    findNextPosition();
                },
                Exit = delegate(AI.AIState next)
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.EVIL_CUBES_IDLE, entity);
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    checkTargetAgent,
                    new AI.Task
                    {
                        Action = delegate()
                        {
                            if (ai.TimeInCurrentState.Value > 15.0f)
                            {
                                Entity voxel = raycastAI.Voxel.Value.Target;
                                if (voxel != null && voxel.Active)
                                {
                                    raycastAI.Coord.Value = raycastAI.LastCoord.Value = voxel.Get <Voxel>().GetCoordinate(transform.Position);
                                }
                                raycastAI.Move(new Vector3(((float)this.random.NextDouble() * 2.0f) - 1.0f, ((float)this.random.NextDouble() * 2.0f) - 1.0f, ((float)this.random.NextDouble() * 2.0f) - 1.0f));
                                ai.CurrentState.Value = "Idle";
                            }
                            else
                            {
                                movement.PositionBlend.Value += (main.ElapsedTime.Value / 1.0f);
                                if (movement.PositionBlend > 1.0f)
                                {
                                    findNextPosition();
                                }
                                transform.Position.Value = Vector3.Lerp(movement.LastPosition, movement.NextPosition, movement.PositionBlend);
                            }
                        }
                    },
                },
            });

            this.SetMain(entity, main);
        }
Beispiel #2
0
        public override void Bind(Entity entity, Main main, bool creating = false)
        {
            PointLight light = entity.GetOrCreate <PointLight>("PointLight");

            light.Serialize = false;

            const float defaultLightAttenuation = 15.0f;

            light.Attenuation.Value = defaultLightAttenuation;

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

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

            if (!main.EditorEnabled)
            {
                AkGameObjectTracker.Attach(entity);
                SoundKiller.Add(entity, AK.EVENTS.STOP_GLOWSQUARE);
                entity.Add(new PostInitialization
                {
                    delegate()
                    {
                        AkSoundEngine.PostEvent(AK.EVENTS.PLAY_GLOWSQUARE, entity);
                        AkSoundEngine.SetRTPCValue(AK.GAME_PARAMETERS.SFX_GLOWSQUARE_PITCH, -1.0f, entity);
                    }
                });
            }

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

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

            model.Add(new Binding <Matrix>(model.Transform, transform.Matrix));
            model.Filename.Value  = "AlphaModels\\box";
            model.Serialize       = false;
            model.DrawOrder.Value = 15;

            RaycastAIMovement movement  = entity.GetOrCreate <RaycastAIMovement>("Movement");
            Levitator         levitator = entity.GetOrCreate <Levitator>("Levitator");

            const float defaultModelScale = 1.0f;

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

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

                case "Chase":
                    return(new Vector3(1.5f, 0.5f, 0.5f));

                case "Levitating":
                    return(new Vector3(2.0f, 1.0f, 0.5f));

                default:
                    return(new Vector3(1.0f, 1.0f, 1.0f));
                }
            }, ai.CurrentState));

            entity.Add(new Updater
                       (
                           delegate(float dt)
            {
                float source            = 1.0f + ((float)this.random.NextDouble() - 0.5f) * 2.0f * 0.05f;
                model.Scale.Value       = new Vector3(defaultModelScale * source);
                light.Attenuation.Value = defaultLightAttenuation * source;
            }
                       ));

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

            Agent agent = entity.GetOrCreate <Agent>();

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

            RaycastAI raycastAI = entity.GetOrCreate <RaycastAI>("RaycastAI");

            raycastAI.Add(new TwoWayBinding <Vector3>(transform.Position, raycastAI.Position));
            raycastAI.Add(new Binding <Quaternion>(transform.Quaternion, raycastAI.Orientation));

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

            AI.Task updatePosition = new AI.Task
            {
                Action = delegate()
                {
                    raycastAI.Update();
                },
            };

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

            const float sightDistance   = 30.0f;
            const float hearingDistance = 15.0f;

            ai.Add(new AI.AIState
            {
                Name  = "Idle",
                Enter = delegate(AI.AIState previous)
                {
                    AkSoundEngine.SetRTPCValue(AK.GAME_PARAMETERS.SFX_GLOWSQUARE_PITCH, -1.0f, entity);
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    updatePosition,
                    new AI.Task
                    {
                        Interval = 1.0f,
                        Action   = delegate()
                        {
                            raycastAI.Move(new Vector3(((float)this.random.NextDouble() * 2.0f) - 1.0f, ((float)this.random.NextDouble() * 2.0f) - 1.0f, ((float)this.random.NextDouble() * 2.0f) - 1.0f));
                        }
                    },
                    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",
                Enter = delegate(AI.AIState previous)
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.STOP_GLOWSQUARE, entity);
                },
                Exit = delegate(AI.AIState next)
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_GLOWSQUARE, entity);
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    updatePosition,
                    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 = "Chase";
                                }
                            }
                        },
                    },
                },
            });

            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";
                    }
                },
            };

            // Levitate

            const int levitateRipRadius = 4;

            Func <bool> tryLevitate = delegate()
            {
                Entity voxelEntity = raycastAI.Voxel.Value.Target;
                if (voxelEntity == null)
                {
                    return(false);
                }

                Voxel       map       = voxelEntity.Get <Voxel>();
                Voxel.Coord?candidate = map.FindClosestFilledCell(raycastAI.Coord, 3);

                if (!candidate.HasValue)
                {
                    return(false);
                }

                if (VoxelRip.Go(map, candidate.Value, levitateRipRadius, delegate(List <DynamicVoxel> spawnedMaps)
                {
                    foreach (DynamicVoxel spawnedMap in spawnedMaps)
                    {
                        if (spawnedMap[candidate.Value] != Voxel.States.Empty)
                        {
                            levitator.LevitatingVoxel.Value = spawnedMap.Entity;
                            break;
                        }
                    }
                }))
                {
                    levitator.GrabCoord.Value = candidate.Value;
                    return(true);
                }

                return(false);
            };

            Action delevitateMap = delegate()
            {
                Entity levitatingMapEntity = levitator.LevitatingVoxel.Value.Target;
                if (levitatingMapEntity == null || !levitatingMapEntity.Active)
                {
                    return;
                }

                DynamicVoxel dynamicMap = levitatingMapEntity.Get <DynamicVoxel>();
                VoxelRip.Consolidate(main, dynamicMap);
            };

            // Chase AI state

            ai.Add(new AI.AIState
            {
                Name  = "Chase",
                Enter = delegate(AI.AIState previous)
                {
                    AkSoundEngine.SetRTPCValue(AK.GAME_PARAMETERS.SFX_GLOWSQUARE_PITCH, 0.0f, entity);
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    checkTargetAgent,
                    new AI.Task
                    {
                        Interval = 0.35f,
                        Action   = delegate()
                        {
                            raycastAI.Move(ai.TargetAgent.Value.Target.Get <Transform>().Position.Value - transform.Position);
                        }
                    },
                    updatePosition,
                    new AI.Task
                    {
                        Interval = 0.1f,
                        Action   = delegate()
                        {
                            Entity target          = ai.TargetAgent.Value.Target;
                            Vector3 targetPosition = target.Get <Transform>().Position;
                            if ((targetPosition - transform.Position).Length() < 15.0f)
                            {
                                if (tryLevitate())
                                {
                                    ai.CurrentState.Value = "Levitating";
                                }
                            }
                        }
                    }
                },
            });

            Action findNextPosition = delegate()
            {
                movement.LastPosition.Value = transform.Position.Value;
                float   radius = 5.0f;
                Vector3 center = ai.TargetAgent.Value.Target.Get <Transform>().Position;
                Vector3 candidate;
                do
                {
                    candidate = center + new Vector3((float)this.random.NextDouble() - 0.5f, (float)this.random.NextDouble(), (float)this.random.NextDouble() - 0.5f) * radius;
                    radius   += 1.0f;
                }while (!RaycastAI.DefaultPositionFilter(candidate));

                movement.NextPosition.Value  = candidate;
                movement.PositionBlend.Value = 0.0f;
            };

            ai.Add(new AI.AIState
            {
                Name  = "Levitating",
                Enter = delegate(AI.AIState previous)
                {
                    findNextPosition();
                },
                Exit = delegate(AI.AIState next)
                {
                    delevitateMap();
                    levitator.LevitatingVoxel.Value = null;

                    //volume.Value = defaultVolume;
                    //pitch.Value = 0.0f;
                },
                Tasks = new[]
                {
                    checkTargetAgent,
                    new AI.Task
                    {
                        Action = delegate()
                        {
                            //volume.Value = 1.0f;
                            //pitch.Value = 1.0f;
                            Entity levitatingMapEntity = levitator.LevitatingVoxel.Value.Target;
                            if (levitatingMapEntity == null || !levitatingMapEntity.Active || ai.TimeInCurrentState.Value > 8.0f)
                            {
                                Entity voxel = raycastAI.Voxel.Value.Target;
                                if (voxel != null && voxel.Active)
                                {
                                    raycastAI.Coord.Value = raycastAI.LastCoord.Value = voxel.Get <Voxel>().GetCoordinate(transform.Position);
                                }
                                raycastAI.Move(new Vector3(((float)this.random.NextDouble() * 2.0f) - 1.0f, ((float)this.random.NextDouble() * 2.0f) - 1.0f, ((float)this.random.NextDouble() * 2.0f) - 1.0f));
                                ai.CurrentState.Value = "Alert";
                                return;
                            }

                            DynamicVoxel dynamicMap = levitatingMapEntity.Get <DynamicVoxel>();

                            movement.PositionBlend.Value += (main.ElapsedTime.Value / 1.0f);
                            if (movement.PositionBlend > 1.0f)
                            {
                                findNextPosition();
                            }

                            transform.Position.Value = Vector3.Lerp(movement.LastPosition, movement.NextPosition, movement.PositionBlend);

                            Vector3 grabPoint = dynamicMap.GetAbsolutePosition(levitator.GrabCoord);
                            Vector3 diff      = transform.Position.Value - grabPoint;
                            if (diff.Length() > 15.0f)
                            {
                                ai.CurrentState.Value = "Chase";
                                return;
                            }

                            diff *= (float)Math.Sqrt(dynamicMap.PhysicsEntity.Mass) * 0.5f;
                            dynamicMap.PhysicsEntity.ApplyImpulse(ref grabPoint, ref diff);
                        },
                    },
                },
            });

            this.SetMain(entity, main);
        }