Multiplying script.Parent.CFrame with location gives you a CFrame that represents location relative to script.Parent.CFrame.
This location is computed like so:
Vector3.new(ran:NextNumber(-halfSize.X, halfSize.X), script.Parent.CFrame.Y, ran:NextNumber(-halfSize.Z, halfSize.Z))
The Y component is the Y position of script.Parent.CFrame.Y. So if we look at the Y component of the CFrame you compute, we get “(script.Parent.CFrame.Y) studs above script.Parent.CFrame.Y”. In other words, the Y position + the Y position, or 2 * Y.
This explains the behavior you see. It’s fine when it’s on the ground, because 2 * a small number isn’t that far from the small number (21=2), a difference of 1, while 2 * a large number is a much bigger difference, e.g. (250 =100), a difference of 50. Much easier to notice.
The fix is this:
local objPos = Vector3.new(ran:NextNumber(-halfSize.X, halfSize.X), 0, ran:NextNumber(-halfSize.Z, halfSize.Z))