Why does it print I'm not allowed to place my tower even though my turret is being placed on the baseplate?

So I’m working on a TDS style game for my bday, and I nearly finished my placement system. I just tested it and I saw that it prints “You are not allowed to place here” when I get too near the edge of the baseplate even though my turret is still on it. Here’s my script:

local repStorage = game:GetService("ReplicatedStorage")
local remotes = require(repStorage:WaitForChild("RemoteModule"))
local runService = game:GetService("RunService")
local tweenService = game:GetService("TweenService")
local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Quint, Enum.EasingDirection.Out, 0, false)
local RotateConnection
local toPlace
local ableToPlace
local rotationDebounce = false
local myTowersFolder = Instance.new("Folder")
myTowersFolder.Parent = game.Workspace
local placeFunction = function(tower, x, z, below, y) --The place function
	if below ~= nil then
		local firstPos = (((Vector3.new(0, below.Position.Y+(below.Size.Y/2), 0))+(Vector3.new(x, 0, z))+Vector3.new(0, tower.Size.Y/2, 0)))
		tower.Position = (firstPos - Vector3.new(0, firstPos.Y, 0))+(Vector3.new(0, tower.Size.Y/2, 0))
	else
		local firstPos = (((Vector3.new(0, y+(game.Workspace.Baseplate.Size.Y/2), 0))+(Vector3.new(x, 0, z))+Vector3.new(0, tower.Size.Y/2, 0)))
		tower.Position = (firstPos - Vector3.new(0, firstPos.Y, 0))+(Vector3.new(0, tower.Size.Y/2, 0))
	end
end
remotes.startPlacing.OnServerEvent:Connect(function(plr, tower)
	myTowersFolder.Name = plr.Name .. "'s Towers"
	print("Received from server!")
	toPlace = tower:Clone()
	toPlace.CanCollide = false
	toPlace.Transparency = 0.5
	toPlace.BrickColor = BrickColor.new("Really red")
	toPlace.Parent = myTowersFolder
	for i, player in ipairs(game.Players:GetPlayers()) do
		if player == plr then continue end
		remotes.SetTransparencyToOtherClients:FireClient(player, 1, toPlace)
	end
	toPlace.Name = "Turret"
	remotes.SendTower:FireClient(plr, toPlace)
	remotes.RotateOnServer.OnServerEvent:Connect(function(plr)
		if not rotationDebounce then
			rotationDebounce = true
			local tween = tweenService:Create(toPlace, tweenInfo, {Orientation = toPlace.Orientation + Vector3.new(0, 90, 0)})
			tween:Play()
			tween.Completed:Wait()
			rotationDebounce = false
		end
	end)
	remotes.isPlacingEvent.OnServerEvent:Connect(function(plr, x, z, y)
		local raycastParams = RaycastParams.new()
		raycastParams.FilterDescendantsInstances = {toPlace}
		raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
		raycastParams.IgnoreWater = true
		local rayCast = game.Workspace:Raycast((Vector3.new(x, 0, z)*1.25)+Vector3.new(0, tower.Size.Y/2, 0), Vector3.new(0, -15, 0), raycastParams)
		local raycastResult
		if rayCast == nil or rayCast.Instance ~= game.Workspace.Baseplate then
			toPlace.UsePartColor = true
			print("You are not allowed to place here")
			ableToPlace = false
			remotes.SendPlacementStatus:FireClient(plr, ableToPlace)
		else
			toPlace.UsePartColor = false
			raycastResult = rayCast.Instance
			ableToPlace = true
			remotes.SendPlacementStatus:FireClient(plr, ableToPlace)
		end
		placeFunction(toPlace, x, z, raycastResult, y)
	end)
end)
remotes.place.OnServerEvent:Connect(function(plr)
	if ableToPlace then
		toPlace.CanCollide = true
		toPlace.Transparency = 0
	else
		print("Cannot place!!!")
	end
end)

Please ignore the fact that I’m using lots of remote events. Also please tell my if I’m doing anything wrong with the raycast, I’m a bit new to it :slight_smile:

1 Like

It doesn’t print “You are not allowed to place here” anywhere, so that’s a bit confusing?

Oh, right. I changed it to print that instead of out of bounds. :laughing:
There, just edited the post.

1 Like

I see! What I’d do to debug is to print rayCast and rayCast.Instance, to see if it’s actually hitting the baseplate like you expect it to.

Although I think I see the problem, actually:

local rayCast = game.Workspace:Raycast(
    (Vector3.new(x, 0, z)*1.25) + Vector3.new(0, tower.Size.Y/2, 0), 
    Vector3.new(0, -15, 0), 
    raycastParams
)

I’m guessing x, y and z are the coordinates where the player is trying to place the building? Well, multiplying the horizontal component (x and z) of the position by 1.25 is the same as making it 1.25 times further from the world origin (0, 0, 0) point.

This can be illustrated by representing points as vectors from the origin to the point:

The smaller red point = the larger red point multiplied by 1.25.

I’m guessing what’s happening near the edge of the baseplate is that the “placement point” gets moved further away from the center by this scaling, causing it to be beyond the edge and ultimately causing the raycast check to fail. You might not have noticed if you only tested near the center of the baseplate, because the closer to the center the less difference the * 1.25 makes.

1 Like

Yay! It works! Now I’ll have to do a bit of modification because I need to somehow add player’s character to mouse.TargetFilter…
EDIT: I think I found a solution to that… I’mma try adding all parts of the character to the FilterDescendantsInstances of the raycast parameters
EDIT 2: GG BOIS MY SOLUTION WORKED

1 Like

mouse.TargetFilter has the limitation that it can only be set to a single thing, i.e. not both the character and the thing that’s getting placed. If you run into that, you’ll want to create your own custom way of doing mouse.Hit and TargetFilter. Just raycast from mouse.UnitRay.Origin towards mouse.UnitRay.Direction * 5000, that way you can set raycastParams.FilterDescendantsInstances to a table containing as many things as you want.

1 Like