492 lines
15 KiB
Plaintext
492 lines
15 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.5</Z>
|
|
<R00>0</R00>
|
|
<R01>0</R01>
|
|
<R02>1</R02>
|
|
<R10>1</R10>
|
|
<R11>0</R11>
|
|
<R12>0</R12>
|
|
<R20>0</R20>
|
|
<R21>1</R21>
|
|
<R22>0</R22>
|
|
</CoordinateFrame>
|
|
<string name="Name">DeleteTool</string>
|
|
<Content name="TextureId"><url>http://www.roblox.com/asset?id=73241901</url></Content>
|
|
<string name="ToolTip">Delete</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">0</token>
|
|
<token name="BottomSurfaceInput">0</token>
|
|
<int name="BrickColor">199</int>
|
|
<CoordinateFrame name="CFrame">
|
|
<X>2.00618601</X>
|
|
<Y>76.3911819</Y>
|
|
<Z>-21.7047653</Z>
|
|
<R00>0.515998006</R00>
|
|
<R01>0.000676945958</R01>
|
|
<R02>-0.856589496</R02>
|
|
<R10>0.000997249852</R10>
|
|
<R11>-0.999999404</R11>
|
|
<R12>-0.000189550163</R12>
|
|
<R20>-0.856589139</R20>
|
|
<R21>-0.000756426307</R21>
|
|
<R22>-0.515998363</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">true</bool>
|
|
<token name="Material">256</token>
|
|
<string name="Name">Handle</string>
|
|
<float name="Reflectance">0.400000006</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.0122278668</X>
|
|
<Y>-0.00862007216</Y>
|
|
<Z>0.00802176818</Z>
|
|
</Vector3>
|
|
<float name="TopParamA">-0.5</float>
|
|
<float name="TopParamB">0.5</float>
|
|
<token name="TopSurface">0</token>
|
|
<token name="TopSurfaceInput">0</token>
|
|
<float name="Transparency">0</float>
|
|
<Vector3 name="Velocity">
|
|
<X>-0.00655405503</X>
|
|
<Y>-0.014042181</Y>
|
|
<Z>0.000928968191</Z>
|
|
</Vector3>
|
|
<token name="formFactorRaw">2</token>
|
|
<token name="shape">1</token>
|
|
<Vector3 name="size">
|
|
<X>1</X>
|
|
<Y>0.800000012</Y>
|
|
<Z>3</Z>
|
|
</Vector3>
|
|
</Properties>
|
|
<Item class="SpecialMesh" referent="RBX2">
|
|
<Properties>
|
|
<token name="LODX">2</token>
|
|
<token name="LODY">2</token>
|
|
<Content name="MeshId"><url>http://www.roblox.com/asset/?id=16198309</url></Content>
|
|
<token name="MeshType">5</token>
|
|
<string name="Name">Mesh</string>
|
|
<Vector3 name="Offset">
|
|
<X>0</X>
|
|
<Y>0</Y>
|
|
<Z>0</Z>
|
|
</Vector3>
|
|
<Vector3 name="Scale">
|
|
<X>1.20000005</X>
|
|
<Y>1.20000005</Y>
|
|
<Z>1.20000005</Z>
|
|
</Vector3>
|
|
<Content name="TextureId"><url>http://www.roblox.com/asset/?id=16198294</url></Content>
|
|
<Vector3 name="VertexColor">
|
|
<X>1</X>
|
|
<Y>1</Y>
|
|
<Z>1</Z>
|
|
</Vector3>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="Sound" referent="RBX3">
|
|
<Properties>
|
|
<bool name="Looped">false</bool>
|
|
<string name="Name">Sound</string>
|
|
<float name="Pitch">1</float>
|
|
<bool name="PlayOnRemove">false</bool>
|
|
<Content name="SoundId"><url>http://www.roblox.com/Asset/?ID=12135982</url></Content>
|
|
<float name="Volume">0.699999988</float>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="LocalScript" referent="RBX4">
|
|
<Properties>
|
|
<bool name="Disabled">false</bool>
|
|
<Content name="LinkedSource"><null></null></Content>
|
|
<string name="Name">DeleteScript</string>
|
|
<ProtectedString name="Source">-- 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
|
|
|
|
-- locals
|
|
local RbxStamper = LoadLibrary("RbxStamper")
|
|
|
|
if not RbxStamper then
|
|
	print("Error: RbxStamper Library Load Fail! Returning")
|
|
	return nil
|
|
end
|
|
|
|
local Tool = script.Parent
|
|
|
|
enabled = true
|
|
game:GetService("ContentProvider"):Preload("rbxasset://icons/delete_sel.png")
|
|
|
|
local cluster = nil
|
|
|
|
local selectionBox
|
|
local currentSelection
|
|
local currentSelectionColors = {}
|
|
local selectionLasso
|
|
|
|
local deleteDistance = 100
|
|
local player = nil
|
|
|
|
local highlight = false
|
|
|
|
local megaClusterSelectionBox = Instance.new("Part")
|
|
megaClusterSelectionBox.FormFactor = "Custom"
|
|
megaClusterSelectionBox.Size = Vector3.new(4, 4, 4) -- a little thicker than 4x4x4 unit clusterpart; just so selection box is more easily seen
|
|
megaClusterSelectionBox.Transparency = 1
|
|
megaClusterSelectionBox.Anchored = true
|
|
megaClusterSelectionBox.CanCollide = false
|
|
megaClusterSelectionBox.Parent = nil
|
|
|
|
waitForProperty(game,"PlaceId")
|
|
local isRestricted = (game.PlaceId == 41324860 or game.PlaceId == 129686177)
|
|
local stampRegion = nil
|
|
local modelToStampIn = nil
|
|
|
|
waitForChild(Tool, "AutoWedgeClusterParts")
|
|
local autoWedgeClusterParts = Tool.AutoWedgeClusterParts.Value
|
|
|
|
waitForChild(Tool, "PlayerOwner")
|
|
local playerOwner = Tool.PlayerOwner
|
|
|
|
-- functions
|
|
|
|
function canDeleteObject(part)
|
|
	-- let them delete anything that they created *or* anything on their baseplate
|
|
	return part and not (part.Locked) and part:IsA("BasePart") and (part.Position - Tool.Parent.Head.Position).Magnitude < deleteDistance and (isChildOfMyModel(part) or inBounds(part))
|
|
end
|
|
|
|
-- For Restricting Stamper Tool (isRestricted)
|
|
function inBounds(partOrModel)
|
|
	if not stampRegion then return true end
|
|
	if not partOrModel then return true end
|
|
	
|
|
	return RbxStamper.CanEditRegion(partOrModel, stampRegion)
|
|
end
|
|
|
|
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
|
|
			if part:IsA("Model") then
|
|
				return part
|
|
			end
|
|
			part = part.Parent
|
|
		end
|
|
		return nil
|
|
	end
|
|
end
|
|
|
|
function cleanOrphanedModel(parent)
|
|
	if not parent then return end
|
|
	if parent.className == "Model" then
|
|
		local children = parent:GetChildren()
|
|
		if #children == 0 and parent.Name ~= "GarbageParts" then
|
|
			local oldParent = parent.Parent
|
|
			parent:Remove()
|
|
			cleanOrphanedModel(oldParent)
|
|
		end
|
|
	end
|
|
end
|
|
|
|
function isChildOfMyModel(part)
|
|
		if not modelToStampIn then return true end
|
|
		if modelToStampIn:IsAncestorOf(part) then
|
|
			return true
|
|
		else return false end
|
|
end
|
|
|
|
function on3dButton1Down(mouse)
|
|
	local part = mouse.Target
|
|
|
|
	if part == nil then
|
|
		return
|
|
	elseif part:IsA("Terrain") and not isRestricted then
|
|
		if cluster ~= nil then
|
|
			local cellPos = cluster:WorldToCellPreferSolid(Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
|
|
			local autoWedgeCell = cluster.AutowedgeCell
|
|
			local x = cellPos.x
|
|
			local y = cellPos.y
|
|
			local z = cellPos.z
|
|
|
|
			cluster:SetCell(x, y, z, 0, 0, 0)
|
|
			
|
|
			if (autoWedgeClusterParts) then
|
|
|
|
				for i = x - 1, x + 1 do
|
|
					for j = y - 1, y + 1 do
|
|
						for k = z - 1, z + 1 do
|
|
							autoWedgeCell(cluster,i,j,k)
|
|
						end
|
|
					end
|
|
				end
|
|
|
|
			end
|
|
|
|
			clearSelection()
|
|
			on3dMouseMove(mouse)
|
|
|
|
		end
|
|
	elseif canDeleteObject(part) then
|
|
		local model = findModel(part)
|
|
		local oldParent
|
|
		if model then
|
|
			if currentSelection == model then
|
|
				currentSelection = nil
|
|
				clearSelection()
|
|
			end
|
|
			oldParent = model.Parent
|
|
			model:Remove()
|
|
		else
|
|
			if currentSelection == part then
|
|
				currentSelection = nil
|
|
				clearSelection()
|
|
			end
|
|
			oldParent = part.Parent
|
|
			part:Remove()
|
|
		end
|
|
		if isRestricted then
|
|
			if oldParent and oldParent ~= modelToStampIn then
|
|
				cleanOrphanedModel(oldParent)
|
|
			end
|
|
		else
|
|
			cleanOrphanedModel(oldParent)
|
|
		end
|
|
	end
|
|
end
|
|
|
|
function saveSelectionColor(instance)
|
|
	if instance:IsA("BasePart") then
|
|
		currentSelectionColors[instance] = instance.BrickColor
|
|
		if instance.BrickColor == BrickColor.Red() then
|
|
			instance.BrickColor = BrickColor.new("Really red")
|
|
		else
|
|
			instance.BrickColor = BrickColor.Red()
|
|
		end
|
|
	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
|
|
	megaClusterSelectionBox.Parent = nil
|
|
end
|
|
|
|
|
|
function on3dMouseMove(mouse)
|
|
	local part = mouse.Target
|
|
|
|
	if not part then
|
|
		clearSelection()
|
|
		return
|
|
	elseif part:IsA("Terrain") and not isRestricted then
|
|
		if not cluster then cluster = game.Workspace.Terrain end
|
|
		local hitCell = cluster:WorldToCellPreferSolid(mouse.Hit.p)
|
|
		if cluster:GetCell(hitCell.x, hitCell.y, hitCell.z).Value > 0 then
|
|
			megaClusterSelectionBox.CFrame = CFrame.new(cluster:CellCenterToWorld(hitCell.x, hitCell.y, hitCell.z))
|
|
|
|
			if isRestricted then
|
|
				megaClusterSelectionBox.Parent = game.Workspace.BaseplateBumpers
|
|
			else
|
|
				megaClusterSelectionBox.Parent = game.Workspace
|
|
			end
|
|
|
|
			selectionBox.Adornee = megaClusterSelectionBox
|
|
			currentSelection = nil -- necessary so selection box can transition between terrain and non-terrain smoothly
|
|
		else
|
|
			clearSelection()
|
|
			return
|
|
		end
|
|
	elseif canDeleteObject(part) then
|
|
		local model = findModel(part)
|
|
		if model then 		
|
|
			selectionBox.Color = BrickColor.Red()
|
|
			setSelection(model)
|
|
		else
|
|
			selectionBox.Color = BrickColor.Red()
|
|
			setSelection(part)
|
|
		end
|
|
	else
|
|
		clearSelection()
|
|
	end
|
|
end
|
|
|
|
local equipCount = 0
|
|
function onEquippedLocal(mouse)
|
|
	equipCount = equipCount + 1
|
|
	local val = equipCount
|
|
|
|
	if isRestricted then
|
|
		waitForChild(game.Workspace, "BuildingAreas")
|
|
		if val ~= equipCount then
|
|
			return
|
|
		end
|
|
	end
|
|
|
|
	mouse.TargetFilter = megaClusterSelectionBox
|
|
|
|
	local character = script.Parent.Parent
|
|
	player = game.Players:GetPlayerFromCharacter(character)
|
|
	
|
|
	if not player then return end
|
|
|
|
	if playerOwner.Value and playerOwner.Value ~= player then return end
|
|
	playerOwner.Value = player
|
|
|
|
	guiMain = Instance.new("ScreenGui")
|
|
	guiMain.Parent = player.PlayerGui
|
|
|
|
	mouse.Button1Down:connect(function() on3dButton1Down(mouse) end)
|
|
	mouse.Move:connect(function() on3dMouseMove(mouse) end)
|
|
	mouse.Icon = "http://www.roblox.com/asset?id=72539748"
|
|
|
|
	selectionBox = Instance.new("SelectionBox")
|
|
	selectionBox.Name = "Model Delete Selection"
|
|
	selectionBox.Color = BrickColor.Red()
|
|
	selectionBox.Adornee = nil
|
|
	selectionBox.Parent = player.PlayerGui
|
|
|
|
	selectionLasso = Instance.new("SelectionPartLasso")
|
|
	selectionLasso.Name = "Model Delete Lasso"
|
|
	selectionLasso.Humanoid = character.Humanoid
|
|
	selectionLasso.archivable = false
|
|
	selectionLasso.Visible = true
|
|
	selectionLasso.Parent = game.workspace
|
|
	selectionLasso.Color = BrickColor.Red()
|
|
|
|
	highlight = true
|
|
end
|
|
|
|
function onUnequippedLocal()
|
|
	highlight = false
|
|
	if selectionBox then
|
|
		clearSelection()
|
|
		selectionBox:Remove()
|
|
	end
|
|
	if selectionLasso then selectionLasso:Remove() 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(onEquippedLocal)
|
|
Tool.Unequipped:connect(onUnequippedLocal)
|
|
</ProtectedString>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="BoolValue" referent="RBX5">
|
|
<Properties>
|
|
<string name="Name">AutoWedgeClusterParts</string>
|
|
<bool name="Value">false</bool>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="ObjectValue" referent="RBX6">
|
|
<Properties>
|
|
<string name="Name">PlayerOwner</string>
|
|
<Ref name="Value">null</Ref>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
</roblox> |