private void sparks(Vector3 pos, Spark type, bool showLight, bool playSound) { for (int j = 0; j < 40; j++) { Vector3 offset = new Vector3((float)this.random.NextDouble() - 0.5f, (float)this.random.NextDouble() - 0.5f, (float)this.random.NextDouble() - 0.5f); this.particles.AddParticle(pos + offset, offset); } if (showLight) { PointLight light; if (this.activeSparkLights < Propagator.maxSparkLights) { light = this.sparkLights[this.activeSparkLights]; light.Enabled.Value = true; this.activeSparkLights++; } else { light = this.sparkLights[this.oldestSparkLight % this.activeSparkLights]; this.oldestSparkLight = (this.oldestSparkLight + 1) % Propagator.maxSparkLights; } light.Color.Value = Vector3.One; light.Position.Value = pos; light.Attenuation.Value = type == Spark.Expander ? 10.0f : 5.0f; if (playSound) { uint sound; switch (type) { case Spark.Dangerous: sound = AK.EVENTS.PLAY_RED_BURN; break; case Spark.Burn: sound = AK.EVENTS.PLAY_ORANGE_BURN; break; default: sound = AK.EVENTS.PLAY_BLUE_BURN; break; } Sound.PostEvent(sound, pos); } } }
public void Update(float dt) { this.raycastTimer += dt; if (this.raycastTimer > RaycastInterval) { this.Update(); } if (!this.main.EditorEnabled) { this.thunderTimer -= dt; if (this.thunderTimer < 0) { float volume = 0.6f + ((float)random.NextDouble() * 0.4f); this.CurrentLightningColor.Value = Vector3.Zero; Property <Vector3> skyboxColor; if (this.skybox == null) { skyboxColor = new Property <Vector3>(); // Dummy property } else { skyboxColor = this.skybox.Color; } this.Entity.Add(new Animation ( new Animation.Set <bool>(this.LightningEnabled, true), new Animation.Parallel ( new Animation.Vector3MoveTo(this.CurrentLightningColor, this.LightningColor.Value * volume, 0.2f), new Animation.Vector3MoveTo(skyboxColor, this.SkyboxColor.Value + this.LightningColor.Value * volume, 0.2f) ), new Animation.Parallel ( new Animation.Vector3MoveTo(this.CurrentLightningColor, Vector3.Zero, 0.5f), new Animation.Vector3MoveTo(skyboxColor, this.SkyboxColor, 0.5f) ), new Animation.Set <bool>(this.LightningEnabled, false), new Animation.Delay((1.0f - volume) * this.ThunderMaxDelay), new Animation.Execute(delegate() { Sound.PostEvent(AK.EVENTS.PLAY_THUNDER, main.Camera.Position + Vector3.Normalize(new Vector3(2.0f * ((float)random.NextDouble() - 0.5f), 1.0f, 2.0f * ((float)random.NextDouble() - 0.5f))) * 1000.0f); }) )); this.thunderTimer = this.ThunderIntervalMin + ((float)random.NextDouble() * (this.ThunderIntervalMax - this.ThunderIntervalMin)); } } }
public void Update(float dt) { if (this.Rolling) { this.rollKickTime += dt; Vector3 originalVelocity = this.LinearVelocity; this.LinearVelocity.Value = new Vector3(this.velocity.X, originalVelocity.Y, this.velocity.Z); if (this.rollKickTime > 0.1f && (this.rollKickTime > 1.0f || Vector3.Dot(originalVelocity - this.SupportVelocity, this.forward) < 0.1f)) { this.Rolling.Value = false; this.EnableWalking.Value = true; if (!this.RollKickButton) { this.AllowUncrouch.Value = true; } this.LastRollKickEnded.Value = main.TotalTime; } else { if (this.VoxelTools.BreakWalls(this.forward, this.right)) { if (this.firstTimeBreak) { this.Rumble.Execute(0.5f); Sound.PostEvent(AK.EVENTS.PLAY_WALL_BREAK, this.FloorPosition + this.forward * 2.0f); } this.firstTimeBreak = false; } if (this.shouldBuildFloor) { this.VoxelTools.BuildFloor(this.floorMap, this.floorCoordinate, this.forwardDir, this.rightDir); } else { this.checkShouldBuildFloor(); } } } else if (this.Kicking) { this.rollKickTime += dt; Vector3 originalVelocity = this.LinearVelocity; this.LinearVelocity.Value = new Vector3(this.velocity.X, originalVelocity.Y, this.velocity.Z); if (!this.IsSupported) { if (this.sliding) { // We started out on the ground, but we kicked off an edge. AkSoundEngine.PostEvent(AK.EVENTS.STOP_PLAYER_SLIDE_LOOP, this.Entity); } else if (originalVelocity.Y - this.SupportVelocity.Value.Y < FallDamage.DamageVelocity) { // We weren't supported when we started kicking. We're flying. // Roll if we hit the ground while kicking mid-air Vector3 playerPos = this.FloorPosition + new Vector3(0, 0.5f, 0); Voxel.GlobalRaycastResult r = this.raycastFloor(); if (r.Voxel != null) { this.StopKick(); this.Go(true); return; } } } if (this.rollKickTime > 1.0f || (this.rollKickTime > 0.7f && (!this.RollKickButton || Vector3.Dot(originalVelocity - this.SupportVelocity, this.forward) < 0.1f))) { this.StopKick(); return; } if (this.VoxelTools.BreakWalls(this.forward, this.right)) { if (this.firstTimeBreak) { this.Rumble.Execute(0.5f); Sound.PostEvent(AK.EVENTS.PLAY_WALL_BREAK, this.FloorPosition + this.forward * 2.0f); } this.firstTimeBreak = false; } if (this.shouldBuildFloor) { this.VoxelTools.BuildFloor(this.floorMap, this.floorCoordinate, this.forwardDir, this.rightDir); } else if (this.sliding) { this.checkShouldBuildFloor(); } } }
private static void explode(Main main, Voxel map, Voxel.Coord coord, Vector3 pos, int radius, float physicsRadius) { float distanceToCamera = (main.Camera.Position.Value - pos).Length(); // Kaboom Sound.PostEvent(distanceToCamera < physicsRadius * 1.5f ? AK.EVENTS.PLAY_EXPLOSION_CLOSE : AK.EVENTS.PLAY_EXPLOSION, pos); Entity lightEntity = Factory.Get <PointLightFactory>().CreateAndBind(main); lightEntity.Serialize = false; PointLight light = lightEntity.Get <PointLight>(); light.Color.Value = new Vector3(1.3f, 1.1f, 0.9f); light.Attenuation.Value = 20.0f; light.Position.Value = pos; lightEntity.Add(new Animation ( new Animation.FloatMoveTo(light.Attenuation, 0.0f, 1.0f), new Animation.Execute(light.Delete) )); main.Add(lightEntity); SmokeFactory smokeFactory = Factory.Get <SmokeFactory>(); for (int i = 0; i < 5; i++) { Entity smoke = smokeFactory.CreateAndBind(main); smoke.Get <Transform>().Position.Value = pos; main.Add(smoke); } ParticleEmitter.Emit(main, "Smoke", pos, physicsRadius * 0.4f, 250); Entity player = PlayerFactory.Instance; if (player != null && player.Active) { player.Get <CameraController>().Shake.Execute(pos, 50.0f); } const float physicsImpulse = 70.0f; const float minPlayerDamage = 0.1f; const float playerDamageMultiplier = 2.0f; // Remove the cells BlockFactory blockFactory = Factory.Get <BlockFactory>(); foreach (Voxel m in Voxel.ActiveVoxels.ToList()) { List <Voxel.Coord> removals = new List <Voxel.Coord>(); Voxel.Coord c = m.GetCoordinate(pos); Vector3 relativePos = m.GetRelativePosition(c); Quaternion quat = m.Entity.Get <Transform>().Quaternion; for (Voxel.Coord x = c.Move(Direction.NegativeX, radius - 1); x.X < c.X + radius; x.X++) { for (Voxel.Coord y = x.Move(Direction.NegativeY, radius - 1); y.Y < c.Y + radius; y.Y++) { for (Voxel.Coord z = y.Move(Direction.NegativeZ, radius - 1); z.Z < c.Z + radius; z.Z++) { Voxel.State s = m[z]; if (s.ID == 0 || s.Permanent) { continue; } Vector3 cellPos = m.GetRelativePosition(z); if ((cellPos - relativePos).Length() < radius - 1) { removals.Add(z); if (random.NextDouble() > 0.5) { Entity block = blockFactory.CreateAndBind(main); Transform blockTransform = block.Get <Transform>(); blockTransform.Position.Value = m.GetAbsolutePosition(cellPos); blockTransform.Quaternion.Value = Quaternion.CreateFromYawPitchRoll(((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI, ((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI, ((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI); s.ApplyToBlock(block); main.Add(block); } } } } } if (removals.Count > 0) { m.Empty(removals); m.Regenerate(); } } // Damage the player if (player != null && player.Active) { Vector3 toPlayer = player.Get <Transform>().Position - pos; float d = toPlayer.Length(); if (d < physicsRadius) { float attenuation = 1.0f; if (d > 0) { Voxel.GlobalRaycast(pos, toPlayer / d, d, delegate(int x, Voxel.t c) { Voxel.State s = Voxel.States.All[c]; if (s.Permanent) { attenuation = 0.0f; return(true); } else if (s.Hard) { attenuation -= 0.6f; } else { attenuation -= 0.35f; } return(false); }); attenuation = Math.Max(0, attenuation); } player.Get <Agent>().Damage.Execute(attenuation * (minPlayerDamage + (1.0f - (d / physicsRadius)) * playerDamageMultiplier)); } } // Apply impulse to dynamic maps foreach (Voxel m in Voxel.ActiveVoxels) { DynamicVoxel dm = m as DynamicVoxel; if (dm == null) { continue; } Vector3 toMap = dm.Transform.Value.Translation - pos; float distanceToMap = toMap.Length(); toMap /= distanceToMap; toMap *= Math.Max(0.0f, 1.0f - (distanceToMap / physicsRadius)) * Math.Min(200.0f, dm.PhysicsEntity.Mass) * physicsImpulse; dm.PhysicsEntity.ApplyImpulse(dm.Transform.Value.Translation + new Vector3(((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f), toMap); } // Apply impulse to physics blocks foreach (Entity b in main.Get("Block")) { PhysicsBlock block = b.Get <PhysicsBlock>(); Vector3 fromExplosion = b.Get <Transform>().Position.Value - pos; float distance = fromExplosion.Length(); if (distance > 0.0f && distance < physicsRadius) { float blend = 1.0f - (distance / physicsRadius); block.Box.LinearVelocity += fromExplosion * blend * 10.0f / distance; block.Box.AngularVelocity += new Vector3(((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f) * blend; } } }
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.Powered || id == Voxel.t.PoweredSwitch || id == Voxel.t.HardPowered || id == Voxel.t.Infected || id == Voxel.t.HardInfected || (transferredFromMap == null && (id == Voxel.t.Blue || id == Voxel.t.Neutral || id == Voxel.t.Hard))) { 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.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; Sound.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, true, map); } else { map.Fill(coord, Voxel.States.Blue, true, map); } } } this.toRegenerate.Add(map); } this.removedPoweredCoords.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 (this.main.TotalTime - EffectBlock.lastSound > 0.15f) { EffectBlock.lastSound = this.main.TotalTime; Sound.PostEvent(this.StateId == Voxel.t.Floater ? AK.EVENTS.PLAY_FLOATER_BUILD : AK.EVENTS.PLAY_BLOCK_BUILD, absolutePos); } 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(); this.EnabledWhenPaused = false; this.Serialize = false; this.Footstep.Action = delegate() { if (this.SoundEnabled && this.main.TotalTime - this.lastFootstepSound > footstepSoundInterval) { AkSoundEngine.PostEvent(AK.EVENTS.FOOTSTEP_PLAY, this.Entity); this.lastFootstepSound = this.main.TotalTime; } }; this.Add(new CommandBinding <Voxel, Voxel.Coord, Direction>(this.WalkedOn, delegate(Voxel map, Voxel.Coord coord, Direction dir) { Voxel.State state = map[coord]; if (state != Voxel.States.Empty) { AkSoundEngine.SetSwitch(AK.SWITCHES.FOOTSTEP_MATERIAL.GROUP, state.FootstepSwitch, this.Entity); if (this.WallRunState.Value == WallRun.State.None) { if (map.GetAbsoluteDirection(dir) == Direction.NegativeY && !this.IsSwimming) { this.walkedOnCount++; if (this.walkedOnCount >= 2) { // Every few tiles, save off the location for the auto-respawn system coord.Data = null; this.RespawnLocations.Add(new RespawnLocation { Coordinate = coord, Map = map.Entity, Rotation = this.Rotation, OriginalPosition = map.GetAbsolutePosition(coord), }); while (this.RespawnLocations.Length > Spawner.RespawnMemoryLength) { this.RespawnLocations.RemoveAt(0); } this.walkedOnCount = 0; } } } } Voxel.t id = state.ID; if (id == Voxel.t.Neutral) { map.Empty(coord, false, true, map); bool isPowered = false; for (int i = 0; i < 6; i++) { Voxel.Coord adjacentCoord = coord.Move(DirectionExtensions.Directions[i]); Voxel.t adjacentId = map[coord].ID; if (adjacentId == Voxel.t.Powered || adjacentId == Voxel.t.PermanentPowered || adjacentId == Voxel.t.PoweredSwitch || adjacentId == Voxel.t.HardPowered) { isPowered = true; break; } } map.Fill(coord, isPowered ? Voxel.States.Powered : Voxel.States.Blue); map.Regenerate(); WorldFactory.Instance.Get <Propagator>().Sparks(map.GetAbsolutePosition(coord), Propagator.Spark.Normal); } else if (id == Voxel.t.Reset) { bool regenerate = false; Queue <Voxel.Coord> queue = new Queue <Voxel.Coord>(); queue.Enqueue(coord); Voxel.CoordSetCache.Add(coord); while (queue.Count > 0) { Voxel.Coord c = queue.Dequeue(); for (int i = 0; i < 6; i++) { Voxel.Coord adjacentCoord = c.Move(DirectionExtensions.Directions[i]); if (!Voxel.CoordSetCache.Contains(adjacentCoord)) { Voxel.CoordSetCache.Add(adjacentCoord); Voxel.t adjacentID = map[adjacentCoord].ID; if (adjacentID == Voxel.t.Reset || adjacentID == Voxel.t.Hard) { queue.Enqueue(adjacentCoord); } else if (adjacentID == Voxel.t.Infected || adjacentID == Voxel.t.Blue || adjacentID == Voxel.t.Powered) { map.Empty(adjacentCoord, false, true, map); map.Fill(adjacentCoord, Voxel.States.Neutral); regenerate = true; } else if (adjacentID == Voxel.t.HardPowered || adjacentID == Voxel.t.HardInfected) { map.Empty(adjacentCoord, false, true, map); map.Fill(adjacentCoord, Voxel.States.Hard); regenerate = true; } } } } Voxel.CoordSetCache.Clear(); if (regenerate) { map.Regenerate(); } } // Lava. Damage the player character if it steps on lava. bool isInfected = id == Voxel.t.Infected || id == Voxel.t.HardInfected; if (isInfected) { this.Damage.Execute(0.2f); } else if (id == Voxel.t.Floater) { // Floater. Delete the block after a delay. Vector3 pos = map.GetAbsolutePosition(coord); ParticleEmitter.Emit(main, "Smoke", pos, 1.0f, 10); Sound.PostEvent(AK.EVENTS.PLAY_CRUMBLE, pos); WorldFactory.Instance.Add(new Animation ( new Animation.Delay(0.5f), new Animation.Execute(delegate() { if (map[coord].ID == Voxel.t.Floater) { map.Empty(coord); map.Regenerate(); } }) )); } this.infectedDamage = isInfected; })); }
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; }