Help with plot saving/loading system

image
This basically brings me back to square one, where the positions arent messed up now, but the circled conveyor was rotated 90 degrees and was supposed to be facing the direction the arrow is pointing, but its rotation was set back to 0

Could you show the saving and loading scripts. In my game this solution is working perfectly.

Loading part:

local function ProfileLoaded(plr, profile, plot)
	--Player Status
	-- 1 = Idle
	-- 2 = Placing
	-- 3 = Destroying
	PlayerData:AddOrSetNumber(plr, 1, "PlayerStatus")
	PlayerData:AddOrSetBool(plr, false, "ObjectDebounce")
	PlayerData:AddOrSetString(plr, "None", "ObjectBeingPlaced")
	for _, obj in pairs(profile.Data.Items) do
		local model = game.ReplicatedStorage.Models:FindFirstChild(obj.ObjectName)
		PlayerData:AddOrSetNumber(plr, obj.Count, obj.ObjectName)
		game.ReplicatedStorage.Remotes.AddClientObject:FireClient(plr, model, obj.Count)
	end
	print(profile.Data.PlotData)
	for index, plotObj in pairs(profile.Data.PlotData) do
		local model = game.ReplicatedStorage.Models:FindFirstChild(plotObj.Object):Clone()
		
		local locpos = CFrame.new(plotObj.Location.x, plotObj.Location.y, plotObj.Location.z) * CFrame.Angles(0, math.rad(plotObj.Location.r), 0)
		local BaseCFrame = workspace.Plots:FindFirstChild(plr.playerdata.Plot.Value).CFrame
		local CurrentSurface = BaseCFrame:ToObjectSpace(locpos)
		model:SetPrimaryPartCFrame(workspace.Plots:FindFirstChild(plr.playerdata.Plot.Value).CFrame:ToWorldSpace(CurrentSurface))
		model.Parent = plot.ItemHolder
		model:SetAttribute("Identifier", index)
	end
end

local function PlayerAdded(plr)
	local playerPlot = nil
	for _, plot in pairs(workspace.Plots:GetChildren()) do
		if plot:GetAttribute("Owner") == "Nobody" then
			PlayerData:AddOrSetString(plr, plot.Name, "Plot")
			plot:SetAttribute("Owner", plr.Name)
			playerPlot = plot
			break
		end
	end
	if playerPlot == nil then
		plr:Kick()
	end
	
	local profile = ProfileStore:LoadProfileAsync("Player_" .. plr.UserId)
	if profile ~= nil then
		profile:AddUserId(plr.UserId)
		profile:Reconcile()
		profile:ListenToRelease(function()
			Profiles[plr] = nil
			plr:Kick()
		end)
		if plr:IsDescendantOf(Players) == true then
			Profiles[plr] = profile
			ProfileLoaded(plr, profile, playerPlot)
		else
			profile:Release()
		end
	else
		plr:Kick() 
	end
end

for _, player in ipairs(Players:GetPlayers()) do
	coroutine.wrap(PlayerAdded)(player)
end

Players.PlayerAdded:Connect(PlayerAdded)

Players.PlayerRemoving:Connect(function(player)
	local profile = Profiles[player]
	if profile ~= nil then
		profile:Release()
	end
end)

Saving part:

game.ReplicatedStorage.Remotes.PlaceObjectServer.OnServerEvent:Connect(function(player)
	local profile = Profiles[player]
	if profile ~= nil then
		profile.Data.PlotData = {}
		for index, p in pairs(workspace.Plots:FindFirstChild(player.playerdata.Plot.Value).ItemHolder:GetChildren()) do
			profile.Data.PlotData[#profile.Data.PlotData + 1] = {
				Object = p.Name,
				Location = {
					x = p.PrimaryPart.CFrame.X,
					y = p.PrimaryPart.CFrame.Y,
					z = p.PrimaryPart.CFrame.Z,
					r = p.PrimaryPart.CFrame.Rotation.Y
				}
			}
			p:SetAttribute("Identifier", index)
			if game.ReplicatedStorage.Models:FindFirstChild(p.Name) then
				profile.Data.Items[p.Name] = {
					ObjectName = p.Name,
					Count = player.playerdata:FindFirstChild(p.Name).Value
				}
			end
		end
		print(profile.Data)
	end
end)

And if your wondering if the data gets corrupted or modified or anything, it doesn’t. The rotation and coords save perfectly, because every time when I check the print(profile.Data) call and check the tables the rotation is stored correctly.

This also messed up deleting things, not sure how but it did – ignore this i fixed it

This should just be r.PrimaryPart.Orientation.Y because you’re using math.rad in the loading part

Also BaseCFrame needs to be a value that is saved in the profile. Just save plot cframe.

Thanks. It makes more sense now.


local locpos = CFrame.new(
    plotObj.Location.x,
    plotObj.Location.y, plotObj.Location.z)
    * CFrame.Angles(0, math.rad(plotObj.Location.r), 0) :ToObjectSpace(workspace.Plots:FindFirstChild(plr.playerdata.Plot.Value).CFrame)
--                                       Add bracket   ^

You forgot to add brackets:

local locpos = ( -- Bracket
	CFrame.new(
		plotObj.Location.x,
		plotObj.Location.y,
		plotObj.Location.z
	) * CFrame.Angles(0, math.rad(plotObj.Location.r), 0)
) --[[<-- Bracket]]:ToObjectSpace(
	workspace.Plots:FindFirstChild(plr.playerdata.Plot.Value).CFrame
)

You’re performing ToObjectSpace before everything else is calculated (so you object space the rotation but not the location).

image
Still doesnt fix it, the one i have selected was rotated 90 degrees

I think it’s performing ToObjectSpace() on the CFrame.Angles

Im just gonna give up on this game for now, thank you 2 for trying to help

You could just send the entire script how it currently is. I can change it to how it works in my game for you and add comments.

Ill do you one better, basically i’ll make a model with the plot and every script so you can take what I have right now and work with it instead of me sending the scripts

Don’t make it a model instead just send it as an rbxl file here. I think there are some bots that automatically steal models.

After some thought, you’re transforming the CFrame to object space when it’s already in object space which would make this happen:

As you can see, you’re not really transforming the CFrame as you want, instead, getting a long Vector that’s positioned elsewhere. In this case, you’re positioning the object from 0, 0, 0 plus the saved CFrame relative to the plots CFrame.


To fix this problem, you can multiply the plot CFrame by the inverse of the saved CFrame (I don’t know why it’s the inverse, but not doing it doesn’t work for me when I was testing):

local locpos = workspace.Plots:FindFirstChild(plr.playerdata.Plot.Value).CFrame * (
	CFrame.new(
		plotObj.Location.x,
		plotObj.Location.y,
		plotObj.Location.z
	) * CFrame.Angles(0, math.rad(plotObj.Location.r), 0)
):Inverse()

Alright ill give you the .rbxl file
gamethingy.rbxl (132.3 KB)
I also dont mind if it was stolen by bots, there isn’t much to go off of anyways

Here is a working version of the game with comments in the script
gamethingyfixed.rbxl (132.3 KB)

Thank you! Will this work with a different plot, like if a player joins for the first time and makes a base on Plot1, but then the next day they join again and someone has already taken Plot1, so it assigns them to Plot2, will their base be the exact same?

Yes it will be the same as the location for the plot they last saved on is stored in the profile.

1 Like

Also, there’s a version on my profile which shouldn’t be copylocked with it fixed