local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local UserInputService = game:GetService("UserInputService") local TweenService = game:GetService("TweenService") local player = Players.LocalPlayer local playerGui = player:WaitForChild("PlayerGui") --================================================== -- FIND UNIT / TOWER FOLDERS -- CASE-INSENSITIVE --================================================== local folderNames = { unit = true, units = true, tower = true, towers = true, } local function isUnitTowerFolder(object) return object:IsA("Folder") and folderNames[object.Name:lower()] == true end -- ONLY SHOW MODELS DIRECTLY INSIDE -- UNIT / UNITS / TOWER / TOWERS FOLDERS local function getAllUnitsAndTowers() local objects = {} local seen = {} for _, folder in ipairs( ReplicatedStorage:GetDescendants() ) do if isUnitTowerFolder(folder) then for _, object in ipairs( folder:GetChildren() ) do if object:IsA("Model") and not seen[object] then seen[object] = true table.insert(objects, object) end end end end table.sort(objects, function(a, b) return a.Name:lower() < b.Name:lower() end) return objects end --================================================== -- GUI --================================================== local gui = Instance.new("ScreenGui") gui.Name = "TowerHub" gui.ResetOnSpawn = false gui.IgnoreGuiInset = true gui.DisplayOrder = 999 gui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling gui.Parent = playerGui --================================================== -- MAIN WINDOW --================================================== local main = Instance.new("Frame") main.Name = "Main" main.AnchorPoint = Vector2.new(0.5, 0.5) main.Position = UDim2.fromScale(0.5, 0.5) -- SMALL HUB main.Size = UDim2.fromOffset(560, 400) main.BackgroundColor3 = Color3.fromRGB(17, 18, 24) main.BorderSizePixel = 0 main.Parent = gui local mainCorner = Instance.new("UICorner") mainCorner.CornerRadius = UDim.new(0, 16) mainCorner.Parent = main local mainStroke = Instance.new("UIStroke") mainStroke.Color = Color3.fromRGB(62, 65, 80) mainStroke.Thickness = 1 mainStroke.Parent = main --================================================== -- RESPONSIVE SCALE -- PC + MOBILE --================================================== local uiScale = Instance.new("UIScale") uiScale.Parent = main local function updateScale() local camera = workspace.CurrentCamera if not camera then return end local viewport = camera.ViewportSize local width = viewport.X local height = viewport.Y -- Keep entire hub inside the screen local scaleX = (width - 20) / 560 local scaleY = (height - 20) / 400 local screenScale = math.min( scaleX, scaleY ) if width <= 390 then -- Small phones uiScale.Scale = math.min( screenScale, 0.82 ) elseif width <= 600 then -- Tablets / larger phones uiScale.Scale = math.min( screenScale, 0.90 ) else -- PC uiScale.Scale = math.min( screenScale, 1 ) end end updateScale() local function connectCamera() local camera = workspace.CurrentCamera if not camera then return end camera:GetPropertyChangedSignal( "ViewportSize" ):Connect(updateScale) updateScale() end connectCamera() workspace:GetPropertyChangedSignal( "CurrentCamera" ):Connect(function() connectCamera() end) --================================================== -- TOP BAR --================================================== local top = Instance.new("Frame") top.Name = "TopBar" top.Size = UDim2.new(1, 0, 0, 50) top.BackgroundColor3 = Color3.fromRGB(25, 27, 35) top.BorderSizePixel = 0 top.Parent = main local topCorner = Instance.new("UICorner") topCorner.CornerRadius = UDim.new(0, 16) topCorner.Parent = top local title = Instance.new("TextLabel") title.BackgroundTransparency = 1 title.Position = UDim2.fromOffset(14, 0) title.Size = UDim2.new(1, -65, 1, 0) title.Text = "universe spawner tower" title.TextColor3 = Color3.fromRGB(255, 255, 255) title.TextSize = 18 title.Font = Enum.Font.GothamBold title.TextXAlignment = Enum.TextXAlignment.Left title.TextTruncate = Enum.TextTruncate.AtEnd title.Parent = top local hideButton = Instance.new("TextButton") hideButton.Size = UDim2.fromOffset(38, 38) hideButton.Position = UDim2.new(1, -45, 0, 6) hideButton.BackgroundColor3 = Color3.fromRGB(47, 49, 61) hideButton.Text = "×" hideButton.TextColor3 = Color3.fromRGB(255, 255, 255) hideButton.TextSize = 23 hideButton.Font = Enum.Font.GothamBold hideButton.AutoButtonColor = false hideButton.Parent = top local hideCorner = Instance.new("UICorner") hideCorner.CornerRadius = UDim.new(0, 9) hideCorner.Parent = hideButton --================================================== -- LEFT UNIT / TOWER PANEL --================================================== local left = Instance.new("Frame") left.Name = "UnitTowerPanel" left.Position = UDim2.fromOffset(8, 58) left.Size = UDim2.new(0.42, -8, 1, -66) left.BackgroundColor3 = Color3.fromRGB(24, 26, 34) left.BorderSizePixel = 0 left.Parent = main local leftCorner = Instance.new("UICorner") leftCorner.CornerRadius = UDim.new(0, 12) leftCorner.Parent = left local listTitle = Instance.new("TextLabel") listTitle.BackgroundTransparency = 1 listTitle.Position = UDim2.fromOffset(11, 7) listTitle.Size = UDim2.new(1, -22, 0, 28) listTitle.Text = "UNITS + TOWERS" listTitle.TextColor3 = Color3.fromRGB(225, 227, 235) listTitle.TextSize = 11 listTitle.Font = Enum.Font.GothamBold listTitle.TextXAlignment = Enum.TextXAlignment.Left listTitle.TextTruncate = Enum.TextTruncate.AtEnd listTitle.Parent = left --================================================== -- TOWER SCROLLING --================================================== local towerList = Instance.new("ScrollingFrame") towerList.Name = "UnitTowerList" towerList.Position = UDim2.fromOffset(7, 39) towerList.Size = UDim2.new(1, -14, 1, -46) towerList.BackgroundTransparency = 1 towerList.BorderSizePixel = 0 -- Better scrollbar towerList.ScrollBarThickness = 5 towerList.ScrollBarImageColor3 = Color3.fromRGB(90, 94, 112) towerList.ScrollBarImageTransparency = 0.15 -- PC + MOBILE SCROLLING towerList.ScrollingDirection = Enum.ScrollingDirection.Y towerList.ScrollingEnabled = true towerList.ElasticBehavior = Enum.ElasticBehavior.Always -- Automatically calculates canvas towerList.AutomaticCanvasSize = Enum.AutomaticSize.Y towerList.CanvasSize = UDim2.new(0, 0, 0, 0) towerList.Parent = left -- Extra space around list local towerPadding = Instance.new("UIPadding") towerPadding.PaddingTop = UDim.new(0, 3) towerPadding.PaddingBottom = UDim.new(0, 10) towerPadding.PaddingLeft = UDim.new(0, 2) towerPadding.PaddingRight = UDim.new(0, 2) towerPadding.Parent = towerList local towerLayout = Instance.new("UIListLayout") towerLayout.Padding = UDim.new(0, 6) towerLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center towerLayout.SortOrder = Enum.SortOrder.LayoutOrder towerLayout.Parent = towerList --================================================== -- RIGHT STATS PANEL --================================================== local right = Instance.new("Frame") right.Name = "StatsPanel" right.Position = UDim2.new(0.42, 4, 0, 58) right.Size = UDim2.new(0.58, -12, 1, -66) right.BackgroundColor3 = Color3.fromRGB(20, 21, 29) right.BorderSizePixel = 0 right.Parent = main local rightCorner = Instance.new("UICorner") rightCorner.CornerRadius = UDim.new(0, 12) rightCorner.Parent = right --================================================== -- SELECTED TITLE --================================================== local selectedTitle = Instance.new("TextLabel") selectedTitle.BackgroundTransparency = 1 selectedTitle.Position = UDim2.fromOffset(13, 8) selectedTitle.Size = UDim2.new(1, -26, 0, 28) selectedTitle.Text = "SELECT A UNIT" selectedTitle.TextColor3 = Color3.fromRGB(255, 255, 255) selectedTitle.TextSize = 16 selectedTitle.Font = Enum.Font.GothamBold selectedTitle.TextXAlignment = Enum.TextXAlignment.Left selectedTitle.TextTruncate = Enum.TextTruncate.AtEnd selectedTitle.Parent = right local subtitle = Instance.new("TextLabel") subtitle.BackgroundTransparency = 1 subtitle.Position = UDim2.fromOffset(14, 34) subtitle.Size = UDim2.new(1, -28, 0, 16) subtitle.Text = "Select an existing unit or tower" subtitle.TextColor3 = Color3.fromRGB(125, 130, 145) subtitle.TextSize = 9 subtitle.Font = Enum.Font.Gotham subtitle.TextXAlignment = Enum.TextXAlignment.Left subtitle.TextTruncate = Enum.TextTruncate.AtEnd subtitle.Parent = right --================================================== -- STAT ALIASES --================================================== local aliases = { Damage = { "Damage", "AttackDamage", "Attack", "DMG" }, Range = { "Range", "AttackRange", "Radius" }, Cooldown = { "Cooldown", "AttackCooldown", "FireRate", "AttackSpeed" }, Price = { "Price", "Cost", "Cash" }, } --================================================== -- READ VALUE OBJECT --================================================== local function readValueObject(object) if object:IsA("NumberValue") or object:IsA("IntValue") or object:IsA("StringValue") or object:IsA("BoolValue") then return object.Value end return nil end --================================================== -- FIND STAT IN OBJECT --================================================== local function findStatInObject( object, statName ) if not object then return nil end -- Attribute local attribute = object:GetAttribute(statName) if attribute ~= nil then return attribute end -- Direct child local direct = object:FindFirstChild(statName) if direct then local value = readValueObject(direct) if value ~= nil then return value end end -- Aliases for _, alias in ipairs( aliases[statName] or {} ) do local child = object:FindFirstChild(alias) if child then local value = readValueObject(child) if value ~= nil then return value end end local attr = object:GetAttribute(alias) if attr ~= nil then return attr end end -- Descendants for _, descendant in ipairs( object:GetDescendants() ) do local attr = descendant:GetAttribute( statName ) if attr ~= nil then return attr end local value = readValueObject(descendant) if value ~= nil then if descendant.Name:lower() == statName:lower() then return value end for _, alias in ipairs( aliases[statName] or {} ) do if descendant.Name:lower() == alias:lower() then return value end end end end return nil end --================================================== -- FIND STAT IN MODULE --================================================== local function findStatInModule( moduleScript, statName ) if not moduleScript then return nil end if not moduleScript:IsA( "ModuleScript" ) then return nil end local success, data = pcall(require, moduleScript) if not success or type(data) ~= "table" then return nil end if data[statName] ~= nil then return data[statName] end for _, alias in ipairs( aliases[statName] or {} ) do if data[alias] ~= nil then return data[alias] end end for key, value in pairs(data) do if type(key) == "string" then if key:lower() == statName:lower() then return value end for _, alias in ipairs( aliases[statName] or {} ) do if key:lower() == alias:lower() then return value end end end end return nil end --================================================== -- FIND STAT --================================================== local function findStat( unit, statName ) local result = findStatInObject( unit, statName ) if result ~= nil then return result end for _, configName in ipairs({ "Config", "Configuration", "Stats", "Data", "TowerData", "UnitData" }) do local config = unit:FindFirstChild( configName ) if config then result = findStatInObject( config, statName ) if result ~= nil then return result end end end for _, object in ipairs( unit:GetDescendants() ) do if object:IsA("ModuleScript") then result = findStatInModule( object, statName ) if result ~= nil then return result end end end return "N/A" end --================================================== -- STATS SCROLL --================================================== local statsScroll = Instance.new("ScrollingFrame") statsScroll.Name = "StatsScroll" statsScroll.Position = UDim2.fromOffset(7, 56) statsScroll.Size = UDim2.new(1, -14, 1, -116) statsScroll.BackgroundTransparency = 1 statsScroll.BorderSizePixel = 0 -- Better scrollbar statsScroll.ScrollBarThickness = 5 statsScroll.ScrollBarImageColor3 = Color3.fromRGB(85, 90, 110) statsScroll.ScrollBarImageTransparency = 0.15 -- PC + MOBILE statsScroll.ScrollingDirection = Enum.ScrollingDirection.Y statsScroll.ScrollingEnabled = true statsScroll.ElasticBehavior = Enum.ElasticBehavior.Always -- Automatic canvas statsScroll.AutomaticCanvasSize = Enum.AutomaticSize.Y statsScroll.CanvasSize = UDim2.new(0, 0, 0, 0) statsScroll.Parent = right local statsPadding = Instance.new("UIPadding") statsPadding.PaddingTop = UDim.new(0, 3) statsPadding.PaddingBottom = UDim.new(0, 10) statsPadding.PaddingLeft = UDim.new(0, 4) statsPadding.PaddingRight = UDim.new(0, 4) statsPadding.Parent = statsScroll local statsLayout = Instance.new("UIListLayout") statsLayout.Padding = UDim.new(0, 7) statsLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center statsLayout.SortOrder = Enum.SortOrder.LayoutOrder statsLayout.Parent = statsScroll local statCards = {} --================================================== -- CREATE STAT CARD --================================================== local function createStatCard( name, icon, color ) local card = Instance.new("Frame") card.Name = name .. "Card" card.Size = UDim2.new(1, 0, 0, 50) card.BackgroundColor3 = Color3.fromRGB(31, 33, 43) card.BorderSizePixel = 0 card.Parent = statsScroll local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(0, 9) corner.Parent = card local stroke = Instance.new("UIStroke") stroke.Color = Color3.fromRGB(45, 47, 59) stroke.Thickness = 1 stroke.Parent = card local iconLabel = Instance.new("TextLabel") iconLabel.Position = UDim2.fromOffset(6, 6) iconLabel.Size = UDim2.fromOffset(38, 38) iconLabel.BackgroundColor3 = color iconLabel.Text = icon iconLabel.TextColor3 = Color3.new(1, 1, 1) iconLabel.TextSize = 17 iconLabel.Font = Enum.Font.GothamBold iconLabel.Parent = card local iconCorner = Instance.new("UICorner") iconCorner.CornerRadius = UDim.new(0, 8) iconCorner.Parent = iconLabel local nameLabel = Instance.new("TextLabel") nameLabel.BackgroundTransparency = 1 nameLabel.Position = UDim2.fromOffset(52, 5) nameLabel.Size = UDim2.new(1, -62, 0, 14) nameLabel.Text = name:upper() nameLabel.TextColor3 = Color3.fromRGB(140, 145, 160) nameLabel.TextSize = 8 nameLabel.Font = Enum.Font.GothamBold nameLabel.TextXAlignment = Enum.TextXAlignment.Left nameLabel.Parent = card local valueLabel = Instance.new("TextLabel") valueLabel.BackgroundTransparency = 1 valueLabel.Position = UDim2.fromOffset(52, 18) valueLabel.Size = UDim2.new(1, -62, 0, 26) valueLabel.Text = "--" valueLabel.TextColor3 = Color3.fromRGB(248, 248, 252) valueLabel.TextSize = 16 valueLabel.Font = Enum.Font.GothamBold valueLabel.TextXAlignment = Enum.TextXAlignment.Left valueLabel.TextTruncate = Enum.TextTruncate.AtEnd valueLabel.Parent = card statCards[name] = { Card = card, Value = valueLabel } end createStatCard( "Damage", "⚔", Color3.fromRGB(190, 60, 70) ) createStatCard( "Range", "◎", Color3.fromRGB(60, 125, 205) ) createStatCard( "Cooldown", "◷", Color3.fromRGB(145, 90, 205) ) createStatCard( "Price", "$", Color3.fromRGB(50, 165, 95) ) --================================================== -- SELECTION --================================================== local selectedUnit = nil local selectedUnitName = nil local towerButtons = {} --================================================== -- ANIMATE STAT --================================================== local function animateStat( name, value ) local data = statCards[name] if not data then return end data.Value.Text = tostring(value) data.Value.TextTransparency = 1 TweenService:Create( data.Value, TweenInfo.new( 0.2, Enum.EasingStyle.Quint, Enum.EasingDirection.Out ), { TextTransparency = 0 } ):Play() end --================================================== -- SHOW UNIT STATS --================================================== local function showUnitStats( unit ) selectedUnit = unit selectedUnitName = unit.Name selectedTitle.Text = unit.Name subtitle.Text = "EXISTING UNIT / TOWER" animateStat( "Damage", findStat( unit, "Damage" ) ) animateStat( "Range", findStat( unit, "Range" ) ) animateStat( "Cooldown", findStat( unit, "Cooldown" ) ) animateStat( "Price", findStat( unit, "Price" ) ) -- Reset stats scroll statsScroll.CanvasPosition = Vector2.new(0, 0) -- Highlight selected tower for button, buttonUnit in pairs( towerButtons ) do if buttonUnit == unit then button.BackgroundColor3 = Color3.fromRGB( 62, 100, 175 ) else button.BackgroundColor3 = Color3.fromRGB( 40, 42, 53 ) end end end --================================================== -- CREATE TOWER BUTTON --================================================== local function createTowerButton( unit ) local button = Instance.new("TextButton") button.Name = unit.Name -- TOUCH FRIENDLY button.Size = UDim2.new( 1, -4, 0, 42 ) button.BackgroundColor3 = Color3.fromRGB( 40, 42, 53 ) button.BorderSizePixel = 0 button.Text = unit.Name button.TextColor3 = Color3.fromRGB( 240, 240, 245 ) button.TextSize = 11 button.Font = Enum.Font.GothamMedium button.TextTruncate = Enum.TextTruncate.AtEnd button.AutoButtonColor = false button.Parent = towerList local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(0, 7) corner.Parent = button towerButtons[button] = unit -- PC HOVER button.MouseEnter:Connect(function() if selectedUnit ~= unit then TweenService:Create( button, TweenInfo.new(0.1), { BackgroundColor3 = Color3.fromRGB( 50, 53, 66 ) } ):Play() end end) button.MouseLeave:Connect(function() if selectedUnit ~= unit then TweenService:Create( button, TweenInfo.new(0.1), { BackgroundColor3 = Color3.fromRGB( 40, 42, 53 ) } ):Play() end end) -- PC + MOBILE button.Activated:Connect(function() showUnitStats(unit) end) end --================================================== -- REFRESH TOWERS --================================================== local function refreshTowers() for button in pairs( towerButtons ) do if button and button.Parent then button:Destroy() end end table.clear( towerButtons ) local objects = getAllUnitsAndTowers() if #objects == 0 then listTitle.Text = "NO TOWERS FOUND" return end for _, object in ipairs( objects ) do createTowerButton( object ) end listTitle.Text = "TOWERS • " .. tostring(#objects) -- Reset list position after refresh task.defer(function() towerList.CanvasPosition = Vector2.new(0, 0) end) end refreshTowers() --================================================== -- AUTO REFRESH --================================================== local function isInsideUnitTowerFolder( object ) local current = object while current and current ~= ReplicatedStorage do if isUnitTowerFolder( current ) then return true end current = current.Parent end return false end ReplicatedStorage.DescendantAdded:Connect( function(object) if isUnitTowerFolder(object) or isInsideUnitTowerFolder( object ) then task.defer( refreshTowers ) end end ) ReplicatedStorage.DescendantRemoving:Connect( function(object) if isUnitTowerFolder(object) or isInsideUnitTowerFolder( object ) then task.defer( refreshTowers ) end end ) --================================================== -- SPAWN AREA --================================================== local spawnArea = Instance.new("Frame") spawnArea.Name = "SpawnArea" spawnArea.AnchorPoint = Vector2.new(0, 1) spawnArea.Position = UDim2.new( 0, 7, 1, -7 ) spawnArea.Size = UDim2.new( 1, -14, 0, 50 ) spawnArea.BackgroundColor3 = Color3.fromRGB( 25, 27, 36 ) spawnArea.BorderSizePixel = 0 spawnArea.Parent = right local spawnAreaCorner = Instance.new("UICorner") spawnAreaCorner.CornerRadius = UDim.new(0, 9) spawnAreaCorner.Parent = spawnArea local spawnButton = Instance.new("TextButton") spawnButton.Name = "SpawnButton" spawnButton.Position = UDim2.fromOffset(6, 6) spawnButton.Size = UDim2.new( 1, -12, 1, -12 ) spawnButton.BackgroundColor3 = Color3.fromRGB( 55, 165, 95 ) spawnButton.BorderSizePixel = 0 spawnButton.Text = "SPAWN SELECTED" spawnButton.TextColor3 = Color3.new(1, 1, 1) spawnButton.TextSize = 11 spawnButton.Font = Enum.Font.GothamBold spawnButton.AutoButtonColor = false spawnButton.Parent = spawnArea local spawnCorner = Instance.new("UICorner") spawnCorner.CornerRadius = UDim.new(0, 8) spawnCorner.Parent = spawnButton --================================================== -- SPAWN BUTTON HOVER --================================================== spawnButton.MouseEnter:Connect( function() TweenService:Create( spawnButton, TweenInfo.new(0.1), { BackgroundColor3 = Color3.fromRGB( 65, 185, 105 ) } ):Play() end ) spawnButton.MouseLeave:Connect( function() TweenService:Create( spawnButton, TweenInfo.new(0.1), { BackgroundColor3 = Color3.fromRGB( 55, 165, 95 ) } ):Play() end ) --================================================== -- SPAWN SELECTED --================================================== spawnButton.Activated:Connect( function() if not selectedUnitName then selectedTitle.Text = "SELECT A UNIT OR TOWER" return end local character = player.Character or player.CharacterAdded:Wait() local root = character:FindFirstChild( "HumanoidRootPart" ) if not root then return end local functions = ReplicatedStorage:FindFirstChild( "Functions" ) if not functions then warn( "Functions folder was not found." ) return end local spawnFunction = functions:FindFirstChild( "SpawnTower" ) if not spawnFunction then warn( "SpawnTower was not found." ) return end if not spawnFunction:IsA( "RemoteFunction" ) then warn( "SpawnTower is not a RemoteFunction." ) return end local success, result = pcall( function() return spawnFunction:InvokeServer( selectedUnitName, root.CFrame ) end ) if not success then warn( "SpawnTower error:", result ) end end ) --================================================== -- HIDE / SHOW BUTTON --================================================== local showButton = Instance.new("TextButton") showButton.Name = "ShowHub" showButton.AnchorPoint = Vector2.new(0, 0.5) showButton.Position = UDim2.new( 0, 10, 0.5, 0 ) showButton.Size = UDim2.fromOffset( 52, 52 ) showButton.BackgroundColor3 = Color3.fromRGB( 35, 38, 49 ) showButton.BorderSizePixel = 0 showButton.Text = "☰" showButton.TextColor3 = Color3.new(1, 1, 1) showButton.TextSize = 22 showButton.Font = Enum.Font.GothamBold showButton.Visible = false showButton.Parent = gui local showCorner = Instance.new("UICorner") showCorner.CornerRadius = UDim.new(1, 0) showCorner.Parent = showButton local showStroke = Instance.new("UIStroke") showStroke.Color = Color3.fromRGB( 65, 68, 82 ) showStroke.Parent = showButton hideButton.Activated:Connect( function() main.Visible = false showButton.Visible = true end ) showButton.Activated:Connect( function() main.Visible = true showButton.Visible = false end ) --================================================== -- PC + MOBILE DRAGGING --================================================== local dragging = false local dragStart = nil local startPosition = nil local dragInput = nil top.InputBegan:Connect( function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = true dragStart = input.Position startPosition = main.Position dragInput = input end end ) top.InputEnded:Connect( function(input) if input == dragInput or input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = false dragInput = nil end end ) UserInputService.InputChanged:Connect( function(input) if not dragging then return end if input.UserInputType ~= Enum.UserInputType.MouseMovement and input.UserInputType ~= Enum.UserInputType.Touch then return end if not dragStart or not startPosition then return end local delta = input.Position - dragStart main.Position = UDim2.new( startPosition.X.Scale, startPosition.X.Offset + delta.X, startPosition.Y.Scale, startPosition.Y.Offset + delta.Y ) end ) --================================================== -- FINISHED --================================================== print( "Tower Hub - Small PC + Mobile + Smooth Scrolling loaded." )