Compare commits
102 Commits
EndcodeVer
...
main
Author | SHA1 | Date | |
---|---|---|---|
e5a04f3c38 | |||
d5ada53b07 | |||
a931a0feea | |||
9f03cf1531 | |||
53ff0cb6bd | |||
8f1c861b42 | |||
59bfa525f6 | |||
17ad0a3655 | |||
6f3685a6aa | |||
b78e92563d | |||
81b8789ec8 | |||
6423b3d9c9 | |||
ee7ad89e46 | |||
2244d88b23 | |||
db14ba3273 | |||
0bc253e584 | |||
e15d8886c5 | |||
327fa6b61b | |||
41759f8a78 | |||
08765aa5d4 | |||
a68150492a | |||
05bbdc4c31 | |||
a53f6cfb97 | |||
dd3fd119d7 | |||
ae56628d9f | |||
bad471b80b | |||
bdb8a87f80 | |||
56eccc024a | |||
113c076d41 | |||
f8a4db11d7 | |||
f35ab94a7f | |||
d45e55cf73 | |||
a1eb2e8ff0 | |||
48f91e7979 | |||
87fcadda59 | |||
177e21c53c | |||
4b70f05aae | |||
1f1162658f | |||
62125a101f | |||
8ee66ee686 | |||
6a85838afd | |||
3af33797a7 | |||
8aa6bd6168 | |||
4b46fbcd72 | |||
85254beed5 | |||
a69d9e2f8c | |||
c70a9eb3ce | |||
712cba45e2 | |||
4c00c477ba | |||
b273c158b5 | |||
deb9dc38f0 | |||
beb0dd6445 | |||
b06a4a37b5 | |||
50a37d9014 | |||
809a4ef749 | |||
a84e3d3e74 | |||
986d561810 | |||
e1aab4e61f | |||
d47b1ee35f | |||
f574100a75 | |||
9433db9df2 | |||
6fb423d938 | |||
7f443d2330 | |||
4995b73286 | |||
f3158f60d7 | |||
f6e093ce04 | |||
0dbf6432e5 | |||
a2118f2458 | |||
d7e13c99af | |||
a7bdf62209 | |||
5932a155a6 | |||
dad1c4642a | |||
30c1b69d60 | |||
33cad9f320 | |||
bacbf3c628 | |||
83de91fe82 | |||
13f4a5818a | |||
e9a343872e | |||
113ba8d604 | |||
ca75cbe280 | |||
285af3b2ce | |||
a225dc5572 | |||
a1f9929fa7 | |||
e99e058f4b | |||
a282fd8822 | |||
41d1bb0737 | |||
e9adb61326 | |||
adf0d2efb7 | |||
16ea27aa24 | |||
336563787f | |||
16626538cb | |||
689c293709 | |||
7fcf199420 | |||
7abc310c2d | |||
f279c4bf2e | |||
df8f7e2406 | |||
ef63da0a6b | |||
8d3692f2c2 | |||
7c264edeef | |||
1ee7bd11d2 | |||
af37b81ff0 | |||
9a498f0b98 |
449
BladeBall/JustHub
Normal file
449
BladeBall/JustHub
Normal file
@ -0,0 +1,449 @@
|
|||||||
|
local RunService = game:GetService("RunService")
|
||||||
|
local Players = game:GetService("Players")
|
||||||
|
local TweenService = game:GetService("TweenService")
|
||||||
|
local VirtualInputManager = game:GetService("VirtualInputManager")
|
||||||
|
|
||||||
|
local Player = Players.LocalPlayer
|
||||||
|
if not Player then error("LocalPlayer tidak ditemukan!") end
|
||||||
|
|
||||||
|
-- Cache fungsi matematika untuk performa
|
||||||
|
local min = math.min
|
||||||
|
local max = math.max
|
||||||
|
local abs = math.abs
|
||||||
|
local deg = math.deg
|
||||||
|
local acos = math.acos
|
||||||
|
local sqrt = math.sqrt
|
||||||
|
local clamp = math.clamp
|
||||||
|
|
||||||
|
-- Flag debug (set false jika tidak ingin banyak log)
|
||||||
|
local DEBUG = true
|
||||||
|
local function AdvancedLog(level, message, data)
|
||||||
|
if not DEBUG then return end
|
||||||
|
local timestamp = os.date("%Y-%m-%d %H:%M:%S")
|
||||||
|
print(string.format("[%s] [%s]: %s", timestamp, level, message))
|
||||||
|
if data then
|
||||||
|
for k, v in pairs(data) do
|
||||||
|
print(string.format(" %s: %s", k, tostring(v)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Konstanta State
|
||||||
|
local STATE_IDLE = "Idle"
|
||||||
|
local STATE_TRACKING = "Tracking"
|
||||||
|
local STATE_ANTICIPATING = "Anticipating"
|
||||||
|
local STATE_PARIED = "Parried"
|
||||||
|
local STATE_COOLDOWN = "Cooldown"
|
||||||
|
local STATE_SPAM = "Spam"
|
||||||
|
|
||||||
|
local MAX_IMPACT_TIME = 4.0 -- Maksimum waktu impact (detik)
|
||||||
|
local INCOMING_ANGLE_THRESHOLD = 20 -- Threshold sudut (derajat)
|
||||||
|
|
||||||
|
---------------------------------
|
||||||
|
-- Advanced Parry Controller (State Machine)
|
||||||
|
---------------------------------
|
||||||
|
local AdvancedParryController = {}
|
||||||
|
AdvancedParryController.__index = AdvancedParryController
|
||||||
|
|
||||||
|
function AdvancedParryController.new()
|
||||||
|
local self = setmetatable({}, AdvancedParryController)
|
||||||
|
self.Player = Player
|
||||||
|
self.State = STATE_IDLE
|
||||||
|
self.LastParryTime = tick()
|
||||||
|
self.CooldownTime = 0.75 -- Cooldown normal (detik)
|
||||||
|
self.BaseThreshold = 0.45 -- Threshold dasar (detik)
|
||||||
|
self.BallStopped = false
|
||||||
|
self.PreviousVelocity = nil
|
||||||
|
self.SmoothedAccel = Vector3.new(0, 0, 0)
|
||||||
|
self.CurrentBall = nil
|
||||||
|
self.Connection = nil
|
||||||
|
self.LastSpamTime = 0
|
||||||
|
self.BaseSpamInterval = 0.1
|
||||||
|
|
||||||
|
-- GUI Full Screen Popup
|
||||||
|
self.FullScreenGui = nil
|
||||||
|
self.AdditionalInfoLabel = nil
|
||||||
|
|
||||||
|
-- Overpower Mode: parry akan menjadi jauh lebih agresif dan responsif
|
||||||
|
self.OverpowerMode = true
|
||||||
|
self.OverpowerThresholdMultiplier = 0.5 -- Mengurangi threshold agar trigger lebih cepat
|
||||||
|
self.OverpowerCooldown = 0.1 -- Cooldown sangat rendah pada mode ini
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Dapatkan ping lokal (detik)
|
||||||
|
function AdvancedParryController:GetLocalPing()
|
||||||
|
local success, ping = pcall(function() return self.Player:GetNetworkPing() end)
|
||||||
|
if not success then
|
||||||
|
AdvancedLog("WARN", "Gagal mendapatkan ping, default 0.1 detik.", nil)
|
||||||
|
return 0.1
|
||||||
|
end
|
||||||
|
return ping or 0.1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Hitung threshold dinamis berdasarkan ping (dikurangi jika OverpowerMode aktif)
|
||||||
|
function AdvancedParryController:ComputeDynamicThreshold()
|
||||||
|
local adjustmentFactor = 0.5
|
||||||
|
local threshold = self.BaseThreshold + (self:GetLocalPing() * adjustmentFactor)
|
||||||
|
if self.OverpowerMode then
|
||||||
|
threshold = threshold * self.OverpowerThresholdMultiplier
|
||||||
|
end
|
||||||
|
return threshold
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Seleksi bola target terbaik (paling mengancam) dari folder "Balls"
|
||||||
|
function AdvancedParryController:SelectTargetBall()
|
||||||
|
local ballsFolder = workspace:FindFirstChild("Balls")
|
||||||
|
local bestBall = nil
|
||||||
|
local bestTImpact = math.huge
|
||||||
|
if ballsFolder then
|
||||||
|
local character = self.Player.Character
|
||||||
|
local HRP = character and character:FindFirstChild("HumanoidRootPart")
|
||||||
|
if not HRP then return nil, math.huge end
|
||||||
|
for _, ball in ipairs(ballsFolder:GetChildren()) do
|
||||||
|
if ball:GetAttribute("realBall") and ball:GetAttribute("target") == self.Player.Name then
|
||||||
|
local distance = (HRP.Position - ball.Position).Magnitude
|
||||||
|
local ballVelocity
|
||||||
|
local success = pcall(function() ballVelocity = ball.zoomies.VectorVelocity end)
|
||||||
|
if success and typeof(ballVelocity) == "Vector3" then
|
||||||
|
-- Untuk seleksi, asumsikan percepatan nol
|
||||||
|
local tImpact = self:PredictImpactTime(distance, ballVelocity, Vector3.new(0,0,0))
|
||||||
|
if tImpact < bestTImpact then
|
||||||
|
bestTImpact = tImpact
|
||||||
|
bestBall = ball
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return bestBall, bestTImpact
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Reset koneksi event bila diperlukan
|
||||||
|
function AdvancedParryController:ResetConnection()
|
||||||
|
if self.Connection then
|
||||||
|
self.Connection:Disconnect()
|
||||||
|
self.Connection = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Inisialisasi listener bola untuk mendeteksi perubahan atribut target
|
||||||
|
function AdvancedParryController:InitializeBallListener()
|
||||||
|
self:ResetConnection()
|
||||||
|
local ball = self:SelectTargetBall() -- Menggunakan target terbaik
|
||||||
|
if ball then
|
||||||
|
self.CurrentBall = ball
|
||||||
|
self.Connection = ball:GetAttributeChangedSignal("target"):Connect(function()
|
||||||
|
self.State = STATE_TRACKING
|
||||||
|
AdvancedLog("INFO", "Atribut target bola berubah, reset state ke TRACKING.", {Ball = ball.Name})
|
||||||
|
end)
|
||||||
|
AdvancedLog("INFO", "Listener bola diinisialisasi.", {Ball = ball.Name})
|
||||||
|
else
|
||||||
|
self.CurrentBall = nil
|
||||||
|
AdvancedLog("WARN", "Bola tidak ditemukan. Listener tidak diinisialisasi.", nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Inisialisasi GUI full-screen (popup hitam) dengan animasi smooth.
|
||||||
|
-- Tampilan: layar penuh yang sedikit transparan, di tengah ada tulisan "Status : Auto Parry",
|
||||||
|
-- label tambahan untuk informasi penting (misal: Ping & State) dan tombol Exit.
|
||||||
|
function AdvancedParryController:InitializeGUI()
|
||||||
|
local playerGui = self.Player:WaitForChild("PlayerGui")
|
||||||
|
local screenGui = Instance.new("ScreenGui")
|
||||||
|
screenGui.Name = "FullScreenPopupGui"
|
||||||
|
screenGui.ResetOnSpawn = false
|
||||||
|
screenGui.IgnoreGuiInset = true -- Menutupi seluruh layar (termasuk area inset)
|
||||||
|
screenGui.Parent = playerGui
|
||||||
|
|
||||||
|
-- Frame full screen dengan background hitam (mulai dari transparansi penuh untuk animasi)
|
||||||
|
local fullScreenFrame = Instance.new("Frame")
|
||||||
|
fullScreenFrame.Name = "FullScreenFrame"
|
||||||
|
fullScreenFrame.BackgroundColor3 = Color3.new(0, 0, 0)
|
||||||
|
fullScreenFrame.BackgroundTransparency = 1 -- Mulai transparan, akan tween ke 0.2
|
||||||
|
fullScreenFrame.Size = UDim2.new(1, 0, 1, 0)
|
||||||
|
fullScreenFrame.Position = UDim2.new(0, 0, 0, 0)
|
||||||
|
fullScreenFrame.Parent = screenGui
|
||||||
|
|
||||||
|
-- Label utama untuk status (di tengah layar)
|
||||||
|
local statusLabel = Instance.new("TextLabel")
|
||||||
|
statusLabel.Name = "StatusLabel"
|
||||||
|
statusLabel.BackgroundTransparency = 1
|
||||||
|
statusLabel.Text = "Just - Hub : Auto Parry"
|
||||||
|
statusLabel.TextColor3 = Color3.new(1, 1, 1)
|
||||||
|
statusLabel.Font = Enum.Font.SourceSansBold
|
||||||
|
statusLabel.TextSize = 36
|
||||||
|
statusLabel.AnchorPoint = Vector2.new(0.5, 0.5)
|
||||||
|
statusLabel.Position = UDim2.new(0.5, 0, 0.35, 0)
|
||||||
|
-- Mulai dengan scale 0 (ukuran 0) untuk animasi scale-in
|
||||||
|
statusLabel.Size = UDim2.new(0, 0, 0, 0)
|
||||||
|
statusLabel.Parent = fullScreenFrame
|
||||||
|
|
||||||
|
-- Label tambahan untuk informasi penting (misal: ping dan state)
|
||||||
|
local additionalInfoLabel = Instance.new("TextLabel")
|
||||||
|
additionalInfoLabel.Name = "AdditionalInfoLabel"
|
||||||
|
additionalInfoLabel.BackgroundTransparency = 1
|
||||||
|
additionalInfoLabel.Text = "Loading info..."
|
||||||
|
additionalInfoLabel.TextColor3 = Color3.new(1, 1, 1)
|
||||||
|
additionalInfoLabel.Font = Enum.Font.SourceSans
|
||||||
|
additionalInfoLabel.TextSize = 24
|
||||||
|
additionalInfoLabel.AnchorPoint = Vector2.new(0.5, 0.5)
|
||||||
|
additionalInfoLabel.Position = UDim2.new(0.5, 0, 0.5, 0)
|
||||||
|
additionalInfoLabel.Size = UDim2.new(0, 400, 0, 50)
|
||||||
|
additionalInfoLabel.Parent = fullScreenFrame
|
||||||
|
self.AdditionalInfoLabel = additionalInfoLabel
|
||||||
|
|
||||||
|
-- Tombol Exit di bawah label tambahan
|
||||||
|
local exitButton = Instance.new("TextButton")
|
||||||
|
exitButton.Name = "ExitButton"
|
||||||
|
exitButton.Text = "Exit"
|
||||||
|
exitButton.TextColor3 = Color3.new(1, 1, 1)
|
||||||
|
exitButton.Font = Enum.Font.SourceSansBold
|
||||||
|
exitButton.TextSize = 28
|
||||||
|
exitButton.BackgroundColor3 = Color3.new(0.3, 0.3, 0.3)
|
||||||
|
exitButton.Size = UDim2.new(0, 150, 0, 50)
|
||||||
|
exitButton.AnchorPoint = Vector2.new(0.5, 0)
|
||||||
|
exitButton.Position = UDim2.new(0.5, 0, 0.65, 0)
|
||||||
|
exitButton.Parent = fullScreenFrame
|
||||||
|
|
||||||
|
exitButton.MouseButton1Click:Connect(function()
|
||||||
|
Player:Kick("Anda telah keluar dari game.")
|
||||||
|
end)
|
||||||
|
|
||||||
|
self.FullScreenGui = screenGui
|
||||||
|
|
||||||
|
-- Tween untuk animasi fade-in (background transparency dari 1 ke 0.2)
|
||||||
|
local tweenInfo = TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.Out)
|
||||||
|
local tweenFrame = TweenService:Create(fullScreenFrame, tweenInfo, {BackgroundTransparency = 0.2})
|
||||||
|
tweenFrame:Play()
|
||||||
|
|
||||||
|
-- Tween untuk animasi scale-in label utama (dari 0 ke ukuran asli)
|
||||||
|
local tweenLabel = TweenService:Create(statusLabel, tweenInfo, {Size = UDim2.new(0, 400, 0, 100)})
|
||||||
|
tweenLabel:Play()
|
||||||
|
|
||||||
|
-- Tween untuk animasi scale-in label informasi tambahan (sedikit scale-up)
|
||||||
|
local tweenInfoLabel = TweenService:Create(additionalInfoLabel, tweenInfo, {TextTransparency = 0})
|
||||||
|
tweenInfoLabel:Play()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Fungsi untuk mengirim event parry (klik mouse) dengan delay minimal
|
||||||
|
function AdvancedParryController:AttemptParry()
|
||||||
|
VirtualInputManager:SendMouseButtonEvent(0, 0, 0, true, game, 0)
|
||||||
|
task.delay(0.01, function()
|
||||||
|
VirtualInputManager:SendMouseButtonEvent(0, 0, 0, false, game, 0)
|
||||||
|
end)
|
||||||
|
self.LastParryTime = tick()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Lakukan exponential smoothing pada percepatan (lebih agresif pada mode overpowered)
|
||||||
|
function AdvancedParryController:SmoothAcceleration(currentVelocity, dt)
|
||||||
|
local alpha = self.OverpowerMode and 0.8 or 0.4
|
||||||
|
if not self.PreviousVelocity then
|
||||||
|
self.PreviousVelocity = currentVelocity
|
||||||
|
return Vector3.new(0, 0, 0)
|
||||||
|
end
|
||||||
|
local instantAccel = (currentVelocity - self.PreviousVelocity) / dt
|
||||||
|
self.SmoothedAccel = self.SmoothedAccel:Lerp(instantAccel, alpha)
|
||||||
|
self.PreviousVelocity = currentVelocity
|
||||||
|
return self.SmoothedAccel
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Prediksi waktu impact menggunakan rumus: s = vt + ½at²
|
||||||
|
function AdvancedParryController:PredictImpactTime(distance, currentVelocity, accel)
|
||||||
|
local v = currentVelocity.Magnitude
|
||||||
|
local a = accel.Magnitude
|
||||||
|
if abs(a) < 0.001 then
|
||||||
|
return (v > 0) and (distance / v) or math.huge
|
||||||
|
end
|
||||||
|
local discriminant = v * v + 2 * a * distance
|
||||||
|
if discriminant < 0 then return math.huge end
|
||||||
|
local t1 = (-v + sqrt(discriminant)) / a
|
||||||
|
local t2 = (-v - sqrt(discriminant)) / a
|
||||||
|
local t = math.huge
|
||||||
|
if t1 > 0 then t = t1 end
|
||||||
|
if t2 > 0 and t2 < t then t = t2 end
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Prediksi posisi bola saat impact (asumsi percepatan konstan)
|
||||||
|
function AdvancedParryController:PredictImpactPosition(ballPos, currentVelocity, accel, t)
|
||||||
|
return ballPos + currentVelocity * t + 0.5 * accel * t * t
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Hitung sudut incoming: antara arah kecepatan bola dan vektor dari bola ke HRP
|
||||||
|
function AdvancedParryController:ComputeIncomingAngle(ballVelocity, HRP, ballPos)
|
||||||
|
local mag = ballVelocity.Magnitude
|
||||||
|
if mag <= 0 then return 180 end
|
||||||
|
local incomingVec = (HRP.Position - ballPos).Unit
|
||||||
|
local velDir = ballVelocity.Unit
|
||||||
|
local dot = clamp(velDir:Dot(incomingVec), -1, 1)
|
||||||
|
return deg(acos(dot))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update state berdasarkan data bola, karakter, prediksi, dan validasi ekstra
|
||||||
|
function AdvancedParryController:UpdateState(dt)
|
||||||
|
local now = tick()
|
||||||
|
local ball, tImpactCandidate = self:SelectTargetBall()
|
||||||
|
if not ball then
|
||||||
|
self.State = STATE_IDLE
|
||||||
|
AdvancedLog("DEBUG", "Tidak ada bola target ditemukan.", nil)
|
||||||
|
self:InitializeBallListener()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.CurrentBall = ball
|
||||||
|
|
||||||
|
local character = self.Player.Character
|
||||||
|
local HRP = character and character:FindFirstChild("HumanoidRootPart")
|
||||||
|
if not HRP then
|
||||||
|
self.State = STATE_IDLE
|
||||||
|
AdvancedLog("WARN", "HumanoidRootPart tidak ditemukan.", nil)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local success, ballVelocity = pcall(function() return ball.zoomies.VectorVelocity end)
|
||||||
|
if not success or typeof(ballVelocity) ~= "Vector3" then
|
||||||
|
AdvancedLog("ERROR", "VectorVelocity bola tidak valid.", {Error = tostring(ballVelocity)})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local speed = ballVelocity.Magnitude
|
||||||
|
local dynamicThreshold = self:ComputeDynamicThreshold()
|
||||||
|
local threshold = min(dynamicThreshold, MAX_IMPACT_TIME)
|
||||||
|
local distance = (HRP.Position - ball.Position).Magnitude
|
||||||
|
|
||||||
|
-- Hitung percepatan, waktu impact, dan incoming angle
|
||||||
|
local prevVelocity = self.PreviousVelocity or ballVelocity
|
||||||
|
local accel = self:SmoothAcceleration(ballVelocity, dt)
|
||||||
|
local tImpact = self:PredictImpactTime(distance, ballVelocity, accel)
|
||||||
|
local incomingAngle = self:ComputeIncomingAngle(ballVelocity, HRP, ball.Position)
|
||||||
|
|
||||||
|
-- Validasi target bola
|
||||||
|
local targetAttr = ball:GetAttribute("target")
|
||||||
|
if type(targetAttr) ~= "string" or targetAttr ~= self.Player.Name then
|
||||||
|
self.State = STATE_IDLE
|
||||||
|
AdvancedLog("DEBUG", "Bola tidak mengincar local player.", {Target = tostring(targetAttr)})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- MODE OVERPOWER: Jika tImpact sudah sangat rendah, trigger parry langsung (bypass kondisi normal)
|
||||||
|
if self.OverpowerMode and tImpact <= threshold * 1.5 then
|
||||||
|
self:AttemptParry()
|
||||||
|
self.State = STATE_PARIED
|
||||||
|
AdvancedLog("ACTION", "OVERPOWER: Forced parry triggered.", {tImpact = tImpact, IncomingAngle = incomingAngle})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Jika bola berada dalam rentang 10-20 studs dengan incoming angle rendah
|
||||||
|
if distance >= 10 and distance <= 20 and incomingAngle < INCOMING_ANGLE_THRESHOLD then
|
||||||
|
self:AttemptParry()
|
||||||
|
self.State = STATE_PARIED
|
||||||
|
AdvancedLog("ACTION", "Direct parry triggered.", {Distance = distance, Angle = incomingAngle, tImpact = tImpact})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Mode SPAM: Jika bola sangat dekat (<= 10 studs)
|
||||||
|
if distance <= 10 then
|
||||||
|
if self.State ~= STATE_SPAM then
|
||||||
|
self.State = STATE_SPAM
|
||||||
|
AdvancedLog("INFO", "Entering SPAM mode.", {Distance = distance})
|
||||||
|
end
|
||||||
|
local spamInterval = max(self.BaseSpamInterval * (1 - (speed / 100)), 0.03)
|
||||||
|
if now - self.LastSpamTime >= spamInterval then
|
||||||
|
self:AttemptParry()
|
||||||
|
self.LastSpamTime = now
|
||||||
|
AdvancedLog("ACTION", "Spam parry triggered.", {Distance = distance, SpamInterval = spamInterval})
|
||||||
|
end
|
||||||
|
return
|
||||||
|
elseif self.State == STATE_SPAM then
|
||||||
|
self.State = STATE_TRACKING
|
||||||
|
AdvancedLog("INFO", "Exiting SPAM mode.", {Distance = distance})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Jika kecepatan bola sangat rendah, anggap bola berhenti
|
||||||
|
if speed < 0.1 then
|
||||||
|
if not self.BallStopped then
|
||||||
|
self.BallStopped = true
|
||||||
|
self.State = STATE_IDLE
|
||||||
|
AdvancedLog("INFO", "Ball stopped.", {Speed = speed})
|
||||||
|
end
|
||||||
|
return
|
||||||
|
elseif self.BallStopped then
|
||||||
|
self.BallStopped = false
|
||||||
|
if self.State == STATE_IDLE then
|
||||||
|
self.State = STATE_TRACKING
|
||||||
|
AdvancedLog("INFO", "Ball resumed.", {Speed = speed})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Hitung curve angle (perubahan arah) antara frame sebelumnya dan saat ini
|
||||||
|
local curveAngle = 0
|
||||||
|
if prevVelocity.Magnitude > 0 and ballVelocity.Magnitude > 0 then
|
||||||
|
local dot = clamp(prevVelocity.Unit:Dot(ballVelocity.Unit), -1, 1)
|
||||||
|
curveAngle = deg(acos(dot))
|
||||||
|
end
|
||||||
|
|
||||||
|
AdvancedLog("DEBUG", "Ball metrics updated.", {
|
||||||
|
Speed = speed,
|
||||||
|
CurveAngle = curveAngle,
|
||||||
|
Distance = distance,
|
||||||
|
tImpact = tImpact,
|
||||||
|
DynamicThreshold = dynamicThreshold,
|
||||||
|
IncomingAngle = incomingAngle,
|
||||||
|
State = self.State
|
||||||
|
})
|
||||||
|
|
||||||
|
if tImpact < dynamicThreshold * 0.5 and self.State ~= STATE_ANTICIPATING then
|
||||||
|
self.State = STATE_ANTICIPATING
|
||||||
|
AdvancedLog("INFO", "Entering ANTICIPATING.", {tImpact = tImpact})
|
||||||
|
end
|
||||||
|
|
||||||
|
if (self.State == STATE_TRACKING or self.State == STATE_ANTICIPATING) then
|
||||||
|
if tImpact <= threshold or (curveAngle >= 15 and tImpact <= MAX_IMPACT_TIME) then
|
||||||
|
self:AttemptParry()
|
||||||
|
self.State = STATE_PARIED
|
||||||
|
AdvancedLog("ACTION", "Parry triggered.", {tImpact = tImpact, CurveAngle = curveAngle})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.State == STATE_PARIED then
|
||||||
|
local effectiveCooldown = self.OverpowerMode and self.OverpowerCooldown or self.CooldownTime
|
||||||
|
if now - self.LastParryTime >= (threshold + effectiveCooldown) then
|
||||||
|
self.State = STATE_COOLDOWN
|
||||||
|
AdvancedLog("INFO", "Entering COOLDOWN.", {Elapsed = now - self.LastParryTime})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.State == STATE_COOLDOWN then
|
||||||
|
local effectiveCooldownFinish = self.OverpowerMode and (self.OverpowerCooldown + 0.05) or (self.CooldownTime + 0.5)
|
||||||
|
if now - self.LastParryTime >= (threshold + effectiveCooldownFinish) then
|
||||||
|
self.State = STATE_TRACKING
|
||||||
|
AdvancedLog("INFO", "Cooldown finished, resuming TRACKING.", nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if curveAngle > 45 and tImpact < threshold then
|
||||||
|
self.State = STATE_TRACKING
|
||||||
|
AdvancedLog("INFO", "Reset parry due to sharp curve.", {CurveAngle = curveAngle})
|
||||||
|
end
|
||||||
|
|
||||||
|
if distance <= 0 then
|
||||||
|
AdvancedLog("WARN", "Invalid distance.", {Distance = distance})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update label tambahan dengan informasi penting (misal: ping & state)
|
||||||
|
if self.AdditionalInfoLabel then
|
||||||
|
local pingMS = math.floor(self:GetLocalPing() * 1000)
|
||||||
|
self.AdditionalInfoLabel.Text = string.format("Ping: %d ms | State: %s", pingMS, self.State)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------
|
||||||
|
-- Main Update Loop
|
||||||
|
-------------------------------
|
||||||
|
local controller = AdvancedParryController.new()
|
||||||
|
controller:InitializeBallListener()
|
||||||
|
controller:InitializeGUI()
|
||||||
|
|
||||||
|
RunService.Heartbeat:Connect(function(dt)
|
||||||
|
pcall(function()
|
||||||
|
controller:UpdateState(dt)
|
||||||
|
end)
|
||||||
|
end)
|
@ -24,26 +24,12 @@ Changelog:addChangelog("Satr - Hub")
|
|||||||
Changelog:addChangelog('- Thanks for using this script')
|
Changelog:addChangelog('- Thanks for using this script')
|
||||||
Changelog:addChangelog('- Beta Test')
|
Changelog:addChangelog('- Beta Test')
|
||||||
Changelog:addChangelog('[January, 11 2025]')
|
Changelog:addChangelog('[January, 11 2025]')
|
||||||
Changelog:addChangelog('- Fixed Auto Farming')
|
|
||||||
Changelog:addChangelog('- Added Auto Attack')
|
Changelog:addChangelog('- Added Auto Attack')
|
||||||
|
Changelog:addChangelog('- Fixed Fast Attack')
|
||||||
|
|
||||||
local Home_Right = Tab.Tab_1:addSection() -- HOME RIGHT SECTION
|
local Home_Right = Tab.Tab_1:addSection() -- HOME RIGHT SECTION
|
||||||
local Main_Home = Home_Right:addMenu("#Home")
|
local Main_Home = Home_Right:addMenu("#Home")
|
||||||
|
|
||||||
-- Fungsi untuk memberikan notifikasi
|
|
||||||
local function notify(title, text, duration)
|
|
||||||
local success, errorMessage = pcall(function()
|
|
||||||
game:GetService("StarterGui"):SetCore("SendNotification", {
|
|
||||||
Title = title;
|
|
||||||
Text = text;
|
|
||||||
Duration = duration or 5;
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
if not success then
|
|
||||||
warn("Gagal mengirim notifikasi: " .. errorMessage)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local Players = game:GetService("Players")
|
local Players = game:GetService("Players")
|
||||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||||
local RunService = game:GetService("RunService")
|
local RunService = game:GetService("RunService")
|
||||||
@ -57,12 +43,12 @@ local COMBAT_CONFIG = {
|
|||||||
attacksPerTarget = 8,
|
attacksPerTarget = 8,
|
||||||
maxTargets = 10,
|
maxTargets = 10,
|
||||||
baseRange = 100,
|
baseRange = 100,
|
||||||
minDelay = 0.02,
|
minDelay = 0.02, -- << Some shit to make sure anti cheat won't reach and ping won't grow
|
||||||
maxDelay = 0.1,
|
maxDelay = 0.1, -- << Some shit to make sure anti cheat won't reach and ping won't grow
|
||||||
hitDelay = 0.01,
|
hitDelay = 0.01, -- << Some shit to make sure anti cheat won't reach and ping won't grow
|
||||||
randomization = {
|
randomization = {
|
||||||
range = {min = -2, max = 2},
|
range = {min = -2, max = 2}, -- << Some shit to make sure anti cheat won't reach and ping won't grow
|
||||||
timing = {min = -0.05, max = 0.05}
|
timing = {min = -0.05, max = 0.05} -- << Some shit to make sure anti cheat won't reach and ping won't grow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,18 +58,23 @@ end
|
|||||||
|
|
||||||
local function IsValidTarget(target)
|
local function IsValidTarget(target)
|
||||||
if not target then return false end
|
if not target then return false end
|
||||||
|
|
||||||
local humanoid = target:FindFirstChildOfClass("Humanoid")
|
local humanoid = target:FindFirstChildOfClass("Humanoid")
|
||||||
if not humanoid or humanoid.Health <= 0 then return false end
|
if not humanoid or humanoid.Health <= 0 then return false end
|
||||||
|
|
||||||
local targetPlayer = Players:GetPlayerFromCharacter(target)
|
local targetPlayer = Players:GetPlayerFromCharacter(target)
|
||||||
if targetPlayer and targetPlayer.Team == LocalPlayer.Team then return false end
|
if targetPlayer and targetPlayer.Team == LocalPlayer.Team then return false end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local function GetNearbyTargets()
|
local function GetNearbyTargets()
|
||||||
local character = LocalPlayer.Character
|
local character = LocalPlayer.Character
|
||||||
if not character or not character.PrimaryPart then return {} end
|
if not character or not character.PrimaryPart then return {} end
|
||||||
|
|
||||||
local charPos = character.PrimaryPart.Position
|
local charPos = character.PrimaryPart.Position
|
||||||
local targets = {}
|
local targets = {}
|
||||||
|
|
||||||
for _, folder in ipairs({workspace.Characters, workspace.Enemies}) do
|
for _, folder in ipairs({workspace.Characters, workspace.Enemies}) do
|
||||||
if folder then
|
if folder then
|
||||||
for _, entity in ipairs(folder:GetChildren()) do
|
for _, entity in ipairs(folder:GetChildren()) do
|
||||||
@ -95,6 +86,7 @@ local function GetNearbyTargets()
|
|||||||
COMBAT_CONFIG.randomization.range.min,
|
COMBAT_CONFIG.randomization.range.min,
|
||||||
COMBAT_CONFIG.randomization.range.max
|
COMBAT_CONFIG.randomization.range.max
|
||||||
)
|
)
|
||||||
|
|
||||||
if distance <= range then
|
if distance <= range then
|
||||||
table.insert(targets, {
|
table.insert(targets, {
|
||||||
part = primaryPart,
|
part = primaryPart,
|
||||||
@ -106,6 +98,7 @@ local function GetNearbyTargets()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
table.sort(targets, function(a, b) return a.distance < b.distance end)
|
table.sort(targets, function(a, b) return a.distance < b.distance end)
|
||||||
return targets
|
return targets
|
||||||
end
|
end
|
||||||
@ -125,11 +118,13 @@ end
|
|||||||
local lastAttackTime = 0
|
local lastAttackTime = 0
|
||||||
local function CombatLoop()
|
local function CombatLoop()
|
||||||
if not COMBAT_CONFIG.enabled then return end
|
if not COMBAT_CONFIG.enabled then return end
|
||||||
|
|
||||||
local now = tick()
|
local now = tick()
|
||||||
local baseDelay = math.random(
|
local baseDelay = math.random(
|
||||||
COMBAT_CONFIG.minDelay * 100,
|
COMBAT_CONFIG.minDelay * 100,
|
||||||
COMBAT_CONFIG.maxDelay * 100
|
COMBAT_CONFIG.maxDelay * 100
|
||||||
) / 100
|
) / 100
|
||||||
|
|
||||||
if now - lastAttackTime >= baseDelay then
|
if now - lastAttackTime >= baseDelay then
|
||||||
local targets = GetNearbyTargets()
|
local targets = GetNearbyTargets()
|
||||||
PerformAttackSequence(targets)
|
PerformAttackSequence(targets)
|
||||||
@ -153,6 +148,7 @@ end
|
|||||||
|
|
||||||
local function SetupCombat()
|
local function SetupCombat()
|
||||||
Cleanup()
|
Cleanup()
|
||||||
|
|
||||||
combatConnection = RunService.Heartbeat:Connect(CombatLoop)
|
combatConnection = RunService.Heartbeat:Connect(CombatLoop)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -163,61 +159,11 @@ end)
|
|||||||
|
|
||||||
SetupCombat()
|
SetupCombat()
|
||||||
|
|
||||||
-- Menambahkan Toggle untuk mengatur kecepatan dan jangkauan
|
Main_Home:addTextbox("Jump Hack", getgenv().JumpValue, function(jumpfunc)
|
||||||
Main_Home:addToggle("Auto Attack", COMBAT_CONFIG.enabled, function(value)
|
getgenv().JumpValue = tonumber(jumpfunc)
|
||||||
COMBAT_CONFIG.enabled = value
|
handleJumpHack()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
Main_Home:addTextbox("Attack Speed (ms)", tostring(COMBAT_CONFIG.minDelay * 1000), function(value)
|
|
||||||
local delay = tonumber(value) -- Konversi input teks menjadi angka
|
|
||||||
if delay and delay > 0 then
|
|
||||||
delay = delay / 1000 -- Konversi dari milidetik ke detik
|
|
||||||
COMBAT_CONFIG.minDelay = delay
|
|
||||||
COMBAT_CONFIG.maxDelay = delay + 0.05 -- Menyesuaikan sedikit jangkauan delay
|
|
||||||
else
|
|
||||||
warn("Invalid value for Attack Speed. Please enter a positive number.")
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
getgenv().HitboxExpanderEnabled = false
|
|
||||||
|
|
||||||
-- Fungsi untuk memperbarui hitbox musuh
|
|
||||||
local function updateHitbox(size, transparency, canCollide)
|
|
||||||
for _, v in pairs(game:GetService("Workspace").Enemies:GetDescendants()) do
|
|
||||||
if v.Name == "HumanoidRootPart" and v.Parent and v.Parent:FindFirstChild("Humanoid") then
|
|
||||||
v.Size = Vector3.new(size, size, size)
|
|
||||||
v.Transparency = transparency
|
|
||||||
v.CanCollide = canCollide
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Fungsi utama untuk mengontrol Hitbox Expander
|
|
||||||
local function HitboxExpander()
|
|
||||||
while getgenv().HitboxExpanderEnabled do
|
|
||||||
local success, errorMessage = pcall(function()
|
|
||||||
updateHitbox(100, 0.5, false) -- Hitbox musuh diperbesar
|
|
||||||
end)
|
|
||||||
if not success then
|
|
||||||
warn("Error pada HitboxExpander: " .. errorMessage)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
wait(0.5)
|
|
||||||
end
|
|
||||||
updateHitbox(2, 1, true) -- Reset ke nilai awal jika dinonaktifkan
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Toggle untuk hitbox expander
|
|
||||||
Main_Home:addToggle("Enable Hitbox Expander", getgenv().HitboxExpanderEnabled, function(value)
|
|
||||||
getgenv().HitboxExpanderEnabled = value
|
|
||||||
if value then
|
|
||||||
spawn(HitboxExpander)
|
|
||||||
notify("Hitbox Expander", "Fitur hitbox aktif!", 2)
|
|
||||||
else
|
|
||||||
notify("Hitbox Expander", "Fitur hitbox nonaktif!", 2)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
-- Menambahkan fitur Infinite Jump
|
-- Menambahkan fitur Infinite Jump
|
||||||
Main_Home:addToggle("Infinite Jump", InfiniteJumpEnabled, function(Value)
|
Main_Home:addToggle("Infinite Jump", InfiniteJumpEnabled, function(Value)
|
||||||
InfiniteJumpEnabled = Value
|
InfiniteJumpEnabled = Value
|
||||||
@ -227,6 +173,27 @@ Main_Home:addToggle("Infinite Jump", InfiniteJumpEnabled, function(Value)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
Main_Home:addToggle("Infinite Exp", false, function(Value)
|
||||||
|
local xpRem = eve:WaitForChild("Exp"):WaitForChild("ChangeExpRE")
|
||||||
|
local XP = 10000000
|
||||||
|
local running = false
|
||||||
|
|
||||||
|
local function start()
|
||||||
|
running = true
|
||||||
|
while running do
|
||||||
|
pcall(function()
|
||||||
|
fr(xpRem, XP)
|
||||||
|
end)
|
||||||
|
task.wait(0.1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if Value then
|
||||||
|
task.spawn(start)
|
||||||
|
else
|
||||||
|
running = false
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
Main_Home:addToggle('No Clip', getgenv().NoClip, function(clipf)
|
Main_Home:addToggle('No Clip', getgenv().NoClip, function(clipf)
|
||||||
getgenv().NoClip = clipf
|
getgenv().NoClip = clipf
|
708
Library/JustHub (1).lua
Normal file
708
Library/JustHub (1).lua
Normal file
@ -0,0 +1,708 @@
|
|||||||
|
local TweenService = game:GetService("TweenService")
|
||||||
|
local UserInputService = game:GetService("UserInputService")
|
||||||
|
local RunService = game:GetService("RunService")
|
||||||
|
local HttpService = game:GetService("HttpService")
|
||||||
|
local Players = game:GetService("Players")
|
||||||
|
local StarterGui = game:GetService("StarterGui")
|
||||||
|
|
||||||
|
local JustHub = {}
|
||||||
|
JustHub.Themes = {
|
||||||
|
Darker = {
|
||||||
|
["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(25,25,25)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(32,32,32)), ColorSequenceKeypoint.new(1, Color3.fromRGB(25,25,25))}),
|
||||||
|
["Color Hub 2"] = Color3.fromRGB(30,30,30),
|
||||||
|
["Color Stroke"] = Color3.fromRGB(40,40,40),
|
||||||
|
["Color Theme"] = Color3.fromRGB(88,101,242),
|
||||||
|
["Color Text"] = Color3.fromRGB(243,243,243),
|
||||||
|
["Color Dark Text"] = Color3.fromRGB(180,180,180)
|
||||||
|
},
|
||||||
|
Dark = {
|
||||||
|
["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(40,40,40)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(47,47,47)), ColorSequenceKeypoint.new(1, Color3.fromRGB(40,40,40))}),
|
||||||
|
["Color Hub 2"] = Color3.fromRGB(45,45,45),
|
||||||
|
["Color Stroke"] = Color3.fromRGB(65,65,65),
|
||||||
|
["Color Theme"] = Color3.fromRGB(65,150,255),
|
||||||
|
["Color Text"] = Color3.fromRGB(245,245,245),
|
||||||
|
["Color Dark Text"] = Color3.fromRGB(190,190,190)
|
||||||
|
},
|
||||||
|
Purple = {
|
||||||
|
["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(28,25,30)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(32,32,32)), ColorSequenceKeypoint.new(1, Color3.fromRGB(28,25,30))}),
|
||||||
|
["Color Hub 2"] = Color3.fromRGB(30,30,30),
|
||||||
|
["Color Stroke"] = Color3.fromRGB(40,40,40),
|
||||||
|
["Color Theme"] = Color3.fromRGB(150,0,255),
|
||||||
|
["Color Text"] = Color3.fromRGB(240,240,240),
|
||||||
|
["Color Dark Text"] = Color3.fromRGB(180,180,180)
|
||||||
|
},
|
||||||
|
Light = {
|
||||||
|
["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(230,230,230)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(245,245,245)), ColorSequenceKeypoint.new(1, Color3.fromRGB(230,230,230))}),
|
||||||
|
["Color Hub 2"] = Color3.fromRGB(240,240,240),
|
||||||
|
["Color Stroke"] = Color3.fromRGB(200,200,200),
|
||||||
|
["Color Theme"] = Color3.fromRGB(0,120,255),
|
||||||
|
["Color Text"] = Color3.fromRGB(30,30,30),
|
||||||
|
["Color Dark Text"] = Color3.fromRGB(80,80,80)
|
||||||
|
},
|
||||||
|
Neon = {
|
||||||
|
["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(10,10,10)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(0,200,200)), ColorSequenceKeypoint.new(1, Color3.fromRGB(10,10,10))}),
|
||||||
|
["Color Hub 2"] = Color3.fromRGB(15,15,15),
|
||||||
|
["Color Stroke"] = Color3.fromRGB(0,255,255),
|
||||||
|
["Color Theme"] = Color3.fromRGB(0,255,0),
|
||||||
|
["Color Text"] = Color3.fromRGB(255,255,255),
|
||||||
|
["Color Dark Text"] = Color3.fromRGB(200,200,200)
|
||||||
|
},
|
||||||
|
Forest = {
|
||||||
|
["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(0,50,0)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(0,80,0)), ColorSequenceKeypoint.new(1, Color3.fromRGB(0,50,0))}),
|
||||||
|
["Color Hub 2"] = Color3.fromRGB(0,60,0),
|
||||||
|
["Color Stroke"] = Color3.fromRGB(0,80,0),
|
||||||
|
["Color Theme"] = Color3.fromRGB(0,120,0),
|
||||||
|
["Color Text"] = Color3.fromRGB(220,220,220),
|
||||||
|
["Color Dark Text"] = Color3.fromRGB(160,160,160)
|
||||||
|
},
|
||||||
|
Aqua = {
|
||||||
|
["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(0,100,100)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(0,150,150)), ColorSequenceKeypoint.new(1, Color3.fromRGB(0,100,100))}),
|
||||||
|
["Color Hub 2"] = Color3.fromRGB(0,110,110),
|
||||||
|
["Color Stroke"] = Color3.fromRGB(0,180,180),
|
||||||
|
["Color Theme"] = Color3.fromRGB(0,220,220),
|
||||||
|
["Color Text"] = Color3.fromRGB(255,255,255),
|
||||||
|
["Color Dark Text"] = Color3.fromRGB(200,200,200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JustHub.Info = {Version="1.1.0"}
|
||||||
|
JustHub.Save = {UISize={550,380},TabSize=100,Theme="Darker"}
|
||||||
|
JustHub.ConfigData = {}
|
||||||
|
JustHub.ControlRegistry = {}
|
||||||
|
|
||||||
|
local function createInstance(c,p,par)
|
||||||
|
local i=Instance.new(c)
|
||||||
|
if p then
|
||||||
|
for k,v in pairs(p) do
|
||||||
|
i[k]=v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if par then
|
||||||
|
i.Parent=par
|
||||||
|
end
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
|
||||||
|
local function tweenProperty(o,t,d)
|
||||||
|
local ti=TweenInfo.new(d,Enum.EasingStyle.Quad,Enum.EasingDirection.Out)
|
||||||
|
local tw=TweenService:Create(o,ti,t)
|
||||||
|
tw:Play()
|
||||||
|
return tw
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getCurrentTheme(c)
|
||||||
|
if type(c)=="table" then
|
||||||
|
return c
|
||||||
|
else
|
||||||
|
return JustHub.Themes[c or JustHub.Save.Theme]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function clampPosition(pos,sz)
|
||||||
|
local x=math.clamp(pos.X.Offset,0,sz.X)
|
||||||
|
local y=math.clamp(pos.Y.Offset,0,sz.Y)
|
||||||
|
return UDim2.new(pos.X.Scale,x,pos.Y.Scale,y)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function addBorder(o,col,th)
|
||||||
|
return createInstance("UIStroke",{Color=col,Thickness=th},o)
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:RegisterControl(k,u)
|
||||||
|
JustHub.ControlRegistry[k]=u
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:ApplyConfig(cf)
|
||||||
|
for k,v in pairs(cf) do
|
||||||
|
if JustHub.ControlRegistry[k] then
|
||||||
|
JustHub.ControlRegistry[k](v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function parseKey(str)
|
||||||
|
for _,kc in pairs(Enum.KeyCode:GetEnumItems()) do
|
||||||
|
if kc.Name:lower()==str:lower() then
|
||||||
|
return kc
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local SectionMethods={}
|
||||||
|
|
||||||
|
function SectionMethods:addMenu(n)
|
||||||
|
n=n or "Menu"
|
||||||
|
local f=createInstance("Frame",{Name=n,Size=UDim2.new(1,0,0,40),BackgroundColor3=getCurrentTheme(JustHub.Save.Theme)["Color Stroke"],BackgroundTransparency=0.3},self.Content)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,6)},f)
|
||||||
|
createInstance("TextLabel",{Name="MenuLabel",Text=n,Size=UDim2.new(1,0,1,0),BackgroundTransparency=1,TextColor3=getCurrentTheme(JustHub.Save.Theme)["Color Text"],Font=Enum.Font.GothamBold,TextSize=16},f)
|
||||||
|
return f
|
||||||
|
end
|
||||||
|
|
||||||
|
function SectionMethods:addToggle(o)
|
||||||
|
o=o or {}
|
||||||
|
local t=o.Name or "Toggle"
|
||||||
|
local d=o.Default or false
|
||||||
|
local cb=o.Callback or function(x)end
|
||||||
|
local f=createInstance("Frame",{Name=t.."Toggle",Size=UDim2.new(1,0,0,20),BackgroundColor3=Color3.fromRGB(40,40,40)},self.Content)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,20)},f)
|
||||||
|
addBorder(f,getCurrentTheme(JustHub.Save.Theme)["Color Stroke"],1)
|
||||||
|
local l=createInstance("TextLabel",{Size=UDim2.new(0.7,0,1,0),Position=UDim2.new(0,0,0,0),BackgroundTransparency=1,Text=t,TextColor3=getCurrentTheme(JustHub.Save.Theme)["Color Text"],Font=Enum.Font.Gotham,TextSize=12,TextXAlignment=Enum.TextXAlignment.Left},f)
|
||||||
|
local sep=createInstance("Frame",{Size=UDim2.new(0,2,1,0),Position=UDim2.new(0.7,0,0,0),BackgroundColor3=Color3.fromRGB(255,255,255)},f)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,1)},sep)
|
||||||
|
local tc=createInstance("Frame",{Size=UDim2.new(0.3,0,1,0),Position=UDim2.new(0.7,0,0,0),BackgroundTransparency=1},f)
|
||||||
|
local sw=createInstance("Frame",{Size=UDim2.new(0,35,0,15),Position=UDim2.new(1,-35,0.5,-7.5),BackgroundColor3=d and Color3.fromRGB(0,200,0) or Color3.fromRGB(100,100,100),BorderSizePixel=0},tc)
|
||||||
|
sw.Active=true
|
||||||
|
sw.Selectable=true
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,15)},sw)
|
||||||
|
local c=createInstance("Frame",{Size=UDim2.new(0,13,0,13),Position=d and UDim2.new(0,20,0.5,-6.5) or UDim2.new(0,2,0.5,-6.5),BackgroundColor3=Color3.new(1,1,1),BorderSizePixel=0},sw)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(1,0)},c)
|
||||||
|
local s=d
|
||||||
|
if d then cb(true) else cb(false) end
|
||||||
|
JustHub.ConfigData[t]=s
|
||||||
|
JustHub:RegisterControl(t,function(v)
|
||||||
|
s=v
|
||||||
|
if s then
|
||||||
|
c.Position=UDim2.new(0,20,0.5,-6.5)
|
||||||
|
sw.BackgroundColor3=Color3.fromRGB(0,200,0)
|
||||||
|
l.TextColor3=Color3.fromRGB(0,255,0)
|
||||||
|
else
|
||||||
|
c.Position=UDim2.new(0,2,0.5,-6.5)
|
||||||
|
sw.BackgroundColor3=Color3.fromRGB(100,100,100)
|
||||||
|
l.TextColor3=Color3.fromRGB(255,255,255)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
sw.InputBegan:Connect(function(i)
|
||||||
|
if i.UserInputType==Enum.UserInputType.MouseButton1 or i.UserInputType==Enum.UserInputType.Touch then
|
||||||
|
if not s then
|
||||||
|
tweenProperty(c,{Position=UDim2.new(0,20,0.5,-6.5)},0.3)
|
||||||
|
tweenProperty(sw,{BackgroundColor3=Color3.fromRGB(0,200,0)},0.3)
|
||||||
|
tweenProperty(l,{TextColor3=Color3.fromRGB(0,255,0)},0.3)
|
||||||
|
else
|
||||||
|
tweenProperty(c,{Position=UDim2.new(0,2,0.5,-6.5)},0.3)
|
||||||
|
tweenProperty(sw,{BackgroundColor3=Color3.fromRGB(100,100,100)},0.3)
|
||||||
|
tweenProperty(l,{TextColor3=Color3.fromRGB(255,255,255)},0.3)
|
||||||
|
end
|
||||||
|
s=not s
|
||||||
|
JustHub.ConfigData[t]=s
|
||||||
|
cb(s)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
return f
|
||||||
|
end
|
||||||
|
|
||||||
|
function SectionMethods:addSlider(o)
|
||||||
|
o=o or {}
|
||||||
|
local n=o.Name or "Slider"
|
||||||
|
local mi=o.Min or 0
|
||||||
|
local ma=o.Max or 100
|
||||||
|
local df=o.Default or mi
|
||||||
|
if JustHub.ConfigData[n]~=nil then
|
||||||
|
df=JustHub.ConfigData[n]
|
||||||
|
else
|
||||||
|
JustHub.ConfigData[n]=df
|
||||||
|
end
|
||||||
|
local cb=o.Callback or function(x)end
|
||||||
|
local f=createInstance("Frame",{Name=n.."Slider",Size=UDim2.new(1,0,0,25),BackgroundTransparency=1},self.Content)
|
||||||
|
addBorder(f,getCurrentTheme(JustHub.Save.Theme)["Color Stroke"],1)
|
||||||
|
local l=createInstance("TextLabel",{Name="Label",Text=n,Size=UDim2.new(0.7,0,1,0),Position=UDim2.new(0,0,0,0),BackgroundTransparency=1,TextColor3=getCurrentTheme(JustHub.Save.Theme)["Color Text"],Font=Enum.Font.Gotham,TextSize=10},f)
|
||||||
|
local sep=createInstance("Frame",{Size=UDim2.new(0,2,1,0),Position=UDim2.new(0.7,0,0,0),BackgroundColor3=Color3.fromRGB(255,255,255)},f)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,1)},sep)
|
||||||
|
local sc=createInstance("Frame",{Name="SliderContainer",Size=UDim2.new(0.3,0,1,0),Position=UDim2.new(0.7,0,0,0),BackgroundTransparency=1},f)
|
||||||
|
local sb=createInstance("Frame",{Name="SliderBar",Size=UDim2.new(1,-20,0,4),Position=UDim2.new(0,10,0.5,-2),BackgroundColor3=getCurrentTheme(JustHub.Save.Theme)["Color Stroke"]},sc)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,4)},sb)
|
||||||
|
local sh=createInstance("Frame",{Name="SliderHandle",Size=UDim2.new(0,12,0,12),BackgroundColor3=getCurrentTheme(JustHub.Save.Theme)["Color Theme"],Position=UDim2.new((df-mi)/(ma-mi),-6,0.5,-6)},sb)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,4)},sh)
|
||||||
|
local drag=false
|
||||||
|
sh.InputBegan:Connect(function(i)
|
||||||
|
if i.UserInputType==Enum.UserInputType.MouseButton1 or i.UserInputType==Enum.UserInputType.Touch then drag=true end
|
||||||
|
end)
|
||||||
|
sh.InputEnded:Connect(function(i)
|
||||||
|
if i.UserInputType==Enum.UserInputType.MouseButton1 or i.UserInputType==Enum.UserInputType.Touch then drag=false end
|
||||||
|
end)
|
||||||
|
UserInputService.InputChanged:Connect(function(i)
|
||||||
|
if drag and (i.UserInputType==Enum.UserInputType.MouseMovement or i.UserInputType==Enum.UserInputType.Touch) then
|
||||||
|
local bp=sb.AbsolutePosition.X
|
||||||
|
local bw=sb.AbsoluteSize.X
|
||||||
|
local rp=math.clamp((i.Position.X-bp)/bw,0,1)
|
||||||
|
sh.Position=UDim2.new(rp,-6,sh.Position.Y.Scale,sh.Position.Y.Offset)
|
||||||
|
local val=mi+rp*(ma-mi)
|
||||||
|
JustHub.ConfigData[n]=val
|
||||||
|
cb(val)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
JustHub:RegisterControl(n,function(sv)
|
||||||
|
local nr=(sv-mi)/(ma-mi)
|
||||||
|
sh.Position=UDim2.new(nr,-6,0.5,-6)
|
||||||
|
end)
|
||||||
|
return f
|
||||||
|
end
|
||||||
|
|
||||||
|
function SectionMethods:addTextBox(o)
|
||||||
|
o=o or {}
|
||||||
|
local n=o.Name or "TextBox"
|
||||||
|
local d=o.Default or ""
|
||||||
|
local cb=o.Callback or function(x)end
|
||||||
|
local f=createInstance("Frame",{Name=n.."TextBox",Size=UDim2.new(1,0,0,20),BackgroundTransparency=1},self.Content)
|
||||||
|
addBorder(f,getCurrentTheme(JustHub.Save.Theme)["Color Stroke"],1)
|
||||||
|
local l=createInstance("TextLabel",{Name="Label",Text=n,Size=UDim2.new(0.7,0,1,0),Position=UDim2.new(0,0,0,0),BackgroundTransparency=1,TextColor3=getCurrentTheme(JustHub.Save.Theme)["Color Text"],Font=Enum.Font.Gotham,TextSize=10},f)
|
||||||
|
local tb=createInstance("TextBox",{Name="Input",Text=d,Size=UDim2.new(0.3,0,1,0),Position=UDim2.new(0.7,0,0,0),BackgroundColor3=getCurrentTheme(JustHub.Save.Theme)["Color Stroke"],TextColor3=getCurrentTheme(JustHub.Save.Theme)["Color Text"],Font=Enum.Font.Gotham,TextSize=10},f)
|
||||||
|
tb.FocusLost:Connect(function(e)
|
||||||
|
JustHub.ConfigData[n]=tb.Text
|
||||||
|
cb(tb.Text)
|
||||||
|
end)
|
||||||
|
JustHub:RegisterControl(n,function(sv)
|
||||||
|
tb.Text=sv
|
||||||
|
end)
|
||||||
|
return f
|
||||||
|
end
|
||||||
|
|
||||||
|
function SectionMethods:addDropdown(o)
|
||||||
|
o=o or {}
|
||||||
|
local t=o.Name or "Dropdown"
|
||||||
|
local df=o.Default or ""
|
||||||
|
local it=o.Items or {}
|
||||||
|
local cb=o.Callback or function(x)end
|
||||||
|
local ch=20
|
||||||
|
local oh=ch+(#it*20+((#it-1)*2))
|
||||||
|
local f=createInstance("Frame",{Name=t.."Dropdown",BackgroundTransparency=1},self.Content)
|
||||||
|
f.Size=UDim2.new(1,0,0,ch)
|
||||||
|
addBorder(f,getCurrentTheme(JustHub.Save.Theme)["Color Stroke"],1)
|
||||||
|
local l=createInstance("TextLabel",{Name="Label",Text=t,Size=UDim2.new(0.7,0,0,ch),Position=UDim2.new(0,0,0,0),BackgroundTransparency=1,TextColor3=getCurrentTheme(JustHub.Save.Theme)["Color Text"],Font=Enum.Font.Gotham,TextSize=10},f)
|
||||||
|
local b=createInstance("TextButton",{Name="DropdownButton",Text=(df~="" and (df.." ▼") or "Select ▼"),Size=UDim2.new(0.3,0,0,ch),Position=UDim2.new(0.7,0,0,0),BackgroundColor3=getCurrentTheme(JustHub.Save.Theme)["Color Stroke"],Font=Enum.Font.GothamBold,TextSize=10},f)
|
||||||
|
local lf=createInstance("Frame",{Name="DropdownList",BackgroundColor3=getCurrentTheme(JustHub.Save.Theme)["Color Hub 2"],Visible=false,Position=UDim2.new(0,0,0,ch)},f)
|
||||||
|
lf.Size=UDim2.new(1,0,0,#it*20+((#it-1)*2))
|
||||||
|
createInstance("UIListLayout",{Padding=UDim.new(0,2),SortOrder=Enum.SortOrder.LayoutOrder,HorizontalAlignment=Enum.HorizontalAlignment.Left},lf)
|
||||||
|
local dt=false
|
||||||
|
b.MouseButton1Click:Connect(function()
|
||||||
|
if dt then
|
||||||
|
tweenProperty(f,{Size=UDim2.new(1,0,0,ch)},0.2)
|
||||||
|
tweenProperty(b,{TextColor3=getCurrentTheme(JustHub.Save.Theme)["Color Text"]},0.2)
|
||||||
|
tweenProperty(lf,{Position=UDim2.new(0,0,0,ch-10)},0.2)
|
||||||
|
wait(0.2)
|
||||||
|
lf.Visible=false
|
||||||
|
else
|
||||||
|
lf.Position=UDim2.new(0,0,0,ch-10)
|
||||||
|
lf.Visible=true
|
||||||
|
tweenProperty(f,{Size=UDim2.new(1,0,0,oh)},0.2)
|
||||||
|
tweenProperty(b,{TextColor3=Color3.fromRGB(0,255,0)},0.2)
|
||||||
|
tweenProperty(lf,{Position=UDim2.new(0,0,0,ch)},0.2)
|
||||||
|
end
|
||||||
|
dt=not dt
|
||||||
|
end)
|
||||||
|
for _,op in ipairs(it) do
|
||||||
|
local btn=createInstance("TextButton",{Size=UDim2.new(1,0,0,20),Text=op,TextColor3=Color3.fromRGB(255,255,255),BackgroundTransparency=1,Font=Enum.Font.Gotham,TextSize=10},lf)
|
||||||
|
btn.MouseButton1Click:Connect(function()
|
||||||
|
l.Text=t.." - "..op
|
||||||
|
JustHub.ConfigData[t]=op
|
||||||
|
pcall(cb,op)
|
||||||
|
tweenProperty(f,{Size=UDim2.new(1,0,0,ch)},0.2)
|
||||||
|
dt=false
|
||||||
|
wait(0.2)
|
||||||
|
lf.Visible=false
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
JustHub.ConfigData[t]=df
|
||||||
|
JustHub:RegisterControl(t,function(sv)
|
||||||
|
l.Text=t.." - "..sv
|
||||||
|
end)
|
||||||
|
local upd={}
|
||||||
|
function upd:Clear()
|
||||||
|
for i,v in pairs(lf:GetChildren()) do
|
||||||
|
if v:IsA("TextButton") then
|
||||||
|
v:Destroy()
|
||||||
|
dt=false
|
||||||
|
l.Text=t
|
||||||
|
tweenProperty(f,{Size=UDim2.new(1,0,0,ch)},0.2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function upd:Refresh(nl)
|
||||||
|
nl=nl or {}
|
||||||
|
for i,v in pairs(nl) do
|
||||||
|
local btn=createInstance("TextButton",{Size=UDim2.new(1,0,0,25),Text=v,TextColor3=Color3.fromRGB(255,255,255),BackgroundTransparency=1,Font=Enum.Font.SourceSansSemibold,TextSize=12},lf)
|
||||||
|
btn.MouseButton1Click:Connect(function()
|
||||||
|
dt=false
|
||||||
|
l.Text=t.." - "..v
|
||||||
|
pcall(cb,v)
|
||||||
|
tweenProperty(f,{Size=UDim2.new(1,0,0,ch)},0.2)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return upd
|
||||||
|
end
|
||||||
|
|
||||||
|
function SectionMethods:addButton(o)
|
||||||
|
o=o or {}
|
||||||
|
local n=o.Name or "Button"
|
||||||
|
local bt=o.ButtonText or "Click"
|
||||||
|
local cb=o.Callback or function()end
|
||||||
|
local c=createInstance("Frame",{Name=n.."ButtonControl",Size=UDim2.new(1,0,0,30),BackgroundTransparency=1},self.Content)
|
||||||
|
addBorder(c,getCurrentTheme(JustHub.Save.Theme)["Color Stroke"],1)
|
||||||
|
local l=createInstance("TextLabel",{Name="Label",Text=n,Size=UDim2.new(0.7,0,1,0),Position=UDim2.new(0,0,0,0),BackgroundTransparency=1,TextColor3=getCurrentTheme(JustHub.Save.Theme)["Color Text"],Font=Enum.Font.Gotham,TextSize=10,TextXAlignment=Enum.TextXAlignment.Left},c)
|
||||||
|
local b=createInstance("TextButton",{Name="ActionButton",Text=bt,Size=UDim2.new(0.3,0,0.8,0),Position=UDim2.new(0.7,0,0.1,0),BackgroundColor3=getCurrentTheme(JustHub.Save.Theme)["Color Theme"],TextColor3=getCurrentTheme(JustHub.Save.Theme)["Color Text"],Font=Enum.Font.GothamBold,TextSize=10},c)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,6)},b)
|
||||||
|
b.MouseButton1Click:Connect(function()
|
||||||
|
pcall(cb)
|
||||||
|
end)
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
|
function SectionMethods:addBind(o)
|
||||||
|
o=o or {}
|
||||||
|
local n=o.Name or "KeyBind"
|
||||||
|
local d=o.Default or "RightShift"
|
||||||
|
local cb=o.Callback or function()end
|
||||||
|
local c=createInstance("Frame",{Name=n.."BindControl",Size=UDim2.new(1,0,0,30),BackgroundTransparency=1},self.Content)
|
||||||
|
addBorder(c,getCurrentTheme(JustHub.Save.Theme)["Color Stroke"],1)
|
||||||
|
local l=createInstance("TextLabel",{Name="Label",Text=n,Size=UDim2.new(0.7,0,1,0),Position=UDim2.new(0,0,0,0),BackgroundTransparency=1,TextColor3=getCurrentTheme(JustHub.Save.Theme)["Color Text"],Font=Enum.Font.Gotham,TextSize=10,TextXAlignment=Enum.TextXAlignment.Left},c)
|
||||||
|
local tb=createInstance("TextBox",{Name="BindInput",Text=d,Size=UDim2.new(0.3,0,1,0),Position=UDim2.new(0.7,0,0,0),BackgroundColor3=getCurrentTheme(JustHub.Save.Theme)["Color Stroke"],TextColor3=getCurrentTheme(JustHub.Save.Theme)["Color Text"],Font=Enum.Font.Gotham,TextSize=10},c)
|
||||||
|
local currentKey
|
||||||
|
local conn
|
||||||
|
local function parseKey(str)
|
||||||
|
for _,k in pairs(Enum.KeyCode:GetEnumItems()) do
|
||||||
|
if k.Name:lower()==str:lower() then
|
||||||
|
return k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local function setKey(k)
|
||||||
|
local kc=parseKey(k)
|
||||||
|
if kc then
|
||||||
|
if conn then conn:Disconnect() end
|
||||||
|
currentKey=kc
|
||||||
|
conn=UserInputService.InputBegan:Connect(function(i,g)
|
||||||
|
if not g and i.KeyCode==currentKey then
|
||||||
|
pcall(cb)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
JustHub.ConfigData[n]=k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
setKey(d)
|
||||||
|
tb.FocusLost:Connect(function(enterPressed)
|
||||||
|
setKey(tb.Text)
|
||||||
|
end)
|
||||||
|
JustHub:RegisterControl(n,function(sv)
|
||||||
|
tb.Text=sv
|
||||||
|
setKey(sv)
|
||||||
|
end)
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:addSection(sn,sh)
|
||||||
|
sn=sn or "Section"
|
||||||
|
sh=sh or 100
|
||||||
|
local sf=createInstance("Frame",{Name=sn,Size=UDim2.new(1,0,0,sh),BackgroundColor3=getCurrentTheme(JustHub.Save.Theme)["Color Hub 2"],BackgroundTransparency=0},nil)
|
||||||
|
addBorder(sf,getCurrentTheme(JustHub.Save.Theme)["Color Stroke"],2)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,8)},sf)
|
||||||
|
local st=createInstance("TextLabel",{Name="SectionTitle",Text=sn,Size=UDim2.new(1,0,0,30),BackgroundTransparency=1,TextColor3=getCurrentTheme(JustHub.Save.Theme)["Color Text"],Font=Enum.Font.GothamBold,TextSize=16,TextXAlignment=Enum.TextXAlignment.Left},sf)
|
||||||
|
local sc=createInstance("Frame",{Name="SectionContent",Size=UDim2.new(1,0,1,-30),Position=UDim2.new(0,0,0,30),BackgroundTransparency=1},sf)
|
||||||
|
createInstance("UIListLayout",{FillDirection=Enum.FillDirection.Vertical,Padding=UDim.new(0,5),SortOrder=Enum.SortOrder.LayoutOrder,HorizontalAlignment=Enum.HorizontalAlignment.Left},sc)
|
||||||
|
local so={Frame=sf,Title=st,Content=sc}
|
||||||
|
setmetatable(so,{__index=SectionMethods})
|
||||||
|
return so
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:CreateWindow(o)
|
||||||
|
o=o or {}
|
||||||
|
local wn=o.Name or "JustHub Window"
|
||||||
|
local th=getCurrentTheme(o.Theme)
|
||||||
|
local gid=HttpService:GenerateGUID(false)
|
||||||
|
local ft=wn.." ["..gid.."]"
|
||||||
|
local pl=Players.LocalPlayer
|
||||||
|
local pg=pl:WaitForChild("PlayerGui")
|
||||||
|
local sg=createInstance("ScreenGui",{Name="JustHub",ResetOnSpawn=false},pg)
|
||||||
|
self.ScreenGui=sg
|
||||||
|
local uw=JustHub.Save.UISize[1]
|
||||||
|
local uh=JustHub.Save.UISize[2]
|
||||||
|
local mf=createInstance("Frame",{Name="MainFrame",AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.new(0.5,0,-0.5,0),Size=UDim2.new(0,uw,0,uh),BackgroundColor3=th["Color Hub 2"]},sg)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,12)},mf)
|
||||||
|
addBorder(mf,th["Color Stroke"],2)
|
||||||
|
local tb=createInstance("Frame",{Name="TopBar",Size=UDim2.new(1,0,0,60),BackgroundColor3=th["Color Hub 2"]},mf)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,12)},tb)
|
||||||
|
local tl=createInstance("TextLabel",{Name="TitleLabel",Size=UDim2.new(1,-180,1,0),Position=UDim2.new(0,10,0,0),BackgroundTransparency=1,Text=ft,TextColor3=th["Color Text"],Font=Enum.Font.GothamBold,TextSize=18,TextXAlignment=Enum.TextXAlignment.Left},tb)
|
||||||
|
local wl=createInstance("TextLabel",{Name="WelcomeLabel",Size=UDim2.new(0,150,0,20),AnchorPoint=Vector2.new(0,1),Position=UDim2.new(0,10,1,-30),BackgroundTransparency=1,Text="Welcome, "..pl.Name,TextColor3=th["Color Text"],Font=Enum.Font.GothamBold,TextSize=16,TextXAlignment=Enum.TextXAlignment.Left},mf)
|
||||||
|
local function ccb(n,s,p)
|
||||||
|
local b=createInstance("TextButton",{Name=n,Text=s,Size=UDim2.new(0,40,0,40),Position=p,BackgroundTransparency=1,TextColor3=th["Color Text"],Font=Enum.Font.GothamBold,TextSize=24},tb)
|
||||||
|
return b
|
||||||
|
end
|
||||||
|
local hb=ccb("HideButton","–",UDim2.new(1,-110,0,10))
|
||||||
|
local xb=ccb("MaxButton","□",UDim2.new(1,-70,0,10))
|
||||||
|
local cb=ccb("CloseButton","X",UDim2.new(1,-30,0,10))
|
||||||
|
local sw=JustHub.Save.TabSize
|
||||||
|
local sb=createInstance("Frame",{Name="Sidebar",Size=UDim2.new(0,sw,1,-60),Position=UDim2.new(0,0,0,60),BackgroundColor3=th["Color Hub 2"]},mf)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,10)},sb)
|
||||||
|
createInstance("UIListLayout",{FillDirection=Enum.FillDirection.Vertical,Padding=UDim.new(0,10),HorizontalAlignment=Enum.HorizontalAlignment.Center,VerticalAlignment=Enum.VerticalAlignment.Top},sb)
|
||||||
|
local cc=createInstance("Frame",{Name="ContentContainer",Size=UDim2.new(1,-sw,1,-60),Position=UDim2.new(0,sw,0,60),BackgroundColor3=th["Color Hub 2"]},mf)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,10)},cc)
|
||||||
|
local sf=createInstance("ScrollingFrame",{Size=UDim2.new(1,0,1,0),BackgroundTransparency=1,ScrollBarThickness=8,BorderSizePixel=0},cc)
|
||||||
|
createInstance("UIListLayout",{SortOrder=Enum.SortOrder.LayoutOrder,Padding=UDim.new(0,10),HorizontalAlignment=Enum.HorizontalAlignment.Left},sf)
|
||||||
|
local fl=createInstance("TextLabel",{Name="FPSLabel",Size=UDim2.new(0,100,0,20),AnchorPoint=Vector2.new(1,1),Position=UDim2.new(1,-10,1,-10),BackgroundTransparency=1,TextColor3=th["Color Text"],Font=Enum.Font.Gotham,TextSize=14,Text="FPS: Calculating..."},mf)
|
||||||
|
RunService.Heartbeat:Connect(function(d)
|
||||||
|
local fps=math.floor(1/d)
|
||||||
|
fl.Text="FPS: "..fps
|
||||||
|
end)
|
||||||
|
local i=TweenInfo.new(0.5,Enum.EasingStyle.Back,Enum.EasingDirection.Out)
|
||||||
|
local tin=TweenService:Create(mf,i,{Position=UDim2.new(0.5,0,0.5,0)})
|
||||||
|
tin:Play()
|
||||||
|
local minimized=false
|
||||||
|
local maximized=false
|
||||||
|
local osz=mf.Size
|
||||||
|
local op=mf.Position
|
||||||
|
hb.MouseButton1Click:Connect(function()
|
||||||
|
if not minimized then
|
||||||
|
tweenProperty(mf,{Size=UDim2.new(osz.X.Scale,osz.X.Offset,0,60)},0.3)
|
||||||
|
wl.Visible=false
|
||||||
|
sb.Visible=false
|
||||||
|
cc.Visible=false
|
||||||
|
fl.Visible=false
|
||||||
|
minimized=true
|
||||||
|
else
|
||||||
|
tweenProperty(mf,{Size=osz},0.3)
|
||||||
|
wait(0.3)
|
||||||
|
wl.Visible=true
|
||||||
|
sb.Visible=true
|
||||||
|
cc.Visible=true
|
||||||
|
fl.Visible=true
|
||||||
|
minimized=false
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
xb.MouseButton1Click:Connect(function()
|
||||||
|
if not maximized then
|
||||||
|
tweenProperty(mf,{Size=UDim2.new(1,0,1,0),Position=UDim2.new(0.5,0,0.5,0)},0.3)
|
||||||
|
maximized=true
|
||||||
|
else
|
||||||
|
tweenProperty(mf,{Size=osz,Position=op},0.3)
|
||||||
|
maximized=false
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
cb.MouseButton1Click:Connect(function()
|
||||||
|
local toi=TweenInfo.new(0.5,Enum.EasingStyle.Back,Enum.EasingDirection.In)
|
||||||
|
local tout=TweenService:Create(mf,toi,{Position=UDim2.new(0.5,0,-0.5,0)})
|
||||||
|
tout:Play()
|
||||||
|
tout.Completed:Connect(function()
|
||||||
|
mf.Visible=false
|
||||||
|
local plr=Players.LocalPlayer
|
||||||
|
local pg2=plr:WaitForChild("PlayerGui")
|
||||||
|
local sg2=Instance.new("ScreenGui")
|
||||||
|
sg2.Name="ShowUI"
|
||||||
|
sg2.ResetOnSpawn=false
|
||||||
|
sg2.Parent=pg2
|
||||||
|
local showBtn=Instance.new("TextButton")
|
||||||
|
showBtn.Name="ShowUIButton"
|
||||||
|
showBtn.Size=UDim2.new(0,150,0,50)
|
||||||
|
showBtn.Position=UDim2.new(0.5,-75,0,0)
|
||||||
|
showBtn.BackgroundColor3=th["Color Hub 2"]
|
||||||
|
showBtn.Text="Show UI"
|
||||||
|
showBtn.TextColor3=Color3.fromRGB(128,0,128)
|
||||||
|
showBtn.Font=Enum.Font.GothamBold
|
||||||
|
showBtn.TextSize=20
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,25)},showBtn)
|
||||||
|
createInstance("UIStroke",{Color=th["Color Theme"],Thickness=1},showBtn)
|
||||||
|
showBtn.Parent=sg2
|
||||||
|
showBtn.MouseButton1Click:Connect(function()
|
||||||
|
mf.Visible=true
|
||||||
|
tweenProperty(mf,{Position=UDim2.new(0.5,0,0.5,0)},0.5)
|
||||||
|
sg2:Destroy()
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
mf.Active=true
|
||||||
|
local dragging=false
|
||||||
|
local dragStart,startPos
|
||||||
|
mf.InputBegan:Connect(function(input)
|
||||||
|
if input.UserInputType==Enum.UserInputType.MouseButton1 or input.UserInputType==Enum.UserInputType.Touch then
|
||||||
|
dragging=true
|
||||||
|
dragStart=input.Position
|
||||||
|
startPos=mf.Position
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
mf.InputChanged:Connect(function(input)
|
||||||
|
if dragging and (input.UserInputType==Enum.UserInputType.MouseMovement or input.UserInputType==Enum.UserInputType.Touch) then
|
||||||
|
local delta=input.Position-dragStart
|
||||||
|
local np=UDim2.new(startPos.X.Scale,startPos.X.Offset+delta.X,startPos.Y.Scale,startPos.Y.Offset+delta.Y)
|
||||||
|
np=clampPosition(np,Vector2.new(sg.AbsoluteSize.X,sg.AbsoluteSize.Y))
|
||||||
|
mf.Position=np
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
UserInputService.InputEnded:Connect(function(input)
|
||||||
|
if input.UserInputType==Enum.UserInputType.MouseButton1 or input.UserInputType==Enum.UserInputType.Touch then
|
||||||
|
dragging=false
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
local notiContainer=createInstance("Frame",{Name="NotificationContainer",AnchorPoint=Vector2.new(1,1),Position=UDim2.new(1,-10,1,-10),Size=UDim2.new(0,300,1,-20),BackgroundTransparency=1},sg)
|
||||||
|
local notiLayout=createInstance("UIListLayout",{Padding=UDim.new(0,8),HorizontalAlignment=Enum.HorizontalAlignment.Right,VerticalAlignment=Enum.VerticalAlignment.Bottom,SortOrder=Enum.SortOrder.LayoutOrder},notiContainer)
|
||||||
|
self.NotificationContainer=notiContainer
|
||||||
|
local wObj={ScreenGui=sg,MainFrame=mf,TopBar=tb,Sidebar=sb,ContentContainer=cc,Tabs={}}
|
||||||
|
function wObj:addTab(tn)
|
||||||
|
tn=tn or "Tab"
|
||||||
|
local b=createInstance("TextButton",{Name=tn.."Button",Text=tn,Size=UDim2.new(1,0,0,20),BackgroundColor3=th["Color Stroke"],TextColor3=Color3.fromRGB(128,0,128),Font=Enum.Font.GothamBold,TextSize=12},sb)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,10)},b)
|
||||||
|
createInstance("UIStroke",{Color=th["Color Theme"],Thickness=1},b)
|
||||||
|
local tc=createInstance("Frame",{Name=tn.."Content",Size=UDim2.new(1,0,1,0),BackgroundTransparency=1,Visible=false},sf)
|
||||||
|
local tObj={Name=tn,Button=b,Content=tc,Sections={}}
|
||||||
|
table.insert(wObj.Tabs,tObj)
|
||||||
|
b.MouseButton1Click:Connect(function()
|
||||||
|
for _,tt in ipairs(wObj.Tabs) do
|
||||||
|
tt.Content.Visible=false
|
||||||
|
end
|
||||||
|
tObj.Content.Visible=true
|
||||||
|
end)
|
||||||
|
if #wObj.Tabs==1 then
|
||||||
|
tObj.Content.Visible=true
|
||||||
|
end
|
||||||
|
function tObj:addSection(sn,sh)
|
||||||
|
sn=sn or "Section"
|
||||||
|
sh=sh or 80
|
||||||
|
local sframe=createInstance("Frame",{Name=sn,Size=UDim2.new(1,0,0,sh),BackgroundColor3=th["Color Hub 2"],BackgroundTransparency=0.0},tc)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,8)},sframe)
|
||||||
|
addBorder(sframe,th["Color Stroke"],2)
|
||||||
|
local st=createInstance("TextLabel",{Name="SectionTitle",Text=sn,Size=UDim2.new(1,0,0,30),BackgroundTransparency=1,TextColor3=th["Color Text"],Font=Enum.Font.GothamBold,TextSize=14,TextXAlignment=Enum.TextXAlignment.Left},sframe)
|
||||||
|
local sc=createInstance("Frame",{Name="SectionContent",Size=UDim2.new(1,0,1,-30),Position=UDim2.new(0,0,0,30),BackgroundTransparency=1},sframe)
|
||||||
|
createInstance("UIListLayout",{FillDirection=Enum.FillDirection.Vertical,Padding=UDim.new(0,5),SortOrder=Enum.SortOrder.LayoutOrder,HorizontalAlignment=Enum.HorizontalAlignment.Left},sc)
|
||||||
|
local sObj={Frame=sframe,Title=st,Content=sc}
|
||||||
|
table.insert(tObj.Sections,sObj)
|
||||||
|
setmetatable(sObj,{__index=SectionMethods})
|
||||||
|
return sObj
|
||||||
|
end
|
||||||
|
return tObj
|
||||||
|
end
|
||||||
|
return wObj
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:ShowLoadingScreen(d,cb)
|
||||||
|
d=d or 5
|
||||||
|
cb=cb or function()end
|
||||||
|
local pl=Players.LocalPlayer
|
||||||
|
local pg=pl:WaitForChild("PlayerGui")
|
||||||
|
local lg=createInstance("ScreenGui",{Name="LoadingScreen",ResetOnSpawn=false,IgnoreGuiInset=true},pg)
|
||||||
|
local bg=createInstance("Frame",{Size=UDim2.new(1,0,1,0),Position=UDim2.new(0,0,0,0),BackgroundColor3=Color3.new(0,0,0),BackgroundTransparency=0.5,BorderSizePixel=0},lg)
|
||||||
|
local tl=createInstance("TextLabel",{Text="JustHub Library",Font=Enum.Font.SourceSansSemibold,TextSize=20,TextColor3=getCurrentTheme(JustHub.Save.Theme)["Color Text"],BackgroundTransparency=1,Size=UDim2.new(0,200,0,50),AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.new(0.5,0,0.5,-50)},lg)
|
||||||
|
local wl=createInstance("TextLabel",{Text="Welcome, "..pl.Name,Font=Enum.Font.SourceSansSemibold,TextSize=16,TextColor3=getCurrentTheme(JustHub.Save.Theme)["Color Text"],BackgroundTransparency=1,Size=UDim2.new(0,200,0,30),AnchorPoint=Vector2.new(0.5,0),Position=UDim2.new(0.5,0,0.5,10)},lg)
|
||||||
|
local pbc=createInstance("Frame",{Size=UDim2.new(0.5,0,0,20),Position=UDim2.new(0.5,0,0.5,50),AnchorPoint=Vector2.new(0.5,0.5),BackgroundColor3=getCurrentTheme(JustHub.Save.Theme)["Color Stroke"],BackgroundTransparency=0.5,BorderSizePixel=0},lg)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,4)},pbc)
|
||||||
|
local pbf=createInstance("Frame",{Size=UDim2.new(0,0,1,0),BackgroundColor3=getCurrentTheme(JustHub.Save.Theme)["Color Theme"],BorderSizePixel=0},pbc)
|
||||||
|
createInstance("UICorner",{CornerRadius=UDim.new(0,4)},pbf)
|
||||||
|
local tinfo=TweenInfo.new(d,Enum.EasingStyle.Quad,Enum.EasingDirection.Out)
|
||||||
|
local pt=TweenService:Create(pbf,tinfo,{Size=UDim2.new(1,0,1,0)})
|
||||||
|
pt:Play()
|
||||||
|
spawn(function()
|
||||||
|
while pt.PlaybackState==Enum.PlaybackState.Playing do
|
||||||
|
tweenProperty(tl,{TextTransparency=0.5},0.5)
|
||||||
|
wait(0.5)
|
||||||
|
tweenProperty(tl,{TextTransparency=0},0.5)
|
||||||
|
wait(0.5)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
pt.Completed:Connect(function()
|
||||||
|
wait(0.5)
|
||||||
|
lg:Destroy()
|
||||||
|
cb()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:InitializeUI(o)
|
||||||
|
self:ShowLoadingScreen(5,function()
|
||||||
|
local w=self:CreateWindow(o)
|
||||||
|
self.Window=w
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:SaveConfig(f)
|
||||||
|
f=f or "JustHub_Config.json"
|
||||||
|
if writefile then
|
||||||
|
local j=HttpService:JSONEncode(JustHub.ConfigData)
|
||||||
|
writefile(f,j)
|
||||||
|
StarterGui:SetCore("SendNotification",{Title="Save Config",Text="Config berhasil disimpan ke "..f,Duration=5})
|
||||||
|
else
|
||||||
|
warn("Saving config is not supported in this environment.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:LoadConfig(f)
|
||||||
|
f=f or "JustHub_Config.json"
|
||||||
|
if readfile then
|
||||||
|
local d=readfile(f)
|
||||||
|
local c=HttpService:JSONDecode(d)
|
||||||
|
JustHub.ConfigData=c
|
||||||
|
JustHub:ApplyConfig(c)
|
||||||
|
StarterGui:SetCore("SendNotification",{Title="Load Config",Text="Config berhasil dimuat dari "..f,Duration=5})
|
||||||
|
return c
|
||||||
|
else
|
||||||
|
warn("Loading config is not supported in this environment.")
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:UpdateTheme(nt)
|
||||||
|
JustHub.Save.Theme=nt
|
||||||
|
local th=getCurrentTheme(nt)
|
||||||
|
if self.Window then
|
||||||
|
local mf=self.Window.MainFrame
|
||||||
|
mf.BackgroundColor3=th["Color Hub 2"]
|
||||||
|
local tb=self.Window.TopBar
|
||||||
|
tb.BackgroundColor3=th["Color Hub 2"]
|
||||||
|
local tl=tb:FindFirstChild("TitleLabel")
|
||||||
|
if tl then tl.TextColor3=th["Color Text"] end
|
||||||
|
local sb=self.Window.Sidebar
|
||||||
|
sb.BackgroundColor3=th["Color Hub 2"]
|
||||||
|
local cc=self.Window.ContentContainer
|
||||||
|
cc.BackgroundColor3=th["Color Hub 2"]
|
||||||
|
for _,tab in ipairs(self.Window.Tabs) do
|
||||||
|
if tab.Button then
|
||||||
|
tab.Button.BackgroundColor3=th["Color Stroke"]
|
||||||
|
tab.Button.TextColor3=th["Color Text"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local fl=mf:FindFirstChild("FPSLabel",true)
|
||||||
|
if fl then
|
||||||
|
fl.TextColor3=th["Color Text"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:SetTheme(nt)
|
||||||
|
self:UpdateTheme(nt)
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:ToggleUIVisibility()
|
||||||
|
if self.ScreenGui and self.ScreenGui.Parent then
|
||||||
|
self.ScreenGui.Enabled=not self.ScreenGui.Enabled
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:Notify(o)
|
||||||
|
o=o or {}
|
||||||
|
local t=o.Title or ""
|
||||||
|
local m=o.Message or ""
|
||||||
|
local d=o.Duration or 5
|
||||||
|
local theme=getCurrentTheme(JustHub.Save.Theme)
|
||||||
|
if not self.NotificationContainer then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local nf=createInstance("Frame",{Size=UDim2.new(0,300,0,0),BackgroundTransparency=0,ClipsDescendants=true},self.NotificationContainer)
|
||||||
|
local corner=createInstance("UICorner",{CornerRadius=UDim.new(0,8)},nf)
|
||||||
|
local stroke=addBorder(nf,theme["Color Stroke"],2)
|
||||||
|
local grad=createInstance("UIGradient",{Color=theme["Color Hub 1"]},nf)
|
||||||
|
local tLabel=createInstance("TextLabel",{Text=t,Size=UDim2.new(1,-10,0,20),Position=UDim2.new(0,5,0,5),BackgroundTransparency=1,TextColor3=theme["Color Text"],Font=Enum.Font.GothamBold,TextSize=14,TextXAlignment=Enum.TextXAlignment.Left},nf)
|
||||||
|
local mLabel=createInstance("TextLabel",{Text=m,Size=UDim2.new(1,-10,0,0),Position=UDim2.new(0,5,0,25),BackgroundTransparency=1,TextColor3=theme["Color Text"],Font=Enum.Font.Gotham,TextSize=12,TextWrapped=true,TextXAlignment=Enum.TextXAlignment.Left},nf)
|
||||||
|
mLabel.Size=UDim2.new(1,-10,0,mLabel.TextBounds.Y+5)
|
||||||
|
local fullHeight=mLabel.AbsolutePosition.Y+mLabel.AbsoluteSize.Y-nf.AbsolutePosition.Y+10
|
||||||
|
nf.Size=UDim2.new(0,300,0,fullHeight)
|
||||||
|
nf.BackgroundColor3=theme["Color Hub 2"]
|
||||||
|
nf.BackgroundTransparency=0.1
|
||||||
|
nf.Position=UDim2.new(1,0,1,0)
|
||||||
|
local inTween=TweenService:Create(nf,TweenInfo.new(0.3,Enum.EasingStyle.Quad,Enum.EasingDirection.Out),{Size=UDim2.new(0,300,0,fullHeight)})
|
||||||
|
inTween:Play()
|
||||||
|
spawn(function()
|
||||||
|
inTween.Completed:Wait()
|
||||||
|
wait(d)
|
||||||
|
local outTween=TweenService:Create(nf,TweenInfo.new(0.3,Enum.EasingStyle.Quad,Enum.EasingDirection.In),{BackgroundTransparency=1,Size=UDim2.new(0,300,0,0)})
|
||||||
|
outTween:Play()
|
||||||
|
outTween.Completed:Wait()
|
||||||
|
nf:Destroy()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return JustHub
|
162
Library/README.md
Normal file
162
Library/README.md
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
# JustHub Library
|
||||||
|
This documentation is for the stable release of Orion Library.
|
||||||
|
|
||||||
|
## Booting the Library
|
||||||
|
```lua
|
||||||
|
local JustHub = loadstring(game:HttpGet(('https://git.warceuproject.org/Apapapa/ScriptRoblox/raw/branch/main/Library/testing2.lua')))()
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Creating a Window
|
||||||
|
```lua
|
||||||
|
JustHub:InitializeUI({Name = "Just Hub", Theme = "Purple"})
|
||||||
|
|
||||||
|
wait(6) -- Waiting Timer Loading Screen
|
||||||
|
|
||||||
|
if not JustHub.Window then
|
||||||
|
warn("Window belum dibuat.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local window = JustHub.Window
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Name = <string> - The name of the UI.
|
||||||
|
Theme = <Darker> - Themes(Colors Ui)
|
||||||
|
|
||||||
|
List Theme > Darker,Dark,Purple,Light,Neon
|
||||||
|
]]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Creating a Tab
|
||||||
|
```lua
|
||||||
|
local Tab = window:addTab("•Home")
|
||||||
|
|
||||||
|
--[[
|
||||||
|
local Tab = window:addTab("Your Name Tabs") - The name of the tab.
|
||||||
|
]]
|
||||||
|
```
|
||||||
|
## Creating a Section
|
||||||
|
```lua
|
||||||
|
local Section = Tab:addSection("Home Section", 120)
|
||||||
|
|
||||||
|
--[[
|
||||||
|
local Section = Tab:addSection("Your Name Section", 120) - The name of the section and size.
|
||||||
|
]]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Notifying the user
|
||||||
|
```lua
|
||||||
|
JustHub:Notify({
|
||||||
|
Title = "Notification",
|
||||||
|
Message = "UI berhasil dibuat!",
|
||||||
|
Duration = 5}),
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Title = <string> - The title of the notification.
|
||||||
|
Message = <string> - The content of the notification.
|
||||||
|
Duration = <number> - The duration of the notfication.
|
||||||
|
]]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Creating a Button
|
||||||
|
```lua
|
||||||
|
Section:addButton({
|
||||||
|
Name = "Execute",
|
||||||
|
ButtonText = "Run",
|
||||||
|
Callback = function()
|
||||||
|
print("Button clicked!")
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Name = <string> - The name of the button.
|
||||||
|
ButtonText = <string> - The name of button
|
||||||
|
Callback = <function> - The function of the button.
|
||||||
|
]]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Creating a Checkbox toggle
|
||||||
|
```lua
|
||||||
|
Section:addToggle({
|
||||||
|
Name = "Toggle",
|
||||||
|
Default = false,
|
||||||
|
Callback = function(state)
|
||||||
|
print("Toggle state:", state)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Name = <string> - The name of the toggle.
|
||||||
|
Default = <bool> - The default value of the toggle.
|
||||||
|
Callback = <function> - The function of the toggle
|
||||||
|
--)]]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Creat Slider
|
||||||
|
```Lua
|
||||||
|
Section:addSlider({
|
||||||
|
Name = "Slider Example",
|
||||||
|
Min = 0,
|
||||||
|
Max = 100,
|
||||||
|
Default = 50,
|
||||||
|
Callback = function(value)
|
||||||
|
print("Slider value:", value)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
--[[
|
||||||
|
Name = <string> - The name of the slider.
|
||||||
|
Min = <number> - The minimal value of the slider.
|
||||||
|
Max = <number> - The maxium value of the slider.
|
||||||
|
Default = <number> - The default value slider
|
||||||
|
Callback = <function> - The function of the slider.
|
||||||
|
]]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Creating an Textbox Input
|
||||||
|
```lua
|
||||||
|
Section:AddTextbox({
|
||||||
|
Name = "Textbox",
|
||||||
|
Default = "default box input",
|
||||||
|
Callback = function(Value)
|
||||||
|
print(Value)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Name = <string> - The name of the textbox.
|
||||||
|
Default = <string> - The default value of the textbox.
|
||||||
|
Callback = <function> - The function of the textbox.
|
||||||
|
]]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Creating a Dropdown menu
|
||||||
|
```lua
|
||||||
|
Section:addDropdown({
|
||||||
|
Name = "Dropdown Example",
|
||||||
|
Default = "",
|
||||||
|
Items = {"Option 1", "Option 2", "Option 3"},
|
||||||
|
Callback = function(selected)
|
||||||
|
print("Dropdown selected:", selected)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Name = <string> - The name of the dropdown.
|
||||||
|
Default = <string> - The default value of the dropdown.
|
||||||
|
Items = <table> - The options in the dropdown.
|
||||||
|
Callback = <function> - The function of the dropdown.
|
||||||
|
]]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Destroying the Interface
|
||||||
|
```lua
|
||||||
|
JustHub:Destroy()
|
||||||
|
```
|
532
Library/testing2.lua
Normal file
532
Library/testing2.lua
Normal file
@ -0,0 +1,532 @@
|
|||||||
|
local TweenService = game:GetService("TweenService")
|
||||||
|
local UserInputService = game:GetService("UserInputService")
|
||||||
|
local RunService = game:GetService("RunService")
|
||||||
|
local HttpService = game:GetService("HttpService")
|
||||||
|
local Players = game:GetService("Players")
|
||||||
|
local StarterGui = game:GetService("StarterGui")
|
||||||
|
local JustHub = {}
|
||||||
|
|
||||||
|
JustHub.Themes = {
|
||||||
|
Darker = {
|
||||||
|
["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(25,25,25)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(32,32,32)), ColorSequenceKeypoint.new(1, Color3.fromRGB(25,25,25))}),
|
||||||
|
["Color Hub 2"] = Color3.fromRGB(30,30,30),
|
||||||
|
["Color Stroke"] = Color3.fromRGB(40,40,40),
|
||||||
|
["Color Theme"] = Color3.fromRGB(88,101,242),
|
||||||
|
["Color Text"] = Color3.fromRGB(243,243,243),
|
||||||
|
["Color Dark Text"] = Color3.fromRGB(180,180,180)
|
||||||
|
},
|
||||||
|
Dark = {
|
||||||
|
["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(40,40,40)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(47,47,47)), ColorSequenceKeypoint.new(1, Color3.fromRGB(40,40,40))}),
|
||||||
|
["Color Hub 2"] = Color3.fromRGB(45,45,45),
|
||||||
|
["Color Stroke"] = Color3.fromRGB(65,65,65),
|
||||||
|
["Color Theme"] = Color3.fromRGB(65,150,255),
|
||||||
|
["Color Text"] = Color3.fromRGB(245,245,245),
|
||||||
|
["Color Dark Text"] = Color3.fromRGB(190,190,190)
|
||||||
|
},
|
||||||
|
Purple = {
|
||||||
|
["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(28,25,30)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(32,32,32)), ColorSequenceKeypoint.new(1, Color3.fromRGB(28,25,30))}),
|
||||||
|
["Color Hub 2"] = Color3.fromRGB(30,30,30),
|
||||||
|
["Color Stroke"] = Color3.fromRGB(40,40,40),
|
||||||
|
["Color Theme"] = Color3.fromRGB(150,0,255),
|
||||||
|
["Color Text"] = Color3.fromRGB(240,240,240),
|
||||||
|
["Color Dark Text"] = Color3.fromRGB(180,180,180)
|
||||||
|
},
|
||||||
|
Light = {
|
||||||
|
["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(230,230,230)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(245,245,245)), ColorSequenceKeypoint.new(1, Color3.fromRGB(230,230,230))}),
|
||||||
|
["Color Hub 2"] = Color3.fromRGB(240,240,240),
|
||||||
|
["Color Stroke"] = Color3.fromRGB(200,200,200),
|
||||||
|
["Color Theme"] = Color3.fromRGB(0,120,255),
|
||||||
|
["Color Text"] = Color3.fromRGB(30,30,30),
|
||||||
|
["Color Dark Text"] = Color3.fromRGB(80,80,80)
|
||||||
|
},
|
||||||
|
Neon = {
|
||||||
|
["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(10,10,10)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(0,200,200)), ColorSequenceKeypoint.new(1, Color3.fromRGB(10,10,10))}),
|
||||||
|
["Color Hub 2"] = Color3.fromRGB(15,15,15),
|
||||||
|
["Color Stroke"] = Color3.fromRGB(0,255,255),
|
||||||
|
["Color Theme"] = Color3.fromRGB(0,255,0),
|
||||||
|
["Color Text"] = Color3.fromRGB(255,255,255),
|
||||||
|
["Color Dark Text"] = Color3.fromRGB(200,200,200)
|
||||||
|
},
|
||||||
|
Forest = {
|
||||||
|
["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(0,50,0)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(0,80,0)), ColorSequenceKeypoint.new(1, Color3.fromRGB(0,50,0))}),
|
||||||
|
["Color Hub 2"] = Color3.fromRGB(0,60,0),
|
||||||
|
["Color Stroke"] = Color3.fromRGB(0,80,0),
|
||||||
|
["Color Theme"] = Color3.fromRGB(0,120,0),
|
||||||
|
["Color Text"] = Color3.fromRGB(220,220,220),
|
||||||
|
["Color Dark Text"] = Color3.fromRGB(160,160,160)
|
||||||
|
},
|
||||||
|
Aqua = {
|
||||||
|
["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(0,100,100)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(0,150,150)), ColorSequenceKeypoint.new(1, Color3.fromRGB(0,100,100))}),
|
||||||
|
["Color Hub 2"] = Color3.fromRGB(0,110,110),
|
||||||
|
["Color Stroke"] = Color3.fromRGB(0,180,180),
|
||||||
|
["Color Theme"] = Color3.fromRGB(0,220,220),
|
||||||
|
["Color Text"] = Color3.fromRGB(255,255,255),
|
||||||
|
["Color Dark Text"] = Color3.fromRGB(200,200,200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JustHub.Info = {Version = "1.1.0"}
|
||||||
|
JustHub.Save = {UISize = {550,380}, TabSize = 160, Theme = "Darker"}
|
||||||
|
JustHub.ConfigData = {}
|
||||||
|
JustHub.ControlRegistry = {}
|
||||||
|
|
||||||
|
local function createInstance(className, properties, parent)
|
||||||
|
local inst = Instance.new(className)
|
||||||
|
if properties then
|
||||||
|
for k, v in pairs(properties) do
|
||||||
|
inst[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if parent then
|
||||||
|
inst.Parent = parent
|
||||||
|
end
|
||||||
|
return inst
|
||||||
|
end
|
||||||
|
|
||||||
|
local function tweenProperty(object, propertyTable, duration)
|
||||||
|
local ti = TweenInfo.new(duration, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
|
||||||
|
local tw = TweenService:Create(object, ti, propertyTable)
|
||||||
|
tw:Play()
|
||||||
|
return tw
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getCurrentTheme(themeChoice)
|
||||||
|
if type(themeChoice) == "table" then
|
||||||
|
return themeChoice
|
||||||
|
else
|
||||||
|
return JustHub.Themes[themeChoice or JustHub.Save.Theme]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function clampPosition(pos, screenSize)
|
||||||
|
local x = math.clamp(pos.X.Offset, 0, screenSize.X)
|
||||||
|
local y = math.clamp(pos.Y.Offset, 0, screenSize.Y)
|
||||||
|
return UDim2.new(pos.X.Scale, x, pos.Y.Scale, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function addBorder(obj, color, thickness)
|
||||||
|
return createInstance("UIStroke", {Color = color, Thickness = thickness}, obj)
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:RegisterControl(key, updateFunction)
|
||||||
|
JustHub.ControlRegistry[key] = updateFunction
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:ApplyConfig(config)
|
||||||
|
for key, savedValue in pairs(config) do
|
||||||
|
if JustHub.ControlRegistry[key] then
|
||||||
|
JustHub.ControlRegistry[key](savedValue)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local SectionMethods = {}
|
||||||
|
|
||||||
|
function SectionMethods:addMenu(menuName)
|
||||||
|
menuName = menuName or "Menu"
|
||||||
|
local menuFrame = createInstance("Frame", {Name = menuName, Size = UDim2.new(1,0,0,40), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], BackgroundTransparency = 0.3}, self.Content)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,6)}, menuFrame)
|
||||||
|
createInstance("TextLabel", {Name = "MenuLabel", Text = menuName, Size = UDim2.new(1,0,1,0), BackgroundTransparency = 1, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.GothamBold, TextSize = 16}, menuFrame)
|
||||||
|
return menuFrame
|
||||||
|
end
|
||||||
|
|
||||||
|
function SectionMethods:addToggle(options)
|
||||||
|
options = options or {}
|
||||||
|
local toggleTitle = options.Name or "Toggle"
|
||||||
|
local default = options.Default or false
|
||||||
|
local callback = options.Callback or function(state) end
|
||||||
|
local toggleFrame = createInstance("Frame", {Name = toggleTitle.."Toggle", Size = UDim2.new(1,0,0,20), BackgroundColor3 = Color3.fromRGB(40,40,40)}, self.Content)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,20)}, toggleFrame)
|
||||||
|
addBorder(toggleFrame, getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], 1)
|
||||||
|
local label = createInstance("TextLabel", {Size = UDim2.new(0.7,0,1,0), Position = UDim2.new(0,0,0,0), BackgroundTransparency = 1, Text = toggleTitle, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.Gotham, TextSize = 12, TextXAlignment = Enum.TextXAlignment.Left}, toggleFrame)
|
||||||
|
local separator = createInstance("Frame", {Size = UDim2.new(0,2,1,0), Position = UDim2.new(0.7,0,0,0), BackgroundColor3 = Color3.fromRGB(255,255,255)}, toggleFrame)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,1)}, separator)
|
||||||
|
local toggleContainer = createInstance("Frame", {Size = UDim2.new(0.3,0,1,0), Position = UDim2.new(0.7,0,0,0), BackgroundTransparency = 1}, toggleFrame)
|
||||||
|
local toggleSwitch = createInstance("Frame", {Size = UDim2.new(0,35,0,15), Position = UDim2.new(1,-35,0.5,-7.5), BackgroundColor3 = default and Color3.fromRGB(0,200,0) or Color3.fromRGB(100,100,100), BorderSizePixel = 0}, toggleContainer)
|
||||||
|
toggleSwitch.Active = true
|
||||||
|
toggleSwitch.Selectable = true
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,15)}, toggleSwitch)
|
||||||
|
local toggleCircle = createInstance("Frame", {Size = UDim2.new(0,13,0,13), Position = default and UDim2.new(0,20,0.5,-6.5) or UDim2.new(0,2,0.5,-6.5), BackgroundColor3 = Color3.new(1,1,1), BorderSizePixel = 0}, toggleSwitch)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(1,0)}, toggleCircle)
|
||||||
|
local state = default
|
||||||
|
if default then callback(true) else callback(false) end
|
||||||
|
JustHub.ConfigData[toggleTitle] = state
|
||||||
|
JustHub:RegisterControl(toggleTitle, function(savedValue)
|
||||||
|
state = savedValue
|
||||||
|
if state then
|
||||||
|
toggleCircle.Position = UDim2.new(0,20,0.5,-6.5)
|
||||||
|
toggleSwitch.BackgroundColor3 = Color3.fromRGB(0,200,0)
|
||||||
|
label.TextColor3 = Color3.fromRGB(0,255,0)
|
||||||
|
else
|
||||||
|
toggleCircle.Position = UDim2.new(0,2,0.5,-6.5)
|
||||||
|
toggleSwitch.BackgroundColor3 = Color3.fromRGB(100,100,100)
|
||||||
|
label.TextColor3 = Color3.fromRGB(255,255,255)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
toggleSwitch.InputBegan:Connect(function(input)
|
||||||
|
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
|
||||||
|
if not state then
|
||||||
|
tweenProperty(toggleCircle, {Position = UDim2.new(0,20,0.5,-6.5)}, 0.3)
|
||||||
|
tweenProperty(toggleSwitch, {BackgroundColor3 = Color3.fromRGB(0,200,0)}, 0.3)
|
||||||
|
tweenProperty(label, {TextColor3 = Color3.fromRGB(0,255,0)}, 0.3)
|
||||||
|
else
|
||||||
|
tweenProperty(toggleCircle, {Position = UDim2.new(0,2,0.5,-6.5)}, 0.3)
|
||||||
|
tweenProperty(toggleSwitch, {BackgroundColor3 = Color3.fromRGB(100,100,100)}, 0.3)
|
||||||
|
tweenProperty(label, {TextColor3 = Color3.fromRGB(255,255,255)}, 0.3)
|
||||||
|
end
|
||||||
|
state = not state
|
||||||
|
JustHub.ConfigData[toggleTitle] = state
|
||||||
|
callback(state)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
return toggleFrame
|
||||||
|
end
|
||||||
|
|
||||||
|
function SectionMethods:addSlider(options)
|
||||||
|
options = options or {}
|
||||||
|
local sliderName = options.Name or "Slider"
|
||||||
|
local min = options.Min or 0
|
||||||
|
local max = options.Max or 100
|
||||||
|
local default = options.Default or min
|
||||||
|
local callback = options.Callback or function(value) end
|
||||||
|
local sliderFrame = createInstance("Frame", {Name = sliderName.."Slider", Size = UDim2.new(1,0,0,25), BackgroundTransparency = 1}, self.Content)
|
||||||
|
addBorder(sliderFrame, getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], 1)
|
||||||
|
local label = createInstance("TextLabel", {Name = "Label", Text = sliderName, Size = UDim2.new(0.7,0,1,0), Position = UDim2.new(0,0,0,0), BackgroundTransparency = 1, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.Gotham, TextSize = 10}, sliderFrame)
|
||||||
|
local separator = createInstance("Frame", {Size = UDim2.new(0,2,1,0), Position = UDim2.new(0.7,0,0,0), BackgroundColor3 = Color3.fromRGB(255,255,255)}, sliderFrame)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,1)}, separator)
|
||||||
|
local sliderContainer = createInstance("Frame", {Name = "SliderContainer", Size = UDim2.new(0.3,0,1,0), Position = UDim2.new(0.7,0,0,0), BackgroundTransparency = 1}, sliderFrame)
|
||||||
|
local sliderBar = createInstance("Frame", {Name = "SliderBar", Size = UDim2.new(1,-20,0,4), Position = UDim2.new(0,10,0.5,-2), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Stroke"]}, sliderContainer)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,4)}, sliderBar)
|
||||||
|
local sliderHandle = createInstance("Frame", {Name = "SliderHandle", Size = UDim2.new(0,12,0,12), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Theme"], Position = UDim2.new((default - min)/(max - min), -6, 0.5,-6)}, sliderBar)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,4)}, sliderHandle)
|
||||||
|
local dragging = false
|
||||||
|
sliderHandle.InputBegan:Connect(function(input)
|
||||||
|
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = true end
|
||||||
|
end)
|
||||||
|
sliderHandle.InputEnded:Connect(function(input)
|
||||||
|
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = false end
|
||||||
|
end)
|
||||||
|
UserInputService.InputChanged:Connect(function(input)
|
||||||
|
if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
|
||||||
|
local barAbsPos = sliderBar.AbsolutePosition.X
|
||||||
|
local barWidth = sliderBar.AbsoluteSize.X
|
||||||
|
local relativePos = math.clamp((input.Position.X - barAbsPos) / barWidth, 0, 1)
|
||||||
|
sliderHandle.Position = UDim2.new(relativePos, -6, sliderHandle.Position.Y.Scale, sliderHandle.Position.Y.Offset)
|
||||||
|
local value = min + relativePos*(max - min)
|
||||||
|
JustHub.ConfigData[sliderName] = value
|
||||||
|
callback(value)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
JustHub:RegisterControl(sliderName, function(savedValue)
|
||||||
|
local newRel = (savedValue - min)/(max - min)
|
||||||
|
sliderHandle.Position = UDim2.new(newRel, -6, 0.5, -6)
|
||||||
|
end)
|
||||||
|
return sliderFrame
|
||||||
|
end
|
||||||
|
|
||||||
|
function SectionMethods:addTextBox(options)
|
||||||
|
options = options or {}
|
||||||
|
local textBoxName = options.Name or "TextBox"
|
||||||
|
local defaultText = options.Default or ""
|
||||||
|
local callback = options.Callback or function(text) end
|
||||||
|
local textBoxFrame = createInstance("Frame", {Name = textBoxName.."TextBox", Size = UDim2.new(1,0,0,20), BackgroundTransparency = 1}, self.Content)
|
||||||
|
addBorder(textBoxFrame, getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], 1)
|
||||||
|
local label = createInstance("TextLabel", {Name = "Label", Text = textBoxName, Size = UDim2.new(0.7,0,1,0), Position = UDim2.new(0,0,0,0), BackgroundTransparency = 1, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.Gotham, TextSize = 10}, textBoxFrame)
|
||||||
|
local textbox = createInstance("TextBox", {Name = "Input", Text = defaultText, Size = UDim2.new(0.3,0,1,0), Position = UDim2.new(0.7,0,0,0), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.Gotham, TextSize = 10}, textBoxFrame)
|
||||||
|
textbox.FocusLost:Connect(function(enterPressed)
|
||||||
|
JustHub.ConfigData[textBoxName] = textbox.Text
|
||||||
|
callback(textbox.Text)
|
||||||
|
end)
|
||||||
|
JustHub:RegisterControl(textBoxName, function(savedText)
|
||||||
|
textbox.Text = savedText
|
||||||
|
end)
|
||||||
|
return textBoxFrame
|
||||||
|
end
|
||||||
|
|
||||||
|
function SectionMethods:addDropdown(options)
|
||||||
|
options = options or {}
|
||||||
|
local dropdownTitle = options.Name or "Dropdown"
|
||||||
|
local default = options.Default or ""
|
||||||
|
local items = options.Items or {}
|
||||||
|
local callback = options.Callback or function(value) end
|
||||||
|
local dropdownFrame = createInstance("Frame", {Name = dropdownTitle.."Dropdown", BackgroundTransparency = 1}, self.Content)
|
||||||
|
dropdownFrame.Size = UDim2.new(1,0,0,20)
|
||||||
|
addBorder(dropdownFrame, getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], 1)
|
||||||
|
local label = createInstance("TextLabel", {Name = "Label", Text = dropdownTitle, Size = UDim2.new(0.7,0,1,0), Position = UDim2.new(0,0,0,0), BackgroundTransparency = 1, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.Gotham, TextSize = 10}, dropdownFrame)
|
||||||
|
local dropdownButton = createInstance("TextButton", {Name = "DropdownButton", Text = (default ~= "" and (default .. " ▼") or "Select ▼"), Size = UDim2.new(0.3,0,1,0), Position = UDim2.new(0.7,0,0,0), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], Font = Enum.Font.GothamBold, TextSize = 10}, dropdownFrame)
|
||||||
|
local listFrame = createInstance("Frame", {Name = "DropdownList", BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Hub 2"], Visible = false, Position = UDim2.new(0,0,1,0)}, dropdownFrame)
|
||||||
|
listFrame.Size = UDim2.new(1,0,0,#items*20 + ((#items-1)*2))
|
||||||
|
createInstance("UIListLayout", {Padding = UDim.new(0,2), SortOrder = Enum.SortOrder.LayoutOrder}, listFrame)
|
||||||
|
local dropdownToggle = false
|
||||||
|
dropdownButton.MouseButton1Click:Connect(function()
|
||||||
|
if dropdownToggle then
|
||||||
|
tweenProperty(listFrame, {Size = UDim2.new(1,0,0,0)}, 0.15)
|
||||||
|
tweenProperty(dropdownButton, {TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"]}, 0.15)
|
||||||
|
wait(0.15)
|
||||||
|
listFrame.Visible = false
|
||||||
|
else
|
||||||
|
listFrame.Visible = true
|
||||||
|
tweenProperty(listFrame, {Size = UDim2.new(1,0,0,#items*20 + ((#items-1)*2))}, 0.15)
|
||||||
|
tweenProperty(dropdownButton, {TextColor3 = Color3.fromRGB(0,255,0)}, 0.15)
|
||||||
|
end
|
||||||
|
dropdownToggle = not dropdownToggle
|
||||||
|
end)
|
||||||
|
for _, option in ipairs(items) do
|
||||||
|
local btn = createInstance("TextButton", {Size = UDim2.new(1,0,0,20), Text = option, TextColor3 = Color3.fromRGB(255,255,255), BackgroundTransparency = 1, Font = Enum.Font.Gotham, TextSize = 10}, listFrame)
|
||||||
|
btn.MouseButton1Click:Connect(function()
|
||||||
|
label.Text = dropdownTitle .. " - " .. option
|
||||||
|
JustHub.ConfigData[dropdownTitle] = option
|
||||||
|
pcall(callback, option)
|
||||||
|
tweenProperty(listFrame, {Size = UDim2.new(1,0,0,0)}, 0.15)
|
||||||
|
dropdownToggle = false
|
||||||
|
wait(0.15)
|
||||||
|
listFrame.Visible = false
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
JustHub.ConfigData[dropdownTitle] = default
|
||||||
|
JustHub:RegisterControl(dropdownTitle, function(savedValue)
|
||||||
|
label.Text = dropdownTitle .. " - " .. savedValue
|
||||||
|
end)
|
||||||
|
local updatedropfunc = {}
|
||||||
|
function updatedropfunc:Clear()
|
||||||
|
for i, v in pairs(listFrame:GetChildren()) do
|
||||||
|
if v:IsA("TextButton") then
|
||||||
|
v:Destroy()
|
||||||
|
dropdownToggle = false
|
||||||
|
label.Text = dropdownTitle
|
||||||
|
tweenProperty(listFrame, {Size = UDim2.new(1,0,0,0)}, 0.15)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function updatedropfunc:Refresh(newlist)
|
||||||
|
newlist = newlist or {}
|
||||||
|
for i, v in pairs(newlist) do
|
||||||
|
local btn = createInstance("TextButton", {Size = UDim2.new(1,0,0,25), Text = v, TextColor3 = Color3.fromRGB(255,255,255), BackgroundTransparency = 1, Font = Enum.Font.SourceSansSemibold, TextSize = 12}, listFrame)
|
||||||
|
btn.MouseButton1Click:Connect(function()
|
||||||
|
dropdownToggle = false
|
||||||
|
label.Text = dropdownTitle .. " - " .. v
|
||||||
|
pcall(callback, v)
|
||||||
|
tweenProperty(listFrame, {Size = UDim2.new(1,0,0,0)}, 0.15)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return updatedropfunc
|
||||||
|
end
|
||||||
|
|
||||||
|
function SectionMethods:addButton(options)
|
||||||
|
options = options or {}
|
||||||
|
local labelText = options.Name or "Button"
|
||||||
|
local buttonText = options.ButtonText or "Click"
|
||||||
|
local callback = options.Callback or function() end
|
||||||
|
local container = createInstance("Frame", {Name = labelText.."ButtonControl", Size = UDim2.new(1,0,0,30), BackgroundTransparency = 1}, self.Content)
|
||||||
|
addBorder(container, getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], 1)
|
||||||
|
local label = createInstance("TextLabel", {Name = "Label", Text = labelText, Size = UDim2.new(0.7,0,1,0), Position = UDim2.new(0,0,0,0), BackgroundTransparency = 1, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.Gotham, TextSize = 10, TextXAlignment = Enum.TextXAlignment.Left}, container)
|
||||||
|
local button = createInstance("TextButton", {Name = "ActionButton", Text = buttonText, Size = UDim2.new(0.3,0,0.8,0), Position = UDim2.new(0.7,0,0.1,0), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Theme"], TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.GothamBold, TextSize = 10}, container)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,6)}, button)
|
||||||
|
button.MouseButton1Click:Connect(function() pcall(callback) end)
|
||||||
|
return container
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:addSection(sectionName, sectionHeight)
|
||||||
|
sectionName = sectionName or "Section"
|
||||||
|
sectionHeight = sectionHeight or 100
|
||||||
|
local sectionFrame = createInstance("Frame", {Name = sectionName, Size = UDim2.new(1,0,0,sectionHeight), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Hub 2"], BackgroundTransparency = 0.2}, nil)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,8)}, sectionFrame)
|
||||||
|
local sectionTitle = createInstance("TextLabel", {Name = "SectionTitle", Text = sectionName, Size = UDim2.new(1,0,0,30), BackgroundTransparency = 1, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.GothamBold, TextSize = 16, TextXAlignment = Enum.TextXAlignment.Left}, sectionFrame)
|
||||||
|
local sectionContent = createInstance("Frame", {Name = "SectionContent", Size = UDim2.new(1,0,1,-30), Position = UDim2.new(0,0,0,30), BackgroundTransparency = 1}, sectionFrame)
|
||||||
|
createInstance("UIListLayout", {FillDirection = Enum.FillDirection.Vertical, Padding = UDim.new(0,5), SortOrder = Enum.SortOrder.LayoutOrder}, sectionContent)
|
||||||
|
local sectionObj = {Frame = sectionFrame, Title = sectionTitle, Content = sectionContent}
|
||||||
|
setmetatable(sectionObj, {__index = SectionMethods})
|
||||||
|
return sectionObj
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:CreateWindow(options)
|
||||||
|
options = options or {}
|
||||||
|
local windowName = options.Name or "JustHub Window"
|
||||||
|
local currentTheme = getCurrentTheme(options.Theme)
|
||||||
|
local windowGUID = HttpService:GenerateGUID(false)
|
||||||
|
local finalTitle = windowName .. " [" .. windowGUID .. "]"
|
||||||
|
local player = Players.LocalPlayer
|
||||||
|
local playerGui = player:WaitForChild("PlayerGui")
|
||||||
|
local screenGui = createInstance("ScreenGui", {Name = "JustHub", ResetOnSpawn = false}, playerGui)
|
||||||
|
self.ScreenGui = screenGui
|
||||||
|
local uiWidth = JustHub.Save.UISize[1]
|
||||||
|
local uiHeight = JustHub.Save.UISize[2]
|
||||||
|
local mainFrame = createInstance("Frame", {Name = "MainFrame", AnchorPoint = Vector2.new(0.5,0.5), Position = UDim2.new(0.5,0,-0.5,0), Size = UDim2.new(0,uiWidth,0,uiHeight), BackgroundColor3 = currentTheme["Color Hub 2"]}, screenGui)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,12)}, mainFrame)
|
||||||
|
addBorder(mainFrame, currentTheme["Color Stroke"], 2)
|
||||||
|
createInstance("UIGradient", {Color = currentTheme["Color Hub 1"]}, mainFrame)
|
||||||
|
local topBar = createInstance("Frame", {Name = "TopBar", Size = UDim2.new(1,0,0,60), BackgroundColor3 = currentTheme["Color Hub 2"]}, mainFrame)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,12)}, topBar)
|
||||||
|
local titleLabel = createInstance("TextLabel", {Name = "TitleLabel", Size = UDim2.new(1,-180,1,0), Position = UDim2.new(0,10,0,0), BackgroundTransparency = 1, Text = finalTitle, TextColor3 = currentTheme["Color Text"], Font = Enum.Font.GothamBold, TextSize = 18, TextXAlignment = Enum.TextXAlignment.Left}, topBar)
|
||||||
|
local welcomeLabel = createInstance("TextLabel", {Name = "WelcomeLabel", Size = UDim2.new(0,150,0,20), AnchorPoint = Vector2.new(0,1), Position = UDim2.new(0,10,1,-30), BackgroundTransparency = 1, Text = "Welcome, " .. player.Name, TextColor3 = currentTheme["Color Text"], Font = Enum.Font.GothamBold, TextSize = 16, TextXAlignment = Enum.TextXAlignment.Left}, mainFrame)
|
||||||
|
local function createControlButton(name, image, pos)
|
||||||
|
return createInstance("ImageButton", {Name = name, Size = UDim2.new(0,40,0,40), Position = pos, BackgroundTransparency = 1, Image = image, ImageColor3 = currentTheme["Color Theme"]}, topBar)
|
||||||
|
end
|
||||||
|
local hideButton = createControlButton("HideButton", "rbxassetid://1307617803", UDim2.new(1,-110,0,10))
|
||||||
|
local maxButton = createControlButton("MaxButton", "rbxassetid://1307617941", UDim2.new(1,-70,0,10))
|
||||||
|
local closeButton = createControlButton("CloseButton", "rbxassetid://3926305904", UDim2.new(1,-30,0,10))
|
||||||
|
local sidebarWidth = JustHub.Save.TabSize
|
||||||
|
local sidebar = createInstance("Frame", {Name = "Sidebar", Size = UDim2.new(0,sidebarWidth,1,-60), Position = UDim2.new(0,0,0,60), BackgroundColor3 = currentTheme["Color Hub 2"]}, mainFrame)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,10)}, sidebar)
|
||||||
|
createInstance("UIListLayout", {FillDirection = Enum.FillDirection.Vertical, Padding = UDim.new(0,10), HorizontalAlignment = Enum.HorizontalAlignment.Center, VerticalAlignment = Enum.VerticalAlignment.Top}, sidebar)
|
||||||
|
local contentContainer = createInstance("Frame", {Name = "ContentContainer", Size = UDim2.new(1,-sidebarWidth,1,-60), Position = UDim2.new(0,sidebarWidth,0,60), BackgroundColor3 = currentTheme["Color Hub 2"]}, mainFrame)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,10)}, contentContainer)
|
||||||
|
local scrollingFrame = createInstance("ScrollingFrame", {Size = UDim2.new(1,0,1,0), BackgroundTransparency = 1, ScrollBarThickness = 8, BorderSizePixel = 0}, contentContainer)
|
||||||
|
createInstance("UIListLayout", {SortOrder = Enum.SortOrder.LayoutOrder, Padding = UDim.new(0,10)}, scrollingFrame)
|
||||||
|
local fpsLabel = createInstance("TextLabel", {Name = "FPSLabel", Size = UDim2.new(0,100,0,20), AnchorPoint = Vector2.new(1,1), Position = UDim2.new(1,-10,1,-10), BackgroundTransparency = 1, TextColor3 = currentTheme["Color Text"], Font = Enum.Font.Gotham, TextSize = 14, Text = "FPS: Calculating..."}, mainFrame)
|
||||||
|
RunService.Heartbeat:Connect(function(delta)
|
||||||
|
local fps = math.floor(1/delta)
|
||||||
|
fpsLabel.Text = "FPS: " .. fps
|
||||||
|
end)
|
||||||
|
local tweenInfoIn = TweenInfo.new(0.5, Enum.EasingStyle.Back, Enum.EasingDirection.Out)
|
||||||
|
local tweenIn = TweenService:Create(mainFrame, tweenInfoIn, {Position = UDim2.new(0.5,0,0.5,0)})
|
||||||
|
tweenIn:Play()
|
||||||
|
closeButton.MouseButton1Click:Connect(function()
|
||||||
|
local tweenInfoOut = TweenInfo.new(0.5, Enum.EasingStyle.Back, Enum.EasingDirection.In)
|
||||||
|
local tweenOut = TweenService:Create(mainFrame, tweenInfoOut, {Position = UDim2.new(0.5,0,-0.5,0)})
|
||||||
|
tweenOut:Play()
|
||||||
|
tweenOut.Completed:Connect(function() screenGui:Destroy() end)
|
||||||
|
end)
|
||||||
|
local dragging = false
|
||||||
|
local dragStart, startPos
|
||||||
|
topBar.InputBegan:Connect(function(input)
|
||||||
|
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
|
||||||
|
dragging = true
|
||||||
|
dragStart = input.Position
|
||||||
|
startPos = mainFrame.Position
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
topBar.InputChanged:Connect(function(input)
|
||||||
|
if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
|
||||||
|
local delta = input.Position - dragStart
|
||||||
|
local newPos = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y)
|
||||||
|
newPos = clampPosition(newPos, Vector2.new(screenGui.AbsoluteSize.X, screenGui.AbsoluteSize.Y))
|
||||||
|
mainFrame.Position = newPos
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
UserInputService.InputEnded:Connect(function(input)
|
||||||
|
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = false end
|
||||||
|
end)
|
||||||
|
print("JustHub Window dibuat.")
|
||||||
|
local windowObject = {ScreenGui = screenGui, MainFrame = mainFrame, TopBar = topBar, Sidebar = sidebar, ContentContainer = contentContainer, Tabs = {}}
|
||||||
|
function windowObject:addTab(tabName)
|
||||||
|
tabName = tabName or "Tab"
|
||||||
|
local tabButton = createInstance("TextButton", {Name = tabName.."Button", Text = tabName, Size = UDim2.new(1,0,0,30), BackgroundColor3 = currentTheme["Color Stroke"], TextColor3 = currentTheme["Color Text"], Font = Enum.Font.GothamBold, TextSize = 16}, self.Sidebar)
|
||||||
|
local tabContent = createInstance("Frame", {Name = tabName.."Content", Size = UDim2.new(1,0,1,0), BackgroundTransparency = 1, Visible = false}, scrollingFrame)
|
||||||
|
local tabObject = {Name = tabName, Button = tabButton, Content = tabContent, Sections = {}}
|
||||||
|
table.insert(self.Tabs, tabObject)
|
||||||
|
tabButton.MouseButton1Click:Connect(function()
|
||||||
|
for _, t in ipairs(self.Tabs) do t.Content.Visible = false end
|
||||||
|
tabObject.Content.Visible = true
|
||||||
|
end)
|
||||||
|
if #self.Tabs == 1 then tabObject.Content.Visible = true end
|
||||||
|
function tabObject:addSection(sectionName, sectionHeight)
|
||||||
|
sectionName = sectionName or "Section"
|
||||||
|
sectionHeight = sectionHeight or 100
|
||||||
|
local sectionFrame = createInstance("Frame", {Name = sectionName, Size = UDim2.new(1,0,0,sectionHeight), BackgroundColor3 = currentTheme["Color Hub 2"], BackgroundTransparency = 0.2}, self.Content)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,8)}, sectionFrame)
|
||||||
|
local sectionTitle = createInstance("TextLabel", {Name = "SectionTitle", Text = sectionName, Size = UDim2.new(1,0,0,30), BackgroundTransparency = 1, TextColor3 = currentTheme["Color Text"], Font = Enum.Font.GothamBold, TextSize = 16, TextXAlignment = Enum.TextXAlignment.Left}, sectionFrame)
|
||||||
|
local sectionContent = createInstance("Frame", {Name = "SectionContent", Size = UDim2.new(1,0,1,-30), Position = UDim2.new(0,0,0,30), BackgroundTransparency = 1}, sectionFrame)
|
||||||
|
createInstance("UIListLayout", {FillDirection = Enum.FillDirection.Vertical, Padding = UDim.new(0,5), SortOrder = Enum.SortOrder.LayoutOrder}, sectionContent)
|
||||||
|
local sectionObj = {Frame = sectionFrame, Title = sectionTitle, Content = sectionContent}
|
||||||
|
table.insert(self.Sections, sectionObj)
|
||||||
|
setmetatable(sectionObj, {__index = SectionMethods})
|
||||||
|
return sectionObj
|
||||||
|
end
|
||||||
|
return tabObject
|
||||||
|
end
|
||||||
|
return windowObject
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:ShowLoadingScreen(duration, callback)
|
||||||
|
duration = duration or 5
|
||||||
|
callback = callback or function() end
|
||||||
|
local player = Players.LocalPlayer
|
||||||
|
local playerGui = player:WaitForChild("PlayerGui")
|
||||||
|
local loadingGui = createInstance("ScreenGui", {Name = "LoadingScreen", ResetOnSpawn = false, IgnoreGuiInset = true}, playerGui)
|
||||||
|
local background = createInstance("Frame", {Size = UDim2.new(1,0,1,0), Position = UDim2.new(0,0,0,0), BackgroundColor3 = Color3.new(0,0,0), BackgroundTransparency = 0.5, BorderSizePixel = 0}, loadingGui)
|
||||||
|
local titleLabel = createInstance("TextLabel", {Text = "JustHub Library", Font = Enum.Font.SourceSansSemibold, TextSize = 20, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], BackgroundTransparency = 1, Size = UDim2.new(0,200,0,50), AnchorPoint = Vector2.new(0.5,0.5), Position = UDim2.new(0.5,0,0.5,-50)}, loadingGui)
|
||||||
|
local welcomeLabel = createInstance("TextLabel", {Text = "Welcome, " .. player.Name, Font = Enum.Font.SourceSansSemibold, TextSize = 16, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], BackgroundTransparency = 1, Size = UDim2.new(0,200,0,30), AnchorPoint = Vector2.new(0.5,0), Position = UDim2.new(0.5,0,0.5,10)}, loadingGui)
|
||||||
|
local progressBarContainer = createInstance("Frame", {Size = UDim2.new(0.5,0,0,20), Position = UDim2.new(0.5,0,0.5,50), AnchorPoint = Vector2.new(0.5,0.5), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], BackgroundTransparency = 0.5, BorderSizePixel = 0}, loadingGui)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,4)}, progressBarContainer)
|
||||||
|
local progressBarFill = createInstance("Frame", {Size = UDim2.new(0,0,1,0), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Theme"], BorderSizePixel = 0}, progressBarContainer)
|
||||||
|
createInstance("UICorner", {CornerRadius = UDim.new(0,4)}, progressBarFill)
|
||||||
|
local tweenInfo = TweenInfo.new(duration, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
|
||||||
|
local progressTween = TweenService:Create(progressBarFill, tweenInfo, {Size = UDim2.new(1,0,1,0)})
|
||||||
|
progressTween:Play()
|
||||||
|
spawn(function()
|
||||||
|
while progressTween.PlaybackState == Enum.PlaybackState.Playing do
|
||||||
|
tweenProperty(titleLabel, {TextTransparency = 0.5}, 0.5)
|
||||||
|
wait(0.5)
|
||||||
|
tweenProperty(titleLabel, {TextTransparency = 0}, 0.5)
|
||||||
|
wait(0.5)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
progressTween.Completed:Connect(function()
|
||||||
|
wait(0.5)
|
||||||
|
loadingGui:Destroy()
|
||||||
|
callback()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:InitializeUI(options)
|
||||||
|
self:ShowLoadingScreen(5, function()
|
||||||
|
local window = self:CreateWindow(options)
|
||||||
|
self.Window = window
|
||||||
|
print("Window dibuat setelah loading screen.")
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:SaveConfig(fileName)
|
||||||
|
fileName = fileName or "JustHub_Config.json"
|
||||||
|
if writefile then
|
||||||
|
local json = HttpService:JSONEncode(JustHub.ConfigData)
|
||||||
|
writefile(fileName, json)
|
||||||
|
StarterGui:SetCore("SendNotification", {Title = "Save Config", Text = "Config berhasil disimpan ke " .. fileName, Duration = 5})
|
||||||
|
else
|
||||||
|
warn("Saving config is not supported in this environment.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:LoadConfig(fileName)
|
||||||
|
fileName = fileName or "JustHub_Config.json"
|
||||||
|
if readfile then
|
||||||
|
local data = readfile(fileName)
|
||||||
|
local config = HttpService:JSONDecode(data)
|
||||||
|
JustHub.ConfigData = config
|
||||||
|
JustHub:ApplyConfig(config)
|
||||||
|
StarterGui:SetCore("SendNotification", {Title = "Load Config", Text = "Config berhasil dimuat dari " .. fileName, Duration = 5})
|
||||||
|
return config
|
||||||
|
else
|
||||||
|
warn("Loading config is not supported in this environment.")
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function JustHub:ToggleUIVisibility()
|
||||||
|
if self.ScreenGui and self.ScreenGui.Parent then
|
||||||
|
self.ScreenGui.Enabled = not self.ScreenGui.Enabled
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
UserInputService.InputBegan:Connect(function(input, gameProcessed)
|
||||||
|
if not gameProcessed and input.KeyCode and input.KeyCode == Enum.KeyCode.RightShift then
|
||||||
|
JustHub:ToggleUIVisibility()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
function JustHub:Notify(options)
|
||||||
|
options = options or {}
|
||||||
|
local title = options.Title or ""
|
||||||
|
local text = options.Message or ""
|
||||||
|
local duration = options.Duration or 5
|
||||||
|
local success, errorMessage = pcall(function()
|
||||||
|
StarterGui:SetCore("SendNotification", {Title = title, Text = text, Duration = duration})
|
||||||
|
end)
|
||||||
|
if not success then
|
||||||
|
warn("Gagal mengirim notifikasi: " .. errorMessage)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return JustHub
|
@ -1,3 +1,3 @@
|
|||||||
# AutoFarm
|
# Roblox
|
||||||
|
|
||||||
This simple script for game roblox
|
This simple script for game roblox
|
1
Treasure hunt simulator/Readme.txt
Normal file
1
Treasure hunt simulator/Readme.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
hi
|
1455
Treasure hunt simulator/start.lua
Normal file
1455
Treasure hunt simulator/start.lua
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user