Hello everyone, today I was working on my 2nd tower which did not involve humanoids (well it did, but i added extra parts outside of the character. Naturally, my code broke ![]()
This was gnomecode’s tutorial which was super helpful and ive made a few edits to include a situation with and without humanoids but the issue is im still using humanoidrootpart to set the position. I need to find a way to stop using them so the extra parts outisde of the character will still work. If you dont get it, heres some screenshots:
What it looks like:

The hierarchy inside:

And then heres my code:
Client (using topbarplus):
local PS = game:GetService("PhysicsService")
local RSS = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local TowerSpawnEvent = RSS.Events.Tower.TowerSpawn
local towers = RSS:WaitForChild("Towers")
local screengui = game.Players.LocalPlayer.PlayerGui.TowerGui
local guifolder = RSS.GUI
local camera = workspace.CurrentCamera
local towerTospawn = nil
local KeybindTowerInfo = nil
local canPlace = true
local Cash = game.Players.LocalPlayer.leaderstats.Cash
local function MouseRaycast(blacklist)
local mousePosition = UserInputService:GetMouseLocation()
local mouseRay = camera:ViewportPointToRay(mousePosition.X, mousePosition.Y)
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.FilterDescendantsInstances = blacklist
local raycastResult = workspace:Raycast(mouseRay.Origin, mouseRay.Direction * 1000, raycastParams)
return raycastResult
end
local function RemovePlaceholderTower()
if towerTospawn then
towerTospawn:Destroy()
towerTospawn = nil
end
end
local function RemovePlaceholderText()
if towerTospawn then
KeybindTowerInfo:Destroy()
KeybindTowerInfo = nil
end
end
local function AddPlaceholderTower(name)
local towerExists = towers:FindFirstChild(name)
if towerExists then
RemovePlaceholderTower()
towerTospawn = towerExists:Clone()
towerTospawn.Parent = workspace.Towers
for i, object in pairs(towerTospawn:GetDescendants()) do
if object:IsA("BasePart") then
object.CollisionGroup = "Tower"
object.Material = Enum.Material.ForceField
end
end
end
end
local function ColorPlaceholderTower(color)
for i, object in pairs(towerTospawn:GetDescendants()) do
if object:IsA("BasePart") then
object.Color = color
end
end
end
AddPlaceholderTower("dealer")
KeybindTowerInfo = guifolder.KeybindTowerInfo:Clone()
KeybindTowerInfo.Parent = screengui
UserInputService.InputBegan:Connect(function(input, processed)
if processed then
return
end
if towerTospawn then
if input.UserInputType == Enum.UserInputType.MouseButton1 then
if canPlace then
if Cash.Value >= towerTospawn:GetAttribute("cost") then
TowerSpawnEvent:FireServer(towerTospawn.Name, towerTospawn.PrimaryPart.CFrame,true)
RemovePlaceholderText()
RemovePlaceholderTower()
else
RemovePlaceholderText()
RemovePlaceholderTower()
end
else
RemovePlaceholderText()
RemovePlaceholderTower()
end
end
if input.KeyCode == Enum.KeyCode.Q then
RemovePlaceholderText()
RemovePlaceholderTower()
end
end
end)
RunService.RenderStepped:Connect(function()
if towerTospawn then
local result = MouseRaycast({towerTospawn})
if result and result.Instance then
if result.Instance.Parent.Name == "TowerSpace" then
canPlace = true
ColorPlaceholderTower(Color3.new(0,1,0))
else
canPlace = false
ColorPlaceholderTower(Color3.new(1,0,0))
end
local x = result.Position.X
local y = result.Position.Y + 0.6034285714 -- this part used to be the hipheight divided by 1.75 but i changed it to the actual value for now
local z = result.Position.Z
local cframe = CFrame.new(x,y,z)
towerTospawn:SetPrimaryPartCFrame(cframe)
end
end
end)
end)
Server:
require(script.Parent.Tower)
Module:
local RSS = game:GetService("ReplicatedStorage")
local towers = RSS.Towers
local events = RSS.Events
local towerevents = events.Tower
local tower = {}
local towerspawnevent = towerevents.TowerSpawn
function tower.Spawn(player, name, pos, normal, hasHumanoid)
if hasHumanoid then
if normal then
local towerExists = RSS.Towers:FindFirstChild(name)
if towerExists then
player.leaderstats.Cash.Value -= towerExists:GetAttribute("cost")
local towerToSpawn = towerExists:Clone()
towerToSpawn.HumanoidRootPart.CFrame = pos
towerToSpawn.Parent = workspace.Towers
towerToSpawn.HumanoidRootPart:SetNetworkOwner(nil)
for i, object in pairs(towerToSpawn:GetDescendants()) do
if object:IsA("BasePart") then
object.CollisionGroup = "Tower"
end
end
else
warn("No Tower Found!")
end
else
local towerExists = RSS.Towers:FindFirstChild(name)
if towerExists then
local towerToSpawn = towerExists:Clone()
towerToSpawn.HumanoidRootPart.CFrame = pos
towerToSpawn.Parent = workspace.Towers
towerToSpawn.HumanoidRootPart:SetNetworkOwner(nil)
for i, object in pairs(towerToSpawn:GetDescendants()) do
if object:IsA("BasePart") then
object.CollisionGroup = "Tower"
end
end
else
warn("No Tower Found!")
end
end
else
if normal then
local towerExists = RSS.Towers:FindFirstChild(name)
if towerExists then
player.leaderstats.Cash.Value -= towerExists:GetAttribute("cost")
local towerToSpawn = towerExists:Clone()
towerToSpawn.HumanoidRootPart.CFrame = pos
towerToSpawn.Parent = workspace.Towers
for i, object in pairs(towerToSpawn:GetDescendants()) do
if object:IsA("BasePart") then
object.CollisionGroup = "Tower"
end
end
else
warn("No Tower Found!")
end
else
local towerExists = RSS.Towers:FindFirstChild(name)
if towerExists then
local towerToSpawn = towerExists:Clone()
towerToSpawn.HumanoidRootPart.CFrame = pos
towerToSpawn.Parent = workspace.Towers
for i, object in pairs(towerToSpawn:GetDescendants()) do
if object:IsA("BasePart") then
object.CollisionGroup = "Tower"
end
end
else
warn("No Tower Found!")
end
end
end
end
towerspawnevent.OnServerEvent:Connect(tower.Spawn)
return tower