| |
|
| |
|
| | local Players = game:GetService("Players")
|
| | local UserInputService = game:GetService("UserInputService")
|
| | local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
| | local RunService = game:GetService("RunService")
|
| |
|
| | local BuildingConfig = require(ReplicatedStorage:WaitForChild("Shared"):WaitForChild("BuildingConfig"))
|
| | local PlaceBlueprintEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("PlaceBlueprintEvent")
|
| |
|
| | local player = Players.LocalPlayer
|
| | local mouse = player:GetMouse()
|
| | local character = player.Character or player.CharacterAdded:Wait()
|
| |
|
| | local buildModeActive = false
|
| | local currentStructureIndex = 1
|
| | local currentStructure = BuildingConfig.StructureOrder[1]
|
| | local currentRotation = 0
|
| | local previewModel = nil
|
| |
|
| | local function snapToGrid(position, gridSize)
|
| | return Vector3.new(
|
| | math.floor((position.X + gridSize/2) / gridSize) * gridSize,
|
| | position.Y,
|
| | math.floor((position.Z + gridSize/2) / gridSize) * gridSize
|
| | )
|
| | end
|
| |
|
| | local function getStructureSize()
|
| | local config = BuildingConfig.Structures[currentStructure]
|
| | if config and config.Size then
|
| | return config.Size
|
| | end
|
| | return Vector3.new(10, 10, 1)
|
| | end
|
| |
|
| | local function cleanupPreview()
|
| | if previewModel then
|
| | previewModel:Destroy()
|
| | previewModel = nil
|
| | end
|
| | end
|
| |
|
| | local function createPreview()
|
| | cleanupPreview()
|
| | local size = getStructureSize()
|
| |
|
| | previewModel = Instance.new("Part")
|
| | previewModel.Size = size
|
| | previewModel.Transparency = 0.5
|
| | previewModel.BrickColor = BrickColor.new("Neon blue")
|
| | previewModel.CanCollide = false
|
| | previewModel.Anchored = true
|
| | previewModel.Material = Enum.Material.ForceField
|
| | previewModel.Parent = workspace.Terrain
|
| |
|
| |
|
| | local billboard = Instance.new("BillboardGui")
|
| | billboard.Size = UDim2.new(0, 200, 0, 50)
|
| | billboard.StudsOffset = Vector3.new(0, size.Y/2 + 2, 0)
|
| | billboard.AlwaysOnTop = true
|
| | billboard.Parent = previewModel
|
| |
|
| | local label = Instance.new("TextLabel")
|
| | label.Name = "StructureLabel"
|
| | label.Size = UDim2.new(1, 0, 1, 0)
|
| | label.BackgroundTransparency = 0.3
|
| | label.BackgroundColor3 = Color3.new(0, 0, 0)
|
| | label.TextColor3 = Color3.new(1, 1, 1)
|
| | label.TextScaled = true
|
| | label.Font = Enum.Font.GothamBold
|
| |
|
| | local config = BuildingConfig.Structures[currentStructure]
|
| | label.Text = (config and config.Name or currentStructure) .. " [Q] Cycle [R] Rotate"
|
| | label.Parent = billboard
|
| | end
|
| |
|
| | local function toggleBuildMode()
|
| | buildModeActive = not buildModeActive
|
| | if not buildModeActive then
|
| | cleanupPreview()
|
| | else
|
| | createPreview()
|
| | end
|
| | end
|
| |
|
| | local function cycleStructure()
|
| | currentStructureIndex = currentStructureIndex + 1
|
| | if currentStructureIndex > #BuildingConfig.StructureOrder then
|
| | currentStructureIndex = 1
|
| | end
|
| | currentStructure = BuildingConfig.StructureOrder[currentStructureIndex]
|
| | if buildModeActive then
|
| | createPreview()
|
| | end
|
| | end
|
| |
|
| | local function updatePreview()
|
| | if not buildModeActive or not previewModel then return end
|
| |
|
| | local char = player.Character
|
| | if char and char:FindFirstChild("HumanoidRootPart") then
|
| | local distance = (char.HumanoidRootPart.Position - mouse.Hit.Position).Magnitude
|
| | if distance <= BuildingConfig.MaxPlacementDistance then
|
| | local snappedPos = snapToGrid(mouse.Hit.Position, BuildingConfig.GridSnap)
|
| | snappedPos = Vector3.new(snappedPos.X, mouse.Hit.Position.Y + (previewModel.Size.Y / 2), snappedPos.Z)
|
| |
|
| | previewModel.CFrame = CFrame.new(snappedPos) * CFrame.Angles(0, math.rad(currentRotation), 0)
|
| | previewModel.BrickColor = BrickColor.new("Neon blue")
|
| | else
|
| | previewModel.Position = mouse.Hit.Position
|
| | previewModel.BrickColor = BrickColor.new("Really red")
|
| | end
|
| | end
|
| | end
|
| |
|
| | local function onInputBegan(input, gameProcessed)
|
| | if gameProcessed then return end
|
| |
|
| | if input.KeyCode == Enum.KeyCode.B then
|
| | toggleBuildMode()
|
| | end
|
| |
|
| | if input.KeyCode == Enum.KeyCode.Q and buildModeActive then
|
| | cycleStructure()
|
| | end
|
| |
|
| | if input.KeyCode == Enum.KeyCode.R and buildModeActive then
|
| | currentRotation = (currentRotation + 90) % 360
|
| | end
|
| |
|
| | if input.UserInputType == Enum.UserInputType.MouseButton1 and buildModeActive then
|
| | if previewModel and previewModel.BrickColor.Name == "Neon blue" then
|
| | PlaceBlueprintEvent:FireServer(currentStructure, previewModel.CFrame)
|
| | end
|
| | end
|
| | end
|
| |
|
| | player.CharacterAdded:Connect(function(char)
|
| | character = char
|
| | end)
|
| |
|
| | UserInputService.InputBegan:Connect(onInputBegan)
|
| |
|
| | RunService.RenderStepped:Connect(function()
|
| | if buildModeActive then
|
| | updatePreview()
|
| | end
|
| | end)
|
| |
|