I am currently building a model of the gates of Arendelle Castle (http://i58.servimg.com/u/f58/18/36/77/95/arende10.jpg), however I have run into a snag with getting them to open and close. A friend of mine provided me with a script she got from somewhere else, however it works imperfectly (http://i58.servimg.com/u/f58/18/36/77/95/arende11.jpg). As can be seen in that image, the gates do not open smoothly.
Here's the code:
local MoveBy = .1
local waittime = 0--wait()
local Rep = 40 --Take the studs it needs to move by, and multiply by the Variable MoveBy to get the movement.
local MoveBy2 = math.rad(1)
local waittime2 = 0--wait()
local NotMoveBy = math.rad(0)
local OldType = 3
local Debounce = false
local Open = false
--I'd like to say that Anaminus made this, but since it's a tool, I can use it?
function RotateModel(model,center,axes,inc,step)
local origin = {}
for _,child in pairs(model:GetChildren()) do
if child:IsA"BasePart" then
origin[child] = center:toObjectSpace(child.CFrame)
end
end
for i = 1,inc or 1 do
center = center * CFrame.fromEulerAnglesXYZ(unpack(axes))
for part,cf in pairs(origin) do
part.CFrame = center:toWorldSpace(cf)
end
if step then wait(step) end
end
end
function OpenDoors(type) --type 1 = slide, type 2 = turn. type 3 = turn backwards
if type == 1 then
delay(0, function() --opens right
for i=1, Rep, 1 do
for a, b in pairs(script.Parent.Right:getChildren()) do
if b:isA("BasePart") then
b.CFrame = b.CFrame + Vector3.new(0, 0, -MoveBy)
end
end
wait(waittime)
end
end)
for i=1, Rep, 1 do --Opens left
for a, b in pairs(script.Parent.Left:getChildren()) do
if b:isA("BasePart") then
b.CFrame = b.CFrame + Vector3.new(0, 0, MoveBy)
end
end
wait(waittime)
end
elseif type == 2 then
delay(0, function() RotateModel(script.Parent.Right, script.Parent.Right.Hinge.CFrame, {NotMoveBy,NotMoveBy, MoveBy2}, 90, waittime2) end)
RotateModel(script.Parent.Left, script.Parent.Left.Hinge.CFrame, {NotMoveBy,NotMoveBy, -MoveBy2}, 90, waittime2)
elseif type == 3 then
delay(0, function() RotateModel(script.Parent.Right, script.Parent.Right.Hinge.CFrame, {NotMoveBy,NotMoveBy, -MoveBy2}, 90, waittime2) end)
RotateModel(script.Parent.Left, script.Parent.Left.Hinge.CFrame, {NotMoveBy,NotMoveBy, MoveBy2}, 90, waittime2)
end
end
function CloseDoors(type) --type 1 = slide, type 2 = turn. type 3 = turn backwards
if type == 1 then
delay(0, function() --opens right
for i=1, Rep, 1 do
for a, b in pairs(script.Parent.Right:getChildren()) do
if b:isA("BasePart") then
b.CFrame = b.CFrame + Vector3.new(0, 0, MoveBy)
end
end
wait(waittime)
end
end)
for i=1, Rep, 1 do --Opens left
for a, b in pairs(script.Parent.Left:getChildren()) do
if b:isA("BasePart") then
b.CFrame = b.CFrame + Vector3.new(0, 0, -MoveBy)
end
end
wait(waittime)
end
elseif type == 2 then
delay(0, function() RotateModel(script.Parent.Right, script.Parent.Right.Hinge.CFrame, {NotMoveBy,NotMoveBy, -MoveBy2}, 90, waittime2) end)
RotateModel(script.Parent.Left, script.Parent.Left.Hinge.CFrame, {NotMoveBy,NotMoveBy, MoveBy2}, 90, waittime2)
elseif type == 3 then
delay(0, function() RotateModel(script.Parent.Right, script.Parent.Right.Hinge.CFrame, {NotMoveBy,NotMoveBy, MoveBy2}, 90, waittime2) end)
RotateModel(script.Parent.Left, script.Parent.Left.Hinge.CFrame, {NotMoveBy,NotMoveBy, -MoveBy2}, 90, waittime2)
end
end
function OnActivation()
if not debounce then
debounce = true
if Open then
CloseDoors(OldType)
Open = false
else
if script.Parent.Open.Type.Value >= 1 and script.Parent.Open.Type.Value <= 3 then
OpenDoors(math.floor(script.Parent.Open.Type.Value))
OldType = math.floor(script.Parent.Open.Type.Value)
Open = true
else
print("Type invalid")
end
end
script.Parent.Open.Value = false
wait()
debounce = false
else
print("Already Opening or closing a door")
end
end
for a, b in pairs(script.Parent:GetChildren()) do
if b and b:IsA("BasePart") and b.Name == "Sensor" then
b.Touched:connect(function(p)
if p and p.Parent and p.Parent:FindFirstChild("Humanoid") then
OnActivation()
end
end)
end
end
for a, b in pairs(script.Parent.Left:GetChildren()) do
if b and b.Name == "ClickSensor" and b:FindFirstChild("ClickDetector") then
b.ClickDetector.MouseClick:connect(function(p)
OnActivation()
end)
end
end
for a, b in pairs(script.Parent.Right:GetChildren()) do
if b and b.Name == "ClickSensor" and b:FindFirstChild("ClickDetector") then
b.ClickDetector.MouseClick:connect(function(p)
OnActivation()
end)
end
end
script.Parent.Open.Changed:connect(function(Value) OnActivation() end)
I suspect the problem lies within the RotateModel function. Each half of the gate has 80 pieces, and this function calculates the position for each part each time the gate's position is updated. It looks fine in Studio's Play Solo mode, but not in the actual game. What I want to know is this: Is it possible to make this script more efficient, and if not, what would be a better alternative to calculating CFrames? I've tried using a BodyGyro, but that rotated the gate about its center instead of the hinge piece.
Any help you can give me would be appreciated. If you want to see the problem in person, you can go to this game: http://www.roblox.com/Kingdom-of-Arendelle-place?id=155458964 The gate in question is the one with grey bricks and wood columns at the far end of the bridge.
