public void CheckForLavaAndWater(Body Body, DwarfTime gameTime, ChunkManager chunks) { foreach (var coordinate in VoxelHelpers.EnumerateCoordinatesInBoundingBox(Body.BoundingBox)) { var voxel = new VoxelHandle(chunks.ChunkData, coordinate); if (!voxel.IsValid || voxel.LiquidLevel == 0) { continue; } if (voxel.LiquidType == LiquidType.Lava) { Heat += 100.0f; } else if (voxel.LiquidType == LiquidType.Water) { Heat = Math.Max(0.0f, Heat - 100.0f); } } }
public IEnumerable <VoxelHandle> Select(BoundingBox buffer, Vector3 start, Vector3 end) { switch (Brush) { case VoxelBrush.Box: return(VoxelHelpers.EnumerateCoordinatesInBoundingBox(buffer) .Select(c => new VoxelHandle(Chunks.ChunkData, c)) .Where(v => v.IsValid)); case VoxelBrush.Shell: return(EnumerateShell(buffer) .Select(c => new VoxelHandle(Chunks.ChunkData, c)) .Where(v => v.IsValid)); case VoxelBrush.Stairs: return(EnumerateStairVoxels(buffer, start, end, SelectionType == VoxelSelectionType.SelectFilled) .Select(c => new VoxelHandle(Chunks.ChunkData, c)) .Where(v => v.IsValid)); default: throw new InvalidOperationException("VoxelBrush has invalid value"); } }
public void Update() { MouseState mouse = Mouse.GetState(); KeyboardState keyboard = Keyboard.GetState(); var underMouse = GetVoxelUnderMouse(); // Keep track of whether a new voxel has been selected. bool newVoxel = underMouse.IsValid && underMouse != VoxelUnderMouse; if (!underMouse.IsValid) { return; } VoxelUnderMouse = underMouse; // Update the cursor light. World.CursorLightPos = underMouse.WorldPosition + new Vector3(0.5f, 0.5f, 0.5f); // Get the type of the voxel and display it to the player. if (Enabled && !underMouse.IsEmpty && underMouse.IsExplored) { string info = underMouse.Type.Name; // If it belongs to a room, display that information. if (World.PlayerFaction.RoomBuilder.IsInRoom(underMouse)) { Room room = World.PlayerFaction.RoomBuilder.GetMostLikelyRoom(underMouse); if (room != null) { info += " (" + room.ID + ")"; } } World.ShowInfo(info); } // Do nothing if not enabled. if (!Enabled) { return; } bool altPressed = false; // If the left or right ALT keys are pressed, we can adjust the height of the selection // for building pits and tall walls using the mouse wheel. if (keyboard.IsKeyDown(Keys.LeftAlt) || keyboard.IsKeyDown(Keys.RightAlt)) { var change = mouse.ScrollWheelValue - LastMouseWheel; BoxYOffset += (change) * 0.01f; int offset = (int)BoxYOffset; if (offset != PrevBoxYOffsetInt) { DragSound.Play(World.CursorLightPos); newVoxel = true; } PrevBoxYOffsetInt = offset; altPressed = true; } else { PrevBoxYOffsetInt = 0; } LastMouseWheel = mouse.ScrollWheelValue; // Draw a box around the current voxel under the mouse. if (underMouse.IsValid) { BoundingBox box = underMouse.GetBoundingBox().Expand(0.05f); Drawer3D.DrawBox(box, CurrentColor, CurrentWidth, true); } // If the left mouse button is pressed, update the slection buffer. if (isLeftPressed) { // On release, select voxels. if (mouse.LeftButton == ButtonState.Released) { ReleaseSound.Play(World.CursorLightPos); isLeftPressed = false; LeftReleasedCallback(); BoxYOffset = 0; PrevBoxYOffsetInt = 0; } // Otherwise, update the selection buffer else { if (SelectionBuffer.Count == 0) { FirstVoxel = underMouse; SelectionBuffer.Add(underMouse); } else { SelectionBuffer.Clear(); SelectionBuffer.Add(FirstVoxel); SelectionBuffer.Add(underMouse); BoundingBox buffer = GetSelectionBox(); // Update the selection box to account for offsets from mouse wheel. if (BoxYOffset > 0) { buffer.Max.Y += (int)BoxYOffset; } else if (BoxYOffset < 0) { buffer.Min.Y += (int)BoxYOffset; } SelectionBuffer = Select(buffer, FirstVoxel.WorldPosition, underMouse.WorldPosition).ToList(); if (!altPressed && Brush != VoxelBrush.Stairs) { if (SelectionType == VoxelSelectionType.SelectFilled) { SelectionBuffer.RemoveAll(v => { if (v.Equals(underMouse)) { return(false); } return(v.IsExplored && !VoxelHelpers.DoesVoxelHaveVisibleSurface( Chunks.ChunkData, v)); }); } } if (newVoxel) { DragSound.Play(World.CursorLightPos, SelectionBuffer.Count / 20.0f); Dragged.Invoke(SelectionBuffer, InputManager.MouseButton.Left); } } } } // If the mouse was not previously pressed, but is now pressed, then notify us of that. else if (mouse.LeftButton == ButtonState.Pressed) { ClickSound.Play(World.CursorLightPos);; isLeftPressed = true; BoxYOffset = 0; PrevBoxYOffsetInt = 0; } // Case where the right mouse button is pressed (mirrors left mouse button) // TODO(Break this into a function) if (isRightPressed) { if (mouse.RightButton == ButtonState.Released) { ReleaseSound.Play(World.CursorLightPos); isRightPressed = false; RightReleasedCallback(); BoxYOffset = 0; PrevBoxYOffsetInt = 0; } else { if (SelectionBuffer.Count == 0) { SelectionBuffer.Add(underMouse); FirstVoxel = underMouse; } else { SelectionBuffer.Clear(); SelectionBuffer.Add(FirstVoxel); SelectionBuffer.Add(underMouse); BoundingBox buffer = GetSelectionBox(); if (BoxYOffset > 0) { buffer.Max.Y += (int)BoxYOffset; } else if (BoxYOffset < 0) { buffer.Min.Y += (int)BoxYOffset; } SelectionBuffer = VoxelHelpers.EnumerateCoordinatesInBoundingBox(buffer) .Select(c => new VoxelHandle(Chunks.ChunkData, c)) .Where(v => v.IsValid) .ToList(); if (newVoxel) { DragSound.Play(World.CursorLightPos, SelectionBuffer.Count / 20.0f); Dragged.Invoke(SelectionBuffer, InputManager.MouseButton.Right); } } } } else if (mouse.RightButton == ButtonState.Pressed) { ClickSound.Play(World.CursorLightPos); RightPressedCallback(); BoxYOffset = 0; isRightPressed = true; } }
public static bool IsValidPlacement( VoxelHandle Location, ResourceType CraftType, WorldManager World, GameComponent PreviewBody, String Verb, String PastParticple) { if (CraftType == null) { return(false); } switch (CraftType.Placement_PlacementRequirement) { case ResourceType.PlacementRequirement.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 ResourceType.PlacementRequirement.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; GenericVoxelListener sensor; if (PreviewBody.GetComponent <GenericVoxelListener>().HasValue(out sensor)) { 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.IsDead) { 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.Placement_PlacementRequirement != ResourceType.PlacementRequirement.NearWall) { World.UserInterface.ShowTooltip("Can't " + Verb + " here: intersects wall."); return(false); } } World.UserInterface.ShowTooltip(""); return(true); }
public static bool IsValidPlacement( VoxelHandle Location, CraftItem CraftType, GameMaster Player, Body PreviewBody, String Verb, String PastParticple) { if (CraftType == null) { return(false); } if (!String.IsNullOrEmpty(CraftType.CraftLocation) && Player.Faction.FindNearestItemWithTags(CraftType.CraftLocation, Location.WorldPosition, false, null) == null) { Player.World.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(Player.World.ChunkManager.ChunkData, c)) .Any(v => v.IsValid && !v.IsEmpty); if (!neighborFound) { Player.World.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) { Player.World.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 Player.World.EnumerateIntersectingObjects(sensorBox, CollisionType.Static)) { if (Object.ReferenceEquals(intersectingObject, sensor)) { continue; } var objectRoot = intersectingObject.GetRoot() as Body; if (objectRoot is WorkPile) { continue; } if (objectRoot != null && objectRoot.GetRotatedBoundingBox().Intersects(previewBox)) { Player.World.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(Player.World.ChunkManager.ChunkData, v); return(tvh.IsValid && !tvh.IsEmpty); }); var current = new VoxelHandle(Player.World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(PreviewBody.Position)); bool underwater = current.IsValid && current.LiquidType != LiquidType.None; if (underwater) { Player.World.ShowTooltip("Can't " + Verb + " here: underwater or in lava."); return(false); } if (intersectsWall && !CraftType.Prerequisites.Contains(CraftItem.CraftPrereq.NearWall)) { Player.World.ShowTooltip("Can't " + Verb + " here: intersects wall."); return(false); } } Player.World.ShowTooltip(""); return(true); }
public void CheckSurroundings(GameComponent Body, DwarfTime gameTime, ChunkManager chunks) { if (Heat > Flashpoint) { var insideBodies = World.EnumerateIntersectingObjects(Body.GetBoundingBox()); foreach (var body in insideBodies.Where(b => b != Parent && b.Active && b.Parent == Manager.RootComponent)) { var flames = body.GetComponent <Flammable>(); if (flames != null) { flames.Heat += 100; } } SoundManager.PlaySound(ContentPaths.Audio.fire, Body.Position, true); } float expansion = Heat > Flashpoint ? 1.0f : 0.0f; foreach (var coordinate in VoxelHelpers.EnumerateCoordinatesInBoundingBox(Body.BoundingBox.Expand(expansion))) { var voxel = new VoxelHandle(chunks, coordinate); if (!voxel.IsValid) { continue; } if (Heat > Flashpoint && MathFunctions.RandEvent(0.5f)) { if (voxel.Type.IsFlammable) { if (MathFunctions.RandEvent(0.1f)) { var existingItems = World.EnumerateIntersectingObjects(voxel.GetBoundingBox().Expand(-0.1f)); if (!existingItems.Any(e => e is Fire)) { EntityFactory.CreateEntity <Fire>("Fire", voxel.GetBoundingBox().Center()); } SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_env_lava_spread, voxel.GetBoundingBox().Center(), true, 1.0f); VoxelHelpers.KillVoxel(World, voxel); } } if (voxel.GrassType != 0x0) { if (MathFunctions.RandEvent(0.1f)) { var box = voxel.GetBoundingBox().Expand(-0.1f); box.Min += Vector3.One; // Todo: Why shifting one on every axis? box.Max += Vector3.One; if (!World.EnumerateIntersectingObjects(box).Any(e => e is Fire)) { EntityFactory.CreateEntity <Fire>("Fire", box.Center()); } } if (MathFunctions.RandEvent(0.5f)) { SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_env_lava_spread, voxel.GetBoundingBox().Center(), true, 1.0f); voxel.GrassType = 0x0; } } } if (voxel.LiquidLevel <= 0) { continue; } if (voxel.LiquidType == LiquidType.Lava) { Heat += 100.0f; } else if (voxel.LiquidType == LiquidType.Water) { Heat = Heat * 0.25f; } } }
public IEnumerable <GlobalVoxelCoordinate> Select(BoundingBox Bounds, Vector3 Start, Vector3 End, bool Invert) { return(VoxelHelpers.EnumerateCoordinatesInBoundingBox(Bounds)); }
public override void Update(DwarfGame game, DwarfTime time) { if (Player.IsCameraRotationModeActive()) { return; } Player.VoxSelector.Enabled = false; Player.VoxSelector.SelectionType = VoxelSelectionType.SelectEmpty; Player.BodySelector.Enabled = SelectedBody == null; Player.BodySelector.AllowRightClickSelection = true; if (Player.World.IsMouseOverGui) { Player.World.SetMouse(Player.World.MousePointer); } else { Player.World.SetMouse(new Gui.MousePointer("mouse", 1, 9)); } if (SelectedBody != null) { var craftDetails = SelectedBody.GetRoot().GetComponent <CraftDetails>(); var voxelUnderMouse = Player.VoxSelector.VoxelUnderMouse; if (voxelUnderMouse != prevVoxel && voxelUnderMouse.IsValid && voxelUnderMouse.IsEmpty) { SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_click_voxel, voxelUnderMouse.WorldPosition, 0.1f); var offset = Vector3.Zero; if (craftDetails != null && CraftLibrary.CraftItems.ContainsKey(craftDetails.CraftType)) { offset = CraftLibrary.CraftItems[craftDetails.CraftType].SpawnOffset; } SelectedBody.LocalPosition = voxelUnderMouse.WorldPosition + Vector3.One * 0.5f + offset; SelectedBody.HasMoved = true; SelectedBody.UpdateTransform(); if (OverrideOrientation) { SelectedBody.Orient(CurrentOrientation); } else { SelectedBody.OrientToWalls(); } SelectedBody.UpdateBoundingBox(); SelectedBody.UpdateTransform(); SelectedBody.PropogateTransforms(); SelectedBody.UpdateBoundingBox(); } var intersectsAnyOther = Player.Faction.OwnedObjects.FirstOrDefault( o => o != SelectedBody && o.Tags.Contains("Moveable") && o.GetRotatedBoundingBox().Intersects(SelectedBody.GetRotatedBoundingBox().Expand(-0.5f))); Drawer3D.DrawBox(SelectedBody.GetRotatedBoundingBox(), Color.White, 0.05f, false); bool intersectsWall = VoxelHelpers.EnumerateCoordinatesInBoundingBox( SelectedBody.GetRotatedBoundingBox().Expand(-0.25f)).Any( v => { var tvh = new VoxelHandle(Player.VoxSelector.Chunks.ChunkData, v); return(tvh.IsValid && !tvh.IsEmpty); }); var tinter = SelectedBody.GetRoot().GetComponent <Tinter>(); if (tinter != null) { tinter.VertexColorTint = intersectsAnyOther == null && !intersectsWall ? Color.Green : Color.Red; } MouseState mouse = Mouse.GetState(); if (mouse.LeftButton == ButtonState.Released && mouseDown) { mouseDown = false; if (intersectsAnyOther == null && !intersectsWall) { SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_confirm_selection, SelectedBody.Position, 0.5f); SelectedBody.UpdateTransform(); SelectedBody.PropogateTransforms(); SelectedBody.UpdateBoundingBox(); SelectedBody = null; OverrideOrientation = false; CurrentOrientation = 0; if (tinter != null) { tinter.VertexColorTint = Color.White; } } else if (!intersectsWall) { Player.World.ShowToolPopup("Can't move here: intersects " + intersectsAnyOther.Name); } else { Player.World.ShowToolPopup("Can't move here: intersects wall."); } } else if (mouse.LeftButton == ButtonState.Pressed) { mouseDown = true; } prevVoxel = voxelUnderMouse; } HandleOrientation(); }
public bool IsValid(CraftDesignation designation) { if (!designation.Valid) { return(false); } if (IsDesignation(designation.Location)) { World.ShowToolPopup("Something is already being built there!"); return(false); } if (!String.IsNullOrEmpty(designation.ItemType.CraftLocation) && Faction.FindNearestItemWithTags(designation.ItemType.CraftLocation, designation.Location.WorldPosition, false) == null) { World.ShowToolPopup("Can't build, need " + designation.ItemType.CraftLocation); return(false); } if (!Faction.HasResources(designation.ItemType.RequiredResources)) { string neededResources = ""; foreach (Quantitiy <Resource.ResourceTags> amount in designation.ItemType.RequiredResources) { neededResources += "" + amount.NumResources + " " + amount.ResourceType.ToString() + " "; } World.ShowToolPopup("Not enough resources! Need " + neededResources + "."); return(false); } foreach (var req in designation.ItemType.Prerequisites) { switch (req) { case CraftItem.CraftPrereq.NearWall: { var neighborFound = VoxelHelpers.EnumerateManhattanNeighbors2D(designation.Location.Coordinate) .Select(c => new VoxelHandle(World.ChunkManager.ChunkData, c)) .Any(v => v.IsValid && !v.IsEmpty); if (!neighborFound) { World.ShowToolPopup("Must be built next to wall!"); return(false); } break; } case CraftItem.CraftPrereq.OnGround: { var below = VoxelHelpers.GetNeighbor(designation.Location, new GlobalVoxelOffset(0, -1, 0)); if (!below.IsValid || below.IsEmpty) { World.ShowToolPopup("Must be built on solid ground!"); return(false); } break; } } } if (CurrentCraftBody != null) { var intersectsAnyOther = Faction.OwnedObjects.FirstOrDefault( o => o != null && o != CurrentCraftBody && o.GetRotatedBoundingBox().Intersects(CurrentCraftBody.GetRotatedBoundingBox().Expand(-0.1f))); var intersectsBuildObjects = Faction.Designations.EnumerateEntityDesignations(DesignationType.Craft) .Any(d => d.Body != CurrentCraftBody && d.Body.GetRotatedBoundingBox().Intersects( CurrentCraftBody.GetRotatedBoundingBox().Expand(-0.1f))); bool intersectsWall = VoxelHelpers.EnumerateCoordinatesInBoundingBox (CurrentCraftBody.GetRotatedBoundingBox().Expand(-0.1f)).Any( v => { var tvh = new VoxelHandle(World.ChunkManager.ChunkData, v); return(tvh.IsValid && !tvh.IsEmpty); }); if (intersectsAnyOther != null) { World.ShowToolPopup("Can't build here: intersects " + intersectsAnyOther.Name); } else if (intersectsBuildObjects) { World.ShowToolPopup("Can't build here: intersects something else being built"); } else if (intersectsWall && !designation.ItemType.Prerequisites.Contains(CraftItem.CraftPrereq.NearWall)) { World.ShowToolPopup("Can't build here: intersects wall."); } return(intersectsAnyOther == null && !intersectsBuildObjects && (!intersectsWall || designation.ItemType.Prerequisites.Contains(CraftItem.CraftPrereq.NearWall))); } return(true); }