private IEnumerable <Voxel.Coord> spreadFromCenter(Voxel.Coord center, Direction dir) { for (Voxel.Coord z = center.Move(dir, -1); z.GetComponent(dir) > center.GetComponent(dir) - 3; z = z.Move(dir.GetReverse())) { yield return(z); } for (Voxel.Coord z = center.Clone(); z.GetComponent(dir) < center.GetComponent(dir) + 3; z = z.Move(dir)) { yield return(z); } }
public override void Awake() { base.Awake(); AkGameObjectTracker.Attach(this.Entity, this.Position); this.particles = ParticleSystem.Get(this.main, "Rift"); this.EnabledInEditMode = false; this.EnabledWhenPaused = false; this.Add(new CommandBinding(this.Enable, delegate() { if (this.Coords.Length == 0) { AkSoundEngine.PostEvent(AK.EVENTS.PLAY_RIFT_OPEN, this.Entity); if (PlayerFactory.Instance != null) { PlayerFactory.Instance.Get <CameraController>().Shake.Execute(this.Position, 30.0f); } Entity voxelEntity = this.Voxel.Value.Target; if (voxelEntity != null && voxelEntity.Active) { Voxel v = voxelEntity.Get <Voxel>(); Voxel.Coord center = this.Coordinate; Vector3 pos = v.GetRelativePosition(center); int radius = this.Radius; List <VoxelFill.CoordinateEntry> coords = Rift.coordSortCache; for (Voxel.Coord x = center.Move(Direction.NegativeX, radius); x.X < center.X + radius; x.X++) { for (Voxel.Coord y = x.Move(Direction.NegativeY, radius); y.Y < center.Y + radius; y.Y++) { for (Voxel.Coord z = y.Move(Direction.NegativeZ, radius); z.Z < center.Z + radius; z.Z++) { float distance = (pos - v.GetRelativePosition(z)).Length(); if (distance <= radius && v[z] != Components.Voxel.States.Empty) { coords.Add(new VoxelFill.CoordinateEntry { Coord = z.Clone(), Distance = distance }); } } } } coords.Sort(new LambdaComparer <VoxelFill.CoordinateEntry>((x, y) => x.Distance.CompareTo(y.Distance))); this.Coords.AddAll(coords.Select(x => x.Coord)); coords.Clear(); } } })); rifts.Add(this); }
private void go() { if (this.Coords.Length == 0) { AkSoundEngine.PostEvent(AK.EVENTS.PLAY_RIFT_OPEN, this.Entity); if (PlayerFactory.Instance != null) { PlayerFactory.Instance.Get <CameraController>().Shake.Execute(this.Position, 30.0f); } Entity voxelEntity = this.Voxel.Value.Target; if (voxelEntity != null && voxelEntity.Active) { Voxel v = voxelEntity.Get <Voxel>(); Voxel.Coord center = this.Coordinate; Vector3 pos = v.GetRelativePosition(center); int radius = this.Radius; List <VoxelFill.CoordinateEntry> coords = Rift.coordSortCache; for (Voxel.Coord x = center.Move(Direction.NegativeX, radius); x.X < center.X + radius; x.X++) { for (Voxel.Coord y = x.Move(Direction.NegativeY, radius); y.Y < center.Y + radius; y.Y++) { for (Voxel.Coord z = y.Move(Direction.NegativeZ, radius); z.Z < center.Z + radius; z.Z++) { float distance = (pos - v.GetRelativePosition(z)).Length(); if (distance <= radius && v[z] != Components.Voxel.States.Empty) { coords.Add(new VoxelFill.CoordinateEntry { Coord = z.Clone(), Distance = distance }); } } } } if (coords.Count == 0) { this.Entity.Delete.Execute(); } else { coords.Sort(new LambdaComparer <VoxelFill.CoordinateEntry>((x, y) => x.Distance.CompareTo(y.Distance))); this.Coords.AddAll(coords.Select(x => x.Coord)); coords.Clear(); } } } }
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(); } })); }
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); }
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); }