null
nil
-
true
true
0
0
0
1
0
0
0
1
0
0
0
1
Clone Tool
http://www.roblox.com/asset/?id=73241863
Clone
-
false
-0.5
0.5
0
0
-0.5
0.5
4
0
194
0
0.600000024
0
1
0
0
0
1
0
0
0
1
true
0.5
0.300000012
-0.5
0.5
0
0
-0.5
0.5
0
0
false
256
Handle
0
-0.5
0.5
0
0
0
0
0
-0.5
0.5
3
0
1
0
0
0
1
1
4
1.20000005
2
-
false
CloneScript
-- basic functions
function waitForChild(instance, name)
while not instance:findFirstChild(name) do
instance.ChildAdded:wait()
end
end
function waitForProperty(instance, name)
while not instance[name] do
instance.Changed:wait()
end
end
function getPlayer()
waitForProperty(game.Players,"LocalPlayer")
return game.Players.LocalPlayer
end
-- locals
local RbxStamper = LoadLibrary("RbxStamper")
if not RbxStamper then
print("Error: RbxStamper Library Load Fail! Returning")
return nil
end
local Tool = script.Parent
local stampControl = nil
local stampingCon = nil
local eyeDropperConnection = nil
local eyeDropperMoveConnection = nil
local keyCon = nil
local eyedropperOffGridTolerance = 0.01
local selectionBox = nil
local currentSelection = nil
local Mouse = nil
local currentSelectionColors = {}
local terrainSelectionBox = Instance.new("Part")
terrainSelectionBox.Parent = nil
terrainSelectionBox.formFactor = "Custom"
terrainSelectionBox.Size = Vector3.new(4, 4, 4)
terrainSelectionBox.Archivable = false
terrainSelectionBox.CFrame = CFrame.new()
local selectionBox = Instance.new("SelectionBox")
selectionBox.Name = "CloneSelection"
selectionBox.Color = BrickColor.Green()
selectionBox.Adornee = nil
selectionBox.Archivable = false
waitForChild(script.Parent,"CloneHintGui")
waitForChild(script.Parent.CloneHintGui,"CloneHint")
local hintGui = script.Parent.CloneHintGui
local shortcutHint = script.Parent.CloneHintGui.CloneHint
waitForProperty(game,"PlaceId")
local isRestricted = (game.PlaceId == 41324860 or game.PlaceId == 129686177)
local showBaseplateScript = nil
local hideBaseplateScript = nil
if isRestricted then
waitForChild(getPlayer(), "PlayerGui")
waitForChild(getPlayer().PlayerGui, "Waypoint")
waitForChild(getPlayer().PlayerGui, "showBaseplateWaypoint")
waitForChild(getPlayer().PlayerGui, "hideBaseplateWaypoint")
showBaseplateScript = getPlayer().PlayerGui.showBaseplateWaypoint
hideBaseplateScript = getPlayer().PlayerGui.hideBaseplateWaypoint
end
local modelToStampIn, stampRegion = nil
-- functions
function findModel(part)
if isRestricted then
while part ~= nil do
if part.className == "Model" and part.Name ~= modelToStampIn.Name and part.Name ~= "GarbageParts" then
return part
elseif part.Name == modelToStampIn.Name or part.Name == "GarbageParts" then
return nil
end
part = part.Parent
end
return nil
else
while part ~= game.Workspace do
if part:FindFirstChild("RobloxModel") then
return part
end
part = part.Parent
end
return nil
end
end
function getClosestColorToTerrainMaterial(terrainValue)
if terrainValue == 1 then
return BrickColor.new("Bright green")
elseif terrainValue == 2 then
return BrickColor.new("Bright yellow")
elseif terrainValue == 3 then
return BrickColor.new("Bright red")
elseif terrainValue == 4 then
return BrickColor.new("Sand red")
elseif terrainValue == 5 then
return BrickColor.new("Black")
elseif terrainValue == 6 then
return BrickColor.new("Dark stone grey")
elseif terrainValue == 7 then
return BrickColor.new("Sand blue")
elseif terrainValue == 8 then
return BrickColor.new("Deep orange")
elseif terrainValue == 9 then
return BrickColor.new("Dark orange")
elseif terrainValue == 10 then
return BrickColor.new("Reddish brown")
elseif terrainValue == 11 then
return BrickColor.new("Light orange")
elseif terrainValue == 12 then
return BrickColor.new("Light stone grey")
elseif terrainValue == 13 then
return BrickColor.new("Sand green")
elseif terrainValue == 14 then
return BrickColor.new("Medium stone grey")
elseif terrainValue == 15 then
return BrickColor.new("Really red")
elseif terrainValue == 16 then
return BrickColor.new("Really blue")
elseif terrainValue == 17 then
return BrickColor.new("Bright blue")
else
return BrickColor.new("Bright green")
end
end
function setTerrainSelection(point)
if selectionBox then
local cell = game.Workspace.Terrain:WorldToCellPreferSolid(point)
local cellCenter = game.Workspace.Terrain:CellCenterToWorld(cell.X, cell.Y, cell.Z)
terrainSelectionBox.CFrame = CFrame.new(cellCenter)
selectionBox.Adornee = terrainSelectionBox
currentSelection = game.Workspace.Terrain
end
end
function setSelection(partOrModel)
if partOrModel ~= currentSelection then
clearSelection()
currentSelection = partOrModel
selectionBox.Adornee = currentSelection
end
end
function clearSelection()
if currentSelection ~= nil then
for part, color in pairs(currentSelectionColors) do
part.BrickColor = color
end
selectionBox.Adornee = nil
end
currentSelectionColors = {}
if currentSelection then currentSelection = nil end
if selectionBox then selectionBox.Adornee = nil end
end
function canEyeDropperObject(part)
local stamperTag = part.Parent:FindFirstChild("RobloxStamper")
if stamperTag == nil then stamperTag = part:FindFirstChild("RobloxStamper") end
if isRestricted then
if not inRegion(part) then return false end
end
return part and not (part.Locked) and part:IsA("BasePart") and stamperTag ~= nil
end
function inRegion(partOrModel)
if not stampRegion then return true end
if not partOrModel then return true end
return RbxStamper.CanEditRegion(partOrModel, stampRegion)
end
function isOnGrid(partOrModel)
-- first check to see if off-grid, and if so, prevent eyedropperage
local modelExtentsInWorldCoords
if partOrModel:IsA("Model") then
modelExtentsInWorldCoords = partOrModel:GetModelCFrame():vectorToWorldSpace(partOrModel:GetModelSize())
else
modelExtentsInWorldCoords = partOrModel.CFrame:vectorToWorldSpace(partOrModel.Size)
end
-- we now simply check to see if the above property fits in a 4x4x4 gridspace
offX = math.fmod(math.abs(modelExtentsInWorldCoords.X), 4)
offY = math.fmod(math.abs(modelExtentsInWorldCoords.Y), 4)
offZ = math.fmod(math.abs(modelExtentsInWorldCoords.Z), 4)
local numberOfAxesOffGrid = 0
if math.min(offX, 4 - offX) > eyedropperOffGridTolerance then numberOfAxesOffGrid = numberOfAxesOffGrid + 1 end
if math.min(offY, 4 - offY) > eyedropperOffGridTolerance then numberOfAxesOffGrid = numberOfAxesOffGrid + 1 end
if math.min(offZ, 4 - offZ) > eyedropperOffGridTolerance then numberOfAxesOffGrid = numberOfAxesOffGrid + 1 end
if numberOfAxesOffGrid > 1 then return false -- we allow one axis to be not fit to grid, since any rotation must necessarily affect >= 2 axes (some of the models are like 4x4x6 :( ).
else return true end
end
function setupFakeTerrainPart(cellMat, cellType, cellOrient, isWater, waterForce,waterDirection)
local newTerrainPiece = nil
if (cellType == 1 or cellType == 4) then
newTerrainPiece = Instance.new("WedgePart")
newTerrainPiece.formFactor = "Custom"
elseif (cellType == 2) then
newTerrainPiece = Instance.new("CornerWedgePart")
else
newTerrainPiece = Instance.new("Part")
newTerrainPiece.formFactor = "Custom"
end
newTerrainPiece.Name = "MegaClusterCube"
newTerrainPiece.Size = Vector3.new(4, 4, 4)
newTerrainPiece.BottomSurface = "Smooth"
newTerrainPiece.TopSurface = "Smooth"
-- can add decals or textures here if feeling particularly adventurous... for now, can make a table of look-up colors
newTerrainPiece.BrickColor = getClosestColorToTerrainMaterial(cellMat)
local sideways = 0
local flipped = math.pi
if cellType == 4 then sideways = -math.pi/2 end
if cellType == 2 or cellType == 3 then flipped = 0 end
newTerrainPiece.CFrame = CFrame.Angles(0, math.pi/2 * cellOrient + flipped, sideways)
if cellType == 3 then
local inverseCornerWedgeMesh = Instance.new("SpecialMesh")
inverseCornerWedgeMesh.MeshType = "FileMesh"
inverseCornerWedgeMesh.MeshId = "http://www.roblox.com/asset?id=66832495"
inverseCornerWedgeMesh.Scale = Vector3.new(2, 2, 2)
inverseCornerWedgeMesh.Parent = newTerrainPiece
end
local materialTag = Instance.new("Vector3Value")
materialTag.Value = Vector3.new(cellMat, cellType, cellOrient)
materialTag.Name = "ClusterMaterial"
materialTag.Parent = newTerrainPiece
if isWater then
local waterForceTag = Instance.new("StringValue",newTerrainPiece)
waterForceTag.Name = "WaterForceTag"
waterForceTag.Value = string.sub(tostring(waterForce),17)
local waterForceDirectionTag = Instance.new("StringValue",newTerrainPiece)
waterForceDirectionTag.Name = "WaterForceDirectionTag"
waterForceDirectionTag.Value = string.sub(tostring(waterDirection),21)
end
return newTerrainPiece
end
function hint(phrase, timeLength)
waitForChild(game.Players.LocalPlayer.PlayerGui,"topHint")
waitForChild(game.Players.LocalPlayer.PlayerGui.topHint, "Add")
waitForChild(game.Players.LocalPlayer.PlayerGui.topHint.Add, "Label")
waitForChild(game.Players.LocalPlayer.PlayerGui.topHint.Add, "Time")
game.Players.LocalPlayer.PlayerGui.topHint.Add.Label.Value = tostring(phrase)
game.Players.LocalPlayer.PlayerGui.topHint.Add.Time.Value = tonumber(timeLength)
game.Players.LocalPlayer.PlayerGui.topHint.Add.Disabled = false
end
function showBaseplateWaypoint()
if modelToStampIn and showBaseplateScript then
local target = showBaseplateScript:FindFirstChild("target")
if target then
delay(0,function()
target.Value = modelToStampIn.Parent:FindFirstChild("RegionBounds")
showBaseplateScript.Disabled = false
showBaseplateScript.Disabled = true
wait(8)
hideBaseplateScript.Disabled = false
hideBaseplateScript.Disabled = true
end)
end
end
end
function stampAttemptFailed()
hint("You can only stamp in your baseplate", 5)
showBaseplateWaypoint()
end
function hasPoints()
waitForChild(game.Players.LocalPlayer, "MaxPoints")
local maxPoints = game.Players.LocalPlayer.MaxPoints
waitForChild(game.Players.LocalPlayer, "PointsUsed")
local pointsUsed = game.Players.LocalPlayer.PointsUsed
return ( (pointsUsed.Value/maxPoints.Value) < 1 )
end
function setupStamper(stampModel)
if stampControl then stampControl.Destroy() end
if stampingCon then
stampingCon:disconnect()
stampingCon = nil
end
if isRestricted then
if not hasPoints() then
hint("Too many parts stamped, delete some to stamp more", 5)
return
else
stampControl = RbxStamper.SetupStamperDragger(stampModel, Mouse, modelToStampIn, stampRegion, stampAttemptFailed)
end
else
stampControl = RbxStamper.SetupStamperDragger(stampModel, Mouse)
end
if stampControl then
stampingCon = stampControl.Stamped.Changed:connect(function()
if stampControl and stampControl.Stamped.Value then
if isRestricted and not hasPoints() then
hint("Too many parts stamped, delete some to stamp more", 5)
if stampCon then stampCon:disconnect() end
stampControl.Destroy()
else
stampControl.ReloadModel()
end
end
end)
shortcutHint.Visible = true
end
end
function onEyeDropperMouseButton1Down()
clearSelection()
if Mouse then
Mouse.Icon = "http://www.roblox.com/asset?id=66887745"
end
-- deny any attempt to clone something that wasn't stamped using the Stamper tool
if not Mouse or not Mouse.Target then
startEyeDropperOperation()
return
end
local cloneInstance = nil
local isTerrainEyedroppering = false
if Mouse.Target == game.Workspace.Terrain and not isRestricted then -- want to eyedropper a terrain piece; do a little extra footwork
-- make the fake part here
local hitCell = game.Workspace.Terrain:WorldToCellPreferSolid(Mouse.Hit.p)
local cellMat, cellType, cellOrient = game.Workspace.Terrain:GetCell(hitCell.x, hitCell.y, hitCell.z)
local hasAnyWater, waterForce, waterDirection = game.Workspace.Terrain:GetWaterCell(hitCell.x, hitCell.y, hitCell.z)
cloneInstance = setupFakeTerrainPart(cellMat.Value, cellType.Value, cellOrient.Value, hasAnyWater, waterForce, waterDirection)
isTerrainEyedroppering = true
end
local stamperTag = Mouse.Target.Parent:FindFirstChild("RobloxStamper")
if stamperTag == nil then stamperTag = Mouse.Target:FindFirstChild("RobloxStamper") end
if stamperTag == nil and not isTerrainEyedroppering then
startEyeDropperOperation()
return
end
local eyeDropperInstance = nil
-- find out if the target part is part of a Roblox Set Model
local robloxModelTag = Mouse.Target.Parent:FindFirstChild("RobloxModel")
if robloxModelTag ~= nil then
eyeDropperInstance = Mouse.Target.Parent
else
eyeDropperInstance = Mouse.Target
end
-- do not allow certain objects to be captured with eye-dropper
-- for now, locked parts
if eyeDropperInstance:IsA("Part") and eyeDropperInstance.Locked and not isTerrainEyedroppering then
startEyeDropperOperation()
else
if not isTerrainEyedroppering then
cloneInstance = eyeDropperInstance:clone()
-- once more, we make sure it's on grid before eyedroppering
if not isOnGrid(cloneInstance) then
if cloneInstance:IsA("Model") then cloneInstance:ResetOrientationToIdentity()
else cloneInstance.CFrame = CFrame.new(cloneInstance.CFrame.p) end
end
cloneInstance:BreakJoints()
end
if eyeDropperConnection then
eyeDropperConnection:disconnect()
eyeDropperConnection = nil
end
if eyeDropperMoveConnection then
eyeDropperMoveConnection:disconnect()
eyeDropperMoveConnection = nil
end
setupStamper(cloneInstance)
end
end
function onEyeDropperMouseMove()
if not Mouse or not Mouse.Target then
clearSelection()
return
end
local part = Mouse.Target
if part:IsA("Terrain") and Mouse.Hit and not isRestricted then
selectionBox.Color = BrickColor.Green()
setTerrainSelection(Mouse.Hit.p)
elseif canEyeDropperObject(part) then
local model = findModel(part)
if model then
selectionBox.Color = BrickColor.Green()
setSelection(model)
else
selectionBox.Color = BrickColor.Green()
setSelection(part)
end
else
clearSelection()
end
end
function keyHandler(key)
key = key:lower()
if key == 'q' then
startEyeDropperOperation()
end
end
function startEyeDropperOperation()
if stampControl then stampControl.Destroy() end
if Mouse then
Mouse.Icon = "http://www.roblox.com/asset?id=67163166"
shortcutHint.Visible = false
if not eyeDropperMoveConnection then
eyeDropperConnection = Mouse.Button1Up:connect(onEyeDropperMouseButton1Down)
end
if not eyeDropperMoveConnection then
eyeDropperMoveConnection = Mouse.Move:connect(onEyeDropperMouseMove)
end
end
end
function onEquipped(mouse)
Mouse = mouse
if game:FindFirstChild("Players") then
if game.Players["LocalPlayer"] then
selectionBox.Parent = game.Players.LocalPlayer.PlayerGui
hintGui.Parent = game.Players.LocalPlayer.PlayerGui
end
end
keyCon = Mouse.KeyDown:connect(keyHandler)
startEyeDropperOperation()
end
function onUnequipped()
if stampControl then
stampControl.Destroy()
end
Mouse = nil
selectionBox.Parent = nil
if eyeDropperMoveConnection then
eyeDropperMoveConnection:disconnect()
eyeDropperMoveConnection = nil
end
if eyeDropperConnection then
eyeDropperConnection:disconnect()
eyeDropperConnection = nil
end
if keyCon then
keyCon:disconnect()
keyCon = nil
end
if hintGui then
hintGui.Parent = nil
end
end
------------------------------------------------------------------------------------------------
if isRestricted then -- setup our variables
waitForChild(game,"Workspace")
waitForChild(game.Workspace, "BuildingAreas")
waitForChild(game.Workspace.BuildingAreas, "Area1")
waitForChild(game.Workspace.BuildingAreas, "Area9") -- all areas loaded
while not modelToStampIn do -- check for build area until we find one
local buildAreas = game.Workspace.BuildingAreas:GetChildren()
for i = 1, #buildAreas do
if buildAreas[i]:IsA("Model") then
waitForChild(buildAreas[i],"Player")
if buildAreas[i].Player.Value == game.Players.LocalPlayer.Name then
waitForChild(buildAreas[i],"PlayerArea")
modelToStampIn = buildAreas[i].PlayerArea
break
end
end
end
if not modelToStampIn then
wait(0.5)
end
end
local lowPos = modelToStampIn.Parent:FindFirstChild("LowPos")
local highPos = modelToStampIn.Parent:FindFirstChild("HighPos")
if not lowPos or highPos then
wait(0.5)
lowPos = modelToStampIn.Parent:FindFirstChild("LowPos")
highPos = modelToStampIn.Parent:FindFirstChild("HighPos")
end
while lowPos.Value == Vector3.new(0,0,0) or highPos.Value == Vector3.new(0,0,0) do
wait(0.5)
end -- tool doesn't work until these are defined
stampRegion = Region3.new(lowPos.Value, highPos.Value) -- this is where we can stamp
end
Tool.Equipped:connect(onEquipped)
Tool.Unequipped:connect(onUnequipped)
-
CloneHintGui
-
false
4278190080
0.5
4279970357
1
false
false
2
5
CloneHint
0.5
-85
0
0
0
170
0
30
0
Press Q to Eyedropper
4294967295
false
4278190080
0
0
false
2
1
false
1