private void fall() { if (this.TimeUntilRebuild.Value > 0 || this.TimeUntilRebuildComplete.Value > 0) { return; } Entity targetVoxel = this.TargetVoxel.Value.Target; if (targetVoxel == null || !targetVoxel.Active) { return; } // Disable the cell-emptied notification. // This way, we won't think that the base has been destroyed by the player. // We are not in fact dying, we're just destroying the base so we can fall over. this.Base.EnableCellEmptyBinding = false; Voxel m = targetVoxel.Get <Voxel>(); m.Empty(this.Base.BaseBoxes.SelectMany(x => x.GetCoords())); m.Regenerate(delegate(List <DynamicVoxel> spawnedMaps) { if (spawnedMaps.Count == 0) { this.Delete.Execute(); } else { Vector3 playerPos = PlayerFactory.Instance.Get <Transform>().Position; playerPos += PlayerFactory.Instance.Get <Player>().Character.LinearVelocity.Value * 0.65f; foreach (DynamicVoxel newMap in spawnedMaps) { Vector3 toPlayer = playerPos - newMap.PhysicsEntity.Position; toPlayer.Normalize(); if (Math.Abs(toPlayer.Y) < 0.9f) { toPlayer *= 25.0f * newMap.PhysicsEntity.Mass; Vector3 positionAtPlayerHeight = newMap.PhysicsEntity.Position; Vector3 impulseAtBase = toPlayer * -0.75f; impulseAtBase.Y = 0.0f; positionAtPlayerHeight.Y = playerPos.Y; newMap.PhysicsEntity.ApplyImpulse(ref positionAtPlayerHeight, ref impulseAtBase); newMap.PhysicsEntity.ApplyLinearImpulse(ref toPlayer); } newMap.PhysicsEntity.Material.KineticFriction = 1.0f; newMap.PhysicsEntity.Material.StaticFriction = 1.0f; this.DynamicVoxels.Add(newMap.Entity); } } }); this.TimeUntilRebuild.Value = RebuildDelay; }
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(); }
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(); } } })); }
public override void Bind(Entity entity, Main main, bool creating = false) { Transform transform = entity.GetOrCreate <Transform>("Transform"); this.SetMain(entity, main); VoxelAttachable attachable = VoxelAttachable.MakeAttachable(entity, main, true, false); attachable.Offset.Value = 1; attachable.Enabled.Value = true; PowerBlockSocket socket = entity.GetOrCreate <PowerBlockSocket>("PowerBlockSocket"); socket.Add(new Binding <Voxel.Coord>(socket.Coord, attachable.Coord)); socket.Add(new Binding <Entity.Handle>(socket.AttachedVoxel, attachable.AttachedVoxel)); const float maxLightAttenuation = 15.0f; PointLight light = entity.Create <PointLight>(); light.Attenuation.Value = maxLightAttenuation; light.Add(new Binding <Vector3>(light.Position, transform.Position)); light.Add(new Binding <Vector3, Voxel.t>(light.Color, delegate(Voxel.t t) { switch (t) { case Voxel.t.GlowBlue: return(new Vector3(0.8f, 0.9f, 1.2f)); case Voxel.t.GlowYellow: return(new Vector3(1.2f, 1.2f, 0.8f)); default: return(Vector3.One); } }, socket.Type)); light.Add(new Binding <bool>(light.Enabled, socket.Powered)); PointLight animationLight = entity.Create <PointLight>(); animationLight.Add(new Binding <Vector3>(animationLight.Position, light.Position)); animationLight.Add(new Binding <Vector3>(animationLight.Color, light.Color)); animationLight.Enabled.Value = false; PlayerTrigger trigger = entity.GetOrCreate <PlayerTrigger>("PlayerTrigger"); trigger.Radius.Value = 7; trigger.Add(new Binding <Vector3>(trigger.Position, transform.Position)); const float minimumChangeTime = 1.5f; float lastChange = -minimumChangeTime; trigger.Add(new CommandBinding(trigger.PlayerEntered, delegate() { if (main.TotalTime - lastChange > minimumChangeTime) { BlockCloud cloud = PlayerFactory.Instance.Get <BlockCloud>(); bool changed = false; Voxel sockVoxel = attachable.AttachedVoxel.Value.Target.Get <Voxel>(); if (!socket.Powered && cloud.Type.Value == socket.Type.Value) { // Plug in to the socket List <Voxel.Coord> coords = new List <Voxel.Coord>(); Queue <Voxel.Coord> queue = new Queue <Voxel.Coord>(); queue.Enqueue(sockVoxel.GetCoordinate(transform.Position)); while (queue.Count > 0) { Voxel.Coord c = queue.Dequeue(); coords.Add(c); if (coords.Count >= cloud.Blocks.Length) { break; } Voxel.CoordDictionaryCache[c] = true; foreach (Direction adjacentDirection in DirectionExtensions.Directions) { Voxel.Coord adjacentCoord = c.Move(adjacentDirection); if (!Voxel.CoordDictionaryCache.ContainsKey(adjacentCoord)) { Voxel.t adjacentID = sockVoxel[adjacentCoord].ID; if (adjacentID == Voxel.t.Empty) { queue.Enqueue(adjacentCoord); } } } } Voxel.CoordDictionaryCache.Clear(); EffectBlockFactory factory = Factory.Get <EffectBlockFactory>(); int i = 0; foreach (Entity block in cloud.Blocks) { Entity effectBlockEntity = factory.CreateAndBind(main); Voxel.States.All[cloud.Type].ApplyToEffectBlock(effectBlockEntity.Get <ModelInstance>()); EffectBlock effectBlock = effectBlockEntity.Get <EffectBlock>(); effectBlock.DoScale = false; Transform blockTransform = block.Get <Transform>(); effectBlock.StartPosition = blockTransform.Position; effectBlock.StartOrientation = blockTransform.Quaternion; effectBlock.TotalLifetime = (i + 1) * 0.04f; effectBlock.Setup(sockVoxel.Entity, coords[i], cloud.Type); main.Add(effectBlockEntity); block.Delete.Execute(); i++; } cloud.Blocks.Clear(); cloud.Type.Value = Voxel.t.Empty; socket.Powered.Value = true; changed = true; } else if (socket.Powered && cloud.Type.Value == Voxel.t.Empty && !socket.PowerOnOnly) { // Pull blocks out of the socket SceneryBlockFactory factory = Factory.Get <SceneryBlockFactory>(); Quaternion quat = Quaternion.CreateFromRotationMatrix(sockVoxel.Transform); cloud.Type.Value = socket.Type; List <Voxel.Coord> coords = sockVoxel.GetContiguousByType(new[] { sockVoxel.GetBox(transform.Position) }).SelectMany(x => x.GetCoords()).ToList(); sockVoxel.Empty(coords, true); sockVoxel.Regenerate(); ParticleSystem particles = ParticleSystem.Get(main, "WhiteShatter"); foreach (Voxel.Coord c in coords) { Vector3 pos = sockVoxel.GetAbsolutePosition(c); for (int j = 0; j < 20; j++) { Vector3 offset = new Vector3((float)this.random.NextDouble() - 0.5f, (float)this.random.NextDouble() - 0.5f, (float)this.random.NextDouble() - 0.5f); particles.AddParticle(pos + offset, offset); } Entity block = factory.CreateAndBind(main); Transform blockTransform = block.Get <Transform>(); blockTransform.Position.Value = pos; blockTransform.Quaternion.Value = quat; SceneryBlock sceneryBlock = block.Get <SceneryBlock>(); sceneryBlock.Type.Value = socket.Type; sceneryBlock.Scale.Value = 0.5f; cloud.Blocks.Add(block); main.Add(block); } socket.Powered.Value = false; changed = true; } if (changed) { lastChange = main.TotalTime; animationLight.Enabled.Value = true; animationLight.Attenuation.Value = 0.0f; entity.Add(new Animation ( new Animation.FloatMoveTo(animationLight.Attenuation, maxLightAttenuation, 0.25f), new Animation.FloatMoveTo(animationLight.Attenuation, 0.0f, 2.0f), new Animation.Set <bool>(animationLight.Enabled, false) )); } } })); entity.Add("Type", socket.Type); entity.Add("Powered", socket.Powered, new PropertyEntry.EditorData { Readonly = true }); entity.Add("PowerOnOnly", socket.PowerOnOnly); entity.Add("OnPowerOn", socket.OnPowerOn); entity.Add("OnPowerOff", socket.OnPowerOff); }
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); }
public void Update(float dt) { float sparkLightFade = sparkLightBrightness * dt / sparkLightFadeTime; for (int i = 0; i < activeSparkLights; i++) { PointLight light = this.sparkLights[i]; float a = light.Color.Value.X - sparkLightFade; if (a < 0.0f) { light.Enabled.Value = false; PointLight swap = this.sparkLights[activeSparkLights - 1]; this.sparkLights[i] = swap; this.sparkLights[activeSparkLights - 1] = light; activeSparkLights--; oldestSparkLight = activeSparkLights; } else { light.Color.Value = new Vector3(a); } } for (int i = 0; i < this.BlockQueue.Length; i++) { ScheduledBlock entry = this.BlockQueue[i]; entry.Time -= dt; if (entry.Time < 0.0f) { this.BlockQueue.RemoveAt(i); i--; Entity mapEntity = entry.Voxel.Target; if (mapEntity != null && mapEntity.Active) { Voxel map = mapEntity.Get <Voxel>(); Voxel.Coord c = entry.Coordinate; Voxel.t id = map[c].ID; bool regenerate = false; if (entry.Removing) { if (entry.Generation == 0 && id == 0) { Direction down = map.GetRelativeDirection(Direction.NegativeY); for (int j = 0; j < 6; j++) { Direction dir = DirectionExtensions.Directions[j]; Voxel.Coord adjacent = c.Move(dir); Voxel.t adjacentID = map[adjacent].ID; bool adjacentIsFloater = adjacentID == Voxel.t.Floater; if (dir != down || adjacentIsFloater) { if (adjacentID == Voxel.t.Powered || adjacentID == Voxel.t.Blue || adjacentID == Voxel.t.Neutral || adjacentID == Voxel.t.Infected || adjacentIsFloater) { if (!this.isInQueue(map.Entity, adjacent, true)) { this.BlockQueue.Add(new ScheduledBlock { Voxel = map.Entity, Coordinate = adjacent, Time = propagateDelay, Removing = true, Generation = 1, }); } } } } } else if (entry.Generation > 0 && (id == Voxel.t.Blue || id == Voxel.t.Infected || id == Voxel.t.Powered || id == Voxel.t.PermanentPowered || id == Voxel.t.HardPowered || id == Voxel.t.PoweredSwitch || id == Voxel.t.Neutral || id == Voxel.t.Floater)) { this.generations[new EffectBlock.Entry { Voxel = map, Coordinate = c }] = entry.Generation; map.Empty(c); this.SparksLowPriority(map.GetAbsolutePosition(c), Spark.Burn); regenerate = true; } } else if (id == Voxel.t.Blue) { for (int j = 0; j < 6; j++) { Direction dir = DirectionExtensions.Directions[j]; Voxel.Coord adjacent = c.Move(dir); Voxel.t adjacentID = map[adjacent].ID; if (adjacentID == Voxel.t.Powered || adjacentID == Voxel.t.PermanentPowered || adjacentID == Voxel.t.HardPowered || adjacentID == Voxel.t.PoweredSwitch) { map.Empty(c, false, true, map); map.Fill(c, Voxel.States.Powered); this.SparksLowPriority(map.GetAbsolutePosition(c), Spark.Normal); regenerate = true; } else if (adjacentID == Voxel.t.Neutral && entry.Generation < maxGenerations) { map.Empty(adjacent, false, true, map); this.generations[new EffectBlock.Entry { Voxel = map, Coordinate = adjacent }] = entry.Generation + 1; map.Fill(adjacent, Voxel.States.Blue); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } } } else if (id == Voxel.t.Neutral) { for (int j = 0; j < 6; j++) { Direction dir = DirectionExtensions.Directions[j]; Voxel.Coord adjacent = c.Move(dir); Voxel.t adjacentID = map[adjacent].ID; if (adjacentID == Voxel.t.Infected || adjacentID == Voxel.t.Blue || adjacentID == Voxel.t.Powered) { map.Empty(adjacent, false, true, map); map.Fill(adjacent, Voxel.States.Neutral); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } else if (adjacentID == Voxel.t.HardInfected) { map.Empty(adjacent, false, true, map); map.Fill(adjacent, Voxel.States.Hard); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } } } else if (id == Voxel.t.Hard) { for (int j = 0; j < 6; j++) { Direction dir = DirectionExtensions.Directions[j]; Voxel.Coord adjacent = c.Move(dir); Voxel.t adjacentID = map[adjacent].ID; if (adjacentID == Voxel.t.HardInfected) { map.Empty(adjacent, false, true, map); map.Fill(adjacent, Voxel.States.Hard); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } } } else if (id == Voxel.t.Powered || id == Voxel.t.PermanentPowered || id == Voxel.t.HardPowered || id == Voxel.t.PoweredSwitch) { for (int j = 0; j < 6; j++) { Direction dir = DirectionExtensions.Directions[j]; Voxel.Coord adjacent = c.Move(dir); Voxel.t adjacentID = map[adjacent].ID; if (id == Voxel.t.Powered && adjacentID == Voxel.t.Neutral && entry.Generation < maxGenerations) { map.Empty(adjacent, false, true, map); this.generations[new EffectBlock.Entry { Voxel = map, Coordinate = adjacent }] = entry.Generation + 1; map.Fill(adjacent, Voxel.States.Powered); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } else if (adjacentID == Voxel.t.Blue) { map.Empty(adjacent, false, true, map); map.Fill(adjacent, Voxel.States.Powered); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } else if (adjacentID == Voxel.t.Switch) { map.Empty(adjacent, true, true, map); map.Fill(adjacent, Voxel.States.PoweredSwitch); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } else if (adjacentID == Voxel.t.Hard) { map.Empty(adjacent, true, true, map); map.Fill(adjacent, Voxel.States.HardPowered); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal); regenerate = true; } else if (adjacentID == Voxel.t.Critical) { map.Empty(adjacent); regenerate = true; } } } else if (id == Voxel.t.Infected || id == Voxel.t.HardInfected) { for (int j = 0; j < 6; j++) { Direction dir = DirectionExtensions.Directions[j]; Voxel.Coord adjacent = c.Move(dir); Voxel.t adjacentID = map[adjacent].ID; if (adjacentID == Voxel.t.Neutral && entry.Generation < maxGenerations) { map.Empty(adjacent, false, true, map); this.generations[new EffectBlock.Entry { Voxel = map, Coordinate = adjacent }] = entry.Generation + 1; map.Fill(adjacent, Voxel.States.Infected); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Dangerous); regenerate = true; } else if (adjacentID == Voxel.t.Hard && entry.Generation < maxGenerations) { map.Empty(adjacent, false, true, map); this.generations[new EffectBlock.Entry { Voxel = map, Coordinate = adjacent }] = entry.Generation + 1; map.Fill(adjacent, Voxel.States.HardInfected); this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Dangerous); regenerate = true; } else if (adjacentID == Voxel.t.Critical) { map.Empty(adjacent); regenerate = true; } } } if (regenerate) { this.toRegenerate.Add(map); } } } } for (int i = 0; i < this.toRegenerate.Count; i++) { this.toRegenerate[i].Regenerate(); } this.toRegenerate.Clear(); }
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; } }
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 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(); } } })); }
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; }
private void fall() { if (this.TimeUntilRebuild.Value > 0 || this.TimeUntilRebuildComplete.Value > 0) { return; } Entity targetVoxel = this.TargetVoxel.Value.Target; if (targetVoxel == null || !targetVoxel.Active) { return; } // Disable the cell-emptied notification. // This way, we won't think that the base has been destroyed by the player. // We are not in fact dying, we're just destroying the base so we can fall over. this.Base.EnableCellEmptyBinding = false; Voxel m = targetVoxel.Get <Voxel>(); m.Empty(this.Base.BaseBoxes.SelectMany(x => x.GetCoords())); Vector3 basePosition = Vector3.Zero; int baseSize = 0; foreach (Voxel.Coord c in this.Base.BaseBoxes.SelectMany(x => x.GetCoords())) { ParticleSystem shatter = ParticleSystem.Get(main, "InfectedShatter"); Vector3 pos = m.GetAbsolutePosition(c); 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(pos + offset, offset); } basePosition += pos; baseSize++; } basePosition /= (float)baseSize; Sound.PostEvent(AK.EVENTS.PLAY_TOWER_FALL, basePosition); m.Regenerate(delegate(List <DynamicVoxel> spawnedMaps) { if (spawnedMaps.Count == 0) { this.Delete.Execute(); } else { Vector3 playerPos = PlayerFactory.Instance.Get <Transform>().Position; playerPos += PlayerFactory.Instance.Get <Player>().Character.LinearVelocity.Value * 0.65f; foreach (DynamicVoxel newMap in spawnedMaps) { newMap.Dangerous.Value = true; Vector3 toPlayer = playerPos - newMap.PhysicsEntity.Position; toPlayer.Normalize(); if (Math.Abs(toPlayer.Y) < 0.9f) { toPlayer *= 25.0f * newMap.PhysicsEntity.Mass; Vector3 positionAtPlayerHeight = newMap.PhysicsEntity.Position; Vector3 impulseAtBase = toPlayer * -0.75f; impulseAtBase.Y = 0.0f; positionAtPlayerHeight.Y = playerPos.Y; newMap.PhysicsEntity.ApplyImpulse(ref positionAtPlayerHeight, ref impulseAtBase); newMap.PhysicsEntity.ApplyLinearImpulse(ref toPlayer); } newMap.PhysicsEntity.Material.KineticFriction = 1.0f; newMap.PhysicsEntity.Material.StaticFriction = 1.0f; this.DynamicVoxels.Add(newMap.Entity); } } }); this.TimeUntilRebuild.Value = RebuildDelay; }