roblonium-web/Game/FinobeTools/PBSTools/CloneTool.rbxm

679 lines
24 KiB
Plaintext

<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="Tool" referent="RBX0">
<Properties>
<bool name="CanBeDropped">true</bool>
<bool name="Enabled">true</bool>
<CoordinateFrame name="Grip">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<string name="Name">Clone Tool</string>
<Content name="TextureId"><url>http://www.roblox.com/asset/?id=73241863</url></Content>
<string name="ToolTip">Clone</string>
</Properties>
<Item class="Part" referent="RBX1">
<Properties>
<bool name="Anchored">false</bool>
<float name="BackParamA">-0.5</float>
<float name="BackParamB">0.5</float>
<token name="BackSurface">0</token>
<token name="BackSurfaceInput">0</token>
<float name="BottomParamA">-0.5</float>
<float name="BottomParamB">0.5</float>
<token name="BottomSurface">4</token>
<token name="BottomSurfaceInput">0</token>
<int name="BrickColor">194</int>
<CoordinateFrame name="CFrame">
<X>0</X>
<Y>0.600000024</Y>
<Z>0</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<bool name="CanCollide">true</bool>
<float name="Elasticity">0.5</float>
<float name="Friction">0.300000012</float>
<float name="FrontParamA">-0.5</float>
<float name="FrontParamB">0.5</float>
<token name="FrontSurface">0</token>
<token name="FrontSurfaceInput">0</token>
<float name="LeftParamA">-0.5</float>
<float name="LeftParamB">0.5</float>
<token name="LeftSurface">0</token>
<token name="LeftSurfaceInput">0</token>
<bool name="Locked">false</bool>
<token name="Material">256</token>
<string name="Name">Handle</string>
<float name="Reflectance">0</float>
<float name="RightParamA">-0.5</float>
<float name="RightParamB">0.5</float>
<token name="RightSurface">0</token>
<token name="RightSurfaceInput">0</token>
<Vector3 name="RotVelocity">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<float name="TopParamA">-0.5</float>
<float name="TopParamB">0.5</float>
<token name="TopSurface">3</token>
<token name="TopSurfaceInput">0</token>
<float name="Transparency">1</float>
<Vector3 name="Velocity">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<token name="formFactorRaw">1</token>
<token name="shape">1</token>
<Vector3 name="size">
<X>4</X>
<Y>1.20000005</Y>
<Z>2</Z>
</Vector3>
</Properties>
</Item>
<Item class="LocalScript" referent="RBX2">
<Properties>
<bool name="Disabled">false</bool>
<Content name="LinkedSource"><null></null></Content>
<string name="Name">CloneScript</string>
<ProtectedString name="Source">-- basic functions
function waitForChild(instance, name)
&#9;while not instance:findFirstChild(name) do
&#9;&#9;instance.ChildAdded:wait()
&#9;end
end
function waitForProperty(instance, name)
&#9;while not instance[name] do
&#9;&#9;instance.Changed:wait()
&#9;end
end
function getPlayer()
&#9;waitForProperty(game.Players,&quot;LocalPlayer&quot;)
&#9;return game.Players.LocalPlayer
end
-- locals
local RbxStamper = LoadLibrary(&quot;RbxStamper&quot;)
if not RbxStamper then
&#9;print(&quot;Error: RbxStamper Library Load Fail! Returning&quot;)
&#9;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(&quot;Part&quot;)
terrainSelectionBox.Parent = nil
terrainSelectionBox.formFactor = &quot;Custom&quot;
terrainSelectionBox.Size = Vector3.new(4, 4, 4)
terrainSelectionBox.Archivable = false
terrainSelectionBox.CFrame = CFrame.new()
local selectionBox = Instance.new(&quot;SelectionBox&quot;)
selectionBox.Name = &quot;CloneSelection&quot;
selectionBox.Color = BrickColor.Green()
selectionBox.Adornee = nil
selectionBox.Archivable = false
waitForChild(script.Parent,&quot;CloneHintGui&quot;)
waitForChild(script.Parent.CloneHintGui,&quot;CloneHint&quot;)
local hintGui = script.Parent.CloneHintGui
local shortcutHint = script.Parent.CloneHintGui.CloneHint
waitForProperty(game,&quot;PlaceId&quot;)
local isRestricted = (game.PlaceId == 41324860 or game.PlaceId == 129686177)
local showBaseplateScript = nil
local hideBaseplateScript = nil
if isRestricted then
&#9;waitForChild(getPlayer(), &quot;PlayerGui&quot;)
&#9;waitForChild(getPlayer().PlayerGui, &quot;Waypoint&quot;)
&#9;waitForChild(getPlayer().PlayerGui, &quot;showBaseplateWaypoint&quot;)
&#9;waitForChild(getPlayer().PlayerGui, &quot;hideBaseplateWaypoint&quot;)
&#9;showBaseplateScript = getPlayer().PlayerGui.showBaseplateWaypoint
&#9;hideBaseplateScript = getPlayer().PlayerGui.hideBaseplateWaypoint
end
local modelToStampIn, stampRegion = nil
-- functions
function findModel(part)
&#9;if isRestricted then
&#9;&#9;while part ~= nil do
&#9;&#9;&#9;if part.className == &quot;Model&quot; and part.Name ~= modelToStampIn.Name and part.Name ~= &quot;GarbageParts&quot; then
&#9;&#9;&#9;&#9;return part
&#9;&#9;&#9;elseif part.Name == modelToStampIn.Name or part.Name == &quot;GarbageParts&quot; then
&#9;&#9;&#9;&#9;return nil
&#9;&#9;&#9;end
&#9;&#9;&#9;part = part.Parent
&#9;&#9;end
&#9;&#9;return nil
&#9;else
&#9;&#9;while part ~= game.Workspace do
&#9;&#9;&#9;if part:FindFirstChild(&quot;RobloxModel&quot;) then
&#9;&#9;&#9;&#9;return part
&#9;&#9;&#9;end
&#9;&#9;&#9;part = part.Parent
&#9;&#9;end
&#9;&#9;return nil
&#9;end
end
function getClosestColorToTerrainMaterial(terrainValue)
&#9;if terrainValue == 1 then
&#9;&#9;return BrickColor.new(&quot;Bright green&quot;)
&#9;elseif terrainValue == 2 then
&#9;&#9;return BrickColor.new(&quot;Bright yellow&quot;)
&#9;elseif terrainValue == 3 then
&#9;&#9;return BrickColor.new(&quot;Bright red&quot;)
&#9;elseif terrainValue == 4 then
&#9;&#9;return BrickColor.new(&quot;Sand red&quot;)
&#9;elseif terrainValue == 5 then
&#9;&#9;return BrickColor.new(&quot;Black&quot;)
&#9;elseif terrainValue == 6 then
&#9;&#9;return BrickColor.new(&quot;Dark stone grey&quot;)
&#9;elseif terrainValue == 7 then
&#9;&#9;return BrickColor.new(&quot;Sand blue&quot;)
&#9;elseif terrainValue == 8 then
&#9;&#9;return BrickColor.new(&quot;Deep orange&quot;)
&#9;elseif terrainValue == 9 then
&#9;&#9;return BrickColor.new(&quot;Dark orange&quot;)
&#9;elseif terrainValue == 10 then
&#9;&#9;return BrickColor.new(&quot;Reddish brown&quot;)
&#9;elseif terrainValue == 11 then
&#9;&#9;return BrickColor.new(&quot;Light orange&quot;)
&#9;elseif terrainValue == 12 then
&#9;&#9;return BrickColor.new(&quot;Light stone grey&quot;)
&#9;elseif terrainValue == 13 then
&#9;&#9;return BrickColor.new(&quot;Sand green&quot;)
&#9;elseif terrainValue == 14 then
&#9;&#9;return BrickColor.new(&quot;Medium stone grey&quot;)
&#9;elseif terrainValue == 15 then
&#9;&#9;return BrickColor.new(&quot;Really red&quot;)
&#9;elseif terrainValue == 16 then
&#9;&#9;return BrickColor.new(&quot;Really blue&quot;)
&#9;elseif terrainValue == 17 then
&#9;&#9;return BrickColor.new(&quot;Bright blue&quot;)
&#9;else
&#9;&#9;return BrickColor.new(&quot;Bright green&quot;)
&#9;end
end
function setTerrainSelection(point)
&#9;if selectionBox then
&#9;&#9;local cell = game.Workspace.Terrain:WorldToCellPreferSolid(point)
&#9;&#9;local cellCenter = game.Workspace.Terrain:CellCenterToWorld(cell.X, cell.Y, cell.Z)
&#9;&#9;terrainSelectionBox.CFrame = CFrame.new(cellCenter)
&#9;&#9;selectionBox.Adornee = terrainSelectionBox
&#9;&#9;currentSelection = game.Workspace.Terrain
&#9;end
end
&#9;
function setSelection(partOrModel)
&#9;if partOrModel ~= currentSelection then
&#9;&#9;clearSelection()
&#9;&#9;currentSelection = partOrModel
&#9;&#9;selectionBox.Adornee = currentSelection
&#9;end
end
function clearSelection()
&#9;if currentSelection ~= nil then
&#9;&#9;for part, color in pairs(currentSelectionColors) do
&#9;&#9;&#9;part.BrickColor = color
&#9;&#9;end
&#9;&#9;selectionBox.Adornee = nil
&#9;end
&#9;currentSelectionColors = {}
&#9;if currentSelection then currentSelection = nil end
&#9;if selectionBox then selectionBox.Adornee = nil end
end
function canEyeDropperObject(part)
&#9;local stamperTag = part.Parent:FindFirstChild(&quot;RobloxStamper&quot;)
&#9;if stamperTag == nil then stamperTag = part:FindFirstChild(&quot;RobloxStamper&quot;) end
&#9;if isRestricted then
&#9;&#9;if not inRegion(part) then return false end
&#9;end
&#9;return part and not (part.Locked) and part:IsA(&quot;BasePart&quot;) and stamperTag ~= nil
end
function inRegion(partOrModel)
&#9;if not stampRegion then return true end
&#9;if not partOrModel then return true end
&#9;return RbxStamper.CanEditRegion(partOrModel, stampRegion)
end
function isOnGrid(partOrModel)
&#9;-- first check to see if off-grid, and if so, prevent eyedropperage
&#9;&#9;local modelExtentsInWorldCoords
&#9;&#9;if partOrModel:IsA(&quot;Model&quot;) then
&#9;&#9;&#9;modelExtentsInWorldCoords = partOrModel:GetModelCFrame():vectorToWorldSpace(partOrModel:GetModelSize())
&#9;&#9;else
&#9;&#9;&#9;modelExtentsInWorldCoords = partOrModel.CFrame:vectorToWorldSpace(partOrModel.Size)
&#9;&#9;end
&#9;&#9;-- we now simply check to see if the above property fits in a 4x4x4 gridspace
&#9;&#9;offX = math.fmod(math.abs(modelExtentsInWorldCoords.X), 4)
&#9;&#9;offY = math.fmod(math.abs(modelExtentsInWorldCoords.Y), 4)
&#9;&#9;offZ = math.fmod(math.abs(modelExtentsInWorldCoords.Z), 4)
&#9;&#9;local numberOfAxesOffGrid = 0
&#9;&#9;if math.min(offX, 4 - offX) &gt; eyedropperOffGridTolerance then numberOfAxesOffGrid = numberOfAxesOffGrid + 1 end
&#9;&#9;if math.min(offY, 4 - offY) &gt; eyedropperOffGridTolerance then numberOfAxesOffGrid = numberOfAxesOffGrid + 1 end
&#9;&#9;if math.min(offZ, 4 - offZ) &gt; eyedropperOffGridTolerance then numberOfAxesOffGrid = numberOfAxesOffGrid + 1 end
&#9;&#9;if numberOfAxesOffGrid &gt; 1 then return false -- we allow one axis to be not fit to grid, since any rotation must necessarily affect &gt;= 2 axes (some of the models are like 4x4x6 :( ).
&#9;&#9;else return true end
end
function setupFakeTerrainPart(cellMat, cellType, cellOrient, isWater, waterForce,waterDirection)
&#9;&#9;local newTerrainPiece = nil
&#9;&#9;if (cellType == 1 or cellType == 4) then
&#9;&#9;&#9;newTerrainPiece = Instance.new(&quot;WedgePart&quot;)
&#9;&#9;&#9;newTerrainPiece.formFactor = &quot;Custom&quot;
&#9;&#9;elseif (cellType == 2) then
&#9;&#9;&#9;newTerrainPiece = Instance.new(&quot;CornerWedgePart&quot;)
&#9;&#9;else
&#9;&#9;&#9;newTerrainPiece = Instance.new(&quot;Part&quot;)
&#9;&#9;&#9;newTerrainPiece.formFactor = &quot;Custom&quot;
&#9;&#9;end
&#9;&#9;newTerrainPiece.Name = &quot;MegaClusterCube&quot;
&#9;&#9;newTerrainPiece.Size = Vector3.new(4, 4, 4)
&#9;&#9;newTerrainPiece.BottomSurface = &quot;Smooth&quot;
&#9;&#9;newTerrainPiece.TopSurface = &quot;Smooth&quot;
&#9;&#9;-- can add decals or textures here if feeling particularly adventurous... for now, can make a table of look-up colors
&#9;&#9;newTerrainPiece.BrickColor = getClosestColorToTerrainMaterial(cellMat)
&#9;&#9;local sideways = 0
&#9;&#9;local flipped = math.pi
&#9;&#9;if cellType == 4 then sideways = -math.pi/2 end
&#9;&#9;if cellType == 2 or cellType == 3 then flipped = 0 end
&#9;&#9;newTerrainPiece.CFrame = CFrame.Angles(0, math.pi/2 * cellOrient + flipped, sideways)
&#9;&#9;if cellType == 3 then
&#9;&#9;&#9;local inverseCornerWedgeMesh = Instance.new(&quot;SpecialMesh&quot;)
&#9;&#9;&#9;inverseCornerWedgeMesh.MeshType = &quot;FileMesh&quot;
&#9;&#9;&#9;inverseCornerWedgeMesh.MeshId = &quot;http://www.roblox.com/asset?id=66832495&quot;
&#9;&#9;&#9;inverseCornerWedgeMesh.Scale = Vector3.new(2, 2, 2)
&#9;&#9;&#9;inverseCornerWedgeMesh.Parent = newTerrainPiece
&#9;&#9;end
&#9;&#9;local materialTag = Instance.new(&quot;Vector3Value&quot;)
&#9;&#9;materialTag.Value = Vector3.new(cellMat, cellType, cellOrient)
&#9;&#9;materialTag.Name = &quot;ClusterMaterial&quot;
&#9;&#9;materialTag.Parent = newTerrainPiece
&#9;&#9;if isWater then
&#9;&#9;&#9;local waterForceTag = Instance.new(&quot;StringValue&quot;,newTerrainPiece)
&#9;&#9;&#9;waterForceTag.Name = &quot;WaterForceTag&quot;
&#9;&#9;&#9;waterForceTag.Value = string.sub(tostring(waterForce),17)
&#9;&#9;&#9;local waterForceDirectionTag = Instance.new(&quot;StringValue&quot;,newTerrainPiece)
&#9;&#9;&#9;waterForceDirectionTag.Name = &quot;WaterForceDirectionTag&quot;
&#9;&#9;&#9;waterForceDirectionTag.Value = string.sub(tostring(waterDirection),21)
&#9;&#9;end
&#9;&#9;return newTerrainPiece
end
function hint(phrase, timeLength)
&#9;waitForChild(game.Players.LocalPlayer.PlayerGui,&quot;topHint&quot;)
&#9;waitForChild(game.Players.LocalPlayer.PlayerGui.topHint, &quot;Add&quot;)
&#9;waitForChild(game.Players.LocalPlayer.PlayerGui.topHint.Add, &quot;Label&quot;)
&#9;waitForChild(game.Players.LocalPlayer.PlayerGui.topHint.Add, &quot;Time&quot;)
&#9;game.Players.LocalPlayer.PlayerGui.topHint.Add.Label.Value = tostring(phrase)
&#9;game.Players.LocalPlayer.PlayerGui.topHint.Add.Time.Value = tonumber(timeLength)
&#9;game.Players.LocalPlayer.PlayerGui.topHint.Add.Disabled = false
end
function showBaseplateWaypoint()
&#9;if modelToStampIn and showBaseplateScript then
&#9;&#9;local target = showBaseplateScript:FindFirstChild(&quot;target&quot;)
&#9;&#9;if target then
&#9;&#9;&#9;delay(0,function()
&#9;&#9;&#9;&#9;target.Value = modelToStampIn.Parent:FindFirstChild(&quot;RegionBounds&quot;)
&#9;&#9;&#9;&#9;showBaseplateScript.Disabled = false
&#9;&#9;&#9;&#9;showBaseplateScript.Disabled = true
&#9;&#9;&#9;&#9;wait(8)
&#9;&#9;&#9;&#9;hideBaseplateScript.Disabled = false
&#9;&#9;&#9;&#9;hideBaseplateScript.Disabled = true
&#9;&#9;&#9;end)
&#9;&#9;end
&#9;end
end
function stampAttemptFailed()
&#9;hint(&quot;You can only stamp in your baseplate&quot;, 5)
&#9;showBaseplateWaypoint()
end
function hasPoints()
&#9;waitForChild(game.Players.LocalPlayer, &quot;MaxPoints&quot;)
&#9;local maxPoints = game.Players.LocalPlayer.MaxPoints
&#9;waitForChild(game.Players.LocalPlayer, &quot;PointsUsed&quot;)
&#9;local pointsUsed = game.Players.LocalPlayer.PointsUsed
&#9;return ( (pointsUsed.Value/maxPoints.Value) &lt; 1 )
end
function setupStamper(stampModel)
&#9;if stampControl then stampControl.Destroy() end
&#9;if stampingCon then
&#9;&#9;stampingCon:disconnect()
&#9;&#9;stampingCon = nil
&#9;end
&#9;if isRestricted then
&#9;&#9;if not hasPoints() then
&#9;&#9;&#9;hint(&quot;Too many parts stamped, delete some to stamp more&quot;, 5)
&#9;&#9;&#9;return
&#9;&#9;else
&#9;&#9;&#9;stampControl = RbxStamper.SetupStamperDragger(stampModel, Mouse, modelToStampIn, stampRegion, stampAttemptFailed)
&#9;&#9;end
&#9;else
&#9;&#9;stampControl = RbxStamper.SetupStamperDragger(stampModel, Mouse)
&#9;end
&#9;if stampControl then
&#9;&#9;stampingCon = stampControl.Stamped.Changed:connect(function()
&#9;&#9;&#9;if stampControl and stampControl.Stamped.Value then
&#9;&#9;&#9;&#9;if isRestricted and not hasPoints() then
&#9;&#9;&#9;&#9;&#9;hint(&quot;Too many parts stamped, delete some to stamp more&quot;, 5)
&#9;&#9;&#9;&#9;&#9;if stampCon then stampCon:disconnect() end
&#9;&#9;&#9;&#9;&#9;stampControl.Destroy()
&#9;&#9;&#9;&#9;else
&#9;&#9;&#9;&#9;&#9;stampControl.ReloadModel()
&#9;&#9;&#9;&#9;end
&#9;&#9;&#9;end
&#9;&#9;end)
&#9;&#9;shortcutHint.Visible = true
&#9;end
end
function onEyeDropperMouseButton1Down()
&#9;clearSelection()
&#9;if Mouse then
&#9;&#9;Mouse.Icon = &quot;http://www.roblox.com/asset?id=66887745&quot;
&#9;end
&#9;-- deny any attempt to clone something that wasn&apos;t stamped using the Stamper tool
&#9;if not Mouse or not Mouse.Target then
&#9;&#9;startEyeDropperOperation()
&#9;&#9;return
&#9;end
&#9;local cloneInstance = nil
&#9;local isTerrainEyedroppering = false
&#9;if Mouse.Target == game.Workspace.Terrain and not isRestricted then -- want to eyedropper a terrain piece; do a little extra footwork
&#9;&#9;-- make the fake part here
&#9;&#9;local hitCell = game.Workspace.Terrain:WorldToCellPreferSolid(Mouse.Hit.p)
&#9;&#9;local cellMat, cellType, cellOrient = game.Workspace.Terrain:GetCell(hitCell.x, hitCell.y, hitCell.z)
&#9;&#9;local hasAnyWater, waterForce, waterDirection = game.Workspace.Terrain:GetWaterCell(hitCell.x, hitCell.y, hitCell.z)
&#9;&#9;cloneInstance = setupFakeTerrainPart(cellMat.Value, cellType.Value, cellOrient.Value, hasAnyWater, waterForce, waterDirection)
&#9;&#9;isTerrainEyedroppering = true
&#9;end
&#9;local stamperTag = Mouse.Target.Parent:FindFirstChild(&quot;RobloxStamper&quot;)
&#9;if stamperTag == nil then stamperTag = Mouse.Target:FindFirstChild(&quot;RobloxStamper&quot;) end
&#9;if stamperTag == nil and not isTerrainEyedroppering then
&#9;&#9;startEyeDropperOperation()
&#9;&#9;return
&#9;end
&#9;local eyeDropperInstance = nil
&#9;-- find out if the target part is part of a Roblox Set Model
&#9;local robloxModelTag = Mouse.Target.Parent:FindFirstChild(&quot;RobloxModel&quot;)
&#9;if robloxModelTag ~= nil then
&#9;&#9;eyeDropperInstance = Mouse.Target.Parent
&#9;else
&#9;&#9;eyeDropperInstance = Mouse.Target
&#9;end
&#9;
&#9;-- do not allow certain objects to be captured with eye-dropper
&#9;-- for now, locked parts
&#9;if eyeDropperInstance:IsA(&quot;Part&quot;) and eyeDropperInstance.Locked and not isTerrainEyedroppering then
&#9;&#9;startEyeDropperOperation()
&#9;else
&#9;&#9;if not isTerrainEyedroppering then
&#9;&#9;&#9;cloneInstance = eyeDropperInstance:clone()
&#9;&#9;&#9;-- once more, we make sure it&apos;s on grid before eyedroppering
&#9;&#9;&#9;if not isOnGrid(cloneInstance) then
&#9;&#9;&#9;&#9;if cloneInstance:IsA(&quot;Model&quot;) then cloneInstance:ResetOrientationToIdentity()
&#9;&#9;&#9;&#9;else cloneInstance.CFrame = CFrame.new(cloneInstance.CFrame.p) end
&#9;&#9;&#9;end
&#9;&#9;&#9;cloneInstance:BreakJoints()
&#9;&#9;end
&#9;&#9;if eyeDropperConnection then
&#9;&#9;&#9;eyeDropperConnection:disconnect()
&#9;&#9;&#9;eyeDropperConnection = nil
&#9;&#9;end
&#9;&#9;if eyeDropperMoveConnection then
&#9;&#9;&#9;eyeDropperMoveConnection:disconnect()
&#9;&#9;&#9;eyeDropperMoveConnection = nil
&#9;&#9;end
&#9;&#9;setupStamper(cloneInstance)
&#9;end
end
function onEyeDropperMouseMove()
&#9;if not Mouse or not Mouse.Target then
&#9;&#9;clearSelection()
&#9;&#9;return
&#9;end
&#9;local part = Mouse.Target
&#9;if part:IsA(&quot;Terrain&quot;) and Mouse.Hit and not isRestricted then
&#9;&#9;selectionBox.Color = BrickColor.Green()
&#9;&#9;setTerrainSelection(Mouse.Hit.p)
&#9;elseif canEyeDropperObject(part) then
&#9;&#9;local model = findModel(part)
&#9;&#9;if model then &#9;&#9;
&#9;&#9;&#9;selectionBox.Color = BrickColor.Green()
&#9;&#9;&#9;setSelection(model)
&#9;&#9;else
&#9;&#9;&#9;selectionBox.Color = BrickColor.Green()
&#9;&#9;&#9;setSelection(part)
&#9;&#9;end
&#9;else
&#9;&#9;clearSelection()
&#9;end
end
function keyHandler(key)
&#9;key = key:lower()
&#9;if key == &apos;q&apos; then
&#9;&#9;startEyeDropperOperation()
&#9;end
end
function startEyeDropperOperation()
&#9;if stampControl then stampControl.Destroy() end
&#9;if Mouse then
&#9;&#9;Mouse.Icon = &quot;http://www.roblox.com/asset?id=67163166&quot;
&#9;&#9;shortcutHint.Visible = false
&#9;&#9;if not eyeDropperMoveConnection then
&#9;&#9;&#9;eyeDropperConnection = Mouse.Button1Up:connect(onEyeDropperMouseButton1Down)
&#9;&#9;end
&#9;&#9;if not eyeDropperMoveConnection then
&#9;&#9;&#9;eyeDropperMoveConnection = Mouse.Move:connect(onEyeDropperMouseMove)
&#9;&#9;end
&#9;end
end
function onEquipped(mouse)
&#9;Mouse = mouse
&#9;if game:FindFirstChild(&quot;Players&quot;) then
&#9;&#9;if game.Players[&quot;LocalPlayer&quot;] then
&#9;&#9;&#9;selectionBox.Parent = game.Players.LocalPlayer.PlayerGui
&#9;&#9;&#9;hintGui.Parent = game.Players.LocalPlayer.PlayerGui
&#9;&#9;end
&#9;end
&#9;keyCon = Mouse.KeyDown:connect(keyHandler)
&#9;startEyeDropperOperation()
end
function onUnequipped()
&#9;if stampControl then
&#9;&#9;stampControl.Destroy()
&#9;end
&#9;Mouse = nil
&#9;selectionBox.Parent = nil
&#9;if eyeDropperMoveConnection then
&#9;&#9;eyeDropperMoveConnection:disconnect()
&#9;&#9;eyeDropperMoveConnection = nil
&#9;end
&#9;if eyeDropperConnection then
&#9;&#9;eyeDropperConnection:disconnect()
&#9;&#9;eyeDropperConnection = nil
&#9;end
&#9;if keyCon then
&#9;&#9;keyCon:disconnect()
&#9;&#9;keyCon = nil
&#9;end
&#9;if hintGui then
&#9;&#9;hintGui.Parent = nil
&#9;end
end
------------------------------------------------------------------------------------------------
if isRestricted then -- setup our variables
&#9;waitForChild(game,&quot;Workspace&quot;)
&#9;waitForChild(game.Workspace, &quot;BuildingAreas&quot;)
&#9;waitForChild(game.Workspace.BuildingAreas, &quot;Area1&quot;)
&#9;waitForChild(game.Workspace.BuildingAreas, &quot;Area9&quot;) -- all areas loaded
&#9;while not modelToStampIn do -- check for build area until we find one
&#9;&#9;local buildAreas = game.Workspace.BuildingAreas:GetChildren()
&#9;&#9;for i = 1, #buildAreas do
&#9;&#9;&#9;if buildAreas[i]:IsA(&quot;Model&quot;) then
&#9;&#9;&#9;&#9;waitForChild(buildAreas[i],&quot;Player&quot;)
&#9;&#9;&#9;&#9;if buildAreas[i].Player.Value == game.Players.LocalPlayer.Name then
&#9;&#9;&#9;&#9;&#9;waitForChild(buildAreas[i],&quot;PlayerArea&quot;)
&#9;&#9;&#9;&#9;&#9;modelToStampIn = buildAreas[i].PlayerArea
&#9;&#9;&#9;&#9;&#9;break
&#9;&#9;&#9;&#9;end
&#9;&#9;&#9;end
&#9;&#9;end
&#9;&#9;if not modelToStampIn then
&#9;&#9;&#9;wait(0.5)
&#9;&#9;end
&#9;end
&#9;local lowPos = modelToStampIn.Parent:FindFirstChild(&quot;LowPos&quot;)
&#9;local highPos = modelToStampIn.Parent:FindFirstChild(&quot;HighPos&quot;)
&#9;if not lowPos or highPos then
&#9;&#9;wait(0.5)
&#9;&#9;lowPos = modelToStampIn.Parent:FindFirstChild(&quot;LowPos&quot;)
&#9;&#9;highPos = modelToStampIn.Parent:FindFirstChild(&quot;HighPos&quot;)
&#9;end
&#9;while lowPos.Value == Vector3.new(0,0,0) or highPos.Value == Vector3.new(0,0,0) do
&#9;&#9;wait(0.5)
&#9;end -- tool doesn&apos;t work until these are defined
&#9;&#9;
&#9;stampRegion = Region3.new(lowPos.Value, highPos.Value) -- this is where we can stamp
end
Tool.Equipped:connect(onEquipped)
Tool.Unequipped:connect(onUnequipped)
</ProtectedString>
</Properties>
</Item>
<Item class="ScreenGui" referent="RBX3">
<Properties>
<string name="Name">CloneHintGui</string>
</Properties>
<Item class="TextLabel" referent="RBX4">
<Properties>
<bool name="Active">false</bool>
<Color3 name="BackgroundColor3">4278190080</Color3>
<float name="BackgroundTransparency">0.5</float>
<Color3 name="BorderColor3">4279970357</Color3>
<int name="BorderSizePixel">1</int>
<bool name="ClipsDescendants">false</bool>
<bool name="Draggable">false</bool>
<token name="Font">2</token>
<token name="FontSize">5</token>
<string name="Name">CloneHint</string>
<UDim2 name="Position">
<XS>0.5</XS>
<XO>-85</XO>
<YS>0</YS>
<YO>0</YO>
</UDim2>
<UDim2 name="Size">
<XS>0</XS>
<XO>170</XO>
<YS>0</YS>
<YO>30</YO>
</UDim2>
<token name="SizeConstraint">0</token>
<string name="Text">Press Q to Eyedropper</string>
<Color3 name="TextColor3">4294967295</Color3>
<bool name="TextScaled">false</bool>
<Color3 name="TextStrokeColor3">4278190080</Color3>
<float name="TextStrokeTransparency">0</float>
<float name="TextTransparency">0</float>
<bool name="TextWrapped">false</bool>
<token name="TextXAlignment">2</token>
<token name="TextYAlignment">1</token>
<bool name="Visible">false</bool>
<int name="ZIndex">1</int>
</Properties>
</Item>
</Item>
</Item>
</roblox>