Archives
Trending
Support
Login
clear text
XML
Django
JavaScript
MATLAB
C
C++
C#
Python
SQL
Shell
Bash
Markdown
YAML
JSON
HTML
CSS
PHP
Java
Ruby
Go
Rust
Swift
Kotlin
Arduino
TypeScript
Perl
Autohotkey
Lua
SQF
R
Scala
Haskell
Groovy
Dart
Clojure
VB.NET
Objective-C
PowerShell
Bash
CoffeeScript
Verilog
local module = {} --// Services local ServerStorage = game:GetService("ServerStorage") local AdditionModule = ServerStorage:WaitForChild("AdditionalModules") --// Local references local workspaceParticlesParent = workspace:FindFirstChild("Particles") or workspace -- fallback --// Splits `part` into smaller parts. If the part is long/thin (aspect ratio below threshold) -- it splits only along the two larger axes into 4 sub-parts, otherwise it splits into 8 octants. -- Returns an array of new parts (the original `part` is destroyed). function module.SubdivideCube(part, minSize) --// Early out: if the part is already small enough, return it as-is. local s = part.Size if s.X <= minSize and s.Y <= minSize and s.Z <= minSize then return { part } end local cframe = part.CFrame local parent = workspaceParticlesParent local minDim = math.min(s.X, s.Y, s.Z) local maxDim = math.max(s.X, s.Y, s.Z) local aspectRatio = minDim / maxDim local threshold = 0.5 local newParts = {} --// Helper: create a clone with size/cframe and parent it local function makePart(newSize, newCFrame) local newPart = part:Clone() newPart.Size = newSize newPart.CFrame = newCFrame newPart.Parent = parent return newPart end if aspectRatio < threshold then --// long thin part: split only the two larger axes => produce 4 parts local smallestAxis if s.X == minDim then smallestAxis = "X" elseif s.Y == minDim then smallestAxis = "Y" else smallestAxis = "Z" end --// new size halves the larger axes, but keeps the smallest axis unchanged local newSize = Vector3.new( (smallestAxis == "X") and s.X or s.X / 2, (smallestAxis == "Y") and s.Y or s.Y / 2, (smallestAxis == "Z") and s.Z or s.Z / 2 ) --// compute offsets depending on which axis stayed full-size local offX = (smallestAxis == "X") and 0 or newSize.X / 2 local offY = (smallestAxis == "Y") and 0 or newSize.Y / 2 local offZ = (smallestAxis == "Z") and 0 or newSize.Z / 2 local offsets = {} if smallestAxis == "X" then offsets = { Vector3.new(0, offY, offZ), Vector3.new(0, offY, -offZ), Vector3.new(0, -offY, offZ), Vector3.new(0, -offY, -offZ), } elseif smallestAxis == "Y" then offsets = { Vector3.new(offX, 0, offZ), Vector3.new(offX, 0, -offZ), Vector3.new(-offX, 0, offZ), Vector3.new(-offX, 0, -offZ), } else -- "Z" offsets = { Vector3.new(offX, offY, 0), Vector3.new(offX, -offY, 0), Vector3.new(-offX, offY, 0), Vector3.new(-offX, -offY, 0), } end for _, offset in ipairs(offsets) do local newCFrame = cframe * CFrame.new(offset) table.insert(newParts, makePart(newSize, newCFrame)) end else --// more cubic: split into 8 octants local newSize = Vector3.new(s.X / 2, s.Y / 2, s.Z / 2) local half = newSize * 0.5 local offsets = { Vector3.new( half.X, half.Y, half.Z), Vector3.new(-half.X, half.Y, half.Z), Vector3.new( half.X, -half.Y, half.Z), Vector3.new(-half.X, -half.Y, half.Z), Vector3.new( half.X, half.Y, -half.Z), Vector3.new(-half.X, half.Y, -half.Z), Vector3.new( half.X, -half.Y, -half.Z), Vector3.new(-half.X, -half.Y, -half.Z), } for _, offset in ipairs(offsets) do local newCFrame = cframe * CFrame.new(offset) table.insert(newParts, makePart(newSize, newCFrame)) end end --// Remove the original part (we replaced it with children) part:Destroy() return newParts end --// Returns true if the axis-aligned box defined by `part` intersects or lies within the sphere. function module.IsPartInSphere(part, sphereCenter, sphereRadius) -- Transform the sphere center into the part's local space local localPoint = part.CFrame:PointToObjectSpace(sphereCenter) local halfSize = part.Size * 0.5 local dx = math.max(math.abs(localPoint.X) - halfSize.X, 0) local dy = math.max(math.abs(localPoint.Y) - halfSize.Y, 0) local dz = math.max(math.abs(localPoint.Z) - halfSize.Z, 0) local distance = math.sqrt(dx * dx + dy * dy + dz * dz) return distance <= sphereRadius end --// Returns a minimum voxel size for subdivision based on the largest dimension of `part`. function module.CalculateMinVoxelSize(part, fraction) fraction = fraction or 0.1 local s = part.Size local maxDim = math.max(s.X, s.Y, s.Z) local minVoxelSize = math.max(maxDim * fraction, 1) return minVoxelSize end --// Calculates how many times to halve the largest dimension until it reaches the min voxel size. function module.CalculateSubdivisionIterations(part, minVoxelSize) local s = part.Size local maxDim = math.max(s.X, s.Y, s.Z) --// iterations = ceil(log2(maxDim / minVoxelSize)) local ratio = maxDim / math.max(minVoxelSize, 1e-6) local iterations = math.ceil(math.log(ratio) / math.log(2)) return math.max(iterations, 0) end --// Recursively subdivides parts that intersect the sphere, down to minSize or until iterations expire. function module.RecursiveSubdivision(parts, sphereCenter, sphereRadius, minSize, iterations) local newParts = {} for _, part in ipairs(parts) do -- Only subdivide if the part is larger than minSize (by magnitude) and intersects the sphere if part and part.Parent and part.Size.Magnitude > minSize and module.IsPartInSphere(part, sphereCenter, sphereRadius) then local subdivided = module.SubdivideCube(part, minSize) for _, sp in ipairs(subdivided) do table.insert(newParts, sp) end else table.insert(newParts, part) end end if iterations and iterations > 1 then return module.RecursiveSubdivision(newParts, sphereCenter, sphereRadius, minSize, iterations - 1) else return newParts end end --// Public function: finds map parts intersecting a sphere, subdivides them around the sphere, -- applies impulses to pieces inside the sphere, and unsubdivides (restores) the others. function module.CauseDestructionAroundPoint(Point: Vector3, Radius: number) --// Helper to gather parts that belong to workspace.Map and intersect the sphere local function CalculateHitParts() -- Create a temporary invisible part to query GetPartsInPart local Temp = Instance.new("Part") Temp.Shape = Enum.PartType.Ball Temp.Size = Vector3.new(Radius * 2, Radius * 2, Radius * 2) -- Size should be diameter Temp.Position = Point Temp.Transparency = 1 Temp.Anchored = true Temp.CanCollide = false Temp.Parent = workspace -- Get parts inside the temp sphere-shaped part local initial = workspace:GetPartsInPart(Temp) -- Clean up temp immediately Temp:Destroy() -- Filter to only parts that are within the Map hierarchy (same logic as original) local mapParts = {} for _, v in ipairs(initial) do if v and v:FindFirstAncestor("Map") then table.insert(mapParts, v) end end -- If nothing to do, return empty if #mapParts == 0 then return {} end -- Find the largest part (by Size.Magnitude) to determine min voxel size & iterations local biggestPart = mapParts[1] for i = 2, #mapParts do local candidate = mapParts[i] if candidate and candidate.Size.Magnitude > biggestPart.Size.Magnitude then biggestPart = candidate end end if not biggestPart then return {} end -- Calculate min voxel size and subdivision iterations based on the biggest part local minSize = module.CalculateMinVoxelSize(biggestPart, 0.05) -- fraction preserved from original local iterations = module.CalculateSubdivisionIterations(biggestPart, minSize) -- Recursively subdivide relevant parts around the sphere center local finalParts = module.RecursiveSubdivision(mapParts, Point, Radius, minSize, iterations) -- Separate parts that are inside the sphere (to be affected) and extras to restore local extras = {} for _, v in ipairs(finalParts) do if v and module.IsPartInSphere(v, Point, Radius) then -- Make dynamic v.Anchored = false -- Apply a modest impulse (kept from original) if v:IsA("BasePart") and v:CanSetNetworkOwnership() then -- ApplyImpulse exists on BasePart, if available pcall(function() v:ApplyImpulse(Vector3.new(40, 40, 40)) end) else -- Fallback: change velocity if ApplyImpulse isn't available if v:IsA("BasePart") then v.AssemblyLinearVelocity = v.AssemblyLinearVelocity + Vector3.new(40, 40, 40) end end else table.insert(extras, v) end end -- Defer unsubdivide/restoration to avoid blocking if #extras > 0 then task.spawn(function() local ok, Result = pcall(function() return require(script.UnSubdivideModule).Unsubdivide(extras) end) if ok and type(Result) == "table" then for _, restored in ipairs(Result) do if restored then restored.Parent = workspace:FindFirstChild("Map") or workspace end end end end) end return finalParts end -- Execute the calculation CalculateHitParts() end return module
Mark as private (unlisted)
for 30 minutes
for 6 hours
for 1 day
for 1 week
for 1 month
for 1 year
everlasting (like CCCP)