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); }
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"); AkGameObjectTracker.Attach(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)); blockCloud.Add(new Binding <Vector3>(blockCloud.Position, transform.Position)); const float operationalRadius = 100.0f; AI.Task checkOperationalRadius = new AI.Task { Interval = 2.0f, Action = delegate() { bool shouldBeActive = (transform.Position.Value - main.Camera.Position).Length() < 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", 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) { ai.TargetAgent.Value = null; ai.CurrentState.Value = "Idle"; } }, }; // Chase AI state ai.Add(new AI.AIState { Name = "Chase", Enter = delegate(AI.AIState previous) { AkSoundEngine.PostEvent(AK.EVENTS.EVIL_CUBES_CHASE, entity); raycastAI.BlendTime.Value = 0.5f; }, Exit = delegate(AI.AIState next) { raycastAI.BlendTime.Value = 1.0f; AkSoundEngine.PostEvent(AK.EVENTS.EVIL_CUBES_IDLE, entity); }, Tasks = new[] { checkOperationalRadius, checkTargetAgent, new AI.Task { Interval = 0.5f, Action = delegate() { raycastAI.Move(ai.TargetAgent.Value.Target.Get <Transform>().Position.Value - transform.Position); } }, updatePosition, }, }); this.SetMain(entity, main); }
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); }
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) { Sound.AttachTracker(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; 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 "Explode": 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; } )); model.Add(new Binding <bool, string>(model.Enabled, x => x != "Exploding", ai.CurrentState)); light.Add(new Binding <Vector3>(light.Color, model.Color)); Agent agent = entity.GetOrCreate <Agent>(); agent.Add(new Binding <Vector3>(agent.Position, transform.Position)); RaycastAIMovement movement = entity.GetOrCreate <RaycastAIMovement>("Movement"); Exploder exploder = entity.GetOrCreate <Exploder>("Exploder"); 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"; } }, }; 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 updatePosition = new AI.Task { Action = delegate() { raycastAI.Update(); }, }; ai.Add(new AI.AIState { Name = "Suspended", Tasks = new[] { checkOperationalRadius, }, }); const float sightDistance = 40.0f; const float hearingDistance = 0.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 = 0.5f, 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"; } }, }; 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); } }, new AI.Task { Action = delegate() { if ((ai.TargetAgent.Value.Target.Get <Transform>().Position.Value - transform.Position).Length() < 10.0f) { ai.CurrentState.Value = "Explode"; } } }, updatePosition, }, }); EffectBlockFactory factory = Factory.Get <EffectBlockFactory>(); ai.Add(new AI.AIState { Name = "Explode", Enter = delegate(AI.AIState previous) { exploder.CoordQueue.Clear(); Entity voxelEntity = raycastAI.Voxel.Value.Target; if (voxelEntity == null || !voxelEntity.Active) { ai.CurrentState.Value = "Alert"; return; } Voxel m = voxelEntity.Get <Voxel>(); Voxel.Coord c = raycastAI.Coord.Value; Direction toSupport = Direction.None; foreach (Direction dir in DirectionExtensions.Directions) { if (m[raycastAI.Coord.Value.Move(dir)].ID != 0) { toSupport = dir; break; } } if (toSupport == Direction.None) { ai.CurrentState.Value = "Alert"; return; } Direction up = toSupport.GetReverse(); exploder.ExplosionOriginalCoord.Value = raycastAI.Coord; Direction right; if (up.IsParallel(Direction.PositiveX)) { right = Direction.PositiveZ; } else { right = Direction.PositiveX; } Direction forward = up.Cross(right); for (Voxel.Coord y = c.Clone(); y.GetComponent(up) < c.GetComponent(up) + 3; y = y.Move(up)) { for (Voxel.Coord x = y.Clone(); x.GetComponent(right) < c.GetComponent(right) + 2; x = x.Move(right)) { for (Voxel.Coord z = x.Clone(); z.GetComponent(forward) < c.GetComponent(forward) + 2; z = z.Move(forward)) { exploder.CoordQueue.Add(z); } } } }, Exit = delegate(AI.AIState next) { exploder.CoordQueue.Clear(); }, Tasks = new[] { checkOperationalRadius, new AI.Task { Interval = 0.15f, Action = delegate() { if (exploder.CoordQueue.Length > 0) { raycastAI.MoveTo(exploder.CoordQueue[0]); exploder.CoordQueue.RemoveAt(0); Entity blockEntity = factory.CreateAndBind(main); Voxel.States.Infected.ApplyToEffectBlock(blockEntity.Get <ModelInstance>()); Entity mapEntity = raycastAI.Voxel.Value.Target; if (mapEntity != null && mapEntity.Active) { EffectBlock effectBlock = blockEntity.Get <EffectBlock>(); Voxel m = mapEntity.Get <Voxel>(); effectBlock.Offset.Value = m.GetRelativePosition(raycastAI.Coord); Vector3 absolutePos = m.GetAbsolutePosition(raycastAI.Coord); effectBlock.StartPosition = absolutePos + new Vector3(0.05f, 0.1f, 0.05f); effectBlock.StartOrientation = Quaternion.CreateFromYawPitchRoll(0.15f, 0.15f, 0); effectBlock.TotalLifetime = 0.05f; effectBlock.Setup(raycastAI.Voxel.Value.Target, raycastAI.Coord, Voxel.t.Infected); main.Add(blockEntity); } } } }, new AI.Task { Action = delegate() { AkSoundEngine.SetRTPCValue(AK.GAME_PARAMETERS.SFX_GLOWSQUARE_PITCH, MathHelper.Lerp(0.0f, 1.0f, ai.TimeInCurrentState.Value / 2.0f), entity); if (exploder.CoordQueue.Length == 0) { // Explode ai.CurrentState.Value = "Exploding"; } }, }, updatePosition, }, }); ai.Add(new AI.AIState { Name = "Exploding", Enter = delegate(AI.AIState previous) { exploder.Exploded.Value = false; AkSoundEngine.PostEvent(AK.EVENTS.STOP_GLOWSQUARE, entity); }, Exit = delegate(AI.AIState next) { exploder.Exploded.Value = false; AkSoundEngine.PostEvent(AK.EVENTS.PLAY_GLOWSQUARE, entity); }, Tasks = new[] { new AI.Task { Interval = 0.1f, Action = delegate() { const int radius = 9; float timeInCurrentState = ai.TimeInCurrentState; if (timeInCurrentState > 1.0f && !exploder.Exploded) { Entity mapEntity = raycastAI.Voxel.Value.Target; if (mapEntity != null && mapEntity.Active) { Explosion.Explode(main, mapEntity.Get <Voxel>(), raycastAI.Coord, radius, 18.0f); } exploder.Exploded.Value = true; } if (timeInCurrentState > 2.0f) { 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"; } }, }, updatePosition, }, }); this.SetMain(entity, main); entity.Add("OperationalRadius", movement.OperationalRadius); }