override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera) { base.Update(gameTime, chunks, camera); Storm.InitializeStatics(); BoundingBox box = chunks.Bounds; box.Expand(10.0f); if (GlobalTransform.Translation.X < box.Min.X || GlobalTransform.Translation.X > box.Max.X || GlobalTransform.Translation.Z < box.Min.Z || GlobalTransform.Translation.Z > box.Max.Z) { Die(); } bool generateRainDrop = MathFunctions.RandEvent(Raininess * 0.75f); if (generateRainDrop) { for (int i = 0; i < MaxRainDrops; i++) { if (!RainDrops[i].IsAlive) { RainDrops[i].IsAlive = true; if (RainDrops[i].Particle != null) { RainDrops[i].Particle.LifeRemaining = 60.0f; RainDrops[i].Particle.TimeAlive = 0.0f; } RainDrops[i].Pos = MathFunctions.RandVector3Box(BoundingBox.Expand(5)); RainDrops[i].Pos = new Vector3(RainDrops[i].Pos.X, BoundingBox.Min.Y - 1, RainDrops[i].Pos.Z); RainDrops[i].Vel = Vector3.Down * Storm.Properties[TypeofStorm].RainSpeed + Velocity; break; } } } bool generateLightning = LightningChance > 0.0f && MathFunctions.RandEvent((float)(LightningChance * 0.001f)); if (generateLightning) { var below = VoxelHelpers.FindFirstVoxelBelowIncludingWater(new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(new Vector3(Position.X, Math.Min(World.WorldSizeInVoxels.Y - 1, Position.Y), Position.Z)))); if (below.IsValid && !below.IsEmpty) { var above = VoxelHelpers.GetVoxelAbove(below); if (above.IsValid) { EntityFactory.CreateEntity <Fire>("Fire", above.GetBoundingBox().Center()); List <Vector3> lightningStrikes = new List <Vector3>(); List <Color> colors = new List <Color>(); var c = above.GetBoundingBox().Center(); for (float t = 0; t < 1.0f; t += 0.25f) { var p = c * t + Position * (1.0f - t); lightningStrikes.Add(p + MathFunctions.RandVector3Box(-5, 5, 0, 0.1f, -5, 5)); colors.Add(Color.White); } lightningStrikes.Add(c); colors.Add(Color.White); Drawer3D.DrawLineList(lightningStrikes, colors, 0.3f); SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_rain_storm_alert, MathFunctions.Rand(0.001f, 0.05f), MathFunctions.Rand(0.5f, 1.0f)); SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_trap_destroyed, c, false, 1.0f, MathFunctions.Rand(-0.5f, 0.5f)); World.ParticleManager.Trigger("explode", c, Color.White, 10); } } } Storm.StormProperties stormProperties = Storm.Properties[TypeofStorm]; var rainEmitter = World.ParticleManager.Effects[stormProperties.RainEffect]; var hitEmitter = World.ParticleManager.Effects[stormProperties.HitEffect]; for (int i = 0; i < MaxRainDrops; i++) { if (!RainDrops[i].IsAlive) { continue; } RainDrops[i].Pos += RainDrops[i].Vel * DwarfTime.Dt; if (stormProperties.RainRandom > 0) { RainDrops[i].Vel.X += MathFunctions.Rand(-1, 1) * stormProperties.RainRandom * DwarfTime.Dt; RainDrops[i].Vel.Z += MathFunctions.Rand(-1, 1) * stormProperties.RainRandom * DwarfTime.Dt; } if (RainDrops[i].Pos.Y < 0) { RainDrops[i].IsAlive = false; } if (!RainDrops[i].IsAlive && RainDrops[i].Particle != null) { RainDrops[i].Particle.LifeRemaining = -1; } else if (RainDrops[i].IsAlive && RainDrops[i].Particle == null) { RainDrops[i].Particle = rainEmitter.Emitters[0].CreateParticle(RainDrops[i].Pos, RainDrops[i].Vel, Color.White); } else if (RainDrops[i].IsAlive && RainDrops[i].Particle != null) { RainDrops[i].Particle.Position = RainDrops[i].Pos; RainDrops[i].Particle.Velocity = RainDrops[i].Vel; } var test = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(RainDrops[i].Pos)); if (!test.IsValid || (test.IsEmpty && test.LiquidLevel == 0)) { continue; } RainDrops[i].IsAlive = false; var hitBodies = World.EnumerateIntersectingObjects(new BoundingBox(RainDrops[i].Pos - Vector3.One, RainDrops[i].Pos + Vector3.One)); foreach (var body in hitBodies) { if (body.Parent != Manager.RootComponent) { continue; } var flames = body.GetRoot().GetComponent <Flammable>(); if (flames != null) { flames.Heat *= 0.25f; } var seeds = body.GetRoot().GetComponent <Seedling>(); if (seeds != null) { if (TypeofStorm == StormType.RainStorm) { seeds.GrowthTime += MathFunctions.Rand(1.0f, 12.0f); } else if (MathFunctions.RandEvent(0.01f)) { seeds.GetRoot().Die(); } } } hitEmitter.Trigger(1, RainDrops[i].Pos + Vector3.UnitY * 0.5f, Color.White); //if (!MathFunctions.RandEvent(0.1f)) continue; var above = test.IsEmpty ? test : VoxelHelpers.GetVoxelAbove(test); if (!above.IsValid || !above.IsEmpty) { continue; } if (TypeofStorm == StormType.RainStorm && (above.LiquidLevel < WaterManager.maxWaterLevel && (above.LiquidType == LiquidType.Water))) { above.LiquidLevel = (byte)Math.Min(WaterManager.maxWaterLevel, above.LiquidLevel + WaterManager.rainFallAmount); above.LiquidType = stormProperties.LiquidToCreate; } else if (TypeofStorm == StormType.SnowStorm && above.IsEmpty && above.LiquidLevel == 0) { if (test.GrassType == 0) { test.GrassType = Library.GetGrassType("snow").ID; test.GrassDecay = Library.GetGrassType("snow").InitialDecayValue; } else { var existingGrass = Library.GetGrassType((byte)test.GrassType); if (!String.IsNullOrEmpty(existingGrass.BecomeWhenSnowedOn)) { var newGrass = Library.GetGrassType(existingGrass.BecomeWhenSnowedOn); test.GrassType = newGrass.ID; test.GrassDecay = newGrass.InitialDecayValue; } } } } Matrix tf = LocalTransform; tf.Translation += Velocity * DwarfTime.Dt; LocalTransform = tf; }
/// <summary> gets the list of actions that the creature can take from a given voxel. </summary> public IEnumerable <MoveAction> GetMoveActions(MoveState state, List <GameComponent> teleportObjects, MoveActionTempStorage Storage) { if (Parent == null) { yield break; } if (!state.Voxel.IsValid) { yield break; } if (Creature == null) { yield break; } if (Storage == null) { Storage = new MoveActionTempStorage(); } GetNeighborhood(state.Voxel.Chunk.Manager, state.Voxel, Storage.Neighborhood); bool inWater = (Storage.Neighborhood[1, 1, 1].IsValid && Storage.Neighborhood[1, 1, 1].LiquidLevel > WaterManager.inWaterThreshold); bool standingOnGround = (Storage.Neighborhood[1, 0, 1].IsValid && !Storage.Neighborhood[1, 0, 1].IsEmpty); bool topCovered = (Storage.Neighborhood[1, 2, 1].IsValid && !Storage.Neighborhood[1, 2, 1].IsEmpty); bool hasNeighbors = HasNeighbors(Storage.Neighborhood); bool isRiding = state.VehicleType != VehicleTypes.None; var neighborHoodBounds = new BoundingBox(Storage.Neighborhood[0, 0, 0].GetBoundingBox().Min, Storage.Neighborhood[2, 2, 2].GetBoundingBox().Max); Storage.NeighborObjects.Clear(); Parent.World.EnumerateIntersectingObjects(neighborHoodBounds, Storage.NeighborObjects); if (Can(MoveType.Teleport)) { foreach (var obj in teleportObjects) { if ((obj.Position - state.Voxel.WorldPosition).LengthSquared() < TeleportDistanceSquared) { yield return new MoveAction() { InteractObject = obj, MoveType = MoveType.Teleport, SourceVoxel = state.Voxel, DestinationState = new MoveState() { Voxel = new VoxelHandle(state.Voxel.Chunk.Manager, GlobalVoxelCoordinate.FromVector3(obj.Position)) }, CostMultiplier = 1.0f } } } } ; var successors = EnumerateSuccessors(state, state.Voxel, Storage, inWater, standingOnGround, topCovered, hasNeighbors); // Now, validate each move action that the creature might take. foreach (MoveAction v in successors) { #if DEBUG if (!v.DestinationVoxel.IsValid) { throw new InvalidOperationException(); } #endif var n = v.DestinationVoxel.IsValid ? v.DestinationVoxel : Storage.Neighborhood[(int)v.Diff.X, (int)v.Diff.Y, (int)v.Diff.Z]; if (n.IsValid && (v.MoveType == MoveType.Dig || isRiding || n.IsEmpty || n.LiquidLevel > 0)) { // Do one final check to see if there is an object blocking the motion. bool blockedByObject = false; if (state.VehicleType == VehicleTypes.None) { var objectsAtNeighbor = Storage.NeighborObjects.Where(o => o.GetBoundingBox().Intersects(n.GetBoundingBox())); // If there is an object blocking the motion, determine if it can be passed through. foreach (var body in objectsAtNeighbor) { var door = body as Door; // ** Doors are in the octtree, pretty sure this was always pointless -- var door = body.GetRoot().EnumerateAll().OfType<Door>().FirstOrDefault(); // If there is an enemy door blocking movement, we can destroy it to get through. if (door != null) { if ( Creature.World.Overworld.GetPolitics(door.TeamFaction.ParentFaction, Creature.Faction.ParentFaction) .GetCurrentRelationship() == Relationship.Hateful) { if (Can(MoveType.DestroyObject)) { yield return(new MoveAction { Diff = v.Diff, MoveType = MoveType.DestroyObject, InteractObject = door, DestinationVoxel = n, SourceState = state, CostMultiplier = 1.0f // Todo: Multiply by toughness of object? }); } blockedByObject = true; } } } } // If no object blocked us, we can move freely as normal. if (!blockedByObject && n.LiquidType != LiquidType.Lava) { var newAction = v; newAction.SourceState = state; newAction.DestinationVoxel = n; yield return(newAction); } } } }
override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera) { var body = Parent as GameComponent; global::System.Diagnostics.Debug.Assert(body != null); Vector3 targetVelocity = TargetPosition - body.GlobalTransform.Translation; if (targetVelocity.LengthSquared() > 0.0001f) { targetVelocity.Normalize(); targetVelocity *= MaxVelocity; } Matrix m = body.LocalTransform; m.Translation += targetVelocity * (float)gameTime.ElapsedGameTime.TotalSeconds; body.LocalTransform = m; body.HasMoved = true; switch (State) { case BalloonState.DeliveringGoods: { var voxel = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(body.GlobalTransform.Translation)); if (voxel.IsValid) { var surfaceVoxel = VoxelHelpers.FindFirstVoxelBelow(voxel); var height = surfaceVoxel.Coordinate.Y + 1; TargetPosition = new Vector3(body.GlobalTransform.Translation.X, height + 5, body.GlobalTransform.Translation.Z); Vector3 diff = body.GlobalTransform.Translation - TargetPosition; if (diff.LengthSquared() < 2) { State = BalloonState.Waiting; } } else { State = BalloonState.Leaving; } } break; case BalloonState.Leaving: TargetPosition = Vector3.UnitY * 100 + body.GlobalTransform.Translation; if (body.GlobalTransform.Translation.Y > World.WorldSizeInVoxels.Y + 2) { Die(); } break; case BalloonState.Waiting: TargetPosition = body.GlobalTransform.Translation; if (!WaitTimer.HasTriggered) { var voxel = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(body.GlobalTransform.Translation)); if (voxel.IsValid) { var surfaceVoxel = VoxelHelpers.FindFirstVoxelBelow(voxel); var height = surfaceVoxel.Coordinate.Y + 6; TargetPosition = new Vector3(body.GlobalTransform.Translation.X, height + 0.5f * (float)Math.Sin(DwarfTime.LastTime.TotalGameTime.TotalSeconds), body.GlobalTransform.Translation.Z); } WaitTimer.Update(DwarfTime.LastTime); break; } if (!shipmentGiven) { shipmentGiven = true; } else { State = BalloonState.Leaving; } break; } }
public static IEnumerable <GlobalVoxelCoordinate> EnumerateCube( GlobalVoxelCoordinate Coordinate) { return(EnumerateNeighbors(Cube, Coordinate)); }
public static IEnumerable <GlobalVoxelCoordinate> EnumerateVertexNeighbors2D( GlobalVoxelCoordinate Coordinate, VoxelVertex Vertex) { return(EnumerateNeighbors(VertexNeighbors2D[(int)Vertex], Coordinate)); }
private List <VoxelHandle> SpiralVoxels() { // Process voxels into a neat grid. if (Voxels.Count == 0) { throw new InvalidOperationException(); } var bounds = this.GetBoundingBox(); var voxelGrid = new VoxelHandle[(int)(bounds.Max.X - bounds.Min.X), (int)(bounds.Max.Z - bounds.Min.Z)]; foreach (var voxel in Voxels) { voxelGrid[(int)(voxel.Coordinate.X - bounds.Min.X), (int)(voxel.Coordinate.Z - bounds.Min.Z)] = voxel; } // if any invalid voxels in grid, go ahead and abort. foreach (var voxel in voxelGrid) { if (!voxel.IsValid) { return(Voxels); } } // Find center voxel. Actually want to round UP - or - spiral in positive direction? var center_c = GlobalVoxelCoordinate.FromVector3(bounds.Center()); var current_v = Voxels.FirstOrDefault(v => v.Coordinate == center_c); if (!current_v.IsValid) { return(Voxels); } var direction = Direction.East; var results = new List <VoxelHandle>(); results.Add(current_v); // Starting at center, spiral around, starting to the right. while (true) { var next_voxel = Voxels.FirstOrDefault(v => v.Coordinate == current_v.Coordinate + GetDirectionOffset(direction)); if (next_voxel.IsValid) { results.Add(next_voxel); current_v = next_voxel; var possible_turn = TurnRight(direction); var possible_ahead = Voxels.FirstOrDefault(v => v.Coordinate == current_v.Coordinate + GetDirectionOffset(possible_turn)); if (possible_ahead.IsValid && !results.Any(v => v.Coordinate == possible_ahead.Coordinate)) { direction = possible_turn; } } else { break; } } // Recover any voxels we missed. foreach (var voxel in Voxels) { if (!results.Any(v => v.Coordinate == voxel.Coordinate)) { results.Add(voxel); } } return(results); // For each voxel - step one in the current direction and return. // If we've hit an edge - try and turn. // If the next direction is unvisited - turn }
public static IEnumerable <GlobalVoxelCoordinate> EnumerateManhattanNeighbors2D_Z(GlobalVoxelCoordinate Coordinate) { return(EnumerateNeighbors(ManhattanNeighbors2D.Select(n => new GlobalVoxelOffset(n.X, -n.Z, 0)), Coordinate)); }
public bool IsCameraUnderwater() { var handle = new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(Camera.Position + Vector3.Up)); return(handle.IsValid && handle.LiquidLevel > 0 && handle.Coordinate.Y <= (PersistentSettings.MaxViewingLevel >= World.WorldSizeInVoxels.Y ? 1000.0f : PersistentSettings.MaxViewingLevel + 0.25f)); }
public void ChangeCameraMode(OrbitCamera.ControlType type) { Camera.Control = type; if (type == OrbitCamera.ControlType.Walk) { SetMaxViewingLevel(World.WorldSizeInVoxels.Y); var below = VoxelHelpers.FindFirstVoxelBelowIncludingWater(new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(new Vector3(Camera.Position.X, World.WorldSizeInVoxels.Y - 1, Camera.Position.Z)))); Camera.Position = below.WorldPosition + Vector3.One * 0.5f + Vector3.Up; } }
/// <summary> /// Rasterizes the line, producing a list of GlobalVoxelCoordinates's that intersect /// the line segment. /// </summary> /// <param name="Start">The start.</param> /// <param name="End">The end.</param> /// <returns></returns> public static IEnumerable <GlobalVoxelCoordinate> FastVoxelTraversal(Vector3 Start, Vector3 End) { if (L1(Start, End) < 1e-12 || HasNan(Start) || HasNan(End)) { yield break; } // From "A Fast DestinationVoxel Traversal Algorithm for Ray Tracing" // by John Amanatides and Andrew Woo, 1987 // <http://www.cse.yorku.ca/~amana/research/grid.pdf> // <http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.42.3443> // Extensions to the described algorithm: // • Imposed a distance limit. // The foundation of this algorithm is a parameterized representation of // the provided ray, // origin + t * direction, // except that t is not actually stored; rather, at any given point in the // traversal, we keep track of the *greater* t values which we would have // if we took a step sufficient to cross a cube boundary along that axis // (i.e. change the integer part of the coordinate) in the variables // tMaxX, tMaxY, and tMaxZ. Vector3 direction = End - Start; var cutoffLength = direction.LengthSquared() * 1.01f; direction.Normalize(); // Direction to increment x,y,z when stepping. var stepX = Math.Sign(direction.X); var stepY = Math.Sign(direction.Y); var stepZ = Math.Sign(direction.Z); // See description above. The initial values depend on the fractional // part of the origin. var tMaxX = IntBound(Start.X, direction.X); var tMaxY = IntBound(Start.Y, direction.Y); var tMaxZ = IntBound(Start.Z, direction.Z); // The change in t when taking a step (always positive). var tDeltaX = stepX / direction.X; var tDeltaY = stepY / direction.Y; var tDeltaZ = stepZ / direction.Z; var endX = FloorInt(End.X); var endY = FloorInt(End.Y); var endZ = FloorInt(End.Z); while (true) { var r = GlobalVoxelCoordinate.FromVector3(Start); yield return(r); if (r.X == endX && r.Y == endY && r.Z == endZ) { yield break; } if ((End - Start).LengthSquared() > cutoffLength) { yield break; } // tMaxX stores the t-value at which we cross a cube boundary along the // X axis, and similarly for Y and Z. Therefore, choosing the least tMax // chooses the closest cube boundary. Only the first case of the four // has been commented in detail. if (tMaxX < tMaxY) { if (tMaxX < tMaxZ) { // Update which cube we are now in. Start.X += stepX; // Adjust tMaxX to the next X-oriented boundary crossing. tMaxX += tDeltaX; } else { Start.Z += stepZ; tMaxZ += tDeltaZ; } } else { if (tMaxY < tMaxZ) { Start.Y += stepY; tMaxY += tDeltaY; } else { // Identical to the second case, repeated for simplicity in // the conditionals. Start.Z += stepZ; tMaxZ += tDeltaZ; } } } }
/// <summary> gets the list of actions that the creature can take from a given voxel. </summary> public IEnumerable <MoveAction> GetMoveActions(MoveState state, OctTreeNode OctTree) { if (Parent == null) { yield break; } var voxel = state.Voxel; if (!voxel.IsValid) { yield break; } var creature = Creature; if (creature == null) { yield break; } var neighborHood = GetNeighborhood(voxel.Chunk.Manager.ChunkData, voxel); bool inWater = (neighborHood[1, 1, 1].IsValid && neighborHood[1, 1, 1].LiquidLevel > WaterManager.inWaterThreshold); bool standingOnGround = (neighborHood[1, 0, 1].IsValid && !neighborHood[1, 0, 1].IsEmpty); bool topCovered = (neighborHood[1, 2, 1].IsValid && !neighborHood[1, 2, 1].IsEmpty); bool hasNeighbors = HasNeighbors(neighborHood); bool isRiding = state.VehicleState.IsRidingVehicle; var neighborHoodBounds = new BoundingBox(neighborHood[0, 0, 0].GetBoundingBox().Min, neighborHood[2, 2, 2].GetBoundingBox().Max); var neighborObjects = new HashSet <Body>(); OctTree.EnumerateItems(neighborHoodBounds, neighborObjects); var successors = EnumerateSuccessors(state, voxel, neighborHood, inWater, standingOnGround, topCovered, hasNeighbors, isRiding, neighborObjects); if (Can(MoveType.Teleport)) { var teleportObjects = Parent.Faction.OwnedObjects.Where(obj => obj.Active && obj.Tags.Contains("Teleporter")); foreach (var obj in teleportObjects) { if ((obj.Position - state.Voxel.WorldPosition).LengthSquared() < TeleportDistanceSquared) { yield return(new MoveAction() { InteractObject = obj, MoveType = MoveType.Teleport, SourceVoxel = voxel, DestinationState = new MoveState() { Voxel = new VoxelHandle(voxel.Chunk.Manager.ChunkData, GlobalVoxelCoordinate.FromVector3(obj.Position)) } }); } } } // Now, validate each move action that the creature might take. foreach (MoveAction v in successors) { var n = v.DestinationVoxel.IsValid ? v.DestinationVoxel : neighborHood[(int)v.Diff.X, (int)v.Diff.Y, (int)v.Diff.Z]; if (n.IsValid && (v.MoveType == MoveType.Dig || isRiding || n.IsEmpty || n.LiquidLevel > 0)) { // Do one final check to see if there is an object blocking the motion. bool blockedByObject = false; if (!isRiding) { var objectsAtNeighbor = neighborObjects.Where(o => o.GetBoundingBox().Intersects(n.GetBoundingBox())); // If there is an object blocking the motion, determine if it can be passed through. foreach (var body in objectsAtNeighbor) { var door = body as Door; // ** Doors are in the octtree, pretty sure this was always pointless -- var door = body.GetRoot().EnumerateAll().OfType<Door>().FirstOrDefault(); // If there is an enemy door blocking movement, we can destroy it to get through. if (door != null) { if ( creature.World.Diplomacy.GetPolitics(door.TeamFaction, creature.Faction) .GetCurrentRelationship() == Relationship.Hateful) { if (Can(MoveType.DestroyObject)) { yield return(new MoveAction { Diff = v.Diff, MoveType = MoveType.DestroyObject, InteractObject = door, DestinationVoxel = n, SourceState = state }); } blockedByObject = true; } } } } // If no object blocked us, we can move freely as normal. if (!blockedByObject && n.LiquidType != LiquidType.Lava) { MoveAction newAction = v; newAction.SourceState = state; newAction.DestinationVoxel = n; yield return(newAction); } } } }
override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera) { base.Update(gameTime, chunks, camera); Storm.InitializeStatics(); BoundingBox box = chunks.Bounds; box.Expand(10.0f); if (GlobalTransform.Translation.X < box.Min.X || GlobalTransform.Translation.X > box.Max.X || GlobalTransform.Translation.Z < box.Min.Z || GlobalTransform.Translation.Z > box.Max.Z) { Die(); } bool generateRainDrop = MathFunctions.RandEvent(Raininess * 0.75f); if (generateRainDrop) { for (int i = 0; i < MaxRainDrops; i++) { if (!RainDrops[i].IsAlive) { RainDrops[i].IsAlive = true; RainDrops[i].Pos = MathFunctions.RandVector3Box(BoundingBox.Expand(5)); RainDrops[i].Pos = new Vector3(RainDrops[i].Pos.X, BoundingBox.Min.Y - 1, RainDrops[i].Pos.Z); RainDrops[i].Vel = Vector3.Down * Storm.Properties[TypeofStorm].RainSpeed + Velocity; break; } } } Storm.StormProperties stormProperties = Storm.Properties[TypeofStorm]; var rainEmitter = World.ParticleManager.Effects[stormProperties.RainEffect]; var hitEmitter = World.ParticleManager.Effects[stormProperties.HitEffect]; for (int i = 0; i < MaxRainDrops; i++) { if (!RainDrops[i].IsAlive) { continue; } RainDrops[i].Pos += RainDrops[i].Vel * DwarfTime.Dt; if (stormProperties.RainRandom > 0) { RainDrops[i].Vel.X += MathFunctions.Rand(-1, 1) * stormProperties.RainRandom * DwarfTime.Dt; RainDrops[i].Vel.Z += MathFunctions.Rand(-1, 1) * stormProperties.RainRandom * DwarfTime.Dt; } if (RainDrops[i].Pos.Y < 0) { RainDrops[i].IsAlive = false; } if (!RainDrops[i].IsAlive && RainDrops[i].Particle != null) { RainDrops[i].Particle.LifeRemaining = -1; RainDrops[i].Particle = null; } else if (RainDrops[i].IsAlive && RainDrops[i].Particle == null) { RainDrops[i].Particle = rainEmitter.Emitters[0].CreateParticle(RainDrops[i].Pos, RainDrops[i].Vel, Color.White); } else if (RainDrops[i].IsAlive && RainDrops[i].Particle != null) { RainDrops[i].Particle.Position = RainDrops[i].Pos; RainDrops[i].Particle.Velocity = RainDrops[i].Vel; } var test = new VoxelHandle(chunks.ChunkData, GlobalVoxelCoordinate.FromVector3(RainDrops[i].Pos)); if (!test.IsValid || test.IsEmpty || test.LiquidLevel > 0) { continue; } RainDrops[i].IsAlive = false; hitEmitter.Trigger(1, RainDrops[i].Pos + Vector3.UnitY * 0.5f, Color.White); //if (!MathFunctions.RandEvent(0.1f)) continue; var above = test.IsEmpty ? test : VoxelHelpers.GetVoxelAbove(test); if (!above.IsValid || !above.IsEmpty) { continue; } if (TypeofStorm == StormType.RainStorm && (above.LiquidLevel < WaterManager.maxWaterLevel && (above.LiquidType == LiquidType.Water))) { above.LiquidLevel = (byte)Math.Min(WaterManager.maxWaterLevel, above.LiquidLevel + WaterManager.rainFallAmount); above.LiquidType = stormProperties.LiquidToCreate; } else if (TypeofStorm == StormType.SnowStorm && above.IsEmpty && above.LiquidLevel == 0) { if (test.GrassType == 0) { test.GrassType = GrassLibrary.GetGrassType("snow").ID; test.GrassDecay = GrassLibrary.GetGrassType("snow").InitialDecayValue; } else { var existingGrass = GrassLibrary.GetGrassType((byte)test.GrassType); if (!String.IsNullOrEmpty(existingGrass.BecomeWhenSnowedOn)) { var newGrass = GrassLibrary.GetGrassType(existingGrass.BecomeWhenSnowedOn); test.GrassType = newGrass.ID; test.GrassDecay = newGrass.InitialDecayValue; } } } } Matrix tf = LocalTransform; tf.Translation += Velocity * DwarfTime.Dt; LocalTransform = tf; }
/// <summary> /// Snaps the supplied coordinate into valid world space. Returns nearest valid voxel to the point. /// </summary> /// <param name="chunks"></param> /// <param name="pos"></param> /// <returns></returns> public static VoxelHandle FindValidVoxelNear(ChunkManager chunks, Microsoft.Xna.Framework.Vector3 pos) { var clampedPos = MathFunctions.Clamp(pos, chunks.Bounds) + Microsoft.Xna.Framework.Vector3.Down * 0.05f; return(chunks.CreateVoxelHandle(GlobalVoxelCoordinate.FromVector3(clampedPos))); }
public override void Update(DwarfTime Time, ChunkManager Chunks, Camera Camera) { if (Active) { ParticleTimer.Update(Time); if (ParticleTimer.HasTriggered) { float t = (float)Time.TotalGameTime.TotalSeconds * 0.5f; Vector3 pos = new Vector3((float)Math.Sin(t) * TeleportDistance, 0, (float)Math.Cos(t) * TeleportDistance) + Position; VoxelHandle voxelBelow = VoxelHelpers.FindFirstVoxelBelow(new VoxelHandle(World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(pos))); if (voxelBelow.IsValid) { World.ParticleManager.Trigger("green_flame", voxelBelow.WorldPosition + Vector3.Up * 1.5f, Color.White, 1); } } } base.Update(Time, Chunks, Camera); }
public void Sense() { if (Name == "turret-sensor") { var x = 5; } if (!Active) { return; } if (Creature != null) { Allies = Creature.Faction; } // Don't sense enemies if we're inside the ground?? var currentVoxel = new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(Position)); if (!(currentVoxel.IsValid && currentVoxel.IsEmpty)) { return; } var sensed = new List <CreatureAI>(); var myRoot = GetRoot(); foreach (var body in Manager.World.EnumerateIntersectingObjects(BoundingBox, b => !Object.ReferenceEquals(b, myRoot) && b.IsRoot())) { if (body.GetComponent <Flammable>().HasValue(out var flames) && flames.IsOnFire) { if (GetRoot().GetComponent <CreatureAI>().HasValue(out var myAI)) { var task = new FleeEntityTask(body, 5) { Priority = TaskPriority.Urgent, AutoRetry = false, ReassignOnDeath = false }; if (!myAI.HasTaskWithName(task)) { myAI.AssignTask(task); } continue; } } if (body.GetComponent <CreatureAI>().HasValue(out var minion)) { if (!minion.Active) { continue; } if (!DetectCloaked && minion.Creature.IsCloaked) { continue; } else if (DetectCloaked && minion.Creature.IsCloaked) { minion.Creature.IsCloaked = false; } if (World.Overworld.GetPolitics(Allies.ParentFaction, minion.Faction.ParentFaction).GetCurrentRelationship() != Relationship.Hateful) { continue; } if (!VoxelHelpers.DoesRayHitSolidVoxel(Manager.World.ChunkManager, Position, minion.Position)) { sensed.Add(minion); } } } if (sensed != null && sensed.Count > 0 && OnEnemySensed != null) { OnEnemySensed.Invoke(sensed); } }
public IEnumerable <Status> TeleportFunction() { GameComponent closestItem = Creature.AI.Blackboard.GetData <GameComponent>(ObjectName); if (closestItem != null) { var location = TeleportOffset + closestItem.BoundingBox.Center(); if (CheckForOcclusion) { VoxelHandle voxAt = new VoxelHandle(Agent.World.ChunkManager, GlobalVoxelCoordinate.FromVector3(location)); bool gotLocation = false; if (!voxAt.IsValid || !voxAt.IsEmpty) { // If we can't go to the preferred location, just try any free neighbor. voxAt = new VoxelHandle(Agent.World.ChunkManager, GlobalVoxelCoordinate.FromVector3(closestItem.BoundingBox.Center())); foreach (var neighbor in VoxelHelpers.EnumerateManhattanNeighbors2D(voxAt.Coordinate)) { VoxelHandle newVox = new VoxelHandle(Agent.World.ChunkManager, neighbor); if (newVox.IsValid && newVox.IsEmpty) { location = newVox.WorldPosition + new Vector3(0.5f, Agent.Physics.BoundingBox.Extents().Y, 0.5f); gotLocation = true; break; } } // If there's no free neighbor, just teleport directly to the object. if (!gotLocation) { location = closestItem.BoundingBox.Center(); } } } TeleportAct act = new TeleportAct(Creature.AI) { Location = location }; act.Initialize(); foreach (Act.Status status in act.Run()) { yield return(status); } } yield return(Status.Fail); }
/// <summary> Animate the PlayState Camera to look at this creature </summary> public void ZoomToMe() { Manager.World.Renderer.Camera.ZoomTo(Position + Vector3.Up * 8.0f); var above = VoxelHelpers.FindFirstVoxelAbove(new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(Position))); if (above.IsValid) { World.Renderer.SetMaxViewingLevel(above.Coordinate.Y); } else { World.Renderer.SetMaxViewingLevel(World.WorldSizeInVoxels.Y); } }
public static Act.Status SetTarget(string voxelOutName, string entityName, Creature creature) { Body target = creature.AI.Blackboard.GetData <Body>(entityName); if (target == null) { return(Status.Fail); } else { var targetPosition = target.BoundingBox.Center(); targetPosition = MathFunctions.Clamp(targetPosition, target.World.ChunkManager.Bounds.Expand(-1)); var voxelUnder = VoxelHelpers.FindFirstVoxelBelowIncludeWater(new VoxelHandle( creature.World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(targetPosition))); if (voxelUnder.IsValid) { if (!voxelUnder.IsEmpty) { voxelUnder = VoxelHelpers.GetVoxelAbove(voxelUnder); } creature.AI.Blackboard.SetData(voxelOutName, voxelUnder); return(Status.Success); } else { return(Status.Fail); } } }
public void Update(ParticleManager manager, DwarfTime gameTime, ChunkManager chunks, Camera camera) { ParticleEmitter._camera = camera; List <Particle> toRemove = new List <Particle>(); TriggerTimer.Update(gameTime); if (TriggerTimer.HasTriggered && Data.ParticlesPerFrame > 0) { Trigger(Data.ParticlesPerFrame, Vector3.Zero, new Color(255, 255, 0)); } bool particlePhysics = GameSettings.Default.ParticlePhysics; foreach (Particle p in Particles) { float vel = p.Velocity.LengthSquared(); if (Data.EmitsLight && p.Scale > 0.1f) { DynamicLight.TempLights.Add(new DynamicLight(10.0f, 255.0f, false) { Position = p.Position }); } p.Position += p.Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds; if (Data.RotatesWithVelocity) { Vector3 cameraVel = camera.Project(p.Velocity + camera.Position); float projectionX = cameraVel.X; float projectionY = cameraVel.Y; p.Angle = (float)Math.Atan2(projectionY, projectionX); } else { p.Angle += (float)(p.AngularVelocity * gameTime.ElapsedGameTime.TotalSeconds); } if (!Data.Sleeps || vel > 0.01f) { p.Velocity += Data.ConstantAccel * (float)gameTime.ElapsedGameTime.TotalSeconds; } p.Velocity *= Data.LinearDamping; p.AngularVelocity *= Data.AngularDamping; if (!Data.UseManualControl) { p.LifeRemaining -= Data.ParticleDecay * (float)gameTime.ElapsedGameTime.TotalSeconds; } else if (p.TimeAlive > 60) { p.LifeRemaining = 0; } p.Scale += Data.GrowthSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds; p.Scale = Math.Max(p.Scale, 0.0f); var v = new VoxelHandle(chunks.ChunkData, GlobalVoxelCoordinate.FromVector3(p.Position)); if (Data.HasLighting) { if (v.IsValid) { p.LightRamp = new Color(v.Sunlight ? 255 : 0, 255, 0); } } else { p.LightRamp = new Color(255, 255, 0); } if (Data.CollidesWorld && particlePhysics && vel > 0.2f) { if (v.IsValid && !v.IsEmpty) { BoundingBox b = new BoundingBox(p.Position - Vector3.One * p.Scale * 0.5f, p.Position + Vector3.One * p.Scale * 0.5f); BoundingBox vBox = v.GetBoundingBox(); Physics.Contact contact = new Physics.Contact(); if (Physics.TestStaticAABBAABB(b, vBox, ref contact)) { p.Position += contact.NEnter * contact.Penetration; Vector3 newVelocity = Vector3.Reflect(p.Velocity, -contact.NEnter); p.Velocity = newVelocity * Data.Damping; p.AngularVelocity *= 0.5f; if (Data.Sleeps) { p.Velocity = Vector3.Zero; p.AngularVelocity = 0.0f; vel = 0.0f; } if (!String.IsNullOrEmpty(Data.SpatterType)) { var above = VoxelHelpers.GetVoxelAbove(v); if (!above.IsValid || above.IsEmpty) { float x = MathFunctions.Clamp(p.Position.X, vBox.Min.X + 0.1f, vBox.Max.X - 0.1f); float z = MathFunctions.Clamp(p.Position.Z, vBox.Min.Z + 0.1f, vBox.Max.Z - 0.1f); manager.Create(Data.SpatterType, VertexNoise.Warp(new Vector3(x, v.RampType == RampType.None ? v.WorldPosition.Y + 1.02f : v.WorldPosition.Y + 0.6f, z)), Vector3.Zero, Color.White, Vector3.Up); } else { manager.Create(Data.SpatterType, p.Position - contact.NEnter * contact.Penetration * 0.95f, Vector3.Zero, Color.White, contact.NEnter); } p.LifeRemaining = -1.0f; } } } } if (p.LifeRemaining < 0) { if (p.InstanceData != null) { p.InstanceData.ShouldDraw = false; p.InstanceData.Transform = Matrix.CreateTranslation(camera.Position + new Vector3(-1000, -1000, -1000)); Sprites[p.Frame].Remove(p.InstanceData); } toRemove.Add(p); } else if (p.InstanceData != null) { p.TimeAlive += (float)gameTime.ElapsedGameTime.TotalSeconds + MathFunctions.Rand() * 0.01f; int prevFrame = p.Frame; int newFrame = AnimPlayer.GetFrame(p.TimeAlive); if (vel < 0.2f && Data.Sleeps) { newFrame = prevFrame; } if (newFrame != prevFrame) { p.Frame = newFrame; if (Sprites.Count > 0) { Sprites[prevFrame].Remove(p.InstanceData); Sprites[newFrame].Add(p.InstanceData); } if (/*!Data.Animation.Loops && */ p.Frame == Data.Animation.Frames.Count - 1) { p.LifeRemaining *= 0.1f; } } p.InstanceData.ShouldDraw = true; p.InstanceData.Transform = MatrixFromParticle(Data, p); p.InstanceData.LightRamp = p.LightRamp; } } foreach (Particle p in toRemove) { Particles.Remove(p); } foreach (var sprites in Sprites) { sprites.Update(gameTime, camera, GameState.Game.GraphicsDevice, chunks.World.Master.MaxViewingLevel); } }
public List <Body> GenerateRandomSpawn(int numCreatures, Vector3 position) { if (Race.CreatureTypes.Count == 0) { return(new List <Body>()); } List <Body> toReturn = new List <Body>(); for (int i = 0; i < numCreatures; i++) { string creature = Race.CreatureTypes[MathFunctions.Random.Next(Race.CreatureTypes.Count)]; Vector3 offset = MathFunctions.RandVector3Cube() * 2; var voxelUnder = VoxelHelpers.FindFirstVoxelBelowIncludeWater(new VoxelHandle( World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(position + offset))); if (voxelUnder.IsValid) { var body = EntityFactory.CreateEntity <Body>(creature, voxelUnder.WorldPosition + new Vector3(0.5f, 1, 0.5f)); var ai = body.EnumerateAll().OfType <CreatureAI>().FirstOrDefault(); if (ai != null) { ai.Faction.Minions.Remove(ai); Minions.Add(ai); ai.Faction = this; ai.Creature.Allies = Name; } toReturn.Add(body); } } return(toReturn); }
public static IEnumerable <GlobalVoxelCoordinate> EnumerateAllNeighbors( GlobalVoxelCoordinate Coordinate) { return(EnumerateNeighbors(AllNeighbors, Coordinate)); }
public VoxelChunk GenerateChunk(Vector3 origin, WorldManager World) { float waterHeight = SeaLevel + 1.0f / VoxelConstants.ChunkSizeY; VoxelChunk c = new VoxelChunk(Manager, origin, GlobalVoxelCoordinate.FromVector3(origin).GetGlobalChunkCoordinate()); for (int x = 0; x < VoxelConstants.ChunkSizeX; x++) { for (int z = 0; z < VoxelConstants.ChunkSizeZ; z++) { Vector2 v = new Vector2(x + origin.X, z + origin.Z) / WorldScale; var biome = Overworld.Map[(int)MathFunctions.Clamp(v.X, 0, Overworld.Map.GetLength(0) - 1), (int)MathFunctions.Clamp(v.Y, 0, Overworld.Map.GetLength(1) - 1)].Biome; BiomeData biomeData = BiomeLibrary.Biomes[biome]; Vector2 pos = new Vector2(x + origin.X, z + origin.Z) / WorldScale; float hNorm = Overworld.LinearInterpolate(pos, Overworld.Map, Overworld.ScalarFieldType.Height); float h = MathFunctions.Clamp(hNorm * VoxelConstants.ChunkSizeY, 0.0f, VoxelConstants.ChunkSizeY - 2); int stoneHeight = (int)(MathFunctions.Clamp((int)(h - (biomeData.SoilLayer.Depth + (Math.Sin(v.X) + Math.Cos(v.Y)))), 1, h)); int currentSubsurfaceLayer = 0; int depthWithinSubsurface = 0; for (int y = VoxelConstants.ChunkSizeY - 1; y >= 0; y--) { var voxel = new VoxelHandle(c, new LocalVoxelCoordinate(x, y, z)); if (y == 0) { voxel.RawSetType(VoxelLibrary.GetVoxelType("Bedrock")); voxel.Health = 255; // ? continue; } if (y <= stoneHeight && stoneHeight > 1) { voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SubsurfaceLayers[currentSubsurfaceLayer].VoxelType)); depthWithinSubsurface++; if (depthWithinSubsurface > biomeData.SubsurfaceLayers[currentSubsurfaceLayer].Depth) { depthWithinSubsurface = 0; currentSubsurfaceLayer++; if (currentSubsurfaceLayer > biomeData.SubsurfaceLayers.Count - 1) { currentSubsurfaceLayer = biomeData.SubsurfaceLayers.Count - 1; } } } else if ((y == (int)h || y == stoneHeight) && hNorm > waterHeight) { if (biomeData.ClumpGrass && NoiseGenerator.Noise(pos.X / biomeData.ClumpSize, 0, pos.Y / biomeData.ClumpSize) > biomeData.ClumpTreshold) { voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType)); if (!String.IsNullOrEmpty(biomeData.GrassDecal)) { var decal = GrassLibrary.GetGrassType(biomeData.GrassDecal); voxel.RawSetGrass(decal.ID); } } else if (!biomeData.ClumpGrass) { voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType)); if (!String.IsNullOrEmpty(biomeData.GrassDecal)) { var decal = GrassLibrary.GetGrassType(biomeData.GrassDecal); voxel.RawSetGrass(decal.ID); } } else { voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType)); } } else if (y > h && y > 0) { voxel.RawSetType(VoxelLibrary.emptyType); } else if (hNorm <= waterHeight) { voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.ShoreVoxel)); } else { voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType)); } } } } GenerateWater(c); GenerateLava(c); UpdateSunlight(c, 255); return(c); }
public static IEnumerable <GlobalVoxelCoordinate> EnumerateManhattanCube( GlobalVoxelCoordinate Coordinate) { return(EnumerateNeighbors(ManhattanCubeNeighbors, Coordinate)); }
internal VoxelHandle(GlobalVoxelCoordinate Coordinate) { this.Coordinate = Coordinate; this._cache_Chunk = null; this._cache_Index = 0; }
public bool IsCameraUnderwater() { var handle = new VoxelHandle(ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(Camera.Position)); return(handle.IsValid && handle.WaterCell.WaterLevel > 0); }
public VoxelHandle(VoxelChunk Chunk, LocalVoxelCoordinate Coordinate) { this.Coordinate = Chunk.ID + Coordinate; this._cache_Chunk = Chunk; this._cache_Index = VoxelConstants.DataIndexOf(Coordinate); }
public static bool IsValidPlacement( VoxelHandle Location, CraftItem CraftType, WorldManager World, GameComponent PreviewBody, String Verb, String PastParticple) { if (CraftType == null) { return(false); } if (!String.IsNullOrEmpty(CraftType.CraftLocation) && World.PlayerFaction.FindNearestItemWithTags(CraftType.CraftLocation, Location.WorldPosition, false, null) == null) { World.UserInterface.ShowTooltip("Can't " + Verb + ", need " + CraftType.CraftLocation); return(false); } foreach (var req in CraftType.Prerequisites) { switch (req) { case CraftItem.CraftPrereq.NearWall: { var neighborFound = VoxelHelpers.EnumerateManhattanNeighbors2D(Location.Coordinate) .Select(c => new VoxelHandle(World.ChunkManager, c)) .Any(v => v.IsValid && !v.IsEmpty); if (!neighborFound) { World.UserInterface.ShowTooltip("Must be " + PastParticple + " next to wall!"); return(false); } break; } case CraftItem.CraftPrereq.OnGround: { var below = VoxelHelpers.GetNeighbor(Location, new GlobalVoxelOffset(0, -1, 0)); if (!below.IsValid || below.IsEmpty) { World.UserInterface.ShowTooltip("Must be " + PastParticple + " on solid ground!"); return(false); } break; } } } if (PreviewBody != null) { // Just check for any intersecting body in octtree. var previewBox = PreviewBody.GetRotatedBoundingBox(); var sensorBox = previewBox; var sensor = PreviewBody.GetComponent <GenericVoxelListener>(); if (sensor != null) { sensorBox = sensor.GetRotatedBoundingBox(); } if (Debugger.Switches.DrawToolDebugInfo) { Drawer3D.DrawBox(sensorBox, Color.Yellow, 0.1f, false); } foreach (var intersectingObject in World.EnumerateIntersectingObjects(sensorBox, CollisionType.Static)) { if (Object.ReferenceEquals(intersectingObject, sensor)) { continue; } var objectRoot = intersectingObject.GetRoot() as GameComponent; if (objectRoot is WorkPile) { continue; } if (objectRoot == PreviewBody) { continue; } if (objectRoot != null && objectRoot.GetRotatedBoundingBox().Intersects(previewBox)) { World.UserInterface.ShowTooltip("Can't " + Verb + " here: intersects " + objectRoot.Name); return(false); } } bool intersectsWall = VoxelHelpers.EnumerateCoordinatesInBoundingBox (PreviewBody.GetRotatedBoundingBox().Expand(-0.1f)).Any( v => { var tvh = new VoxelHandle(World.ChunkManager, v); return(tvh.IsValid && !tvh.IsEmpty); }); var current = new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(PreviewBody.Position)); bool underwater = current.IsValid && current.LiquidType != LiquidType.None; if (underwater) { World.UserInterface.ShowTooltip("Can't " + Verb + " here: underwater or in lava."); return(false); } if (intersectsWall && !CraftType.Prerequisites.Contains(CraftItem.CraftPrereq.NearWall)) { World.UserInterface.ShowTooltip("Can't " + Verb + " here: intersects wall."); return(false); } } World.UserInterface.ShowTooltip(""); return(true); }
private void Place(VoxelHandle Location) { var assignments = new List <Task>(); for (var i = 0; i < PreviewBodies.Count; ++i) { var body = PreviewBodies[i]; var piece = Pattern.Pieces[i]; var actualPosition = new VoxelHandle(Location.Chunk.Manager.ChunkData, Location.Coordinate + new GlobalVoxelOffset(piece.Offset.X, 0, piece.Offset.Y)); var addNewDesignation = true; foreach (var entity in Player.World.CollisionManager.EnumerateIntersectingObjects(actualPosition.GetBoundingBox().Expand(-0.2f), CollisionManager.CollisionType.Static)) { if (!addNewDesignation) { break; } if (Object.ReferenceEquals(entity, body)) { continue; } var possibleCombination = FindPossibleCombination(piece, entity); if (possibleCombination != null) { var combinedPiece = new Rail.JunctionPiece { RailPiece = possibleCombination.Result, Orientation = Rail.OrientationHelper.Rotate((entity as RailPiece).Piece.Orientation, (int)possibleCombination.ResultRelativeOrientation), }; var existingDesignation = Player.Faction.Designations.EnumerateEntityDesignations(DesignationType.Craft).FirstOrDefault(d => Object.ReferenceEquals(d.Body, entity)); if (existingDesignation != null) { (entity as RailPiece).UpdatePiece(combinedPiece, actualPosition); (existingDesignation.Tag as CraftDesignation).Progress = 0.0f; body.Delete(); addNewDesignation = false; } else { (entity as RailPiece).Die(); body.UpdatePiece(combinedPiece, actualPosition); } } } if (addNewDesignation) { var startPos = body.Position + new Vector3(0.0f, -0.3f, 0.0f); var endPos = body.Position; var designation = new CraftDesignation { Entity = body, WorkPile = new WorkPile(Player.World.ComponentManager, startPos), OverrideOrientation = false, Valid = true, ItemType = RailCraftItem, SelectedResources = SelectedResources, Location = new VoxelHandle(Player.World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(body.Position)), HasResources = false, ResourcesReservedFor = null, Orientation = 0.0f, Progress = 0.0f, }; Player.World.ComponentManager.RootComponent.AddChild(designation.WorkPile); designation.WorkPile.AnimationQueue.Add(new EaseMotion(1.1f, Matrix.CreateTranslation(startPos), endPos)); Player.World.ParticleManager.Trigger("puff", endPos, Color.White, 10); Player.Faction.Designations.AddEntityDesignation(body, DesignationType.Craft, designation); assignments.Add(new CraftItemTask(designation)); } } if (assignments.Count > 0) { Player.World.Master.TaskManager.AddTasks(assignments); } }
public void HandlePosessedDwarf() { KeyboardState keyState = Keyboard.GetState(); if (SelectedMinions.Count != 1) { CameraController.FollowAutoTarget = false; CameraController.EnableControl = true; foreach (var creature in Faction.Minions) { creature.IsPosessed = false; } return; } var dwarf = SelectedMinions[0]; if (!dwarf.IsPosessed) { CameraController.FollowAutoTarget = false; CameraController.EnableControl = true; return; } CameraController.EnableControl = false; CameraController.AutoTarget = dwarf.Position; CameraController.FollowAutoTarget = true; if (dwarf.Velocity.Length() > 0.1) { var above = VoxelHelpers.FindFirstVoxelAbove(new VoxelHandle( World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(dwarf.Position))); if (above.IsValid) { World.ChunkManager.ChunkData.SetMaxViewingLevel(above.Coordinate.Y, ChunkManager.SliceMode.Y); } else { World.ChunkManager.ChunkData.SetMaxViewingLevel(VoxelConstants.ChunkSizeY, ChunkManager.SliceMode.Y); } } Vector3 forward = CameraController.GetForwardVector(); Vector3 right = CameraController.GetRightVector(); Vector3 desiredVelocity = Vector3.Zero; bool hadCommand = false; bool jumpCommand = false; if (keyState.IsKeyDown(ControlSettings.Mappings.Forward) || keyState.IsKeyDown(Keys.Up)) { hadCommand = true; desiredVelocity += forward * 10; } if (keyState.IsKeyDown(ControlSettings.Mappings.Back) || keyState.IsKeyDown(Keys.Down)) { hadCommand = true; desiredVelocity -= forward * 10; } if (keyState.IsKeyDown(ControlSettings.Mappings.Right) || keyState.IsKeyDown(Keys.Right)) { hadCommand = true; desiredVelocity += right * 10; } if (keyState.IsKeyDown(ControlSettings.Mappings.Left) || keyState.IsKeyDown(Keys.Left)) { hadCommand = true; desiredVelocity -= right * 10; } if (keyState.IsKeyDown(ControlSettings.Mappings.Jump)) { jumpCommand = true; hadCommand = true; } if (hadCommand) { if (dwarf.CurrentTask != null) { dwarf.CurrentTask.Cancel(); } dwarf.CurrentTask = null; dwarf.TryMoveVelocity(desiredVelocity, jumpCommand); } else if (dwarf.CurrentTask == null) { if (dwarf.Creature.IsOnGround) { if (dwarf.Physics.Velocity.LengthSquared() < 1) { dwarf.Creature.CurrentCharacterMode = DwarfCorp.CharacterMode.Idle; } dwarf.Physics.Velocity = new Vector3(dwarf.Physics.Velocity.X * 0.9f, dwarf.Physics.Velocity.Y, dwarf.Physics.Velocity.Z * 0.9f); dwarf.TryMoveVelocity(Vector3.Zero, false); } } }
/// <summary> /// Checks the voxels around the creature and reacts to changes in its immediate environment. /// For example this function determines when the creature is standing on solid ground. /// </summary> public void CheckNeighborhood(ChunkManager chunks, float dt) { var below = new VoxelHandle(chunks.ChunkData, GlobalVoxelCoordinate.FromVector3(Physics.GlobalTransform.Translation - Vector3.UnitY * 0.8f)); var above = new VoxelHandle(chunks.ChunkData, GlobalVoxelCoordinate.FromVector3(Physics.GlobalTransform.Translation + Vector3.UnitY * 0.8f)); if (above.IsValid) { IsHeadClear = above.IsEmpty; } if (below.IsValid && Physics.IsInLiquid) { IsOnGround = false; } else if (below.IsValid) { IsOnGround = !below.IsEmpty; } else { IsOnGround = false; } if (!IsOnGround) { if (CurrentCharacterMode != CharacterMode.Flying) { if (Physics.Velocity.Y > 0.05) { CurrentCharacterMode = CharacterMode.Jumping; } else if (Physics.Velocity.Y < -0.05) { CurrentCharacterMode = CharacterMode.Falling; } } if (Physics.IsInLiquid) { CurrentCharacterMode = CharacterMode.Swimming; } } if (CurrentCharacterMode == CharacterMode.Falling && IsOnGround) { CurrentCharacterMode = CharacterMode.Idle; } if (Status.IsAsleep) { CurrentCharacterMode = CharacterMode.Sleeping; if (MathFunctions.RandEvent(0.01f)) { NoiseMaker.MakeNoise("Sleep", AI.Position, true); } } else if (currentCharacterMode == CharacterMode.Sleeping) { CurrentCharacterMode = CharacterMode.Idle; } if (!Status.Energy.IsDissatisfied()) { Status.IsAsleep = false; } }