private const int rumbleCount = 50; // Average the last X block positions to get the position of the rumble public void Update(float dt) { intervalTimer += dt; Entity targetEntity = this.Target.Value.Target; if (targetEntity != null && targetEntity.Active && this.Index < this.Coords.Length) { EffectBlockFactory factory = Factory.Get <EffectBlockFactory>(); Voxel m = targetEntity.Get <Voxel>(); float interval = 0.03f * this.IntervalMultiplier; while (intervalTimer > interval && this.Index < this.Coords.Length) { CoordinateEntry entry = this.Coords[this.Index]; Entity blockEntity = factory.CreateAndBind(main); EffectBlock effectBlock = blockEntity.Get <EffectBlock>(); entry.Coord.Data.ApplyToEffectBlock(blockEntity.Get <ModelInstance>()); effectBlock.CheckAdjacent = false; effectBlock.Offset.Value = m.GetRelativePosition(entry.Coord); effectBlock.DoScale = true; effectBlock.StartPosition = entry.Position + new Vector3(8.0f, 20.0f, 8.0f) * this.BlockLifetime.Value; effectBlock.StartOrientation = Quaternion.CreateFromYawPitchRoll(0.15f * this.Index, 0.15f * this.Index, 0); effectBlock.TotalLifetime = this.BlockLifetime; effectBlock.Setup(targetEntity, entry.Coord, entry.Coord.Data.ID); main.Add(blockEntity); this.rumbleSum += entry.Position; int lastIndex = this.Index - rumbleCount; if (lastIndex >= 0) { this.rumbleSum -= this.Coords[lastIndex].Position; } this.Index.Value++; intervalTimer -= interval; } if (this.Coords.Count > 200) { this.RumblePosition.Value = this.rumbleSum / Math.Min(this.Index + 1, rumbleCount); if (!this.rumbling) { AkSoundEngine.PostEvent(AK.EVENTS.PLAY_BLOCK_RUMBLE, this.Entity); this.rumbling = true; } } } else { this.Delete.Execute(); } }
public void Update(float dt) { intervalTimer += dt; Entity targetEntity = this.Target.Value.Target; if (targetEntity != null && targetEntity.Active && this.Index < this.Coords.Length) { float interval = 0.03f * this.IntervalMultiplier; while (intervalTimer > interval && this.Index < this.Coords.Length) { EffectBlockFactory factory = Factory.Get <EffectBlockFactory>(); Voxel m = targetEntity.Get <Voxel>(); CoordinateEntry entry = this.Coords[this.Index]; Entity blockEntity = factory.CreateAndBind(main); EffectBlock effectBlock = blockEntity.Get <EffectBlock>(); entry.Coord.Data.ApplyToEffectBlock(blockEntity.Get <ModelInstance>()); effectBlock.CheckAdjacent = false; effectBlock.Offset.Value = m.GetRelativePosition(entry.Coord); effectBlock.DoScale = true; effectBlock.StartPosition = entry.Position + new Vector3(8.0f, 20.0f, 8.0f) * this.BlockLifetime.Value; effectBlock.StartOrientation = Quaternion.CreateFromYawPitchRoll(0.15f * this.Index, 0.15f * this.Index, 0); effectBlock.TotalLifetime = this.BlockLifetime; effectBlock.Setup(targetEntity, entry.Coord, entry.Coord.Data.ID); main.Add(blockEntity); this.Index.Value++; intervalTimer -= interval; } } else { this.Delete.Execute(); } }
public static void Consolidate(Main main, DynamicVoxel voxel, Voxel targetVoxel, Voxel.Coord targetCoord, float interval = 1.0f) { if (targetVoxel != null) { // Combine this map with the other one Direction x = targetVoxel.GetRelativeDirection(voxel.GetAbsoluteVector(Vector3.Right)); Direction y = targetVoxel.GetRelativeDirection(voxel.GetAbsoluteVector(Vector3.Up)); Direction z = targetVoxel.GetRelativeDirection(voxel.GetAbsoluteVector(Vector3.Backward)); if (x.IsParallel(y)) { x = y.Cross(z); } else if (y.IsParallel(z)) { y = x.Cross(z); } Voxel.Coord offset = new Voxel.Coord(); float closestCoordDistance = float.MaxValue; Vector3 closestCoordPosition = targetVoxel.GetAbsolutePosition(targetCoord); foreach (Voxel.Coord c in voxel.Chunks.SelectMany(c => c.Boxes).SelectMany(b => b.GetCoords())) { float distance = (voxel.GetAbsolutePosition(c) - closestCoordPosition).LengthSquared(); if (distance < closestCoordDistance) { closestCoordDistance = distance; offset = c; } } Vector3 toLevitatingMap = voxel.Transform.Value.Translation - targetVoxel.GetAbsolutePosition(targetCoord); offset = offset.Move(voxel.GetRelativeDirection(-toLevitatingMap)); Quaternion orientation = Quaternion.CreateFromRotationMatrix(voxel.Transform.Value); EffectBlockFactory blockFactory = Factory.Get <EffectBlockFactory>(); int index = 0; List <Voxel.Coord> coords = voxel.Chunks.SelectMany(c => c.Boxes).SelectMany(b => b.GetCoords()).ToList(); Voxel.Coord camera = voxel.GetCoordinate(main.Camera.Position); foreach (Voxel.Coord c in coords.OrderBy(c2 => new Vector3(c2.X - camera.X, c2.Y - camera.Y, c2.Z - camera.Z).LengthSquared())) { Voxel.Coord offsetFromCenter = c.Move(-offset.X, -offset.Y, -offset.Z); Voxel.Coord targetCoord2 = new Voxel.Coord(); targetCoord2.SetComponent(x, offsetFromCenter.GetComponent(Direction.PositiveX)); targetCoord2.SetComponent(y, offsetFromCenter.GetComponent(Direction.PositiveY)); targetCoord2.SetComponent(z, offsetFromCenter.GetComponent(Direction.PositiveZ)); targetCoord2 = targetCoord2.Move(targetCoord.X, targetCoord.Y, targetCoord.Z); if (targetVoxel[targetCoord2].ID == 0) { Entity blockEntity = blockFactory.CreateAndBind(main); c.Data.ApplyToEffectBlock(blockEntity.Get <ModelInstance>()); EffectBlock effectBlock = blockEntity.Get <EffectBlock>(); effectBlock.Offset.Value = targetVoxel.GetRelativePosition(targetCoord2); effectBlock.DoScale = false; effectBlock.StartPosition = voxel.GetAbsolutePosition(c); effectBlock.StartOrientation = orientation; effectBlock.TotalLifetime = (0.05f + (index * 0.0075f)) * interval; effectBlock.Setup(targetVoxel.Entity, targetCoord2, c.Data.ID); main.Add(blockEntity); index++; } } // Delete the map voxel.Entity.Delete.Execute(); } }
public override void Awake() { base.Awake(); this.blockFactory = Factory.Get <EffectBlockFactory>(); this.EnabledWhenPaused = false; if (main.EditorEnabled) { this.BlockQueue.Clear(); } this.particles = ParticleSystem.Get(main, "WhiteShatter"); for (int i = 0; i < maxSparkLights; i++) { PointLight light = new PointLight(); light.Serialize = false; light.Color.Value = new Vector3(1.0f); light.Enabled.Value = false; this.Entity.Add(light); this.sparkLights.Add(light); } if (!this.main.EditorEnabled) { this.Add(new CommandBinding <Voxel, IEnumerable <Voxel.Coord>, Voxel>(Voxel.GlobalCellsFilled, delegate(Voxel map, IEnumerable <Voxel.Coord> coords, Voxel transferredFromMap) { foreach (Voxel.Coord c in coords) { Voxel.t id = c.Data.ID; if (id == Voxel.t.Blue || id == Voxel.t.Powered || id == Voxel.t.PoweredSwitch || id == Voxel.t.Infected || id == Voxel.t.Neutral || id == Voxel.t.HardPowered || id == Voxel.t.Hard || id == Voxel.t.HardInfected) { Voxel.Coord newCoord = c; newCoord.Data = Voxel.States.Empty; int generation; EffectBlock.Entry generationsKey = new EffectBlock.Entry { Voxel = map, Coordinate = newCoord }; if (this.generations.TryGetValue(generationsKey, out generation)) { this.generations.Remove(generationsKey); } if (!this.isInQueue(map.Entity, newCoord, false)) { this.BlockQueue.Add(new ScheduledBlock { Voxel = map.Entity, Coordinate = newCoord, Time = propagateDelay, Generation = generation, }); } } } })); this.Add(new CommandBinding <Voxel, IEnumerable <Voxel.Coord>, Voxel>(Voxel.GlobalCellsEmptied, delegate(Voxel map, IEnumerable <Voxel.Coord> coords, Voxel transferringToNewMap) { foreach (Voxel.Coord coord in coords) { Voxel.t id = coord.Data.ID; if (id == Voxel.t.Powered || id == Voxel.t.PoweredSwitch || id == Voxel.t.HardPowered || id == Voxel.t.PermanentPowered) { this.removedPoweredCoords.Add(coord); } if (transferringToNewMap != null) { continue; } if (id == Voxel.t.Critical) // Critical. Explodes when destroyed. { Explosion.Explode(main, map, coord); } else if (id == Voxel.t.HardInfected) // Infected. Shatter effects. { ParticleSystem shatter = ParticleSystem.Get(main, "InfectedShatter"); Vector3 pos = map.GetAbsolutePosition(coord); AkSoundEngine.PostEvent(AK.EVENTS.PLAY_INFECTED_CRITICAL_SHATTER, pos); 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); } } else if (id == Voxel.t.Powered || id == Voxel.t.Blue || id == Voxel.t.Neutral || id == Voxel.t.Infected || id == Voxel.t.Floater) { int generation; Voxel.Coord c = coord; c.Data = Voxel.States.Empty; EffectBlock.Entry generationKey = new EffectBlock.Entry { Voxel = map, Coordinate = c }; if (this.generations.TryGetValue(generationKey, out generation)) { this.generations.Remove(generationKey); } if (id == Voxel.t.Floater) { Entity blockEntity = this.blockFactory.CreateAndBind(main); EffectBlock effectBlock = blockEntity.Get <EffectBlock>(); coord.Data.ApplyToEffectBlock(blockEntity.Get <ModelInstance>()); effectBlock.Delay = 4.0f; effectBlock.Offset.Value = map.GetRelativePosition(coord); effectBlock.StartPosition = map.GetAbsolutePosition(coord) + new Vector3(2.5f, 5.0f, 2.5f); effectBlock.StartOrientation = Quaternion.CreateFromYawPitchRoll(1.0f, 1.0f, 0); effectBlock.TotalLifetime = 0.5f; effectBlock.Setup(map.Entity, coord, coord.Data.ID); main.Add(blockEntity); } if (generation == 0) { if (!this.isInQueue(map.Entity, coord, true)) { this.BlockQueue.Add(new ScheduledBlock { Voxel = map.Entity, Coordinate = coord, Time = propagateDelay, Removing = true, }); } } else if (generation < maxGenerations) { Direction down = map.GetRelativeDirection(Direction.NegativeY); for (int i = 0; i < 6; i++) { Direction dir = DirectionExtensions.Directions[i]; Voxel.Coord adjacent = coord.Move(dir); if (!coords.Contains(adjacent)) { 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 = generation + 1, }); } } } } } } } else if (id == Voxel.t.White || id == Voxel.t.Glass) // Shatter effects. { ParticleSystem shatter = ParticleSystem.Get(main, "WhiteShatter"); Vector3 pos = map.GetAbsolutePosition(coord); for (int i = 0; i < 50; i++) { Vector3 offset = new Vector3((float)this.random.NextDouble() - 0.5f, (float)this.random.NextDouble() - 0.5f, (float)this.random.NextDouble() - 0.5f); shatter.AddParticle(pos + offset, offset); } float time = this.main.TotalTime; if (time - this.lastShatterSound > 0.3f) { this.lastShatterSound = time; AkSoundEngine.PostEvent(AK.EVENTS.PLAY_WHITE_SHATTER, pos); } } } if (this.removedPoweredCoords.Count > 0) { IEnumerable <IEnumerable <Voxel.Box> > poweredIslands = map.GetAdjacentIslands(this.removedPoweredCoords, x => x.ID == Voxel.t.Powered || x.ID == Voxel.t.HardPowered, x => x == Voxel.States.PermanentPowered || x == Voxel.States.PoweredSwitch); List <Voxel.Coord> poweredCoords = poweredIslands.SelectMany(x => x).SelectMany(x => x.GetCoords()).ToList(); if (poweredCoords.Count > 0) { lock (map.MutationLock) { map.Empty(poweredCoords, true, true, map, false); for (int i = 0; i < poweredCoords.Count; i++) { Voxel.Coord coord = poweredCoords[i]; if (coord.Data.ID == Voxel.t.HardPowered) { map.Fill(coord, Voxel.States.Hard, false); } else { map.Fill(coord, Voxel.States.Blue, false); } } } this.toRegenerate.Add(map); } this.removedPoweredCoords.Clear(); } })); } }
// Function for finding a wall to build for the player public Possibility FindWall(Vector3 position, Vector2 direction) { Voxel shortestMap = null; Voxel.Coord shortestPlayerCoord = new Voxel.Coord(); Direction shortestWallDirection = Direction.None; Direction shortestBuildDirection = Direction.None; int shortestDistance = searchDistance; EffectBlockFactory blockFactory = Factory.Get <EffectBlockFactory>(); foreach (Voxel map in Voxel.ActivePhysicsVoxels) { if (!ignoreTypes.Contains(map.Entity.Type)) { foreach (Direction absoluteWallDir in DirectionExtensions.HorizontalDirections) { Direction relativeWallDir = map.GetRelativeDirection(absoluteWallDir); Vector3 wallVector = map.GetAbsoluteVector(relativeWallDir.GetVector()); float dot = Vector2.Dot(direction, Vector2.Normalize(new Vector2(wallVector.X, wallVector.Z))); if (dot > -0.25f && dot < 0.8f) { Voxel.Coord coord = map.GetCoordinate(position).Move(relativeWallDir, 2); foreach (Direction dir in DirectionExtensions.Directions.Where(x => x.IsPerpendicular(relativeWallDir))) { for (int i = 0; i < shortestDistance; i++) { Voxel.Coord c = coord.Move(dir, i); Voxel.State state = map[c]; if (state == Voxel.States.Empty) { continue; } if (this.canBuild(state) && this.canBuild(map.GetAbsolutePosition(c))) { shortestMap = map; shortestBuildDirection = dir; shortestWallDirection = relativeWallDir; shortestDistance = i; shortestPlayerCoord = coord; } break; } } } } } } if (shortestMap != null) { // Found something to build a wall on. Direction dirU = shortestBuildDirection; Direction dirV = dirU.Cross(shortestWallDirection); Voxel.Coord startCoord = shortestPlayerCoord.Move(dirU, shortestDistance).Move(dirV, additionalWallDistance); Voxel.Coord endCoord = shortestPlayerCoord.Move(dirU, -additionalWallDistance).Move(dirV, -additionalWallDistance).Move(shortestWallDirection); return(new Possibility { Map = shortestMap, StartCoord = new Voxel.Coord { X = Math.Min(startCoord.X, endCoord.X), Y = Math.Min(startCoord.Y, endCoord.Y), Z = Math.Min(startCoord.Z, endCoord.Z) }, EndCoord = new Voxel.Coord { X = Math.Max(startCoord.X, endCoord.X), Y = Math.Max(startCoord.Y, endCoord.Y), Z = Math.Max(startCoord.Z, endCoord.Z) }, }); } return(null); }
// Function for finding a platform to build for the player public Possibility FindPlatform(Vector3 position) { int shortestDistance = searchDistance; Direction relativeShortestDirection = Direction.None, absoluteShortestDirection = Direction.None; Voxel.Coord shortestCoordinate = new Voxel.Coord(); Voxel shortestMap = null; EffectBlockFactory blockFactory = Factory.Get <EffectBlockFactory>(); foreach (Voxel map in Voxel.ActivePhysicsVoxels) { if (!ignoreTypes.Contains(map.Entity.Type)) { List <Matrix> results = new List <Matrix>(); Voxel.Coord absolutePlayerCoord = map.GetCoordinate(position); bool inMap = map.GetChunk(absolutePlayerCoord, false) != null; foreach (Direction absoluteDir in platformBuildableDirections) { Voxel.Coord playerCoord = absoluteDir == Direction.NegativeY ? absolutePlayerCoord : map.GetCoordinate(position + new Vector3(0, platformSize / -2.0f, 0)); Direction relativeDir = map.GetRelativeDirection(absoluteDir); if (!inMap && map.GetChunk(playerCoord.Move(relativeDir, searchDistance), false) == null) { continue; } for (int i = 1; i < shortestDistance; i++) { Voxel.Coord coord = playerCoord.Move(relativeDir, i); Voxel.State state = map[coord]; if (state == Voxel.States.Empty) { continue; } if (this.canBuild(state) && this.canBuild(map.GetAbsolutePosition(coord))) { shortestDistance = i; relativeShortestDirection = relativeDir; absoluteShortestDirection = absoluteDir; shortestCoordinate = playerCoord; shortestMap = map; } break; } } } } if (shortestMap != null && shortestDistance > 1) { Direction yDir = relativeShortestDirection.IsParallel(Direction.PositiveY) ? Direction.PositiveX : Direction.PositiveY; Direction zDir = relativeShortestDirection.Cross(yDir); int initialOffset = absoluteShortestDirection == Direction.NegativeY ? 0 : -2; Voxel.Coord startCoord = shortestCoordinate.Move(relativeShortestDirection, initialOffset).Move(yDir, platformSize / -2).Move(zDir, platformSize / -2); Voxel.Coord endCoord = startCoord.Move(relativeShortestDirection, -initialOffset + shortestDistance).Move(yDir, platformSize).Move(zDir, platformSize); return(new Possibility { Map = shortestMap, StartCoord = new Voxel.Coord { X = Math.Min(startCoord.X, endCoord.X), Y = Math.Min(startCoord.Y, endCoord.Y), Z = Math.Min(startCoord.Z, endCoord.Z) }, EndCoord = new Voxel.Coord { X = Math.Max(startCoord.X, endCoord.X), Y = Math.Max(startCoord.Y, endCoord.Y), Z = Math.Max(startCoord.Z, endCoord.Z) }, }); } return(null); }
public void Update(float dt) { if (this.TimeUntilRebuild > 0) { if (this.TargetVoxel.Value.Target == null || !this.TargetVoxel.Value.Target.Active) { this.Delete.Execute(); return; } float newValue = Math.Max(0.0f, this.TimeUntilRebuild.Value - dt); this.TimeUntilRebuild.Value = newValue; if (newValue == 0.0f) { // Rebuild Entity targetMap = this.TargetVoxel.Value.Target; Voxel m = targetMap.Get <Voxel>(); EffectBlockFactory factory = Factory.Get <EffectBlockFactory>(); int startIndex = this.Base.BaseBoxes.Sum(x => x.Volume); int index = startIndex; foreach (Entity.Handle e in this.DynamicVoxels) { Entity dynamicMap = e.Target; Voxel dynamicMapComponent = dynamicMap != null && dynamicMap.Active ? dynamicMap.Get <Voxel>() : null; if (dynamicMap == null || !dynamicMap.Active) { continue; } Quaternion orientation = Quaternion.CreateFromRotationMatrix(dynamicMapComponent.Transform.Value); List <Voxel.Coord> coords = new List <Voxel.Coord>(); foreach (Voxel.Coord c in dynamicMapComponent.Chunks.SelectMany(x => x.Boxes).SelectMany(x => x.GetCoords())) { if (m[c].ID == 0) { coords.Add(c); } } foreach (Voxel.Coord c in coords.OrderBy(x => (new Vector3(x.X, x.Y, x.Z) - this.Base.Position).LengthSquared())) { Entity blockEntity = factory.CreateAndBind(main); c.Data.ApplyToEffectBlock(blockEntity.Get <ModelInstance>()); EffectBlock effectBlock = blockEntity.Get <EffectBlock>(); effectBlock.Offset.Value = m.GetRelativePosition(c); effectBlock.DoScale = dynamicMapComponent == null; if (dynamicMapComponent != null && dynamicMapComponent[c].ID == c.Data.ID) { effectBlock.StartPosition = dynamicMapComponent.GetAbsolutePosition(c); effectBlock.StartOrientation = orientation; } else { effectBlock.StartPosition = m.GetAbsolutePosition(c) + new Vector3(0.25f, 0.5f, 0.25f) * index; effectBlock.StartOrientation = Quaternion.CreateFromYawPitchRoll(0.15f * index, 0.15f * index, 0); } effectBlock.TotalLifetime = 0.05f + (index * rebuildTimeMultiplier * RebuildTime); effectBlock.Setup(targetMap, c, c.Data.ID); main.Add(blockEntity); index++; } dynamicMap.Delete.Execute(); } this.DynamicVoxels.Clear(); if (index > startIndex) // We built some stuff. Build the base. { int baseIndex = 0; foreach (Voxel.Coord c in this.Base.BaseBoxes.SelectMany(x => x.GetCoords())) { if (m[c].ID == 0) { Entity blockEntity = factory.CreateAndBind(main); EffectBlock effectBlock = blockEntity.Get <EffectBlock>(); c.Data.ApplyToEffectBlock(blockEntity.Get <ModelInstance>()); effectBlock.Offset.Value = m.GetRelativePosition(c); effectBlock.StartPosition = m.GetAbsolutePosition(c) + new Vector3(0.25f, 0.5f, 0.25f) * baseIndex; effectBlock.StartOrientation = Quaternion.CreateFromYawPitchRoll(0.15f * baseIndex, 0.15f * baseIndex, 0); effectBlock.TotalLifetime = 0.05f + (baseIndex * rebuildTimeMultiplier * RebuildTime); effectBlock.Setup(targetMap, c, c.Data.ID); main.Add(blockEntity); baseIndex++; } } this.TimeUntilRebuildComplete.Value = 0.05f + (index * rebuildTimeMultiplier * RebuildTime); } else // We didn't build anything. Delete ourselves. { this.Delete.Execute(); } } } else if (this.TimeUntilRebuildComplete > 0) { // Rebuilding float newValue = Math.Max(0.0f, this.TimeUntilRebuildComplete.Value - dt); this.TimeUntilRebuildComplete.Value = newValue; if (newValue == 0.0f) { // Done rebuilding if (!this.Base.IsValid) { this.Delete.Execute(); } else { this.Base.EnableCellEmptyBinding = !main.EditorEnabled; if (this.IsTriggered) { fall(); } } } } }