Hello everyone :)
I'm making a replacement system in my game. When player will change his mind of replacing a model, he simply presses "q" button and model gets in its previous position... Well, here's the problem
When player presses the "Move" button, I immediately save model's CFrame in LocalScript's variable:
local firstCFrame = model.PrimaryPart.CFrame
Then, when player presses 'q', LocalScript fires RemoteEvent with arguments: model, firstCFrame.
Script:
function returnBack(model, firstCFrame) model:SetPrimaryPartCFrame(firstCFrame) end
Unfortunately, it doesn't work, and I don't know what's the issue. I tried making something like this:
print(model.PrimaryPart.CFrame) model:SetPrimaryPartCFrame(firstCFrame) print(model.PrimaryPart.CFrame)
Andddd.... First "print" prints model's CFrame in moment of player pressing "q", and the second "print" prints firstCFrame
EDIT 1: FULL CODE: LocalScript:
-- Events & functions local replicatedStorage = game:GetService("ReplicatedStorage") local edit_menu_function = replicatedStorage.edit_menu_function local edit_menu_event = replicatedStorage.edit_menu_event local structure_pucharse_event = replicatedStorage.structure_pucharse_event local structure_pucharse_function = replicatedStorage.structure_pucharse_function -- GUIs local gui = script.Parent.Parent.Parent.Parent.Parent local menu = gui:FindFirstChild("BuildingsMenu") -- Player local mouse = game.Players.LocalPlayer:GetMouse() local camera = workspace.CurrentCamera local canPlace = gui.Buildings.CanPlace -- Rotation local angle = gui.Options.RotationAngle local rotation = CFrame.Angles(0,0,0) angle.Changed:connect(function() rotation = CFrame.Angles(0,0,0) end) -- Event script.Parent.MouseButton1Click:Connect(function() menu.Enabled = false local model = menu.LoadingScripts.lastStructure.Value local firstCFrame = model.PrimaryPart.CFrame local stopper, debounce, canNotify = false, false, false local soldiers = edit_menu_function:InvokeServer("prepare", model, gui.AreaBusy) -- turning on tips gui.Buildings.Place.Visible = true gui.Buildings.Rotate.Visible = true gui.Buildings.Quit.Visible = true -- getting a player's area local region = structure_pucharse_function:InvokeServer("findRegion") while stopper == false do wait() structure_pucharse_event:FireServer("move", mouse.Hit.p, camera.CFrame.Position, model, region, rotation) mouse.KeyDown:connect(function(key) if key == "e" then if stopper == false and canPlace.Value == true then stopper = true gui.Buildings.Place.Visible = false gui.Buildings.Rotate.Visible = false gui.Buildings.Quit.Visible = false local dataEvent = replicatedStorage.dataEvent menu.Enabled = true edit_menu_event:FireServer("set", gui.AreaBusy, soldiers) elseif stopper == false and canPlace.Value == false and canNotify == false then canNotify = true local notification = gui.Notifications.TextLabel notification.Visible = true wait(1.5) for i = 0, 1, 0.1 do notification.TextTransparency = i wait(0.1) end notification.Visible = false notification.TextTransparency = 0 canNotify = false end end if key == "r" then if debounce == false then debounce = true local newRotation = structure_pucharse_function:InvokeServer("rotate", rotation, angle.Value) rotation = newRotation wait(0.1) debounce = false end end if key == "q" and stopper == false then stopper = true gui.Buildings.Place.Visible = false gui.Buildings.Rotate.Visible = false gui.Buildings.Quit.Visible = false edit_menu_event:FireServer("set", gui.AreaBusy, soldiers, model, firstCFrame) menu.Enabled = true end end) end end)
Script:
local module = require(workspace.teamsVariables) local replicatedStorage = game:GetService("ReplicatedStorage") local remoteEvent = replicatedStorage:FindFirstChild("edit_menu_event") local remoteFunction = replicatedStorage:FindFirstChild("edit_menu_function") if not remoteEvent then warn(script:GetFullName() ": edit_menu_event couldn't been found. Check if you haven't replaced or renamed it") end function main(player, action, arg1, arg2, arg3, arg4) local color = module.getColor(player) local type_, object = arg1, arg2 -- Defining arguments local counter = player.PlayerGui.Counter if action == "destroy" then if type_ == "structure" then local occupants = object:FindFirstChild("Data"):FindFirstChild("Occupants") if occupants then for i, v in pairs(occupants:GetChildren()) do if v.Value ~= nil then local occupant = v.Value occupant:Destroy() counter.soldierCounter.Placed.Value = counter.soldierCounter.Placed.Value - 1 end end end counter.soldierCounter.TextLabel.Text = counter.soldierCounter.Placed.Value .. "/" .. counter.soldierCounter.Max.Value if object.Name ~= color .. "Barrack" and object.Name ~= color .. "Garage" then counter.structureCounter.Placed.Value = counter.structureCounter.Placed.Value - 1 elseif object.Name == color .. "Barrack" then counter.soldierCounter.Max.Value = counter.soldierCounter.Max.Value - 1 elseif object.Name == color .. "Garage" then counter.structureCounter.Max.Value = counter.structureCounter.Max.Value - 1 end object:Destroy() counter.structureCounter.TextLabel.Text = counter.structureCounter.Placed.Value .. "/" .. counter.structureCounter.Max.Value counter.soldierCounter.TextLabel.Text = counter.soldierCounter.Placed.Value .. "/" .. counter.soldierCounter.Max.Value elseif type_ == "soldier" then local spot, value = arg3, arg4 object:Destroy() print("object destroyed") value.Value = nil counter.soldierCounter.Placed.Value = counter.soldierCounter.Placed.Value - 1 if spot then spot:SetPrimaryPartCFrame(spot.PrimaryPart.CFrame * CFrame.new(0, 15, 0)) end counter.soldierCounter.TextLabel.Text = counter.soldierCounter.Placed.Value .. "/" .. counter.soldierCounter.Max.Value return end elseif action == "prepare" then local model, areaBusy = arg1, arg2 local occupants = model.Data:FindFirstChild("Occupants") areaBusy.Value = true -- putting all soldiers to model local soldiers = {} for i, soldier in pairs(occupants:GetChildren()) do if soldier.ClassName == "ObjectValue" and soldier.Value ~= nil then local soldier = soldier.Value table.insert(soldiers, soldier) soldier.Parent = model soldier:FindFirstChild("HumanoidRootPart").Anchored = true end end return soldiers elseif action == "set" then local areaBusy, soldiers, model, firstCFrame = arg1, arg2, arg3, arg4 -- disabling areabusy arg1.Value = false if model and firstCFrame then print(model.PrimaryPart.CFrame) model:SetPrimaryPartCFrame(firstCFrame) print(model.PrimaryPart.CFrame) end wait(1) -- moving soldiers out of the model local colorfinder = require(workspace.teamsVariables) local color = colorfinder.getColor(player) local battlefield = workspace.Map:FindFirstChild(color).Battlefield for i, soldier in pairs(soldiers) do soldier.Parent = battlefield soldier:FindFirstChild("HumanoidRootPart").Anchored = false end else warn(script:GetFullName() .. ": Action not recognised") end end remoteEvent.OnServerEvent:connect(main) remoteFunction.OnServerInvoke = main
This doesn't get any errors
EDIT 2: VIDEO A little video of what's going on. Output says:
-180, 1.90120101, 195, 1, -1.71992952e-17, 1.74820436e-36, -1.71992952e-17, 1, -2.16840434e-19, 1.74820436e-36, -2.16840434e-19, 1
-236, 1.90120101, 237, 1, -3.43985903e-17, 7.225911e-36, -3.43985903e-17, 1, -4.33680869e-19, 7.225911e-36, -4.33680869e-19, 1
Where the second is FirstCFrame value
https://streamable.com/ug39hz
I would be grateful for any help :) Thanks in advance, Krzysiek
So this module script would go directly under your server script. I also took most of your old code and just copy and pasted it in and fixed some compatibility, so it should work the same, but if not let me know.
Server Script (the same one as your old one):
local module = require(workspace.teamsVariables) local replicatedStorage = game:GetService("ReplicatedStorage") local remoteEvent = replicatedStorage:FindFirstChild("edit_menu_event") local remoteFunction = replicatedStorage:FindFirstChild("edit_menu_function") if not remoteEvent then warn(script:GetFullName() ": edit_menu_event couldn't been found. Check if you haven't replaced or renamed it") end local Action = require(script.Actions) function main(player, action, ...) local color = module.getColor(player) local args = {...} args[#args+1] = script:GetFullName() -- for your error handling, it adds it to the end of the argument list so it can easily be handed to the module local type_, object = args[1], args[2] -- Defining arguments local counter = player.PlayerGui.Counter if action == "destroy" then Action.DESTROY[string.upper(type_)](object,counter,color) else Action:get("prepare", player, args) end end remoteEvent.OnServerEvent:Connect(main) remoteFunction.OnServerInvoke = main
Module Script:
local Action = { ["DESTROY"] = { ["STRUCTURE"] = function(object,counter,color) local occupants = object:FindFirstChild("Data"):FindFirstChild("Occupants") if occupants then for i, v in pairs(occupants:GetChildren()) do if v.Value ~= nil then local occupant = v.Value occupant:Destroy() counter.soldierCounter.Placed.Value = counter.soldierCounter.Placed.Value - 1 end end end counter.soldierCounter.TextLabel.Text = counter.soldierCounter.Placed.Value .. "/" .. counter.soldierCounter.Max.Value if object.Name ~= color .. "Barrack" and object.Name ~= color .. "Garage" then counter.structureCounter.Placed.Value = counter.structureCounter.Placed.Value - 1 elseif object.Name == color .. "Barrack" then counter.soldierCounter.Max.Value = counter.soldierCounter.Max.Value - 1 elseif object.Name == color .. "Garage" then counter.structureCounter.Max.Value = counter.structureCounter.Max.Value - 1 end object:Destroy() counter.structureCounter.TextLabel.Text = counter.structureCounter.Placed.Value .. "/" .. counter.structureCounter.Max.Value counter.soldierCounter.TextLabel.Text = counter.soldierCounter.Placed.Value .. "/" .. counter.soldierCounter.Max.Value end, ["SOLDIER"] = function(object, counter, ...) local args = {...} local spot, value = args[3], args[4] object:Destroy() print("object destroyed") value.Value = nil counter.soldierCounter.Placed.Value = counter.soldierCounter.Placed.Value - 1 if spot then spot:SetPrimaryPartCFrame(spot.PrimaryPart.CFrame * CFrame.new(0, 15, 0)) end counter.soldierCounter.TextLabel.Text = counter.soldierCounter.Placed.Value .. "/" .. counter.soldierCounter.Max.Value return end }, ["PREPARE"] = function(player, ...) local args = {...} local model, areaBusy = args[1], args[2] local occupants = model.Data:FindFirstChild("Occupants") areaBusy.Value = true -- putting all soldiers to model local soldiers = {} for i, soldier in pairs(occupants:GetChildren()) do if soldier.ClassName == "ObjectValue" and soldier.Value ~= nil then local soldier = soldier.Value table.insert(soldiers, soldier) soldier.Parent = model soldier:FindFirstChild("HumanoidRootPart").Anchored = true end end return soldiers end , ["SET"] = function(player, ...) local args = {...} local areaBusy, soldiers, model, firstCFrame = args[1], args[2], args[3], args[4] -- disabling areabusy args[1].Value = false if model and firstCFrame then print(model.PrimaryPart.CFrame) model:SetPrimaryPartCFrame(firstCFrame) print(model.PrimaryPart.CFrame) end wait(1) -- moving soldiers out of the model local colorfinder = require(workspace.teamsVariables) local color = colorfinder.getColor(player) local battlefield = workspace.Map:FindFirstChild(color).Battlefield for i, soldier in pairs(soldiers) do soldier.Parent = battlefield soldier:FindFirstChild("HumanoidRootPart").Anchored = false end end } function Action:get(action,player,...) local args = {...} if self[string.upper(action)]~=nil then self[string.upper(action)](player,args) else warn(args[5] .. ": Action not recognised") end end return Action
Since I couldn't test this, I'm really not sure if it will work, but as far as the module script structure goes, it should be fine.