-- src/ServerScriptService/EnvironmentalPuzzleManager.server.lua local CollectionService = game:GetService("CollectionService") local ReplicatedStorage = game:GetService("ReplicatedStorage") local RunService = game:GetService("RunService") local ExplorationConfig = require(ReplicatedStorage:WaitForChild("Shared"):WaitForChild("ExplorationConfig")) -- Manage Weight Switches (Pressure Plates that require heavy logs) local function bindWeightSwitch(switchModel) local platePart = switchModel:FindFirstChild("Plate") local targetDoor = switchModel:FindFirstChild("LinkedDoor") or switchModel.Parent:FindFirstChild("Door") if not platePart or not targetDoor then return end local config = ExplorationConfig.Puzzles.WeightSwitch local isActive = false RunService.Heartbeat:Connect(function() -- Calculate total mass resting on the plate local touchingParts = workspace:GetPartsInPart(platePart) local totalMass = 0 for _, part in ipairs(touchingParts) do if part:IsA("BasePart") and not part.Anchored then totalMass = totalMass + part.AssemblyMass end end if totalMass >= config.RequiredWeight and not isActive then isActive = true platePart.BrickColor = BrickColor.new("Bright green") -- Open Door Tween targetDoor.Transparency = 0.5 targetDoor.CanCollide = false print("Puzzle Solved: Door Opened") elseif totalMass < config.RequiredWeight and isActive then isActive = false platePart.BrickColor = BrickColor.new("Bright red") -- Close Door Tween targetDoor.Transparency = 0 targetDoor.CanCollide = true print("Puzzle Reset: Door Closed") end end) end CollectionService:GetInstanceAddedSignal("WeightSwitch"):Connect(bindWeightSwitch) for _, switch in pairs(CollectionService:GetTagged("WeightSwitch")) do bindWeightSwitch(switch) end -- Manage Biome Hazards (e.g., Sinking in Swamps) local function bindSwampZone(zonePart) local config = ExplorationConfig.Biomes.Swamp RunService.Heartbeat:Connect(function(dt) local touchingParts = workspace:GetPartsInPart(zonePart) for _, part in ipairs(touchingParts) do -- Sink objects that aren't specifically built for swamps if part:IsA("BasePart") and not part.Anchored and not CollectionService:HasTag(part, "SwampTires") then -- Apply a downward velocity to simulate sinking part.AssemblyLinearVelocity = Vector3.new( part.AssemblyLinearVelocity.X, -config.SinkingSpeed, part.AssemblyLinearVelocity.Z ) end -- Can add Player damage logic here if character parts touch it end end) end CollectionService:GetInstanceAddedSignal("SwampZone"):Connect(bindSwampZone) for _, zone in pairs(CollectionService:GetTagged("SwampZone")) do bindSwampZone(zone) end