Need a bit of code

I’m working on some code that allows players to create some kind of ‘track’. There is one thing though I am unable to make with my skills, but I know that there are people on this forum who can probably do it in like 30 minutes.

Here’s what I want:
When I click, I want a part to appear at mouse.Hit. When I click again, I want a second part to appear, also at mouse.Hit. The two parts will now face each other:

External Media

Now comes the hard part I am unable to make. When I click to place the 3rd part at mouse.Hit, the first and second part do not change rotation, but instead a 4th part (part A) is made which is connected perfectly to the edge of the 2nd part and rotated in a way that it perfectly faces part 3.

External Media

Every step from now on will act the same as the last step. After clicking to place a new part, another part is created which is connected perfectly to the corner of the previous part so the two newly created parts face each other.

External Media

A few notes:

  • All parts are placed at the exact same height, so for each part, only the rotation in the Y-axis shouldn’t equal 0.
  • I have already made a small start with the code found below. It can only place the first and second part though. The variables PartWidth and PartLength (size in X-axis and Z-axis) in the code should still work when changed.
  • The code below is a LocalScript found in the StarterGui.

Reward:
1.4k Robux after tax (= 3,5 dollars) (so make a shirt that costs 2k robux)

I think this is enough money for something I believe can be done in like 30 minutes. If you’re up for this, please respond to this topic with the code and a link to the T-shirt I have to buy.

My thanks in advance.

My attempt:

local mouse = script.Parent.Parent:GetMouse()

local PartWidth = 12
local PartLength = 2
local AtY = 10
local TimesClicked = 0

function CreatePart()
	local P = Instance.new("Part")
	P.FormFactor = "Custom"
	P.BrickColor = BrickColor.new("Bright red")
	P.Anchored = true
	P.Size = Vector3.new(PartWidth, 1, PartLength)
	return P
end

local AllParts = {}

mouse.Button1Down:connect(
	function()
		if mouse.Target then
			TimesClicked = TimesClicked+1
			local B = CreatePart()
			if TimesClicked == 1 then
				AllParts[#AllParts+1] = B
				B.CFrame = CFrame.new(mouse.Hit.X, AtY, mouse.Hit.Z)
				B.Parent = game.Workspace
			elseif TimesClicked == 2 then
				AllParts[#AllParts+1] = B
				B.CFrame = CFrame.new(mouse.Hit.X, AtY, mouse.Hit.Z)
				B.Parent = game.Workspace
				AllParts[1].CFrame = CFrame.new(AllParts[1].Position, AllParts[2].Position)
				AllParts[2].CFrame = CFrame.new(AllParts[2].Position, AllParts[1].Position)
			elseif TimesClicked >= 3 then
				-- the thing I can't do
			end
		end
	end
)

Assuming the Y axis is negligible then you can solve it by doing this.
First you need to solve which side of part2 that part3 exists on, we can use the relative CFrame to solve this.

local side = part2.CFrame:toObjectSpace(part3.CFrame).Z --Might be X, can't recall off the top of my head.
if side < 0 then
-- Part3 is Left of Part2
elseif side > 0 then
-- Part3 is Right of Part2
else
-- Part3 is directly in line with Part2
end

Once you know this, you know which corner that Part4 will be placed on and can then solve the rotation of Part3 such that it’s side is in line with the corner of Part2.

Once you’ve worked out the rotation you need to work out the distance between the corner of Part2 and the center of the side of Part3.

local a = (part2.CFrame * CFrame.new(part2.Size.X/2, 0, part2.Size.Z/2)).p -- Make sure this is the correct corner (it will depend on the left/right corner)
local b = (part3.CFrame * CFrame.new(part3.Size.X/2, 0, 0)).p -- Same again
local distance = (a-b).magnitude

Using the solved distance you can then position Part4 based on Part3’s CFrame.

You’ll also want to subtract half the parts size.

part4.CFrame = part3.CFrame * CFrame.new(0, 0, distance-part4.Size.Z/2)

Used woot’s advice and gave it a shot, but I ran into a problem. I can’t seem to get the rotation right. Here’s my current code:

local mouse = script.Parent.Parent:GetMouse()

local PartWidth = 12
local PartLength = 2
local AtY = 10
local TimesClicked = 0

function CreatePart()
	local P = Instance.new("Part")
	P.FormFactor = "Custom"
	P.BrickColor = BrickColor.new("Bright red")
	P.Anchored = true
	P.Size = Vector3.new(PartWidth, 1, PartLength)
	return P
end

local AllParts = {}

mouse.Button1Down:connect(
	function()
		if mouse.Target then
			TimesClicked = TimesClicked+1
			local B = CreatePart()
			AllParts[#AllParts+1] = B
			if TimesClicked == 1 then
				B.CFrame = CFrame.new(mouse.Hit.X, AtY, mouse.Hit.Z)
				B.Parent = game.Workspace
			elseif TimesClicked == 2 then
				B.CFrame = CFrame.new(mouse.Hit.X, AtY, mouse.Hit.Z)
				B.Parent = game.Workspace
				AllParts[1].CFrame = CFrame.new(AllParts[1].Position, AllParts[2].Position)
				AllParts[2].CFrame = CFrame.new(AllParts[2].Position, AllParts[1].Position)*CFrame.Angles(0, math.pi, 0)
			elseif TimesClicked >= 3 then
				B.CFrame = CFrame.new(mouse.Hit.X, AtY, mouse.Hit.Z)
				local Dif = AllParts[#AllParts-1].CFrame:toObjectSpace(B.CFrame)
				--print(Dif.X)
				local Cor = CFrame.new()
				local N = 0
				if Dif.X < 0 then
					--left side
					Cor = AllParts[#AllParts-1].CFrame*CFrame.new(-PartWidth/2, 0, -PartLength/2)
					N = 1
				else
					--right side
					Cor = AllParts[#AllParts-1].CFrame*CFrame.new(PartWidth/2, 0, -PartLength/2)
					N = -1
				end
				local Block = CreatePart()
				Block.Size = Vector3.new(1, 3, 1)
				Block.CFrame = CFrame.new(Cor.X, Cor.Y, Cor.Z)*(Cor-Cor.p)
				Block.BrickColor = BrickColor.new("Bright green")
				Block.Parent = game.workspace
				local B2 = B:clone()
				
				local OV = PartWidth/2 -- opposite edge
				local SC = (B.Position-Cor.p).magnitude -- diagonal edge
				local Angle = math.asin(OV/SC)*N
				print("OV: ", math.floor(OV*100)/100, ", SC: ", math.floor(SC*100)/100, "Angle (deg): ", math.deg(Angle))
				
				B.CFrame = B.CFrame*CFrame.Angles(0, Angle, 0)
				B.Parent = game.workspace
				B2.CFrame = CFrame.new(Cor.X, Cor.Y, Cor.Z)*(Cor-Cor.p)*CFrame.Angles(0, Angle, 0)*CFrame.new(N*PartWidth/2, 0, -B.Size.Z/2)
				B2.Parent = game.workspace
			end
		end
	end
)

[strike]I’m still willing to pay if someone is able to get this to work.[/strike]
Edit:
Managed to get it to work. I made a somewhat silly mistake. Here’s the code that does work:

local mouse = script.Parent.Parent:GetMouse()

local PartWidth = 12
local PartLength = 2
local AtY = 10
local TimesClicked = 0

function CreatePart()
	local P = Instance.new("Part")
	P.FormFactor = "Custom"
	P.BrickColor = BrickColor.new("Bright red")
	P.Anchored = true
	P.Size = Vector3.new(PartWidth, 1, PartLength)
	return P
end

local AllParts = {}

mouse.Button1Down:connect(
	function()
		if mouse.Target then
			TimesClicked = TimesClicked+1
			local B = CreatePart()
			AllParts[#AllParts+1] = B
			if TimesClicked == 1 then
				B.CFrame = CFrame.new(mouse.Hit.X, AtY, mouse.Hit.Z)
				B.Parent = game.Workspace
			elseif TimesClicked == 2 then
				B.CFrame = CFrame.new(mouse.Hit.X, AtY, mouse.Hit.Z)
				B.Parent = game.Workspace
				AllParts[1].CFrame = CFrame.new(AllParts[1].Position, AllParts[2].Position)
				AllParts[2].CFrame = CFrame.new(AllParts[2].Position, AllParts[1].Position)*CFrame.Angles(0, math.pi, 0)
			elseif TimesClicked >= 3 then
				B.CFrame = CFrame.new(mouse.Hit.X, AtY, mouse.Hit.Z)
				local Dif = AllParts[#AllParts-1].CFrame:toObjectSpace(B.CFrame)
				--print(Dif.X)
				local Cor = CFrame.new()
				local N = 0
				if Dif.X < 0 then
					--left side
					Cor = AllParts[#AllParts-1].CFrame*CFrame.new(-PartWidth/2, 0, -PartLength/2)
					N = 1
				else
					--right side
					Cor = AllParts[#AllParts-1].CFrame*CFrame.new(PartWidth/2, 0, -PartLength/2)
					N = -1
				end
				local Block = CreatePart()
				Block.Size = Vector3.new(1, 3, 1)
				Block.CFrame = CFrame.new(Cor.X, Cor.Y, Cor.Z)*(Cor-Cor.p)
				Block.BrickColor = BrickColor.new("Bright green")
				Block.Parent = game.workspace
				local B2 = B:clone()
				
				local OV = PartWidth/2 -- opposite edge
				local SC = (B.Position-Cor.p).magnitude -- diagonal edge
				local Angle = math.asin(OV/SC)*N
				print("OV: ", math.floor(OV*100)/100, ", SC: ", math.floor(SC*100)/100, "Angle (deg): ", math.deg(Angle))
				
				B2.CFrame = CFrame.new(Cor.X, Cor.Y, Cor.Z)*(Cor-Cor.p)
				B2.CFrame = CFrame.new(B2.Position, B.Position)*CFrame.Angles(0, Angle, 0)*CFrame.new(N*PartWidth/2, 0, -B.Size.Z/2)
				B2.Parent = game.workspace
				B.CFrame = CFrame.new(B.Position, B2.Position)*CFrame.Angles(0, math.pi, 0)--B.CFrame*CFrame.Angles(0, Angle, 0)
				B.Parent = game.workspace
			end
		end
	end
)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.