Pressing 2 then 1 to switch towers leaves tower stuck in place

I have a tower system where if you press 1, you can place tower in slot 1, pressing 2 lets you place tower in slot 2, etc. But I want it so that you can press 2, then 1 (and vice versa) to switch what tower you want to place. With my code, you can do it and start placing the tower, but the tower is never actually placed (it won’t shoot at the enemy) and you cannot move it to where you want to place it.

Code for pressing 2 to place tower slot 2:

uis.InputBegan:Connect(function(input, processed)
	if input.KeyCode == Enum.KeyCode.R then
		place.Value:SetPrimaryPartCFrame(place.PrimaryPart.CFrame * CFrame.Angles(0, math.pi/2, 0))
	elseif input.KeyCode == Enum.KeyCode.Two then
		print(foundName)
		controlscript.placetower(2, foundName, worktowerfold, collisionsmod, towersfold)
	elseif input.KeyCode == Enum.KeyCode.Backspace or input.KeyCode == Enum.KeyCode.Delete then
		controlscript.delete()
	end
end)

Pretty much the same for tower slot 1:

uis.InputBegan:Connect(function(input, processed)
	if input.KeyCode == Enum.KeyCode.R then
		place.Value:SetPrimaryPartCFrame(place.PrimaryPart.CFrame * CFrame.Angles(0, math.pi/2, 0))
	elseif input.KeyCode == Enum.KeyCode.One then
		controlscript.placetower(1, foundName, worktowerfold, collisionsmod, towersfold)
	elseif input.KeyCode == Enum.KeyCode.Backspace or input.KeyCode == Enum.KeyCode.Delete then
		controlscript.delete()
	end
end)

controlscript.placetower:

function guicontrol.initplacetower(tf, fn, worktf, cm)
	local tower = tf:FindFirstChild(fn)
	if tower then
		ttp.Value = tower:Clone()
		ttp.Value.PrimaryPart = ttp.Value:WaitForChild("HumanoidRootPart")
		print(ttp.Value.PrimaryPart)
		ttp.Value.Parent = worktf
		local placedesc = ttp.Value:GetDescendants()
		cm.SetPartToGroup(placedesc, "Towers & Monsters")
	end
end

function guicontrol.placetower(num, fn, worktf, cm, tf)
	print(tf)
	if ipt.Value == false then
		tsp.Value = num
		guicontrol.initplacetower(tf, fn, worktf, cm) --This will initialize placing the tower, and will allow it to be moved and placed, this part is the problem
		ipt.Value = true
	elseif ipt.Value == true then
		for i = 1, 2 do
			if i == num then
				continue
			end
			if tsp.Value == i then
				tsp.Value = num
				eventstable[i]:Fire()
				guicontrol.initplacetower(tf, fn, worktf, cm) --This will initialize placing the tower, but won't allow it to be moved and placed
			end
		end
	end
end

What happens when eventstable[i] is fired:

controlscript.r2.Event:Connect(function() --r2 is r1 in the script for slot 1
	place.Value:Destroy()
	task.wait()
	place.Value = nil
end)

Moving tower script: (It probably won’t be useful though)

runservice.RenderStepped:Connect(function()
	if place ~= nil then
		if place.Value ~= nil then
			if place.Value.Parent ~= nil then --3 if statements. Quite cautious, don't you think?
				local castpar = RaycastParams.new()
				castpar.FilterType = Enum.RaycastFilterType.Blacklist
				castpar.FilterDescendantsInstances = place:GetDescendants()
				if uis.KeyboardEnabled == true and uis.MouseEnabled == true then --Mouse
					getcast = controlscript.castmouse(uis, camera)
				elseif uis.KeyboardEnabled == true and uis.TouchEnabled == true and uis.MouseEnabled == false then --Touch
					getcast = controlscript.casttap(lastplacetapped, camera)
				elseif uis.TouchEnabled == true and uis.MouseEnabled == true then --Touch/Mouse
					getcast = controlscript.castmouse(uis, camera)
				end
				if getcast and getcast.Instance then
					if getcast.Instance.Name ~= "CanPlaceOn" then
							canPlace = false
					else
						canPlace = true
					end
					local x = getcast.Position.X
						print(place.Value.PrimaryPart)
					local y = getcast.Position.Y +(place.Value.PrimaryPart.Size.Y) / 2 + place.Value["Left Leg"].Size.Y
					local z = getcast.Position.Z
					local placecframe = CFrame.new(x, y, z)
					local primpart = place.Value.PrimaryPart
					local orientationX, orientationY, orientationZ = primpart.CFrame.Rotation:ToOrientation()
					place.Value:SetPrimaryPartCFrame(placecframe * CFrame.fromOrientation(orientationX, orientationY, orientationZ))
				end
			end
		end
	end
end)

Why isn’t it working?

1 Like

Is the tower behavior logic handled by the server or client?
Anything that physically moves/changes the model must be done by the server and not the client.
ONLY in the case that the behavior of the towers is handled by the server.
If the tower behavior is done by the client then something else is going on.

It’s done in the client, actually placing the tower is done on the server, as seen here:

controlscript.spawnfinaltower(spawna)
function guicontrol.spawnfinaltower(sre)
	if ipt.Value == true then
		sre:FireServer(ttp.Value.Name, ttp.Value.PrimaryPart.CFrame)
		ttp.Value:Destroy()
		ttp.Value = nil
		ipt.Value = false
	end
end
1 Like

I’m looking at the call stack and I don’t see spawnfinaltower called anywhere in guicontrol.placetower

1 Like

That’s just putting the tower in workspace, spawnfinaltower locks it in there and starts the tower scripts.
Full tower placement script:

local rs = game:GetService("ReplicatedStorage")
local runservice = game:GetService("RunService")
local uis = game:GetService("UserInputService")
local ps = game:GetService("Players")

local controlscript = require(script.Parent.Parent.Parent:WaitForChild("GUIControlScript"))
local button = script.Parent
local placetowerbutton = script.Parent.Parent:WaitForChild("PlaceTower")
local towersfold = rs:WaitForChild("TDTowers")
local foundName = (button:WaitForChild("Tower")).Value
local collisionsmod = require(rs:WaitForChild("Collisions"))
local canPlace = true
local spawna = rs:WaitForChild("SpawnTower")
local worktowerfold = game.Workspace:WaitForChild("Towers")
local camera = game.Workspace.CurrentCamera
local getcast
local lastplacetapped
local localplr = ps.LocalPlayer
local localui = localplr:WaitForChild("PlayerGui")
local screenui = localui:WaitForChild("ScreenGUI1")
local place = screenui:WaitForChild("TowerToPlace")

uis.TouchTapInWorld:Connect(function(tappedplace)
	lastplacetapped = controlscript.casttaptoworld(tappedplace)
end)

button.MouseButton1Click:Connect(function()
	controlscript.placetower(1, foundName, worktowerfold, collisionsmod, towersfold)
end)

runservice.RenderStepped:Connect(function()
	if place ~= nil then
		if place.Value ~= nil then
			if place.Value.Parent ~= nil then
				local castpar = RaycastParams.new()
				castpar.FilterType = Enum.RaycastFilterType.Blacklist
				castpar.FilterDescendantsInstances = place:GetDescendants()
				if uis.KeyboardEnabled == true and uis.MouseEnabled == true then --Mouse
					getcast = controlscript.castmouse(uis, camera)
				elseif uis.KeyboardEnabled == true and uis.TouchEnabled == true and uis.MouseEnabled == false then --Touch
					getcast = controlscript.casttap(lastplacetapped, camera)
				elseif uis.TouchEnabled == true and uis.MouseEnabled == true then --Touch/Mouse
					getcast = controlscript.castmouse(uis, camera)
				end
				if getcast and getcast.Instance then
					if getcast.Instance.Name ~= "CanPlaceOn" then
						canPlace = false
					else
						canPlace = true
					end
					local x = getcast.Position.X
					print(place.Value.PrimaryPart)
					local y = getcast.Position.Y +(place.Value.PrimaryPart.Size.Y) / 2 + place.Value["Left Leg"].Size.Y
					local z = getcast.Position.Z
					local placecframe = CFrame.new(x, y, z)
					local primpart = place.Value.PrimaryPart
					local orientationX, orientationY, orientationZ = primpart.CFrame.Rotation:ToOrientation()
					place.Value:SetPrimaryPartCFrame(placecframe * CFrame.fromOrientation(orientationX, orientationY, orientationZ))
				end
			end
		end
	end
end)

uis.InputBegan:Connect(function(input, processed)
	if input.KeyCode == Enum.KeyCode.R then
		place.Value:SetPrimaryPartCFrame(place.PrimaryPart.CFrame * CFrame.Angles(0, math.pi/2, 0))
	elseif input.KeyCode == Enum.KeyCode.One then
		controlscript.placetower(1, foundName, worktowerfold, collisionsmod, towersfold)
	elseif input.KeyCode == Enum.KeyCode.Backspace or input.KeyCode == Enum.KeyCode.Delete then
		controlscript.delete()
	end
end)

uis.InputBegan:Connect(function(input, processed)
	if input.KeyCode == Enum.KeyCode.E then
		if canPlace == true then
			controlscript.spawnfinaltower(spawna)
		else
			controlscript.Error("Cannot place here!")
		end
	end
end)

placetowerbutton.TouchTap:Connect(function()
	if canPlace == true then
		controlscript.spawnfinaltower(spawna)
	else
		controlscript.Error("Cannot place here!")
	end
end)

placetowerbutton.MouseButton1Click:Connect(function()
	if canPlace == true then
		controlscript.spawnfinaltower(spawna)
	else
		controlscript.Error("Cannot place here!")
	end
end)

controlscript.r1.Event:Connect(function()
	place.Value:Destroy()
	task.wait()
	place.Value = nil
end)
1 Like

Pressing 2 then 1 to switch towers works, but pressing 1 then 2 will not allow me to place tower slot 2 and lock it in place… I will look into this later.

EDIT: After testing again I have found that pressing 2 then 1 doesn’t exactly work, but when I press 2 again the tower slot 1 is stuck in its place and I can place tower slot 2, same happens when pressing 1 then 2

1 Like

I solved it. Turns out the ipt value (Is Placing Tower, turned on when I am currently placing a tower) was stuck as false, thank you to anyone who helped :slight_smile: