First and foremost, I followed a zblox youtube tutorial to get the maths and general system out of the way. I have been modifying it with my own keybinds and code since. (I probably broke something)
-
What do you want to achieve? Keep it simple and clear!
A fully functioning placement system; more specifically I want the placement:finish() function to be called. -
What is the issue? Include screenshots / videos if possible!
Placing items using my Inventory GUI works for two of the three buttons, and completely breaks when the third one becomes in use. When you click the gui button and press “E” to place the object, a few things happen. I have printed them out in the console for debugging reasons and I just cannot find the issue. This is what occurs. -
A table containing plot information is updated
-
The inventory table has the item removed (is it now in the plot table because it is placed)
-
The Gui button and everything in it is destroyed (including the local script… maybe it has something to do with it?)
-
The placement:finish() function calls to finish the placement and destroy the object so you dont have the grid and object following you anymore but it only calls for the first 2 GUI Buttons.
There are no errors, just the Output saying that the finish placement function was not called the 3rd and final time. (And outright refuses to let me place or cancel or use any other keybind i set in the localscript until i click on a different button) button to place an object. It just seems to be the last one that does not work ??? Also, I am using the ContextActionService Service to assign and bind functions. Maybe this has something to do with it?
The finish placement function
function placement:finish()
-- basically its the same as cancel function above but u dont use a keybind. useful for when game needs to force quit placement instead of user ending placement and incase any other script needs to use.
object:Destroy()
if plot:FindFirstChild("Texture") then
plot:FindFirstChild("Texture"):Destroy()
end
--contextActionService:UnbindAction("Place")
print("Finish placement called")
mouse.TargetFilter = nil
end
The place function
local function place(actionName, inputState, inputObject)
if inputState == Enum.UserInputState.Begin then
-- cframe for the part to be placed
local cf = getInstantCframe()
-- Invoke a remote server function with the object's name, placed objects, CFrame, and plot
game.ReplicatedStorage.Remotes.Place:InvokeServer(object.Name, placedobjects, cf, plot, IsMoving)
placement:finish() -- this should be called when i place the last object down, but for some reason in the output it is only called for the first 2 times.
--unbindInputs() -- Doesnt do anything for some reason???
--[[ needs work
if IsMoving == true then
IsMoving = false
print(IsMoving)
placement:finish()
return
end
--]]
end
end
The local script (inside the gui button)
local player = game.Players.LocalPlayer
local location = player:WaitForChild("Plot")
local module = require(game:GetService("ReplicatedStorage").Modules.PlacementHandler)
local plot = game.Workspace.Plots:FindFirstChild(location.Value)
local placement = module.new(
1, --grid size
game.ReplicatedStorage.Items,
Enum.KeyCode.R, Enum.KeyCode.X,Enum.KeyCode.M,Enum.KeyCode.E
)
local mouse = game.Players.LocalPlayer:GetMouse()
script.Parent.MouseButton1Down:Connect(function()
placement:bindInputs()
placement:activate("crate", plot.itemHolder, plot, false)
end)
the place remote event
local Datastorev2 = require(game:GetService("ServerScriptService"):WaitForChild("Modules"):WaitForChild("DataStore2"))
local key = require(game.ServerScriptService.Modules.Dataversion)[1]
-- handles collisions on the hitbox
local function handleCollisions(object, char)
local collided = false
if object then
local collisionpoint = object.PrimaryPart.Touched:Connect(function() end)
local collisionpoints = object.PrimaryPart:GetTouchingParts()
for i = 1, #collisionpoints, 1 do
if not collisionpoints[i]:IsDescendantOf(object) and not collisionpoints[i]:IsDescendantOf(char) then
collided = true
break
end
end
collisionpoint:Disconnect()
return collided
end
end
local function place(plr, id, location, cf, plot, wasmovedobject)
local item = game.ReplicatedStorage.Items:FindFirstChild(id):Clone()
item.PrimaryPart.CanCollide = false
item:PivotTo(cf)
if plot then
item.Parent = location
local PlayerDatastore = Datastorev2(key, plr)
PlayerDatastore:Update(function(DataTable)
local relative = plot.CFrame:ToObjectSpace(cf)
local saveitem = {
["id"] = id,
["CFrame"] = tostring(relative),
["Location"] = tostring(location)
}
local index = #DataTable.Plot + 1
print(index.." placed down on plot")
DataTable.Plot[index] = saveitem
print(DataTable.Plot)
local objectid = Instance.new("NumberValue")
objectid.Parent = item
objectid.Name = "TableID"
objectid.Value = index -- Use the index instead of DataTable.Plot[saveitem]
local ItemTable = DataTable.Inventory.Items
if wasmovedobject == false then -- dont need to subtract from the inventory if the item was moved bc it was already on the plot to begin with
for object,ammount in pairs(ItemTable) do
-- find the item that was placed, and remove it from the items table bc it was put on the plot
if object == id then
local invgui = plr.PlayerGui.Inventory.Holder.ScrollingFrame:GetChildren()
for i,v in pairs(invgui) do
if v:IsA("TextButton") and v.tablenum.value == ammount then
print(v.Name.." was removed from the gui")
v:Destroy()
end
end
ItemTable[object] = ammount - 1
print(ItemTable[object].." in inventory left")
if ItemTable[object] == 0 then
-- if they place all the items u dont want a random entry being ["Desk"] = 0; bc thats just a waste of rescourses so get rid of it
ItemTable[object] = nil
end
end
end
end
return DataTable
end)
if handleCollisions(item, plr.Character) and wasmovedobject == false then
item:Destroy()
return false
end
end
return true
end
game.ReplicatedStorage.Remotes.Place.OnServerInvoke = place -- use "place" function when invoked from client
The keybinds
function placement:bindInputs()
contextActionService:BindAction("Rotate", rotate, false, ROTATE_KEY) -- XBOX ROTATE KEY HERE IF CONSOLE ETC
contextActionService:BindAction("Cancel", cancel, false, TERMINATE_KEY)
contextActionService:BindAction("Move", move, false, MOVE_KEY)
contextActionService:BindAction("Place",place, false, PLACE_KEY)
end
Screenshots
Output
The last Gui button that breaks everything
And example of what placing one of the other buttons looks like (no grid left no box left bc placement:finish() was called)
placing the last gui button (green arrow) (placed the object, but didnt delete the grid or the object and placement:finish() was not called)
I’m sorry if this post is confusing or clunky (or the code) I’m still very inexperienced and I dont post much here; I’m trying my hardest to make a game. Thanks for all your help!