This commit is contained in:
watrabi
2025-09-18 17:55:52 -04:00
commit 977f1ff4b8
15030 changed files with 17324420 additions and 0 deletions
@@ -0,0 +1,889 @@
-- Backpack Version 4.2
-- OnlyTwentyCharacters
-- Configurables --
local ICON_SIZE = 60
local ICON_BUFFER = 5
local SLOT_TRANSPARENCY = 0.70
local SLOT_COLOR_EQUIP = Color3.new(0.35, 0.55, 0.91)
local SLOT_COLOR_NORMAL = Color3.new(0, 0, 0)
local ARROW_IMAGE_OPEN = 'rbxasset://textures/ui/Backpack_Open.png'
local ARROW_IMAGE_CLOSE = 'rbxasset://textures/ui/Backpack_Close.png'
local ARROW_SIZE = UDim2.new(0, 14, 0, 9)
local ARROW_HOTKEY = Enum.KeyCode.Backquote.Value --TODO: Hookup '~' too?
local ARROW_HOTKEY_STRING = '`'
local HOTBAR_SLOTS_FULL = 10
local HOTBAR_SLOTS_MINI = 3
local HOTBAR_SLOTS_WIDTH_CUTOFF = 1024 -- Anything smaller is MINI
local HOTBAR_OFFSET_FROMBOTTOM = 30
local INVENTORY_ROWS = 5
local INVENTORY_HEADER_SIZE = 40
local TITLE_OFFSET = 20 -- From left side
local TITLE_TEXT = "Backpack"
local SEARCH_BUFFER = 5
local SEARCH_WIDTH = 200
local SEARCH_TEXT = "Search"
local SEARCH_TEXT_OFFSET_FROMLEFT = 15
local DOUBLE_CLICK_TIME = 0.5
-- Variables --
print = function() end --TODO: Remove all prints when full implementation is complete
local PlayersService = game:GetService('Players')
local UserInputService = game:GetService('UserInputService')
local StarterGui = game:GetService('StarterGui')
local GuiService = game:GetService('GuiService')
local HOTBAR_SLOTS = (UserInputService.TouchEnabled and GuiService:GetScreenResolution().X < HOTBAR_SLOTS_WIDTH_CUTOFF) and HOTBAR_SLOTS_MINI or HOTBAR_SLOTS_FULL
local HOTBAR_SIZE = UDim2.new(0, ICON_BUFFER + (HOTBAR_SLOTS * (ICON_SIZE + ICON_BUFFER)), 0, ICON_BUFFER + ICON_SIZE + ICON_BUFFER)
local ZERO_KEY_VALUE = Enum.KeyCode.Zero.Value
local DROP_HOTKEY_VALUE = Enum.KeyCode.Backspace.Value
local Player = PlayersService.LocalPlayer
local CoreGui = script.Parent
local MainFrame = nil
local HotbarFrame = nil
local InventoryFrame = nil
local ScrollingFrame = nil
local Character = nil
local Humanoid = nil
local Backpack = nil
local Slots = {} -- List of all Slots by index
local LowestEmptySlot = nil
local SlotsByTool = {} -- Map of Tools to their assigned Slots
local HotkeyFns = {} -- Map of KeyCode values to their assigned behaviors
local Dragging = {} -- Only used to check if anything is being dragged, to disable other input
local FullHotbarSlots = 0
local UpdateArrowFrame = nil -- Function defined in Init logic at the bottom
local ActiveHopper = nil --NOTE: HopperBin
local StarterToolFound = false
local WholeThingEnabled = false
local TextBoxFocused = false
local ResultsIndices = nil -- Results of a search
-- Functions --
local function NewGui(className, objectName)
local newGui = Instance.new(className)
newGui.Name = objectName
newGui.BackgroundColor3 = Color3.new(0, 0, 0)
newGui.BackgroundTransparency = 1
newGui.BorderColor3 = Color3.new(0, 0, 0)
newGui.BorderSizePixel = 0
newGui.Size = UDim2.new(1, 0, 1, 0)
if className:match('Text') then
newGui.TextColor3 = Color3.new(1, 1, 1)
newGui.Text = ''
newGui.Font = Enum.Font.SourceSans
newGui.FontSize = Enum.FontSize.Size14
newGui.TextWrapped = true
newGui.BackgroundTransparency = 1
if className == 'TextButton' then
newGui.Font = Enum.Font.SourceSansBold
newGui.BorderSizePixel = 2
end
end
return newGui
end
local function FindLowestEmpty()
for i = 1, HOTBAR_SLOTS do
local slot = Slots[i]
if not slot.Tool then
return slot
end
end
return nil
end
local function AdjustHotbarFrames()
local inventoryOpen = InventoryFrame.Visible
local visualTotal = (inventoryOpen) and HOTBAR_SLOTS or FullHotbarSlots
local visualIndex = 0
for i = 1, HOTBAR_SLOTS do
local slot = Slots[i]
if slot.Tool or inventoryOpen then
visualIndex = visualIndex + 1
slot:Readjust(visualIndex, visualTotal)
slot.Frame.Visible = true
else
slot.Frame.Visible = false
end
end
end
local function CheckBounds(guiObject, x, y)
local pos = guiObject.AbsolutePosition
local size = guiObject.AbsoluteSize
return (x > pos.X and x <= pos.X + size.X and y > pos.Y and y <= pos.Y + size.Y)
end
local function GetOffset(guiObject, point)
local centerPoint = guiObject.AbsolutePosition + (guiObject.AbsoluteSize / 2)
return (centerPoint - point).magnitude
end
local function DisableActiveHopper() --NOTE: HopperBin
print("Disabling active hopper:", ActiveHopper)
ActiveHopper:ToggleSelect()
SlotsByTool[ActiveHopper]:UpdateEquipView()
ActiveHopper = nil
end
local function UnequipTools() --NOTE: HopperBin
Humanoid:UnequipTools()
if ActiveHopper then
DisableActiveHopper()
end
end
local function EquipTool(tool) --NOTE: HopperBin
UnequipTools()
if tool:IsA('HopperBin') then
tool:ToggleSelect()
SlotsByTool[tool]:UpdateEquipView()
ActiveHopper = tool
else
Humanoid:EquipTool(tool) --NOTE: This would also unequip current Tool
end
end
local function MakeSlot(parent, index)
index = index or (#Slots + 1)
-- Slot Definition --
local slot = {}
slot.Tool = nil
slot.Index = index
slot.Frame = nil
local slotFrame = NewGui('Frame', slot.Index)
slotFrame.BackgroundTransparency = SLOT_TRANSPARENCY
slotFrame.BackgroundColor3 = SLOT_COLOR_NORMAL
slotFrame.Size = UDim2.new(0, ICON_SIZE, 0, ICON_SIZE)
slotFrame.Active = true
slotFrame.Draggable = false
slot.Frame = slotFrame
local toolIcon = NewGui('ImageLabel', 'Icon')
toolIcon.Size = UDim2.new(0.8, 0, 0.8, 0)
toolIcon.Position = UDim2.new(0.1, 0, 0.1, 0)
toolIcon.Parent = slotFrame
local toolName = NewGui('TextLabel', 'ToolName')
toolName.Parent = slotFrame
local toolTip = nil --TODO: Clean up
if slot.Index <= HOTBAR_SLOTS then
toolTip = NewGui('TextLabel', 'ToolTip')
toolTip.TextWrapped = false
toolTip.TextYAlignment = Enum.TextYAlignment.Top
toolTip.BackgroundColor3 = Color3.new(0.4, 0.4, 0.4)
toolTip.BackgroundTransparency = 0
toolTip.Visible = false
toolTip.Parent = slotFrame
slotFrame.MouseEnter:connect(function()
if toolTip.Text ~= '' then
toolTip.Visible = true
end
end)
slotFrame.MouseLeave:connect(function() toolTip.Visible = false end)
end
local slotNumber = nil --NOTE: Only defined for Hotbar Slots
local clickArea = nil --NOTE: Only defined for Hotbar Slots
-- Slot Functions --
function slot:Reposition()
-- Slots are positioned into rows
local index = (ResultsIndices and ResultsIndices[self]) or self.Index
local sizePlus = ICON_BUFFER + ICON_SIZE
local modSlots = ((index - 1) % HOTBAR_SLOTS) + 1
local row = (index > HOTBAR_SLOTS) and (math.floor((index - 1) / HOTBAR_SLOTS)) - 1 or 0
slotFrame.Position = UDim2.new(0, ICON_BUFFER + ((modSlots - 1) * sizePlus), 0, ICON_BUFFER + (sizePlus * row))
-- print(" Reposition", self.Index, "at...............", index, " Output:", slotFrame.Position.X.Offset, slotFrame.Position.Y.Offset, " row:", row)
end
slot:Reposition()
function slot:Readjust(visualIndex, visualTotal)
local centered = HOTBAR_SIZE.X.Offset / 2
local sizePlus = ICON_BUFFER + ICON_SIZE
local midpointish = (visualTotal / 2) + 0.5
local factor = visualIndex - midpointish
--print(" Slot", self.Index, "'s new visualIndex:", visualIndex, "MN:", midpointish, "factor:", factor)
slotFrame.Position = UDim2.new(0, centered - (ICON_SIZE / 2) + (sizePlus * factor), 0, ICON_BUFFER)
end
function slot:Fill(tool)
print(" Filling gui data for slot", self.Index, "tool:", tool)
self.Tool = tool
slotFrame.Draggable = true
local icon = tool.TextureId
toolIcon.Image = icon
toolName.Text = (icon == '') and tool.Name or ''
if toolTip and tool:IsA('Tool') then --NOTE: HopperBin
--TODO: No magic numbers
toolTip.Text = tool.ToolTip
local width = toolTip.TextBounds.X + 6
toolTip.Size = UDim2.new(0, width, 0, 16)
toolTip.Position = UDim2.new(0.5, -width / 2, 0, -25)
end
self:UpdateEquipView()
if self.Index <= HOTBAR_SLOTS then
FullHotbarSlots = FullHotbarSlots + 1
end
SlotsByTool[tool] = self
LowestEmptySlot = FindLowestEmpty()
AdjustHotbarFrames()
UpdateArrowFrame()
end
function slot:Clear()
print(" Clearing gui data for slot", self.Index, "tool:", self.Tool)
slotFrame.Draggable = false
toolIcon.Image = ''
toolName.Text = ''
if toolTip then
toolTip.Text = ''
toolTip.Visible = false
end
self:UpdateEquipView(true) -- Always show as unequipped
if self.Index <= HOTBAR_SLOTS then
FullHotbarSlots = FullHotbarSlots - 1
end
SlotsByTool[self.Tool] = nil
self.Tool = nil
LowestEmptySlot = FindLowestEmpty()
AdjustHotbarFrames()
UpdateArrowFrame()
end
function slot:UpdateEquipView(unequippedOverride)
local tool = self.Tool
if not unequippedOverride and (tool.Parent == Character or (tool:IsA('HopperBin') and tool.Active)) then -- Equipped --NOTE: HopperBin
print(" Showing", self.Index, "as equipped:", tool)
slotFrame.BackgroundColor3 = SLOT_COLOR_EQUIP
slotFrame.BackgroundTransparency = 0
else -- In the Backpack
print(" Showing", self.Index, "as unequipped:", tool)
slotFrame.BackgroundTransparency = SLOT_TRANSPARENCY
slotFrame.BackgroundColor3 = SLOT_COLOR_NORMAL
end
end
function slot:Delete()
print(" Deleting slot", self.Index, "Tool:", self.Tool)
slotFrame:Destroy()
table.remove(Slots, self.Index)
local newSize = #Slots
-- Now adjust the rest (both visually and representationally)
for i = self.Index, newSize do
Slots[i]:SlideBack()
end
if newSize % HOTBAR_SLOTS == 0 then -- We lost a row at the end! Adjust the CanvasSize
local lastSlot = Slots[newSize]
local lowestPoint = lastSlot.Frame.Position.Y.Offset + lastSlot.Frame.Size.Y.Offset
ScrollingFrame.CanvasSize = UDim2.new(0, 0, 0, lowestPoint + ICON_BUFFER)
local offset = Vector2.new(0, math.max(0, ScrollingFrame.CanvasPosition.Y - (lastSlot.Frame.Size.Y.Offset + ICON_BUFFER)))
ScrollingFrame.CanvasPosition = offset
end
end
function slot:Swap(targetSlot) --NOTE: This slot (self) must not be empty!
print(" Swapping content of slots:", self.Index, "and", targetSlot.Index)
local myTool, otherTool = self.Tool, targetSlot.Tool
self:Clear()
if otherTool then -- (Target slot might be empty)
targetSlot:Clear()
self:Fill(otherTool)
end
targetSlot:Fill(myTool)
end
function slot:SlideBack() -- For inventory slot shifting
print(" SlideBack:", self.Index, "to", self.Index - 1)
self.Index = self.Index - 1
self:Reposition()
end
function slot:TurnNumber(on)
slotNumber.Visible = on
end
function slot:SetClickability(on)
clickArea.Visible = on
end
function slot:CheckTerms(terms)
local hits = 0
local function checkEm(str, term)
local _, n = str:lower():gsub(term, '')
hits = hits + n
end
local tool = self.Tool
for term in pairs(terms) do
checkEm(tool.Name, term)
checkEm(tool.ToolTip, term)
end
return hits
end
if index <= HOTBAR_SLOTS then -- Hotbar-Specific Slot Stuff
local function selectSlot()
print("Click!")
local tool = slot.Tool
if tool then
if tool.Parent == Character or (tool:IsA('HopperBin') and tool.Active) then --NOTE: HopperBin
print(" UNEQUIP!")
UnequipTools()
elseif tool.Parent == Backpack then
print(" EQUIP!")
EquipTool(tool)
end
end
end
clickArea = NewGui('TextButton', 'GimmieYerClicks')
clickArea.MouseButton1Click:connect(selectSlot)
clickArea.Parent = slotFrame
-- Show label and assign hotkeys for 1-9 and 0 (zero is always last slot when > 10 total)
if index < 10 or index == HOTBAR_SLOTS then -- NOTE: Hardcoded on purpose!
local slotNum = (index < 10) and index or 0
slotNumber = NewGui('TextLabel', 'Number')
slotNumber.Text = slotNum
slotNumber.Size = UDim2.new(0.15, 0, 0.15, 0)
slotNumber.Visible = false
slotNumber.Parent = slotFrame
HotkeyFns[ZERO_KEY_VALUE + slotNum] = selectSlot
end
else -- Inventory-Specific Slot Stuff
if index % HOTBAR_SLOTS == 1 then -- We are the first slot of a new row! Adjust the CanvasSize
local lowestPoint = slotFrame.Position.Y.Offset + slotFrame.Size.Y.Offset
ScrollingFrame.CanvasSize = UDim2.new(0, 0, 0, lowestPoint + ICON_BUFFER)
end
end
do -- Dragging Logic
local startPoint = slotFrame.Position
local background = nil
local lastUpTime = 0
local startParent = nil
slotFrame.DragBegin:connect(function(dragPoint)
print("DragBegin at:", dragPoint)
Dragging[slotFrame] = true
startPoint = dragPoint
-- Raise above other slots
slotFrame.ZIndex = 3
toolIcon.ZIndex = 3
toolName.ZIndex = 3
if slotNumber then
slotNumber.ZIndex = 3
end
background = NewGui('Frame', 'Background')
background.ZIndex = 2
background.BackgroundTransparency = 0
background.Parent = slotFrame
-- Circumvent the ScrollingFrame's ClipsDescendants
startParent = slotFrame.Parent
if startParent == ScrollingFrame then
slotFrame.Parent = InventoryFrame
local pos = ScrollingFrame.Position
local offset = ScrollingFrame.CanvasPosition - Vector2.new(pos.X.Offset, pos.Y.Offset)
slotFrame.Position = slotFrame.Position - UDim2.new(0, offset.X, 0, offset.Y)
end
end)
slotFrame.DragStopped:connect(function(x, y)
print("DragStopped at:", x, y)
local now = tick()
slotFrame.Position = startPoint
slotFrame.Parent = startParent
if background then -- Why? Just in case
background:Destroy()
end
-- Restore height
slotFrame.ZIndex = 1
toolIcon.ZIndex = 1
toolName.ZIndex = 1
if slotNumber then
slotNumber.ZIndex = 1
end
local function moveToInventory()
if slot.Index <= HOTBAR_SLOTS then -- From a Hotbar slot
print(" Move to inventory!")
local tool = slot.Tool
slot:Clear() --NOTE: Order matters here
local newSlot = MakeSlot(ScrollingFrame)
newSlot:Fill(tool)
if tool.Parent == Character or (tool:IsA('HopperBin') and tool.Active) then -- Also unequip it --NOTE: HopperBin
UnequipTools()
end
-- Also hide the inventory slot if we're showing results right now
if ResultsIndices then
newSlot.Frame.Visible = false
end
end
end
-- Check where we were dropped
if CheckBounds(InventoryFrame, x, y) then
moveToInventory()
-- Check for double clicking on an inventory slot, to move into empty hotbar slot
if slot.Index > HOTBAR_SLOTS and now - lastUpTime < DOUBLE_CLICK_TIME then
if LowestEmptySlot then
local myTool = slot.Tool
slot:Clear()
LowestEmptySlot:Fill(myTool)
slot:Delete()
end
now = 0 -- Resets the timer
end
elseif CheckBounds(HotbarFrame, x, y) then
print(" Swap this with closest Hotbar Slot!")
local closest = {math.huge, nil}
for i = 1, HOTBAR_SLOTS do
local otherSlot = Slots[i]
local offset = GetOffset(otherSlot.Frame, Vector2.new(x, y))
if offset < closest[1] then
closest = {offset, otherSlot}
end
end
print(" Closest slot:", closest[2].Index)
local closestSlot = closest[2]
if closestSlot ~= slot then
slot:Swap(closestSlot)
if slot.Index > HOTBAR_SLOTS then
local tool = slot.Tool
if not tool then -- Clean up after ourselves if we're an inventory slot that's now empty
slot:Delete()
else -- Moved inventory slot to hotbar slot, and gained a tool that needs to be unequipped
if tool.Parent == Character or (tool:IsA('HopperBin') and tool.Active) then --NOTE: HopperBin
UnequipTools()
end
-- Also hide the inventory slot if we're showing results right now
if ResultsIndices then
slot.Frame.Visible = false
end
end
end
end
else
-- print(" DROP!")
-- local tool = slot.Tool
-- if tool.CanBeDropped then --TODO: HopperBins
-- tool.Parent = workspace
-- --TODO: Move away from character
-- end
moveToInventory() --NOTE: Temporary
end
lastUpTime = now
Dragging[slotFrame] = nil
end)
end
-- All ready!
slotFrame.Parent = parent
Slots[index] = slot
return slot
end
local function OnChildAdded(child) -- To Character or Backpack
if not child:IsA('Tool') and not child:IsA('HopperBin') then --NOTE: HopperBin
if child:IsA('Humanoid') and child.Parent == Character then
Humanoid = child
end
return
end
local tool = child
print("A" .. (tool.Parent == Backpack and 'B' or (tool.Parent == Character and 'C' or '?')), tool)
if ActiveHopper then --NOTE: HopperBin
DisableActiveHopper()
end
--TODO: Optimize / refactor / do something else
if not StarterToolFound and tool.Parent == Character then
local starterGear = Player:FindFirstChild('StarterGear')
if starterGear then
local startTool = starterGear:GetChildren()[1]
if startTool and tool.Name == startTool.Name then
StarterToolFound = true
local firstEmptyIndex = LowestEmptySlot and LowestEmptySlot.Index or #Slots + 1
if LowestEmptySlot then
firstEmptyIndex = LowestEmptySlot.Index
else -- No slots free in hotbar, make a new inventory slot
local newSlot = MakeSlot(ScrollingFrame)
firstEmptyIndex = newSlot.Index
end
for i = firstEmptyIndex, 1, -1 do
local curr = Slots[i] -- An empty slot, because above
local pIndex = i - 1
if pIndex > 0 then
local prev = Slots[pIndex] -- Guaranteed to be full, because above
prev:Swap(curr)
else
curr:Fill(tool)
end
end
return -- We're done here
end
end
end
-- either moving or new
local slot = SlotsByTool[tool]
if slot then
print(" Already exists")
slot:UpdateEquipView()
else -- Not yet showing this tool
print(" New! Showing in lowest empty or a new inventory slot")
slot = LowestEmptySlot or MakeSlot(ScrollingFrame)
slot:Fill(tool)
end
end
local function OnChildRemoved(child) -- From Character or Backpack
if not child:IsA('Tool') and not child:IsA('HopperBin') then --NOTE: HopperBin
return
end
local tool = child
print("R-->" .. (tool.Parent == Backpack and 'B' or (tool.Parent == Character and 'C' or '?')), tool)
-- Ignore this event if we're just moving between the two
local newParent = tool.Parent
if newParent == Character or newParent == Backpack then
return
end
local slot = SlotsByTool[tool]
if slot then
slot:Clear()
local index = slot.Index
if index > HOTBAR_SLOTS then -- Inventory slot
slot:Delete()
end
end
end
local function OnCharacterAdded(character)
-- First, clean up any old slots
for i = #Slots, 1, -1 do
local slot = Slots[i]
if slot.Tool then
slot:Clear()
end
if i > HOTBAR_SLOTS then
slot:Delete()
end
end
Character = character
character.ChildRemoved:connect(OnChildRemoved)
character.ChildAdded:connect(OnChildAdded)
for _, child in pairs(character:GetChildren()) do
OnChildAdded(child)
end
--NOTE: Humanoid is set inside OnChildAdded
Backpack = Player:WaitForChild('Backpack')
local addTime = tick(); Backpack.Changed:connect(function(prop) if prop == 'Parent' then print("Backpack added", tick() - addTime, "seconds ago just got removed! Izat coo?") end end) --TODO: Remove
Backpack.ChildRemoved:connect(OnChildRemoved)
Backpack.ChildAdded:connect(OnChildAdded)
for _, child in pairs(Backpack:GetChildren()) do
OnChildAdded(child)
end
print("CharAdded finished")
end
local function OnInputBegan(input, isProcessed)
if not TextBoxFocused and (WholeThingEnabled or input.KeyCode.Value == DROP_HOTKEY_VALUE) and input.UserInputType == Enum.UserInputType.Keyboard then
local hotkeyBehavior = HotkeyFns[input.KeyCode.Value]
if hotkeyBehavior then
hotkeyBehavior()
end
end
end
local function OnUISChanged(property)
--print("UIS CHANGED:", property)
if property == 'KeyboardEnabled' then
local on = UserInputService.KeyboardEnabled
for i = 1, HOTBAR_SLOTS do
Slots[i]:TurnNumber(on)
end
end
end
local function OnCoreGuiChanged(coreGuiType, enabled)
if coreGuiType == Enum.CoreGuiType.Backpack or coreGuiType == Enum.CoreGuiType.All then
print("Make whole everything", enabled and "visible" or "hidden!")
WholeThingEnabled = enabled
MainFrame.Visible = enabled
end
if coreGuiType == Enum.CoreGuiType.Health or coreGuiType == Enum.CoreGuiType.All then
print("Move whole everything", enabled and "back up!" or "down!")
MainFrame.Position = UDim2.new(0, 0, 0, enabled and 0 or HOTBAR_OFFSET_FROMBOTTOM)
end
end
-- Script Logic --
-- Make the main frame, which covers the screen
MainFrame = NewGui('Frame', 'Backpack')
MainFrame.Visible = false
MainFrame.Parent = CoreGui
-- Make the HotbarFrame, which holds only the Hotbar Slots
HotbarFrame = NewGui('Frame', 'Hotbar')
HotbarFrame.Active = true
HotbarFrame.Size = HOTBAR_SIZE
HotbarFrame.Position = UDim2.new(0.5, -HotbarFrame.Size.X.Offset / 2, 1, -HotbarFrame.Size.Y.Offset - HOTBAR_OFFSET_FROMBOTTOM)
HotbarFrame.Parent = MainFrame
-- Make all the Hotbar Slots
for i = 1, HOTBAR_SLOTS do
local slot = MakeSlot(HotbarFrame, i)
slot.Frame.Visible = false
if not LowestEmptySlot then
LowestEmptySlot = slot
end
end
-- Make the Inventory, which holds the ScrollingFrame, the header, and the search box
InventoryFrame = NewGui('Frame', 'Inventory')
InventoryFrame.BackgroundTransparency = SLOT_TRANSPARENCY
InventoryFrame.Active = true
InventoryFrame.Size = UDim2.new(0, HotbarFrame.Size.X.Offset, 0, HotbarFrame.Size.Y.Offset * 5) --TODO: No MNs
InventoryFrame.Position = UDim2.new(0.5, -InventoryFrame.Size.X.Offset / 2, 1, HotbarFrame.Position.Y.Offset - InventoryFrame.Size.Y.Offset)
InventoryFrame.Visible = false
InventoryFrame.Parent = MainFrame
-- Make the header title, in the Inventory
-- local headerText = NewGui('TextLabel', 'Header')
-- headerText.Text = TITLE_TEXT
-- headerText.TextXAlignment = Enum.TextXAlignment.Left
-- headerText.Font = Enum.Font.SourceSansBold
-- headerText.FontSize = Enum.FontSize.Size48
-- headerText.TextStrokeColor3 = SLOT_COLOR_EQUIP
-- headerText.TextStrokeTransparency = 0.75 --TODO: No MNs
-- headerText.Size = UDim2.new(0, (InventoryFrame.Size.X.Offset / 2) - TITLE_OFFSET, 0, INVENTORY_HEADER_SIZE)
-- headerText.Position = UDim2.new(0, TITLE_OFFSET, 0, 0)
-- headerText.Parent = InventoryFrame
do -- Search stuff
local searchFrame = NewGui('Frame', 'Search')
searchFrame.BackgroundColor3 = Color3.new(0.37, 0.37, 0.37) --TODO: NO MNs
searchFrame.BackgroundTransparency = 0.15 --TODO: NO MNs
searchFrame.Size = UDim2.new(0, SEARCH_WIDTH, 0, INVENTORY_HEADER_SIZE - (SEARCH_BUFFER * 2))
searchFrame.Position = UDim2.new(1, -searchFrame.Size.X.Offset - SEARCH_BUFFER, 0, SEARCH_BUFFER)
searchFrame.Parent = InventoryFrame
local searchBox = NewGui('TextBox', 'TextBox')
searchBox.Text = SEARCH_TEXT
searchBox.ClearTextOnFocus = false
searchBox.FontSize = Enum.FontSize.Size24
searchBox.TextXAlignment = Enum.TextXAlignment.Left
searchBox.Size = searchFrame.Size - UDim2.new(0, SEARCH_TEXT_OFFSET_FROMLEFT, 0, 0)
searchBox.Position = UDim2.new(0, SEARCH_TEXT_OFFSET_FROMLEFT, 0, 0)
searchBox.Parent = searchFrame
local xButton = NewGui('TextButton', 'X')
xButton.Text = 'x'
xButton.TextColor3 = SLOT_COLOR_EQUIP
xButton.FontSize = Enum.FontSize.Size24
xButton.TextYAlignment = Enum.TextYAlignment.Bottom
xButton.Size = UDim2.new(0, searchFrame.Size.Y.Offset - (SEARCH_BUFFER * 2), 0, searchFrame.Size.Y.Offset - (SEARCH_BUFFER * 2))
xButton.Position = UDim2.new(1, -xButton.Size.X.Offset - (SEARCH_BUFFER * 2), 0.5, -xButton.Size.Y.Offset / 2)
xButton.ZIndex = 3
xButton.Visible = false
xButton.Parent = searchFrame
local clickArea = NewGui('TextButton', 'GimmieYerClicks')
clickArea.MouseButton1Click:connect(function()
print("YOINK!")
searchBox:CaptureFocus()
if searchBox.Text == SEARCH_TEXT then
searchBox.Text = ''
end
end)
clickArea.ZIndex = 2
clickArea.Parent = searchFrame
local function resetSearch()
print("Reset!")
if xButton.Visible then
ResultsIndices = nil
for i = HOTBAR_SLOTS + 1, #Slots do
local slot = Slots[i]
slot:Reposition()
slot.Frame.Visible = true
end
end
xButton.Visible = false
searchBox.Text = SEARCH_TEXT
end
xButton.MouseButton1Click:connect(resetSearch)
searchBox.FocusLost:connect(function(enterPressed)
print("FocusLost! enterPressed:", enterPressed)
if enterPressed then
local text = searchBox.Text
print(" Want to search for:", text)
local terms = {}
for word in text:gmatch('%S+') do
terms[word:lower()] = true
end
local hitTable = {}
for i = HOTBAR_SLOTS + 1, #Slots do -- Only search inventory slots
local slot = Slots[i]
local hits = slot:CheckTerms(terms)
table.insert(hitTable, {slot, hits})
slot.Frame.Visible = false
end
table.sort(hitTable, function(left, right)
return left[2] > right[2]
end)
ResultsIndices = {}
for i, data in ipairs(hitTable) do
local slot, hits = data[1], data[2]
if hits > 0 then
ResultsIndices[slot] = HOTBAR_SLOTS + i
print(" ", i, "- Slot ", slot.Index, "Hits", hits)
slot:Reposition()
slot.Frame.Visible = true
end
end
xButton.Visible = true
else
resetSearch()
end
end)
end
-- Make the ScrollingFrame, which holds the rest of the Slots (however many)
ScrollingFrame = NewGui('ScrollingFrame', 'ScrollingFrame')
ScrollingFrame.Size = UDim2.new(1, ScrollingFrame.ScrollBarThickness + 1, 1, -INVENTORY_HEADER_SIZE)
ScrollingFrame.Position = UDim2.new(0, 0, 0, INVENTORY_HEADER_SIZE)
ScrollingFrame.CanvasSize = UDim2.new(0, 0, 0, 0)
ScrollingFrame.Parent = InventoryFrame
do -- Make the Inventory expand/collapse arrow
local arrowFrame = NewGui('Frame', 'Arrow')
arrowFrame.BackgroundTransparency = SLOT_TRANSPARENCY
arrowFrame.Size = UDim2.new(0, ICON_SIZE, 0, ICON_SIZE / 2)
local hotbarBottom = HotbarFrame.Position.Y.Offset + HotbarFrame.Size.Y.Offset
arrowFrame.Position = UDim2.new(0.5, -arrowFrame.Size.X.Offset / 2, 1, hotbarBottom - arrowFrame.Size.Y.Offset)
local arrowIcon = NewGui('ImageLabel', 'Icon')
arrowIcon.Image = ARROW_IMAGE_OPEN
arrowIcon.Size = ARROW_SIZE
arrowIcon.Position = UDim2.new(0.5, -arrowIcon.Size.X.Offset / 2, 0.5, -arrowIcon.Size.Y.Offset / 2)
arrowIcon.Parent = arrowFrame
local collapsed = arrowFrame.Position
local closed = collapsed + UDim2.new(0, 0, 0, -HotbarFrame.Size.Y.Offset)
local opened = closed + UDim2.new(0, 0, 0, -InventoryFrame.Size.Y.Offset)
local function openClose()
if not next(Dragging) then -- Only continue if nothing is being dragged
InventoryFrame.Visible = not InventoryFrame.Visible
local nowOpen = InventoryFrame.Visible
arrowIcon.Image = (nowOpen) and ARROW_IMAGE_CLOSE or ARROW_IMAGE_OPEN
AdjustHotbarFrames()
UpdateArrowFrame()
for i = 1, HOTBAR_SLOTS do
Slots[i]:SetClickability(not nowOpen)
end
end
end
local clickArea = NewGui('TextButton', 'GimmieYerClicks')
clickArea.MouseButton1Click:connect(openClose)
clickArea.Parent = arrowFrame
HotkeyFns[ARROW_HOTKEY] = openClose
-- Define global function
UpdateArrowFrame = function()
arrowFrame.Position = (InventoryFrame.Visible) and opened or ((FullHotbarSlots == 0) and collapsed or closed)
end
arrowFrame.Parent = MainFrame
end
-- Finally, connect the major events
while not Player do --TODO: Only necessary in RunSolo? -- Still a valid case though.
wait()
Player = PlayersService.LocalPlayer
end
Player.CharacterAdded:connect(OnCharacterAdded)
if Player.Character then
OnCharacterAdded(Player.Character)
end
-- Eat keys
for i = 0, 9 do
GuiService:AddKey(tostring(i))
end
GuiService:AddKey(ARROW_HOTKEY_STRING)
UserInputService.InputBegan:connect(OnInputBegan)
UserInputService.Changed:connect(OnUISChanged)
OnUISChanged('KeyboardEnabled')
UserInputService.TextBoxFocused:connect(function() TextBoxFocused = true end)
UserInputService.TextBoxFocusReleased:connect(function() TextBoxFocused = false end)
HotkeyFns[DROP_HOTKEY_VALUE] = function() --NOTE: HopperBin
if ActiveHopper then
UnequipTools()
end
end
StarterGui.CoreGuiChangedSignal:connect(OnCoreGuiChanged)
local backpackType = Enum.CoreGuiType.Backpack
OnCoreGuiChanged(backpackType, StarterGui:GetCoreGuiEnabled(backpackType))
@@ -0,0 +1,588 @@
-- This script creates almost all gui elements found in the backpack (warning: there are a lot!)
-- TODO: automate this process
local ICON_SIZE = 46
local gui = script.Parent
-- A couple of necessary functions
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
local function IsTouchDevice()
return Game:GetService('UserInputService').TouchEnabled
end
local function IsPhone()
if Game:GetService("GuiService"):GetScreenResolution().Y <= 500 and IsTouchDevice() then
return true
end
return false
end
waitForChild(game,"Players")
waitForProperty(game:GetService("Players"),"LocalPlayer")
local player = game:GetService("Players").LocalPlayer
-- First up is the current loadout
local CurrentLoadout = Instance.new("Frame")
CurrentLoadout.Name = "CurrentLoadout"
CurrentLoadout.Position = UDim2.new(0.5, -300, 1, -85)
CurrentLoadout.Size = UDim2.new(0, 600, 0, ICON_SIZE)
CurrentLoadout.BackgroundTransparency = 1
CurrentLoadout.RobloxLocked = true
CurrentLoadout.Parent = gui
local CLBackground = Instance.new('ImageLabel')
CLBackground.Name = 'Background';
CLBackground.Size = UDim2.new(1.2, 0, 1.2, 0);
CLBackground.Image = "http://www.watrbx.wtf/asset/?id=96536002"
CLBackground.BackgroundTransparency = 1.0;
CLBackground.Position = UDim2.new(-0.1, 0, -0.1, 0);
CLBackground.ZIndex = 0.0;
CLBackground.Parent = CurrentLoadout
CLBackground.Visible = false
local Debounce = Instance.new("BoolValue")
Debounce.Name = "Debounce"
Debounce.RobloxLocked = true
Debounce.Parent = CurrentLoadout
local BackpackButton = Instance.new("ImageButton")
BackpackButton.RobloxLocked = true
BackpackButton.Visible = false
BackpackButton.Name = "BackpackButton"
BackpackButton.BackgroundTransparency = 1
BackpackButton.Image = "rbxasset://textures/ui/Backpack_Open.png"
BackpackButton.Position = UDim2.new(0.5, -7, 1, -55)
BackpackButton.Size = UDim2.new(0, 14, 0, 9)
waitForChild(gui,"ControlFrame")
BackpackButton.Parent = gui.ControlFrame
local NumSlots = 9
if IsPhone() then
NumSlots = 3
CurrentLoadout.Size = UDim2.new(0,180,0,ICON_SIZE)
CurrentLoadout.Position = UDim2.new(0.5,-90,1,-85)
end
for i = 0, NumSlots do
local slotFrame = Instance.new("Frame")
slotFrame.RobloxLocked = true
slotFrame.BackgroundColor3 = Color3.new(0,0,0)
slotFrame.BackgroundTransparency = 1
slotFrame.BorderColor3 = Color3.new(1, 1, 1)
slotFrame.BorderSizePixel = 0
slotFrame.Name = "Slot" .. tostring(i)
slotFrame.ZIndex = 4.0
if i == 0 then
slotFrame.Position = UDim2.new(0.9, 48, 0, 0)
else
slotFrame.Position = UDim2.new((i - 1) * 0.1, (i-1)* 6,0,0)
end
slotFrame.Size = UDim2.new(0, ICON_SIZE, 0, ICON_SIZE)
slotFrame.Parent = CurrentLoadout
if gui.AbsoluteSize.Y <= 320 then
slotFrame.Position = UDim2.new(0, (i-1)* 60, 0, -50)
end
if gui.AbsoluteSize.Y <= 320 and i == 0 then
slotFrame:Destroy()
end
end
local TempSlot = Instance.new("ImageButton")
TempSlot.Name = "TempSlot"
TempSlot.Active = true
TempSlot.Size = UDim2.new(1,0,1,0)
TempSlot.BackgroundTransparency = 1.0
TempSlot.Style = 'Custom'
TempSlot.Visible = false
TempSlot.RobloxLocked = true
TempSlot.Parent = CurrentLoadout
TempSlot.ZIndex = 3.0
local slotBackground = Instance.new('Frame')
slotBackground.Name = 'Background'
slotBackground.BackgroundTransparency = 1.0
slotBackground.Style = "DropShadow"
slotBackground.Position = UDim2.new(0, -10, 0, -10)
slotBackground.Size = UDim2.new(1, 20, 1, 20)
slotBackground.Parent = TempSlot
local HighLight = Instance.new('ImageLabel')
HighLight.Name = 'Highlight'
HighLight.BackgroundTransparency = 1.0
HighLight.Image = 'http://www.watrbx.wtf/asset/?id=97643886'
HighLight.Size = UDim2.new(1, 0, 1, 0)
--HighLight.Parent = TempSlot
HighLight.Visible = false
-- TempSlot Children
local GearReference = Instance.new("ObjectValue")
GearReference.Name = "GearReference"
GearReference.RobloxLocked = true
GearReference.Parent = TempSlot
local ToolTipLabel = Instance.new("TextLabel")
ToolTipLabel.Name = "ToolTipLabel"
ToolTipLabel.RobloxLocked = true
ToolTipLabel.Text = ""
ToolTipLabel.BackgroundTransparency = 0.5
ToolTipLabel.BorderSizePixel = 0
ToolTipLabel.Visible = false
ToolTipLabel.TextColor3 = Color3.new(1,1,1)
ToolTipLabel.BackgroundColor3 = Color3.new(0,0,0)
ToolTipLabel.TextStrokeTransparency = 0
ToolTipLabel.Font = Enum.Font.ArialBold
ToolTipLabel.FontSize = Enum.FontSize.Size14
--ToolTipLabel.TextWrap = true
ToolTipLabel.Size = UDim2.new(1,60,0,20)
ToolTipLabel.Position = UDim2.new(0,-30,0,-30)
ToolTipLabel.Parent = TempSlot
local Kill = Instance.new("BoolValue")
Kill.Name = "Kill"
Kill.RobloxLocked = true
Kill.Parent = TempSlot
local GearImage = Instance.new("ImageLabel")
GearImage.Name = "GearImage"
GearImage.BackgroundTransparency = 1
GearImage.Position = UDim2.new(0, 0, 0, 0)
GearImage.Size = UDim2.new(1, 0, 1, 0)
GearImage.ZIndex = 5.0
GearImage.RobloxLocked = true
GearImage.Parent = TempSlot
local SlotNumber = Instance.new("TextLabel")
SlotNumber.Name = "SlotNumber"
SlotNumber.BackgroundTransparency = 1
SlotNumber.BorderSizePixel = 0
SlotNumber.Font = Enum.Font.ArialBold
SlotNumber.FontSize = Enum.FontSize.Size18
SlotNumber.Position = UDim2.new(0, 0, 0, 0)
SlotNumber.Size = UDim2.new(0,10,0,15)
SlotNumber.TextColor3 = Color3.new(1,1,1)
SlotNumber.TextTransparency = 0
SlotNumber.TextXAlignment = Enum.TextXAlignment.Left
SlotNumber.TextYAlignment = Enum.TextYAlignment.Bottom
SlotNumber.RobloxLocked = true
SlotNumber.Parent = TempSlot
SlotNumber.ZIndex = 5
if IsTouchDevice() then
SlotNumber.Visible = false
end
local SlotNumberDownShadow = SlotNumber:Clone()
SlotNumberDownShadow.Name = "SlotNumberDownShadow"
SlotNumberDownShadow.TextColor3 = Color3.new(0,0,0)
SlotNumberDownShadow.Position = UDim2.new(0, 1, 0, -1)
SlotNumberDownShadow.Parent = TempSlot
SlotNumberDownShadow.ZIndex = 2
local SlotNumberUpShadow = SlotNumberDownShadow:Clone()
SlotNumberUpShadow.Name = "SlotNumberUpShadow"
SlotNumberUpShadow.Position = UDim2.new(0, -1, 0, -1)
SlotNumberUpShadow.Parent = TempSlot
local GearText = Instance.new("TextLabel")
GearText.RobloxLocked = true
GearText.Name = "GearText"
GearText.BackgroundTransparency = 1
GearText.Font = Enum.Font.Arial
GearText.FontSize = Enum.FontSize.Size14
GearText.Position = UDim2.new(0,0,0,0)
GearText.Size = UDim2.new(1,0,1,0)
GearText.Text = ""
GearText.TextColor3 = Color3.new(1,1,1)
GearText.TextWrap = true
GearText.Parent = TempSlot
GearText.ZIndex = 5.0
--- Great, now lets make the inventory!
local Backpack = Instance.new("Frame")
Backpack.RobloxLocked = true
Backpack.Visible = false
Backpack.Name = "Backpack"
Backpack.Position = UDim2.new(0.5, 0, 0.5, 0)
Backpack.BackgroundColor3 = Color3.new(32/255, 32/255, 32/255)
Backpack.BackgroundTransparency = 0.5
Backpack.BorderSizePixel = 0
Backpack.Parent = gui
Backpack.Active = true
-- Backpack Children
local SwapSlot = Instance.new("BoolValue")
SwapSlot.RobloxLocked = true
SwapSlot.Name = "SwapSlot"
SwapSlot.Parent = Backpack
-- SwapSlot Children
local Slot = Instance.new("IntValue")
Slot.RobloxLocked = true
Slot.Name = "Slot"
Slot.Parent = SwapSlot
local GearButton = Instance.new("ObjectValue")
GearButton.RobloxLocked = true
GearButton.Name = "GearButton"
GearButton.Parent = SwapSlot
local Tabs = Instance.new("Frame")
Tabs.Name = "Tabs"
Tabs.Visible = false
Tabs.Active = false
Tabs.RobloxLocked = true
Tabs.BackgroundColor3 = Color3.new(0,0,0)
Tabs.BackgroundTransparency = 0.08
Tabs.BorderSizePixel = 0
Tabs.Position = UDim2.new(0,0,-0.1,-4)
Tabs.Size = UDim2.new(1,0,0.1,4)
Tabs.Parent = Backpack
-- Tabs Children
local tabLine = Instance.new("Frame")
tabLine.RobloxLocked = true
tabLine.Name = "TabLine"
tabLine.BackgroundColor3 = Color3.new(53/255, 53/255, 53/255)
tabLine.BorderSizePixel = 0
tabLine.Position = UDim2.new(0,5,1,-4)
tabLine.Size = UDim2.new(1,-10,0,4)
tabLine.ZIndex = 2
tabLine.Parent = Tabs
local InventoryButton = Instance.new("TextButton")
InventoryButton.RobloxLocked = true
InventoryButton.Name = "InventoryButton"
InventoryButton.Size = UDim2.new(0,60,0,30)
InventoryButton.Position = UDim2.new(0,7,1,-31)
InventoryButton.BackgroundColor3 = Color3.new(1,1,1)
InventoryButton.BorderColor3 = Color3.new(1,1,1)
InventoryButton.Font = Enum.Font.ArialBold
InventoryButton.FontSize = Enum.FontSize.Size18
InventoryButton.Text = "Gear"
InventoryButton.AutoButtonColor = false
InventoryButton.TextColor3 = Color3.new(0,0,0)
InventoryButton.Selected = true
InventoryButton.Active = true
InventoryButton.ZIndex = 3
InventoryButton.Parent = Tabs
local closeButton = Instance.new("TextButton")
closeButton.RobloxLocked = true
closeButton.Name = "CloseButton"
closeButton.Font = Enum.Font.ArialBold
closeButton.FontSize = Enum.FontSize.Size24
closeButton.Position = UDim2.new(1,-33,0,4)
closeButton.Size = UDim2.new(0,30,0,30)
closeButton.Style = Enum.ButtonStyle.RobloxButton
closeButton.Text = ""
closeButton.TextColor3 = Color3.new(1,1,1)
closeButton.Parent = Tabs
closeButton.Modal = true
--closeButton child
local XImage = Instance.new("ImageLabel")
XImage.RobloxLocked = true
XImage.Name = "XImage"
game:GetService("ContentProvider"):Preload("http://www.watrbx.wtf/asset/?id=75547445")
XImage.Image = "http://www.watrbx.wtf/asset/?id=75547445" --TODO: move to rbxasset
XImage.BackgroundTransparency = 1
XImage.Position = UDim2.new(-.25,-1,-.25,-1)
XImage.Size = UDim2.new(1.5,2,1.5,2)
XImage.ZIndex = 2
XImage.Parent = closeButton
-- Generic Search gui used across backpack
local SearchFrame = Instance.new("Frame")
SearchFrame.RobloxLocked = true
SearchFrame.Name = "SearchFrame"
SearchFrame.BackgroundTransparency = 1
SearchFrame.Position = UDim2.new(1,-220,0,2)
SearchFrame.Size = UDim2.new(0,220,0,24)
SearchFrame.Parent = Backpack
-- SearchFrame Children
local SearchButton = Instance.new("ImageButton")
SearchButton.RobloxLocked = true
SearchButton.Name = "SearchButton"
SearchButton.Size = UDim2.new(0,25,0,25)
SearchButton.BackgroundTransparency = 1
SearchButton.Image = "rbxasset://textures/ui/SearchIcon.png"
SearchButton.Parent = SearchFrame
local SearchBoxFrame = Instance.new("TextButton")
SearchBoxFrame.RobloxLocked = true
SearchBoxFrame.Position = UDim2.new(0,25,0,-2)
SearchBoxFrame.Size = UDim2.new(1,-28,0,30)
SearchBoxFrame.Name = "SearchBoxFrame"
SearchBoxFrame.Text = ""
SearchBoxFrame.Style = Enum.ButtonStyle.RobloxRoundButton
SearchBoxFrame.Parent = SearchFrame
-- SearchBoxFrame Children
local SearchBox = Instance.new("TextBox")
SearchBox.RobloxLocked = true
SearchBox.Name = "SearchBox"
SearchBox.BackgroundTransparency = 1
SearchBox.Font = Enum.Font.ArialBold
SearchBox.FontSize = Enum.FontSize.Size12
SearchBox.Position = UDim2.new(0,-5,0,-5)
SearchBox.Size = UDim2.new(1,10,1,10)
SearchBox.TextColor3 = Color3.new(1,1,1)
SearchBox.TextXAlignment = Enum.TextXAlignment.Left
SearchBox.ZIndex = 2
SearchBox.TextWrap = true
SearchBox.Text = "Search..."
SearchBox.Parent = SearchBoxFrame
local ResetButton = Instance.new("TextButton")
ResetButton.RobloxLocked = true
ResetButton.Visible = false
ResetButton.Name = "ResetButton"
ResetButton.Position = UDim2.new(1,-26,0,3)
ResetButton.Size = UDim2.new(0,20,0,20)
ResetButton.Style = Enum.ButtonStyle.RobloxButtonDefault
ResetButton.Text = "X"
ResetButton.TextColor3 = Color3.new(1,1,1)
ResetButton.Font = Enum.Font.ArialBold
ResetButton.FontSize = Enum.FontSize.Size18
ResetButton.ZIndex = 3
ResetButton.Parent = SearchFrame
------------------------------- GEAR -------------------------------------------------------
local Gear = Instance.new("Frame")
Gear.Name = "Gear"
Gear.RobloxLocked = true
Gear.BackgroundTransparency = 1
Gear.Size = UDim2.new(1,0,1,0)
Gear.ClipsDescendants = true
Gear.Parent = Backpack
-- Gear Children
local AssetsList = Instance.new("Frame")
AssetsList.RobloxLocked = true
AssetsList.Name = "AssetsList"
AssetsList.BackgroundTransparency = 1
AssetsList.Size = UDim2.new(0.2,0,1,0)
AssetsList.Style = Enum.FrameStyle.RobloxSquare
AssetsList.Visible = false
AssetsList.Parent = Gear
local GearGrid = Instance.new("Frame")
GearGrid.RobloxLocked = true
GearGrid.Name = "GearGrid"
GearGrid.Size = UDim2.new(0.95, 0, 1, 0)
GearGrid.BackgroundTransparency = 1
GearGrid.Parent = Gear
local GearButton = Instance.new("ImageButton")
GearButton.RobloxLocked = true
GearButton.Visible = false
GearButton.Name = "GearButton"
GearButton.Size = UDim2.new(0, ICON_SIZE, 0, ICON_SIZE)
GearButton.Style = 'Custom'
GearButton.Parent = GearGrid
GearButton.BackgroundTransparency = 1.0
local slotBackground = Instance.new('Frame')
slotBackground.Name = 'Background'
slotBackground.BackgroundTransparency = 1.0
slotBackground.Size = UDim2.new(1, 16, 1, 16)
slotBackground.Position = UDim2.new(0, -8, 0, -8)
slotBackground.Parent = GearButton
slotBackground.Style = "DropShadow"
-- GearButton Children
local GearReference = Instance.new("ObjectValue")
GearReference.RobloxLocked = true
GearReference.Name = "GearReference"
GearReference.Parent = GearButton
local GreyOutButton = Instance.new("Frame")
GreyOutButton.RobloxLocked = true
GreyOutButton.Name = "GreyOutButton"
GreyOutButton.BackgroundTransparency = 0.5
GreyOutButton.Size = UDim2.new(1,0,1,0)
GreyOutButton.Active = true
GreyOutButton.Visible = false
GreyOutButton.ZIndex = 3
GreyOutButton.Parent = GearButton
local GearText = Instance.new("TextLabel")
GearText.RobloxLocked = true
GearText.Name = "GearText"
GearText.BackgroundTransparency = 1
GearText.Font = Enum.Font.Arial
GearText.FontSize = Enum.FontSize.Size14
GearText.Position = UDim2.new(0,-8,0,-8)
GearText.Size = UDim2.new(1,16,1,16)
GearText.Text = ""
GearText.ZIndex = 2
GearText.TextColor3 = Color3.new(1,1,1)
GearText.TextWrap = true
GearText.Parent = GearButton
local GearGridScrollingArea = Instance.new("Frame")
GearGridScrollingArea.RobloxLocked = true
GearGridScrollingArea.Name = "GearGridScrollingArea"
GearGridScrollingArea.Position = UDim2.new(1, -19, 0, 35)
GearGridScrollingArea.Size = UDim2.new(0, 17, 1, -45)
GearGridScrollingArea.BackgroundTransparency = 1
GearGridScrollingArea.Parent = Gear
local GearLoadouts = Instance.new("Frame")
GearLoadouts.RobloxLocked = true
GearLoadouts.Name = "GearLoadouts"
GearLoadouts.BackgroundTransparency = 1
GearLoadouts.Position = UDim2.new(0.7,23,0.5,1)
GearLoadouts.Size = UDim2.new(0.3,-23,0.5,-1)
GearLoadouts.Parent = Gear
GearLoadouts.Visible = false
-- GearLoadouts Children
local GearLoadoutsHeader = Instance.new("Frame")
GearLoadoutsHeader.RobloxLocked = true
GearLoadoutsHeader.Name = "GearLoadoutsHeader"
GearLoadoutsHeader.BackgroundColor3 = Color3.new(0,0,0)
GearLoadoutsHeader.BackgroundTransparency = 0.2
GearLoadoutsHeader.BorderColor3 = Color3.new(1,0,0)
GearLoadoutsHeader.Size = UDim2.new(1,2,0.15,-1)
GearLoadoutsHeader.Parent = GearLoadouts
-- GearLoadoutsHeader Children
local LoadoutsHeaderText = Instance.new("TextLabel")
LoadoutsHeaderText.RobloxLocked = true
LoadoutsHeaderText.Name = "LoadoutsHeaderText"
LoadoutsHeaderText.BackgroundTransparency = 1
LoadoutsHeaderText.Font = Enum.Font.ArialBold
LoadoutsHeaderText.FontSize = Enum.FontSize.Size18
LoadoutsHeaderText.Size = UDim2.new(1,0,1,0)
LoadoutsHeaderText.Text = "Loadouts"
LoadoutsHeaderText.TextColor3 = Color3.new(1,1,1)
LoadoutsHeaderText.Parent = GearLoadoutsHeader
local GearLoadoutsScrollingArea = GearGridScrollingArea:clone()
GearLoadoutsScrollingArea.RobloxLocked = true
GearLoadoutsScrollingArea.Name = "GearLoadoutsScrollingArea"
GearLoadoutsScrollingArea.Position = UDim2.new(1,-15,0.15,2)
GearLoadoutsScrollingArea.Size = UDim2.new(0,17,0.85,-2)
GearLoadoutsScrollingArea.Parent = GearLoadouts
local LoadoutsList = Instance.new("Frame")
LoadoutsList.RobloxLocked = true
LoadoutsList.Name = "LoadoutsList"
LoadoutsList.Position = UDim2.new(0,0,0.15,2)
LoadoutsList.Size = UDim2.new(1,-17,0.85,-2)
LoadoutsList.Style = Enum.FrameStyle.RobloxSquare
LoadoutsList.Parent = GearLoadouts
local GearPreview = Instance.new("Frame")
GearPreview.RobloxLocked = true
GearPreview.Name = "GearPreview"
GearPreview.Position = UDim2.new(0.7,23,0,0)
GearPreview.Size = UDim2.new(0.3,-28,0.5,-1)
GearPreview.BackgroundTransparency = 1
GearPreview.ZIndex = 7
GearPreview.Parent = Gear
-- GearPreview Children
local GearStats = Instance.new("Frame")
GearStats.RobloxLocked = true
GearStats.Name = "GearStats"
GearStats.BackgroundTransparency = 1
GearStats.Position = UDim2.new(0,0,0.75,0)
GearStats.Size = UDim2.new(1,0,0.25,0)
GearStats.ZIndex = 8
GearStats.Parent = GearPreview
-- GearStats Children
local GearName = Instance.new("TextLabel")
GearName.RobloxLocked = true
GearName.Name = "GearName"
GearName.BackgroundTransparency = 1
GearName.Font = Enum.Font.ArialBold
GearName.FontSize = Enum.FontSize.Size18
GearName.Position = UDim2.new(0,-3,0,0)
GearName.Size = UDim2.new(1,6,1,5)
GearName.Text = ""
GearName.TextColor3 = Color3.new(1,1,1)
GearName.TextWrap = true
GearName.ZIndex = 9
GearName.Parent = GearStats
local GearImage = Instance.new("ImageLabel")
GearImage.RobloxLocked = true
GearImage.Name = "GearImage"
GearImage.Image = ""
GearImage.BackgroundTransparency = 1
GearImage.Position = UDim2.new(0.125,0,0,0)
GearImage.Size = UDim2.new(0.75,0,0.75,0)
GearImage.ZIndex = 8
GearImage.Parent = GearPreview
--GearImage Children
local GearIcons = Instance.new("Frame")
GearIcons.BackgroundColor3 = Color3.new(0,0,0)
GearIcons.BackgroundTransparency = 0.5
GearIcons.BorderSizePixel = 0
GearIcons.RobloxLocked = true
GearIcons.Name = "GearIcons"
GearIcons.Position = UDim2.new(0.4,2,0.85,-2)
GearIcons.Size = UDim2.new(0.6,0,0.15,0)
GearIcons.Visible = false
GearIcons.ZIndex = 9
GearIcons.Parent = GearImage
-- GearIcons Children
local GenreImage = Instance.new("ImageLabel")
GenreImage.RobloxLocked = true
GenreImage.Name = "GenreImage"
GenreImage.BackgroundColor3 = Color3.new(102/255,153/255,1)
GenreImage.BackgroundTransparency = 0.5
GenreImage.BorderSizePixel = 0
GenreImage.Size = UDim2.new(0.25,0,1,0)
GenreImage.Parent = GearIcons
local AttributeOneImage = GenreImage:clone()
AttributeOneImage.RobloxLocked = true
AttributeOneImage.Name = "AttributeOneImage"
AttributeOneImage.BackgroundColor3 = Color3.new(1,51/255,0)
AttributeOneImage.Position = UDim2.new(0.25,0,0,0)
AttributeOneImage.Parent = GearIcons
local AttributeTwoImage = GenreImage:clone()
AttributeTwoImage.RobloxLocked = true
AttributeTwoImage.Name = "AttributeTwoImage"
AttributeTwoImage.BackgroundColor3 = Color3.new(153/255,1,153/255)
AttributeTwoImage.Position = UDim2.new(0.5,0,0,0)
AttributeTwoImage.Parent = GearIcons
local AttributeThreeImage = GenreImage:clone()
AttributeThreeImage.RobloxLocked = true
AttributeThreeImage.Name = "AttributeThreeImage"
AttributeThreeImage.BackgroundColor3 = Color3.new(0,0.5,0.5)
AttributeThreeImage.Position = UDim2.new(0.75,0,0,0)
AttributeThreeImage.Parent = GearIcons
script:Destroy()
@@ -0,0 +1,871 @@
-- A couple of necessary functions
local function waitForChild(instance, name)
assert(instance)
assert(name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
return instance:FindFirstChild(name)
end
local function waitForProperty(instance, property)
assert(instance)
assert(property)
while not instance[property] do
instance.Changed:wait()
end
end
local function IsTouchDevice()
return Game:GetService('UserInputService').TouchEnabled
end
waitForChild(game,"Players")
waitForProperty(game:GetService("Players"),"LocalPlayer")
local player = game:GetService("Players").LocalPlayer
local RbxGui, msg = LoadLibrary("RbxGuiFourTeen")
if not RbxGui then print("could not find RbxGui!") return end
--- Begin Locals
local StaticTabName = "gear"
local backpack = script.Parent
local screen = script.Parent.Parent
local backpackItems = {}
local buttons = {}
local debounce = false
local browsingMenu = false
local mouseEnterCons = {}
local mouseClickCons = {}
local characterChildAddedCon = nil
local characterChildRemovedCon = nil
local backpackAddCon = nil
local playerBackpack = waitForChild(player,"Backpack")
waitForChild(backpack,"Tabs")
waitForChild(backpack,"Gear")
local gearPreview = waitForChild(backpack.Gear,"GearPreview")
local scroller = waitForChild(backpack.Gear,"GearGridScrollingArea")
local currentLoadout = waitForChild(backpack.Parent,"CurrentLoadout")
local grid = waitForChild(backpack.Gear,"GearGrid")
local gearButton = waitForChild(grid,"GearButton")
local swapSlot = waitForChild(script.Parent,"SwapSlot")
local backpackManager = waitForChild(script.Parent,"CoreScripts/BackpackScripts/BackpackManager")
local backpackOpenEvent = waitForChild(backpackManager,"BackpackOpenEvent")
local backpackCloseEvent = waitForChild(backpackManager,"BackpackCloseEvent")
local tabClickedEvent = waitForChild(backpackManager,"TabClickedEvent")
local resizeEvent = waitForChild(backpackManager,"ResizeEvent")
local searchRequestedEvent = waitForChild(backpackManager,"SearchRequestedEvent")
local tellBackpackReadyFunc = waitForChild(backpackManager,"BackpackReady")
-- creating scroll bar early as to make sure items get placed correctly
local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil, "grid", Vector2.new(6, 6))
scrollFrame.Position = UDim2.new(0,0,0,30)
scrollFrame.Size = UDim2.new(1,0,1,-30)
scrollFrame.Parent = backpack.Gear.GearGrid
local scrollBar = Instance.new("Frame")
scrollBar.Name = "ScrollBar"
scrollBar.BackgroundTransparency = 0.9
scrollBar.BackgroundColor3 = Color3.new(1,1,1)
scrollBar.BorderSizePixel = 0
scrollBar.Size = UDim2.new(0, 17, 1, -36)
scrollBar.Position = UDim2.new(0,0,0,18)
scrollBar.Parent = scroller
scrollDown.Position = UDim2.new(0,0,1,-17)
scrollUp.Parent = scroller
scrollDown.Parent = scroller
local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame()
scrollFrameLoadout.Position = UDim2.new(0,0,0,0)
scrollFrameLoadout.Size = UDim2.new(1,0,1,0)
scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList
local LoadoutButton = Instance.new("TextButton")
LoadoutButton.RobloxLocked = true
LoadoutButton.Name = "LoadoutButton"
LoadoutButton.Font = Enum.Font.ArialBold
LoadoutButton.FontSize = Enum.FontSize.Size14
LoadoutButton.Position = UDim2.new(0,0,0,0)
LoadoutButton.Size = UDim2.new(1,0,0,32)
LoadoutButton.Style = Enum.ButtonStyle.RobloxButton
LoadoutButton.Text = "Loadout #1"
LoadoutButton.TextColor3 = Color3.new(1,1,1)
LoadoutButton.Parent = scrollFrameLoadout
local LoadoutButtonTwo = LoadoutButton:clone()
LoadoutButtonTwo.Text = "Loadout #2"
LoadoutButtonTwo.Parent = scrollFrameLoadout
local LoadoutButtonThree = LoadoutButton:clone()
LoadoutButtonThree.Text = "Loadout #3"
LoadoutButtonThree.Parent = scrollFrameLoadout
local LoadoutButtonFour = LoadoutButton:clone()
LoadoutButtonFour.Text = "Loadout #4"
LoadoutButtonFour.Parent = scrollFrameLoadout
local scrollBarLoadout = Instance.new("Frame")
scrollBarLoadout.Name = "ScrollBarLoadout"
scrollBarLoadout.BackgroundTransparency = 0.9
scrollBarLoadout.BackgroundColor3 = Color3.new(1,1,1)
scrollBarLoadout.BorderSizePixel = 0
scrollBarLoadout.Size = UDim2.new(0, 17, 1, -36)
scrollBarLoadout.Position = UDim2.new(0,0,0,18)
scrollBarLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
scrollDownLoadout.Position = UDim2.new(0,0,1,-17)
scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
-- Begin Functions
function removeFromMap(map,object)
for i = 1, #map do
if map[i] == object then
table.remove(map,i)
break
end
end
end
function robloxLock(instance)
instance.RobloxLocked = true
children = instance:GetChildren()
if children then
for i, child in ipairs(children) do
robloxLock(child)
end
end
end
function resize()
local size = 0
if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then
size = gearPreview.AbsoluteSize.X * 0.75
else
size = gearPreview.AbsoluteSize.Y * 0.75
end
waitForChild(gearPreview,"GearImage")
gearPreview.GearImage.Size = UDim2.new(0,size,0,size)
gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size)
resizeGrid()
end
function addToGrid(child)
if not child:IsA("Tool") then
if not child:IsA("HopperBin") then
return
end
end
if child:FindFirstChild("RobloxBuildTool") then return end
for i,v in pairs(backpackItems) do -- check to see if we already have this gear registered
if v == child then return end
end
table.insert(backpackItems,child)
local changeCon = child.Changed:connect(function(prop)
if prop == "Name" then
if buttons[child] then
if buttons[child].Image == "" then
buttons[child].GearText.Text = child.Name
end
end
end
end)
local ancestryCon = nil
ancestryCon = child.AncestryChanged:connect(function(theChild,theParent)
local thisObject = nil
for k,v in pairs(backpackItems) do
if v == child then
thisObject = v
break
end
end
waitForProperty(player,"Character")
waitForChild(player,"Backpack")
if (child.Parent ~= player.Backpack and child.Parent ~= player.Character) then
if ancestryCon then ancestryCon:disconnect() end
if changeCon then changeCon:disconnect() end
for k,v in pairs(backpackItems) do
if v == thisObject then
if mouseEnterCons[buttons[v]] then mouseEnterCons[buttons[v]]:disconnect() end
if mouseClickCons[buttons[v]] then mouseClickCons[buttons[v]]:disconnect() end
buttons[v].Parent = nil
buttons[v] = nil
break
end
end
removeFromMap(backpackItems,thisObject)
resizeGrid()
else
resizeGrid()
end
updateGridActive()
end)
resizeGrid()
end
function buttonClick(button)
if button:FindFirstChild("UnequipContextMenu") and not button.Active then
button.UnequipContextMenu.Visible = true
browsingMenu = true
end
end
function previewGear(button)
if not browsingMenu then
gearPreview.Visible = false
gearPreview.GearImage.Image = button.Image
gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name
end
end
function findEmptySlot()
local smallestNum = nil
local loadout = currentLoadout:GetChildren()
for i = 1, #loadout do
if loadout[i]:IsA("Frame") and #loadout[i]:GetChildren() <= 0 then
local frameNum = tonumber(string.sub(loadout[i].Name,5))
if frameNum == 0 then frameNum = 10 end
if not smallestNum or (smallestNum > frameNum) then
smallestNum = frameNum
end
end
end
if smallestNum == 10 then smallestNum = 0 end
return smallestNum
end
function checkForSwap(button,x,y)
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then
if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then
local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
swapGearSlot(slot,button)
return true
end
end
end
end
return false
end
function resizeGrid()
for k,v in pairs(backpackItems) do
if not v:FindFirstChild("RobloxBuildTool") then
if not buttons[v] then
local buttonClone = gearButton:clone()
buttonClone.Parent = grid.ScrollingFrame
buttonClone.Visible = true
buttonClone.Image = v.TextureId
if buttonClone.Image == "" then
buttonClone.GearText.Text = v.Name
end
buttonClone.GearReference.Value = v
buttonClone.Draggable = true
buttons[v] = buttonClone
if not IsTouchDevice() then
local unequipMenu = getGearContextMenu()
unequipMenu.Visible = false
unequipMenu.Parent = buttonClone
end
local beginPos = nil
buttonClone.DragBegin:connect(function(value)
waitForChild(buttonClone, 'Background')
buttonClone['Background'].ZIndex = 10
buttonClone.ZIndex = 10
beginPos = value
end)
buttonClone.DragStopped:connect(function(x,y)
waitForChild(buttonClone, 'Background')
buttonClone['Background'].ZIndex = 1.0
buttonClone.ZIndex = 2
if beginPos ~= buttonClone.Position then
if not checkForSwap(buttonClone,x,y) then
buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true)
buttonClone.Draggable = false
delay(0.5,function()
buttonClone.Draggable = true
end)
else
buttonClone.Position = beginPos
end
end
end)
local clickTime = tick()
mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end)
mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function()
local newClickTime = tick()
if buttonClone.Active and (newClickTime - clickTime) < 0.5 then
local slot = findEmptySlot()
if slot then
buttonClone.ZIndex = 1
swapGearSlot(slot,buttonClone)
end
else
buttonClick(buttonClone)
end
clickTime = newClickTime
end)
end
end
end
recalculateScroll()
end
function showPartialGrid(subset)
for k,v in pairs(buttons) do
v.Parent = nil
end
if subset then
for k,v in pairs(subset) do
v.Parent = grid.ScrollingFrame
end
end
recalculateScroll()
end
function showEntireGrid()
for k,v in pairs(buttons) do
v.Parent = grid.ScrollingFrame
end
recalculateScroll()
end
function inLoadout(gear)
local children = currentLoadout:GetChildren()
for i = 1, #children do
if children[i]:IsA("Frame") then
local button = children[i]:GetChildren()
if #button > 0 then
if button[1].GearReference.Value and button[1].GearReference.Value == gear then
return true
end
end
end
end
return false
end
function updateGridActive()
for k,v in pairs(backpackItems) do
if buttons[v] then
local gear = nil
local gearRef = buttons[v]:FindFirstChild("GearReference")
if gearRef then gear = gearRef.Value end
if not gear then
buttons[v].Active = false
elseif inLoadout(gear) then
buttons[v].Active = false
else
buttons[v].Active = true
end
end
end
end
function centerGear(loadoutChildren)
local gearButtons = {}
local lastSlotAdd = nil
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then
if loadoutChildren[i].Name == "Slot0" then
lastSlotAdd = loadoutChildren[i]
else
table.insert(gearButtons, loadoutChildren[i])
end
end
end
if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end
local startPos = ( 1 - (#gearButtons * 0.1) ) / 2
for i = 1, #gearButtons do
gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
end
end
function tabClickHandler(tabName)
if tabName == StaticTabName then
backpackOpenHandler(tabName)
else
backpackCloseHandler(tabName)
end
end
function backpackOpenHandler(currentTab)
if currentTab and currentTab ~= StaticTabName then
backpack.Gear.Visible = false
return
end
backpack.Gear.Visible = true
updateGridActive()
resizeGrid()
resize()
tellBackpackReadyFunc:Invoke()
end
function backpackCloseHandler(currentTab)
if currentTab and currentTab ~= StaticTabName then
backpack.Gear.Visible = false
return
end
backpack.Gear.Visible = false
resizeGrid()
resize()
tellBackpackReadyFunc:Invoke()
end
function loadoutCheck(child, selectState)
if not child:IsA("ImageButton") then return end
for k,v in pairs(backpackItems) do
if buttons[v] then
if child:FindFirstChild("GearReference") and buttons[v]:FindFirstChild("GearReference") then
if buttons[v].GearReference.Value == child.GearReference.Value then
buttons[v].Active = selectState
break
end
end
end
end
end
function clearPreview()
gearPreview.GearImage.Image = ""
gearPreview.GearStats.GearName.Text = ""
end
function removeAllEquippedGear(physGear)
local stuff = player.Character:GetChildren()
for i = 1, #stuff do
if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then
stuff[i].Parent = playerBackpack
end
end
end
function equipGear(physGear)
removeAllEquippedGear(physGear)
physGear.Parent = player.Character
updateGridActive()
end
function unequipGear(physGear)
physGear.Parent = playerBackpack
updateGridActive()
end
function highlight(button)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundColor3 = Color3.new(0.8,0.8,0.8)
end
function clearHighlight(button)
button.TextColor3 = Color3.new(1,1,1)
button.BackgroundColor3 = Color3.new(0,0,0)
end
function swapGearSlot(slot,gearButton)
if not swapSlot.Value then -- signal loadout to swap a gear out
swapSlot.Slot.Value = slot
swapSlot.GearButton.Value = gearButton
swapSlot.Value = true
updateGridActive()
end
end
local UnequipGearMenuClick = function(element, menu)
if type(element.Action) ~= "number" then return end
local num = element.Action
if num == 1 then -- remove from loadout
unequipGear(menu.Parent.GearReference.Value)
local inventoryButton = menu.Parent
local gearToUnequip = inventoryButton.GearReference.Value
local loadoutChildren = currentLoadout:GetChildren()
local slot = -1
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
local button = loadoutChildren[i]:GetChildren()
if button[1] and button[1].GearReference.Value == gearToUnequip then
slot = button[1].SlotNumber.Text
break
end
end
end
swapGearSlot(slot,nil)
end
end
function setupCharacterConnections()
if backpackAddCon then backpackAddCon:disconnect() end
backpackAddCon = game:GetService("Players").LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
-- make sure we get all the children
local backpackChildren = game:GetService("Players").LocalPlayer.Backpack:GetChildren()
for i = 1, #backpackChildren do
addToGrid(backpackChildren[i])
end
if characterChildAddedCon then characterChildAddedCon:disconnect() end
characterChildAddedCon =
game:GetService("Players").LocalPlayer.Character.ChildAdded:connect(function(child)
addToGrid(child)
updateGridActive()
end)
if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
characterChildRemovedCon =
game:GetService("Players").LocalPlayer.Character.ChildRemoved:connect(function(child)
updateGridActive()
end)
wait()
centerGear(currentLoadout:GetChildren())
end
function removeCharacterConnections()
if characterChildAddedCon then characterChildAddedCon:disconnect() end
if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
if backpackAddCon then backpackAddCon:disconnect() end
end
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
function filterGear(terms)
local filteredGear = {}
for k,v in pairs(backpackItems) do
if buttons[v] then
local gearString = string.lower(buttons[v].GearReference.Value.Name)
gearString = trim(gearString)
for i = 1, #terms do
if string.match(gearString,terms[i]) then
table.insert(filteredGear,buttons[v])
break
end
end
end
end
return filteredGear
end
function splitByWhitespace(text)
if type(text) ~= "string" then return nil end
local terms = {}
for token in string.gmatch(text, "[^%s]+") do
if string.len(token) > 0 then
table.insert(terms,token)
end
end
return terms
end
function showSearchGear(searchTerms)
if not backpack.Gear.Visible then return end -- currently not active tab
local searchTermTable = splitByWhitespace(searchTerms)
if searchTermTable and (#searchTermTable > 0) then
currSearchTerms = searchTermTable
else
currSearchTerms = nil
end
if searchTermTable == nil then
showEntireGrid()
return
end
local filteredButtons = filterGear(currSearchTerms)
showPartialGrid(filteredButtons)
end
function nukeBackpack()
while #buttons > 0 do
table.remove(buttons)
end
buttons = {}
while #backpackItems > 0 do
table.remove(backpackItems)
end
backpackItems = {}
local scrollingFrameChildren = grid.ScrollingFrame:GetChildren()
for i = 1, #scrollingFrameChildren do
scrollingFrameChildren[i]:remove()
end
end
function getGearContextMenu()
local gearContextMenu = Instance.new("Frame")
gearContextMenu.Active = true
gearContextMenu.Name = "UnequipContextMenu"
gearContextMenu.Size = UDim2.new(0,115,0,70)
gearContextMenu.Position = UDim2.new(0,-16,0,-16)
gearContextMenu.BackgroundTransparency = 1
gearContextMenu.Visible = false
local gearContextMenuButton = Instance.new("TextButton")
gearContextMenuButton.Name = "UnequipContextMenuButton"
gearContextMenuButton.Text = ""
gearContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault
gearContextMenuButton.ZIndex = 8
gearContextMenuButton.Size = UDim2.new(1, 0, 1, -20)
gearContextMenuButton.Visible = true
gearContextMenuButton.Parent = gearContextMenu
local elementHeight = 12
local contextMenuElements = {}
local contextMenuElementsName = {"Remove Hotkey"}
for i = 1, #contextMenuElementsName do
local element = {}
element.Type = "Button"
element.Text = contextMenuElementsName[i]
element.Action = i
element.DoIt = UnequipGearMenuClick
table.insert(contextMenuElements,element)
end
for i, contextElement in ipairs(contextMenuElements) do
local element = contextElement
if element.Type == "Button" then
local button = Instance.new("TextButton")
button.Name = "UnequipContextButton" .. i
button.BackgroundColor3 = Color3.new(0,0,0)
button.BorderSizePixel = 0
button.TextXAlignment = Enum.TextXAlignment.Left
button.Text = " " .. contextElement.Text
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size14
button.Size = UDim2.new(1, 8, 0, elementHeight)
button.Position = UDim2.new(0,0,0,elementHeight * i)
button.TextColor3 = Color3.new(1,1,1)
button.ZIndex = 9
button.Parent = gearContextMenuButton
if not IsTouchDevice() then
button.MouseButton1Click:connect(function()
if button.Active and not gearContextMenu.Parent.Active then
local success, result = pcall(function() element.DoIt(element, gearContextMenu) end)
browsingMenu = false
gearContextMenu.Visible = false
clearHighlight(button)
clearPreview()
end
end)
button.MouseEnter:connect(function()
if button.Active and gearContextMenu.Parent.Active then
highlight(button)
end
end)
button.MouseLeave:connect(function()
if button.Active and gearContextMenu.Parent.Active then
clearHighlight(button)
end
end)
end
contextElement.Button = button
contextElement.Element = button
elseif element.Type == "Label" then
local frame = Instance.new("Frame")
frame.Name = "ContextLabel" .. i
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1, 8, 0, elementHeight)
local label = Instance.new("TextLabel")
label.Name = "Text1"
label.BackgroundTransparency = 1
label.BackgroundColor3 = Color3.new(1,1,1)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Left
label.Font = Enum.Font.ArialBold
label.FontSize = Enum.FontSize.Size14
label.Position = UDim2.new(0.0, 0, 0, 0)
label.Size = UDim2.new(0.5, 0, 1, 0)
label.TextColor3 = Color3.new(1,1,1)
label.ZIndex = 9
label.Parent = frame
element.Label1 = label
if element.GetText2 then
label = Instance.new("TextLabel")
label.Name = "Text2"
label.BackgroundTransparency = 1
label.BackgroundColor3 = Color3.new(1,1,1)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Right
label.Font = Enum.Font.Arial
label.FontSize = Enum.FontSize.Size14
label.Position = UDim2.new(0.5, 0, 0, 0)
label.Size = UDim2.new(0.5, 0, 1, 0)
label.TextColor3 = Color3.new(1,1,1)
label.ZIndex = 9
label.Parent = frame
element.Label2 = label
end
frame.Parent = gearContextMenuButton
element.Label = frame
element.Element = frame
end
end
gearContextMenu.ZIndex = 4
gearContextMenu.MouseLeave:connect(function()
browsingMenu = false
gearContextMenu.Visible = false
clearPreview()
end)
robloxLock(gearContextMenu)
return gearContextMenu
end
function coreGuiChanged(coreGuiType,enabled)
if coreGuiType == Enum.CoreGuiType.Backpack or coreGuiType == Enum.CoreGuiType.All then
if not enabled then
backpack.Gear.Visible = false
end
end
end
local backpackChildren = player.Backpack:GetChildren()
for i = 1, #backpackChildren do
addToGrid(backpackChildren[i])
end
------------------------- Start Lifelong Connections -----------------------
resizeEvent.Event:connect(function(absSize)
if debounce then return end
debounce = true
wait()
resize()
resizeGrid()
debounce = false
end)
currentLoadout.ChildAdded:connect(function(child) loadoutCheck(child, false) end)
currentLoadout.ChildRemoved:connect(function(child) loadoutCheck(child, true) end)
currentLoadout.DescendantAdded:connect(function(descendant)
if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
centerGear(currentLoadout:GetChildren())
end
end)
currentLoadout.DescendantRemoving:connect(function(descendant)
if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
wait()
centerGear(currentLoadout:GetChildren())
end
end)
grid.MouseEnter:connect(function() clearPreview() end)
grid.MouseLeave:connect(function() clearPreview() end)
player.CharacterRemoving:connect(function()
removeCharacterConnections()
nukeBackpack()
end)
player.CharacterAdded:connect(function() setupCharacterConnections() end)
player.ChildAdded:connect(function(child)
if child:IsA("Backpack") then
playerBackpack = child
if backpackAddCon then backpackAddCon:disconnect() end
backpackAddCon = game:GetService("Players").LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
end
end)
swapSlot.Changed:connect(function()
if not swapSlot.Value then
updateGridActive()
end
end)
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
loadoutChildren[i].ChildRemoved:connect(function()
updateGridActive()
end)
loadoutChildren[i].ChildAdded:connect(function()
updateGridActive()
end)
end
end
------------------------- End Lifelong Connections -----------------------
coreGuiChanged(Enum.CoreGuiType.Backpack, Game:GetService("StarterGui"):GetCoreGuiEnabled(Enum.CoreGuiType.Backpack))
Game:GetService("StarterGui").CoreGuiChangedSignal:connect(coreGuiChanged)
resize()
resizeGrid()
-- make sure any items in the loadout are accounted for in inventory
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
loadoutCheck(loadoutChildren[i], false)
end
if not backpack.Visible then centerGear(currentLoadout:GetChildren()) end
-- make sure that inventory is listening to gear reparenting
if characterChildAddedCon == nil and game:GetService("Players").LocalPlayer["Character"] then
setupCharacterConnections()
end
if not backpackAddCon then
backpackAddCon = game:GetService("Players").LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
end
backpackOpenEvent.Event:connect(backpackOpenHandler)
backpackCloseEvent.Event:connect(backpackCloseHandler)
tabClickedEvent.Event:connect(tabClickHandler)
searchRequestedEvent.Event:connect(showSearchGear)
recalculateScrollLoadout()
@@ -0,0 +1,416 @@
-- This script manages context switches in the backpack (Gear to Wardrobe, etc.) and player state changes. Also manages global functions across different tabs (currently only search)
-- basic functions
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
return instance:FindFirstChild(name)
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
-- don't do anything if we are in an empty game
waitForChild(game,"Players")
if #game:GetService("Players"):GetChildren() < 1 then
game:GetService("Players").ChildAdded:wait()
end
-- make sure everything is loaded in before we do anything
-- get our local player
waitForProperty(game:GetService("Players"),"LocalPlayer")
local player = game:GetService("Players").LocalPlayer
------------------------ Locals ------------------------------
local backpack = script.Parent
waitForChild(backpack,"Gear")
local screen = script.Parent.Parent
assert(screen:IsA("ScreenGui"))
waitForChild(backpack, "Tabs")
waitForChild(backpack.Tabs, "CloseButton")
local closeButton = backpack.Tabs.CloseButton
waitForChild(backpack.Tabs, "InventoryButton")
local inventoryButton = backpack.Tabs.InventoryButton
waitForChild(backpack.Parent,"ControlFrame")
local backpackButton = waitForChild(backpack.Parent.ControlFrame,"BackpackButton")
local currentTab = "gear"
local searchFrame = waitForChild(backpack,"SearchFrame")
waitForChild(backpack.SearchFrame,"SearchBoxFrame")
local searchBox = waitForChild(backpack.SearchFrame.SearchBoxFrame,"SearchBox")
local searchButton = waitForChild(backpack.SearchFrame,"SearchButton")
local resetButton = waitForChild(backpack.SearchFrame,"ResetButton")
local robloxGui = waitForChild(Game:GetService("CoreGui"), 'RobloxGui')
local currentLoadout = waitForChild(robloxGui, 'CurrentLoadout')
local canToggle = true
local readyForNextEvent = true
local backpackIsOpen = false
local active = true
local disabledByDeveloper = false
local humanoidDiedCon = nil
local backpackButtonPos
local guiTweenSpeed = 0.25 -- how quickly we open/close the backpack
local searchDefaultText = "Search..."
local tilde = "~"
local backquote = "`"
local backpackSize = UDim2.new(0, 600, 0, 400)
if robloxGui.AbsoluteSize.Y <= 500 then
backpackSize = UDim2.new(0, 200, 0, 140)
end
------------------------ End Locals ---------------------------
---------------------------------------- Public Event Setup ----------------------------------------
function createPublicEvent(eventName)
assert(eventName, "eventName is nil")
assert(tostring(eventName),"eventName is not a string")
local newEvent = Instance.new("BindableEvent")
newEvent.Name = tostring(eventName)
newEvent.Parent = script
return newEvent
end
function createPublicFunction(funcName, invokeFunc)
assert(funcName, "funcName is nil")
assert(tostring(funcName), "funcName is not a string")
assert(invokeFunc, "invokeFunc is nil")
assert(type(invokeFunc) == "function", "invokeFunc should be of type 'function'")
local newFunction = Instance.new("BindableFunction")
newFunction.Name = tostring(funcName)
newFunction.OnInvoke = invokeFunc
newFunction.Parent = script
return newFunction
end
-- Events
local resizeEvent = createPublicEvent("ResizeEvent")
local backpackOpenEvent = createPublicEvent("BackpackOpenEvent")
local backpackCloseEvent = createPublicEvent("BackpackCloseEvent")
local tabClickedEvent = createPublicEvent("TabClickedEvent")
local searchRequestedEvent = createPublicEvent("SearchRequestedEvent")
---------------------------------------- End Public Event Setup ----------------------------------------
--------------------------- Internal Functions ----------------------------------------
function deactivateBackpack()
backpack.Visible = false
active = false
end
function activateBackpack()
initHumanoidDiedConnections()
active = true
backpack.Visible = backpackIsOpen
if backpackIsOpen then
toggleBackpack()
end
end
function initHumanoidDiedConnections()
if humanoidDiedCon then
humanoidDiedCon:disconnect()
end
waitForProperty(game:GetService("Players").LocalPlayer,"Character")
waitForChild(game:GetService("Players").LocalPlayer.Character,"Humanoid")
humanoidDiedCon = game:GetService("Players").LocalPlayer.Character.Humanoid.Died:connect(deactivateBackpack)
end
local hideBackpack = function()
backpackIsOpen = false
readyForNextEvent = false
backpackButton.Selected = false
resetSearch()
backpackCloseEvent:Fire(currentTab)
backpack.Tabs.Visible = false
searchFrame.Visible = false
backpack:TweenSizeAndPosition(UDim2.new(0, backpackSize.X.Offset,0, 0), UDim2.new(0.5, -backpackSize.X.Offset/2, 1, -85), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true,
function()
game:GetService("GuiService"):RemoveCenterDialog(backpack)
backpack.Visible = false
backpackButton.Selected = false
end)
delay(guiTweenSpeed,function()
game:GetService("GuiService"):RemoveCenterDialog(backpack)
backpack.Visible = false
backpackButton.Selected = false
readyForNextEvent = true
canToggle = true
end)
end
function showBackpack()
game:GetService("GuiService"):AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog,
function()
backpack.Visible = true
backpackButton.Selected = true
end,
function()
backpack.Visible = false
backpackButton.Selected = false
end)
backpack.Visible = true
backpackButton.Selected = true
backpack:TweenSizeAndPosition(backpackSize, UDim2.new(0.5, -backpackSize.X.Offset/2, 1, -backpackSize.Y.Offset - 88), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true)
delay(guiTweenSpeed,function()
backpack.Tabs.Visible = false
searchFrame.Visible = true
backpackOpenEvent:Fire(currentTab)
canToggle = true
readyForNextEvent = true
backpackButton.Image = "rbxasset://textures/ui/Backpack_Close.png"
backpackButton.Position = UDim2.new(0.5, -7, 1, -backpackSize.Y.Offset - 108)
end)
end
function toggleBackpack()
if not game:GetService("Players").LocalPlayer then return end
if not game:GetService("Players").LocalPlayer["Character"] then return end
if not canToggle then return end
if not readyForNextEvent then return end
readyForNextEvent = false
canToggle = false
backpackIsOpen = not backpackIsOpen
if backpackIsOpen then
showBackpack()
else
backpackButton.Position = UDim2.new(0.5, -7, 1, -55)
backpackButton.Selected = false
backpackButton.Image = "rbxasset://textures/ui/Backpack_Open.png"
hideBackpack()
local clChildren = currentLoadout:GetChildren()
for i = 1, #clChildren do
if clChildren[i] and clChildren[i]:IsA('Frame') then
local frame = clChildren[i]
if #frame:GetChildren() > 0 then
backpackButton.Position = UDim2.new(0.5, -7, 1, -108)
backpackButton.Visible = true
if frame:GetChildren()[1]:IsA('ImageButton') then
local imgButton = frame:GetChildren()[1]
imgButton.Active = true
imgButton.Draggable = false
end
end
end
end
end
end
function closeBackpack()
if backpackIsOpen then
toggleBackpack()
end
end
function setSelected(tab)
assert(tab)
assert(tab:IsA("TextButton"))
tab.BackgroundColor3 = Color3.new(1,1,1)
tab.TextColor3 = Color3.new(0,0,0)
tab.Selected = true
tab.ZIndex = 3
end
function setUnselected(tab)
assert(tab)
assert(tab:IsA("TextButton"))
tab.BackgroundColor3 = Color3.new(0,0,0)
tab.TextColor3 = Color3.new(1,1,1)
tab.Selected = false
tab.ZIndex = 1
end
function updateTabGui(selectedTab)
assert(selectedTab)
if selectedTab == "gear" then
setSelected(inventoryButton)
elseif selectedTab == "wardrobe" then
setUnselected(inventoryButton)
end
end
function mouseLeaveTab(button)
assert(button)
assert(button:IsA("TextButton"))
if button.Selected then return end
button.BackgroundColor3 = Color3.new(0,0,0)
end
function mouseOverTab(button)
assert(button)
assert(button:IsA("TextButton"))
if button.Selected then return end
button.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
end
function newTabClicked(tabName)
assert(tabName)
tabName = string.lower(tabName)
currentTab = tabName
updateTabGui(tabName)
tabClickedEvent:Fire(tabName)
resetSearch()
end
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
function splitByWhitespace(text)
if type(text) ~= "string" then return nil end
local terms = {}
for token in string.gmatch(text, "[^%s]+") do
if string.len(token) > 0 then
table.insert(terms,token)
end
end
return terms
end
function resetSearchBoxGui()
resetButton.Visible = false
searchBox.Text = searchDefaultText
end
function doSearch()
local searchText = searchBox.Text
if searchText == "" then
resetSearch()
return
end
searchText = trim(searchText)
resetButton.Visible = true
termTable = splitByWhitespace(searchText)
searchRequestedEvent:Fire(searchText) -- todo: replace this with termtable when table passing is possible
end
function resetSearch()
resetSearchBoxGui()
searchRequestedEvent:Fire()
end
local backpackReady = function()
readyForNextEvent = true
end
function coreGuiChanged(coreGuiType,enabled)
if coreGuiType == Enum.CoreGuiType.Backpack or coreGuiType == Enum.CoreGuiType.All then
active = enabled
disabledByDeveloper = not enabled
if disabledByDeveloper then
game:GetService("GuiService"):RemoveKey(tilde)
game:GetService("GuiService"):RemoveKey(backquote)
else
game:GetService("GuiService"):AddKey(tilde)
game:GetService("GuiService"):AddKey(backquote)
end
resetSearch()
searchFrame.Visible = enabled and backpackIsOpen
currentLoadout.Visible = enabled
backpack.Visible = false
backpackButton.Visible = enabled
end
end
--------------------------- End Internal Functions -------------------------------------
------------------------------ Public Functions Setup -------------------------------------
createPublicFunction("CloseBackpack", hideBackpack)
createPublicFunction("BackpackReady", backpackReady)
------------------------------ End Public Functions Setup ---------------------------------
------------------------ Connections/Script Main -------------------------------------------
coreGuiChanged(Enum.CoreGuiType.Backpack, Game:GetService("StarterGui"):GetCoreGuiEnabled(Enum.CoreGuiType.Backpack))
Game:GetService("StarterGui").CoreGuiChangedSignal:connect(coreGuiChanged)
inventoryButton.MouseButton1Click:connect(function() newTabClicked("gear") end)
inventoryButton.MouseEnter:connect(function() mouseOverTab(inventoryButton) end)
inventoryButton.MouseLeave:connect(function() mouseLeaveTab(inventoryButton) end)
closeButton.MouseButton1Click:connect(closeBackpack)
screen.Changed:connect(function(prop)
if prop == "AbsoluteSize" then
resizeEvent:Fire(screen.AbsoluteSize)
end
end)
-- GuiService key setup
game:GetService("GuiService"):AddKey(tilde)
game:GetService("GuiService"):AddKey(backquote)
game:GetService("GuiService").KeyPressed:connect(function(key)
if not active or disabledByDeveloper then return end
if key == tilde or key == backquote then
toggleBackpack()
end
end)
backpackButton.MouseButton1Click:connect(function()
if not active or disabledByDeveloper then return end
toggleBackpack()
end)
if game:GetService("Players").LocalPlayer["Character"] then
activateBackpack()
end
game:GetService("Players").LocalPlayer.CharacterAdded:connect(activateBackpack)
-- search functions
searchBox.FocusLost:connect(function(enterPressed)
if enterPressed or searchBox.Text ~= "" then
doSearch()
elseif searchBox.Text == "" then
resetSearch()
end
end)
searchButton.MouseButton1Click:connect(doSearch)
resetButton.MouseButton1Click:connect(resetSearch)
if searchFrame and robloxGui.AbsoluteSize.Y <= 500 then
searchFrame.RobloxLocked = false
searchFrame:Destroy()
end
@@ -0,0 +1,965 @@
if game:GetService("CoreGui").Version < 3 then return end -- peace out if we aren't using the right client
-- A couple of necessary functions
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
waitForChild(game,"Players")
waitForProperty(game:GetService("Players"),"LocalPlayer")
local player = game:GetService("Players").LocalPlayer
local RbxGui,msg = LoadLibrary("RbxGuiFourTeen")
if not RbxGui then print("could not find RbxGui!") return end
--- Begin Locals
waitForChild(game,"Players")
-- don't do anything if we are in an empty game
if #game:GetService("Players"):GetChildren() < 1 then
game:GetService("Players").ChildAdded:wait()
end
local tilde = "~"
local backquote = "`"
game:GetService("GuiService"):AddKey(tilde) -- register our keys
game:GetService("GuiService"):AddKey(backquote)
local player = game:GetService("Players").LocalPlayer
local backpack = script.Parent
local screen = script.Parent.Parent
local closeButton = backpack.Tabs.CloseButton
local openCloseDebounce = false
local backpackItems = {}
local buttons = {}
local debounce = false
local guiTweenSpeed = 1
local backpackOldStateVisible = false
local browsingMenu = false
local mouseEnterCons = {}
local mouseClickCons = {}
local characterChildAddedCon = nil
local characterChildRemovedCon = nil
local backpackAddCon = nil
local humanoidDiedCon = nil
local backpackButtonClickCon = nil
local guiServiceKeyPressCon = nil
waitForChild(player,"Backpack")
local playerBackpack = player.Backpack
waitForChild(backpack,"Gear")
waitForChild(backpack.Gear,"GearPreview")
local gearPreview = backpack.Gear.GearPreview
waitForChild(backpack.Gear,"GearGridScrollingArea")
local scroller = backpack.Gear.GearGridScrollingArea
waitForChild(backpack.Parent,"CurrentLoadout")
local currentLoadout = backpack.Parent.CurrentLoadout
waitForChild(backpack.Parent,"ControlFrame")
waitForChild(backpack.Parent.ControlFrame,"BackpackButton")
local backpackButton = backpack.Parent.ControlFrame.BackpackButton
waitForChild(backpack.Gear,"GearGrid")
waitForChild(backpack.Gear.GearGrid,"GearButton")
local gearButton = backpack.Gear.GearGrid.GearButton
local grid = backpack.Gear.GearGrid
waitForChild(backpack.Gear.GearGrid,"SearchFrame")
waitForChild(backpack.Gear.GearGrid.SearchFrame,"SearchBoxFrame")
waitForChild(backpack.Gear.GearGrid.SearchFrame.SearchBoxFrame,"SearchBox")
local searchBox = backpack.Gear.GearGrid.SearchFrame.SearchBoxFrame.SearchBox
waitForChild(backpack.Gear.GearGrid.SearchFrame,"SearchButton")
local searchButton = backpack.Gear.GearGrid.SearchFrame.SearchButton
waitForChild(backpack.Gear.GearGrid,"ResetFrame")
local resetFrame = backpack.Gear.GearGrid.ResetFrame
waitForChild(backpack.Gear.GearGrid.ResetFrame,"ResetButtonBorder")
local resetButton = backpack.Gear.GearGrid.ResetFrame.ResetButtonBorder
waitForChild(script.Parent,"SwapSlot")
local swapSlot = script.Parent.SwapSlot
-- creating scroll bar early as to make sure items get placed correctly
local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil, "grid", Vector2.new(4, 4))
scrollFrame.Position = UDim2.new(0,0,0,30)
scrollFrame.Size = UDim2.new(1,0,1,-30)
scrollFrame.Parent = backpack.Gear.GearGrid
local scrollBar = Instance.new("Frame")
scrollBar.Name = "ScrollBar"
scrollBar.BackgroundTransparency = 0.9
scrollBar.BackgroundColor3 = Color3.new(1,1,1)
scrollBar.BorderSizePixel = 0
scrollBar.Size = UDim2.new(0, 17, 1, -36)
scrollBar.Position = UDim2.new(0,0,0,18)
scrollBar.Parent = scroller
scrollDown.Position = UDim2.new(0,0,1,-17)
scrollUp.Parent = scroller
scrollDown.Parent = scroller
local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame()
scrollFrameLoadout.Position = UDim2.new(0,0,0,0)
scrollFrameLoadout.Size = UDim2.new(1,0,1,0)
scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList
local LoadoutButton = Instance.new("TextButton")
LoadoutButton.RobloxLocked = true
LoadoutButton.Name = "LoadoutButton"
LoadoutButton.Font = Enum.Font.ArialBold
LoadoutButton.FontSize = Enum.FontSize.Size14
LoadoutButton.Position = UDim2.new(0,0,0,0)
LoadoutButton.Size = UDim2.new(1,0,0,32)
LoadoutButton.Style = Enum.ButtonStyle.RobloxButton
LoadoutButton.Text = "Loadout #1"
LoadoutButton.TextColor3 = Color3.new(1,1,1)
LoadoutButton.Parent = scrollFrameLoadout
local LoadoutButtonTwo = LoadoutButton:clone()
LoadoutButtonTwo.Text = "Loadout #2"
LoadoutButtonTwo.Parent = scrollFrameLoadout
local LoadoutButtonThree = LoadoutButton:clone()
LoadoutButtonThree.Text = "Loadout #3"
LoadoutButtonThree.Parent = scrollFrameLoadout
local LoadoutButtonFour = LoadoutButton:clone()
LoadoutButtonFour.Text = "Loadout #4"
LoadoutButtonFour.Parent = scrollFrameLoadout
local scrollBarLoadout = Instance.new("Frame")
scrollBarLoadout.Name = "ScrollBarLoadout"
scrollBarLoadout.BackgroundTransparency = 0.9
scrollBarLoadout.BackgroundColor3 = Color3.new(1,1,1)
scrollBarLoadout.BorderSizePixel = 0
scrollBarLoadout.Size = UDim2.new(0, 17, 1, -36)
scrollBarLoadout.Position = UDim2.new(0,0,0,18)
scrollBarLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
scrollDownLoadout.Position = UDim2.new(0,0,1,-17)
scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
-- Begin Functions
function removeFromMap(map,object)
for i = 1, #map do
if map[i] == object then
table.remove(map,i)
break
end
end
end
function robloxLock(instance)
instance.RobloxLocked = true
children = instance:GetChildren()
if children then
for i, child in ipairs(children) do
robloxLock(child)
end
end
end
function resize()
local size = 0
if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then
size = gearPreview.AbsoluteSize.X * 0.75
else
size = gearPreview.AbsoluteSize.Y * 0.75
end
gearPreview.GearImage.Size = UDim2.new(0,size,0,size)
gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size)
resizeGrid()
end
function addToGrid(child)
if not child:IsA("Tool") then
if not child:IsA("HopperBin") then
return
end
end
if child:FindFirstChild("RobloxBuildTool") then return end
for i,v in pairs(backpackItems) do -- check to see if we already have this gear registered
if v == child then return end
end
table.insert(backpackItems,child)
local changeCon = child.Changed:connect(function(prop)
if prop == "Name" then
if buttons[child] then
if buttons[child].Image == "" then
buttons[child].GearText.Text = child.Name
end
end
end
end)
local ancestryCon = nil
ancestryCon = child.AncestryChanged:connect(function(theChild,theParent)
local thisObject = nil
for k,v in pairs(backpackItems) do
if v == child then
thisObject = v
break
end
end
waitForProperty(player,"Character")
waitForChild(player,"Backpack")
if (child.Parent ~= player.Backpack and child.Parent ~= player.Character) then
if ancestryCon then ancestryCon:disconnect() end
if changeCon then changeCon:disconnect() end
for k,v in pairs(backpackItems) do
if v == thisObject then
if mouseEnterCons[buttons[v]] then mouseEnterCons[buttons[v]]:disconnect() end
if mouseClickCons[buttons[v]] then mouseClickCons[buttons[v]]:disconnect() end
buttons[v].Parent = nil
buttons[v] = nil
break
end
end
removeFromMap(backpackItems,thisObject)
resizeGrid()
else
resizeGrid()
end
updateGridActive()
end)
resizeGrid()
end
function buttonClick(button)
if button:FindFirstChild("UnequipContextMenu") and not button.Active then
button.UnequipContextMenu.Visible = true
browsingMenu = true
end
end
function previewGear(button)
if not browsingMenu then
gearPreview.GearImage.Image = button.Image
gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name
end
end
function findEmptySlot()
local smallestNum = nil
local loadout = currentLoadout:GetChildren()
for i = 1, #loadout do
if loadout[i]:IsA("Frame") and #loadout[i]:GetChildren() <= 0 then
local frameNum = tonumber(string.sub(loadout[i].Name,5))
if frameNum == 0 then frameNum = 10 end
if not smallestNum or (smallestNum > frameNum) then
smallestNum = frameNum
end
end
end
if smallestNum == 10 then smallestNum = 0 end
return smallestNum
end
function checkForSwap(button,x,y)
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then
if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then
local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
swapGearSlot(slot,button)
return true
end
end
end
end
return false
end
function resizeGrid()
for k,v in pairs(backpackItems) do
if not v:FindFirstChild("RobloxBuildTool") then
if not buttons[v] then
local buttonClone = gearButton:clone()
buttonClone.Parent = grid.ScrollingFrame
buttonClone.Visible = true
buttonClone.Image = v.TextureId
if buttonClone.Image == "" then
buttonClone.GearText.Text = v.Name
end
buttonClone.GearReference.Value = v
buttonClone.Draggable = true
buttons[v] = buttonClone
local unequipMenu = getGearContextMenu()
unequipMenu.Visible = false
unequipMenu.Parent = buttonClone
local beginPos = nil
buttonClone.DragBegin:connect(function(value)
buttonClone.ZIndex = 9
beginPos = value
end)
buttonClone.DragStopped:connect(function(x,y)
buttonClone.ZIndex = 1
if beginPos ~= buttonClone.Position then
if not checkForSwap(buttonClone,x,y) then
buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true)
buttonClone.Draggable = false
delay(0.5,function()
buttonClone.Draggable = true
end)
else
buttonClone.Position = beginPos
end
end
end)
local clickTime = tick()
mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end)
mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function()
local newClickTime = tick()
if buttonClone.Active and (newClickTime - clickTime) < 0.5 then
local slot = findEmptySlot()
if slot then
buttonClone.ZIndex = 1
swapGearSlot(slot,buttonClone)
end
else
buttonClick(buttonClone)
end
clickTime = newClickTime
end)
end
end
end
recalculateScroll()
end
function showPartialGrid(subset)
resetFrame.Visible = true
for k,v in pairs(buttons) do
v.Parent = nil
end
for k,v in pairs(subset) do
v.Parent = grid.ScrollingFrame
end
recalculateScroll()
end
function showEntireGrid()
resetFrame.Visible = false
for k,v in pairs(buttons) do
v.Parent = grid.ScrollingFrame
end
recalculateScroll()
end
function inLoadout(gear)
local children = currentLoadout:GetChildren()
for i = 1, #children do
if children[i]:IsA("Frame") then
local button = children[i]:GetChildren()
if #button > 0 then
if button[1].GearReference.Value and button[1].GearReference.Value == gear then
return true
end
end
end
end
return false
end
function updateGridActive()
for k,v in pairs(backpackItems) do
if buttons[v] then
local gear = nil
local gearRef = buttons[v]:FindFirstChild("GearReference")
if gearRef then gear = gearRef.Value end
if not gear then
buttons[v].Active = false
elseif inLoadout(gear) then
buttons[v].Active = false
else
buttons[v].Active = true
end
end
end
end
function centerGear(loadoutChildren)
local gearButtons = {}
local lastSlotAdd = nil
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then
if loadoutChildren[i].Name == "Slot0" then
lastSlotAdd = loadoutChildren[i]
else
table.insert(gearButtons, loadoutChildren[i])
end
end
end
if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end
local startPos = ( 1 - (#gearButtons * 0.1) ) / 2
for i = 1, #gearButtons do
gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
end
end
function spreadOutGear(loadoutChildren)
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
if slot == 0 then slot = 10 end
loadoutChildren[i]:TweenPosition(UDim2.new((slot - 1)/10,0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
end
end
end
function openCloseBackpack(close)
if openCloseDebounce then return end
openCloseDebounce = true
local visible = not backpack.Visible
if visible and not close then
updateGridActive()
local centerDialogSupported, msg = pcall(function() game:GetService("GuiService"):AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog,
function()
backpack.Visible = true
loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
loadoutChildren[i].BackgroundTransparency = 0.5
end
end
spreadOutGear(loadoutChildren)
end,
function()
backpack.Visible = false
end)
end)
backpackButton.Selected = true
backpack:TweenSizeAndPosition(UDim2.new(0.55, 0, 0.6, 0),UDim2.new(0.225, 0, 0.2, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed/2, true)
delay(guiTweenSpeed/2 + 0.01,
function()
local children = backpack:GetChildren()
for i = 1, #children do
if children[i]:IsA("Frame") then
children[i].Visible = true
end
end
resizeGrid()
resize()
openCloseDebounce = false
end)
else
backpackButton.Selected = false
local children = backpack:GetChildren()
for i = 1, #children do
if children[i]:IsA("Frame") then
children[i].Visible = false
end
end
loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
loadoutChildren[i].BackgroundTransparency = 1
end
end
centerGear(loadoutChildren)
backpack:TweenSizeAndPosition(UDim2.new(0,0,0,0),UDim2.new(0.5,0,0.5,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed/2, true)
delay(guiTweenSpeed/2 + 0.01,
function()
backpack.Visible = visible
resizeGrid()
resize()
pcall(function() game:GetService("GuiService"):RemoveCenterDialog(backpack) end)
openCloseDebounce = false
end)
end
end
function loadoutCheck(child, selectState)
if not child:IsA("ImageButton") then return end
for k,v in pairs(backpackItems) do
if buttons[v] then
if child:FindFirstChild("GearReference") and buttons[v]:FindFirstChild("GearReference") then
if buttons[v].GearReference.Value == child.GearReference.Value then
buttons[v].Active = selectState
break
end
end
end
end
end
function clearPreview()
gearPreview.GearImage.Image = ""
gearPreview.GearStats.GearName.Text = ""
end
function removeAllEquippedGear(physGear)
local stuff = player.Character:GetChildren()
for i = 1, #stuff do
if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then
stuff[i].Parent = playerBackpack
end
end
end
function equipGear(physGear)
removeAllEquippedGear(physGear)
physGear.Parent = player.Character
updateGridActive()
end
function unequipGear(physGear)
physGear.Parent = playerBackpack
updateGridActive()
end
function highlight(button)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundColor3 = Color3.new(0.8,0.8,0.8)
end
function clearHighlight(button)
button.TextColor3 = Color3.new(1,1,1)
button.BackgroundColor3 = Color3.new(0,0,0)
end
function swapGearSlot(slot,gearButton)
if not swapSlot.Value then -- signal loadout to swap a gear out
swapSlot.Slot.Value = slot
swapSlot.GearButton.Value = gearButton
swapSlot.Value = true
updateGridActive()
end
end
local UnequipGearMenuClick = function(element, menu)
if type(element.Action) ~= "number" then return end
local num = element.Action
if num == 1 then -- remove from loadout
unequipGear(menu.Parent.GearReference.Value)
local inventoryButton = menu.Parent
local gearToUnequip = inventoryButton.GearReference.Value
local loadoutChildren = currentLoadout:GetChildren()
local slot = -1
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
local button = loadoutChildren[i]:GetChildren()
if button[1] and button[1].GearReference.Value == gearToUnequip then
slot = button[1].SlotNumber.Text
break
end
end
end
swapGearSlot(slot,nil)
end
end
-- these next two functions are used to stop any use of backpack while the player is dead (can cause issues)
function activateBackpack()
backpack.Visible = backpackOldStateVisible
loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
loadoutChildren[i].BackgroundTransparency = 1
end
end
backpackButtonClickCon = backpackButton.MouseButton1Click:connect(function() openCloseBackpack() end)
guiServiceKeyPressCon = game:GetService("GuiService").KeyPressed:connect(function(key)
if key == tilde or key == backquote then
openCloseBackpack()
end
end)
end
function deactivateBackpack()
if backpackButtonClickCon then backpackButtonClickCon:disconnect() end
if guiServiceKeyPressCon then guiServiceKeyPressCon:disconnect() end
backpackOldStateVisible = backpack.Visible
backpack.Visible = false
openCloseBackpack(true)
end
function setupCharacterConnections()
if backpackAddCon then backpackAddCon:disconnect() end
backpackAddCon = game:GetService("Players").LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
-- make sure we get all the children
local backpackChildren = game:GetService("Players").LocalPlayer.Backpack:GetChildren()
for i = 1, #backpackChildren do
addToGrid(backpackChildren[i])
end
if characterChildAddedCon then characterChildAddedCon:disconnect() end
characterChildAddedCon =
game:GetService("Players").LocalPlayer.Character.ChildAdded:connect(function(child)
addToGrid(child)
updateGridActive()
end)
if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
characterChildRemovedCon =
game:GetService("Players").LocalPlayer.Character.ChildRemoved:connect(function(child)
updateGridActive()
end)
if humanoidDiedCon then humanoidDiedCon:disconnect() end
local localPlayer = game:GetService("Players").LocalPlayer
waitForProperty(localPlayer,"Character")
waitForChild(localPlayer.Character,"Humanoid")
humanoidDiedCon = game:GetService("Players").LocalPlayer.Character.Humanoid.Died:connect(function() deactivateBackpack() end)
activateBackpack()
wait()
centerGear(currentLoadout:GetChildren())
end
function removeCharacterConnections()
if characterChildAddedCon then characterChildAddedCon:disconnect() end
if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
if backpackAddCon then backpackAddCon:disconnect() end
end
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
function splitByWhiteSpace(text)
if type(text) ~= "string" then return nil end
local terms = {}
for token in string.gmatch(text, "[^%s]+") do
if string.len(token) > 2 then
table.insert(terms,token)
end
end
return terms
end
function filterGear(searchTerm)
string.lower(searchTerm)
searchTerm = trim(searchTerm)
if string.len(searchTerm) < 2 then return nil end
local terms = splitByWhiteSpace(searchTerm)
local filteredGear = {}
for k,v in pairs(backpackItems) do
if buttons[v] then
local gearString = string.lower(buttons[v].GearReference.Value.Name)
gearString = trim(gearString)
for i = 1, #terms do
if string.match(gearString,terms[i]) then
table.insert(filteredGear,buttons[v])
break
end
end
end
end
return filteredGear
end
function showSearchGear()
local searchText = searchBox.Text
searchBox.Text = "Search..."
local filteredButtons = filterGear(searchText)
if filteredButtons and #filteredButtons > 0 then
showPartialGrid(filteredButtons)
else
showEntireGrid()
end
end
function nukeBackpack()
while #buttons > 0 do
table.remove(buttons)
end
buttons = {}
while #backpackItems > 0 do
table.remove(backpackItems)
end
backpackItems = {}
local scrollingFrameChildren = grid.ScrollingFrame:GetChildren()
for i = 1, #scrollingFrameChildren do
scrollingFrameChildren[i]:remove()
end
end
function getGearContextMenu()
local gearContextMenu = Instance.new("Frame")
gearContextMenu.Active = true
gearContextMenu.Name = "UnequipContextMenu"
gearContextMenu.Size = UDim2.new(0,115,0,70)
gearContextMenu.Position = UDim2.new(0,-16,0,-16)
gearContextMenu.BackgroundTransparency = 1
gearContextMenu.Visible = false
local gearContextMenuButton = Instance.new("TextButton")
gearContextMenuButton.Name = "UnequipContextMenuButton"
gearContextMenuButton.Text = ""
gearContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault
gearContextMenuButton.ZIndex = 8
gearContextMenuButton.Size = UDim2.new(1, 0, 1, -20)
gearContextMenuButton.Visible = true
gearContextMenuButton.Parent = gearContextMenu
local elementHeight = 12
local contextMenuElements = {}
local contextMenuElementsName = {"Remove Hotkey"}
for i = 1, #contextMenuElementsName do
local element = {}
element.Type = "Button"
element.Text = contextMenuElementsName[i]
element.Action = i
element.DoIt = UnequipGearMenuClick
table.insert(contextMenuElements,element)
end
for i, contextElement in ipairs(contextMenuElements) do
local element = contextElement
if element.Type == "Button" then
local button = Instance.new("TextButton")
button.Name = "UnequipContextButton" .. i
button.BackgroundColor3 = Color3.new(0,0,0)
button.BorderSizePixel = 0
button.TextXAlignment = Enum.TextXAlignment.Left
button.Text = " " .. contextElement.Text
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size14
button.Size = UDim2.new(1, 8, 0, elementHeight)
button.Position = UDim2.new(0,0,0,elementHeight * i)
button.TextColor3 = Color3.new(1,1,1)
button.ZIndex = 9
button.Parent = gearContextMenuButton
button.MouseButton1Click:connect(function()
if button.Active and not gearContextMenu.Parent.Active then
local success, result = pcall(function() element.DoIt(element, gearContextMenu) end)
browsingMenu = false
gearContextMenu.Visible = false
clearHighlight(button)
clearPreview()
end
end)
button.MouseEnter:connect(function()
if button.Active and gearContextMenu.Parent.Active then
highlight(button)
end
end)
button.MouseLeave:connect(function()
if button.Active and gearContextMenu.Parent.Active then
clearHighlight(button)
end
end)
contextElement.Button = button
contextElement.Element = button
elseif element.Type == "Label" then
local frame = Instance.new("Frame")
frame.Name = "ContextLabel" .. i
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1, 8, 0, elementHeight)
local label = Instance.new("TextLabel")
label.Name = "Text1"
label.BackgroundTransparency = 1
label.BackgroundColor3 = Color3.new(1,1,1)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Left
label.Font = Enum.Font.ArialBold
label.FontSize = Enum.FontSize.Size14
label.Position = UDim2.new(0.0, 0, 0, 0)
label.Size = UDim2.new(0.5, 0, 1, 0)
label.TextColor3 = Color3.new(1,1,1)
label.ZIndex = 9
label.Parent = frame
element.Label1 = label
if element.GetText2 then
label = Instance.new("TextLabel")
label.Name = "Text2"
label.BackgroundTransparency = 1
label.BackgroundColor3 = Color3.new(1,1,1)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Right
label.Font = Enum.Font.Arial
label.FontSize = Enum.FontSize.Size14
label.Position = UDim2.new(0.5, 0, 0, 0)
label.Size = UDim2.new(0.5, 0, 1, 0)
label.TextColor3 = Color3.new(1,1,1)
label.ZIndex = 9
label.Parent = frame
element.Label2 = label
end
frame.Parent = gearContextMenuButton
element.Label = frame
element.Element = frame
end
end
gearContextMenu.ZIndex = 4
gearContextMenu.MouseLeave:connect(function()
browsingMenu = false
gearContextMenu.Visible = false
clearPreview()
end)
robloxLock(gearContextMenu)
return gearContextMenu
end
local backpackChildren = player.Backpack:GetChildren()
for i = 1, #backpackChildren do
addToGrid(backpackChildren[i])
end
------------------------- Start Lifelong Connections -----------------------
screen.Changed:connect(function(prop)
if prop == "AbsoluteSize" then
if debounce then return end
debounce = true
wait()
resize()
resizeGrid()
debounce = false
end
end)
currentLoadout.ChildAdded:connect(function(child) loadoutCheck(child, false) end)
currentLoadout.ChildRemoved:connect(function(child) loadoutCheck(child, true) end)
currentLoadout.DescendantAdded:connect(function(descendant)
if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
centerGear(currentLoadout:GetChildren())
end
end)
currentLoadout.DescendantRemoving:connect(function(descendant)
if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
wait()
centerGear(currentLoadout:GetChildren())
end
end)
grid.MouseEnter:connect(function() clearPreview() end)
grid.MouseLeave:connect(function() clearPreview() end)
player.CharacterRemoving:connect(function()
removeCharacterConnections()
nukeBackpack()
end)
player.CharacterAdded:connect(function() setupCharacterConnections() end)
player.ChildAdded:connect(function(child)
if child:IsA("Backpack") then
playerBackpack = child
if backpackAddCon then backpackAddCon:disconnect() end
backpackAddCon = game:GetService("Players").LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
end
end)
swapSlot.Changed:connect(function()
if not swapSlot.Value then
updateGridActive()
end
end)
searchBox.FocusLost:connect(function(enterPressed)
if enterPressed then
showSearchGear()
end
end)
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
loadoutChildren[i].ChildRemoved:connect(function()
updateGridActive()
end)
loadoutChildren[i].ChildAdded:connect(function()
updateGridActive()
end)
end
end
closeButton.Modal = true
closeButton.MouseButton1Click:connect(function() openCloseBackpack() end)
searchButton.MouseButton1Click:connect(function() showSearchGear() end)
resetButton.MouseButton1Click:connect(function() showEntireGrid() end)
------------------------- End Lifelong Connections -----------------------
resize()
resizeGrid()
-- make sure any items in the loadout are accounted for in inventory
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
loadoutCheck(loadoutChildren[i], false)
end
if not backpack.Visible then centerGear(currentLoadout:GetChildren()) end
-- make sure that inventory is listening to gear reparenting
if characterChildAddedCon == nil and game:GetService("Players").LocalPlayer["Character"] then
setupCharacterConnections()
end
if not backpackAddCon then
backpackAddCon = game:GetService("Players").LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
end
backpackButton.Visible = true
recalculateScrollLoadout()
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,174 @@
-- Responsible for giving out tools in personal servers
-- first, lets see if buildTools have already been created
-- create the object in ReplicatedStorage if not
local container = Game:GetService("ReplicatedStorage")
local toolsArray = container:FindFirstChild("BuildToolsModel")
local ownerArray = container:FindFirstChild("OwnerToolsModel")
local hasBuildTools = false
local function waitForProperty(instance, name)
while not instance[name] do
instance.Changed:wait()
end
end
waitForProperty(Game:GetService("Players"),"LocalPlayer")
waitForProperty(Game:GetService("Players").LocalPlayer,"userId")
local player = Game:GetService("Players").LocalPlayer
if not player then
script:Destroy()
return
end
function getIds(idTable, assetTable)
for i = 1, #idTable do
local model = Game:GetService("InsertService"):LoadAsset(idTable[i])
if model then
local children = model:GetChildren()
for i = 1, #children do
if children[i]:IsA("Tool") then
table.insert(assetTable,children[i])
end
end
end
end
end
function storeInContainer(modelName, assetTable)
local model = Instance.new("Model")
model.Archivable = false
model.Name = modelName
for i = 1, #assetTable do
assetTable[i].Parent = model
end
if not container:FindFirstChild(modelName) then -- no one beat us to it, we get to insert
model.Parent = container
end
end
if not toolsArray then -- no one has made build tools yet, we get to!
local buildToolIds = {}
local ownerToolIds = {}
local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower()
if BaseUrl:find("www.watrbx.wtf") or BaseUrl:find("gametest1") then
table.insert(buildToolIds,73089166) -- PartSelectionTool
table.insert(buildToolIds,73089190) -- DeleteTool
table.insert(buildToolIds,73089204) -- CloneTool
table.insert(buildToolIds,73089214) -- RotateTool
table.insert(buildToolIds,73089229) -- RecentPartTool
table.insert(buildToolIds,73089239) -- ConfigTool
table.insert(buildToolIds,73089259) -- WiringTool
elseif BaseUrl:find("gametest2") then
table.insert(buildToolIds,70353315) -- PartSelectionTool
table.insert(buildToolIds,70353317) -- DeleteTool
table.insert(buildToolIds,70353314) -- CloneTool
table.insert(buildToolIds,70353318) -- RotateTool
table.insert(buildToolIds,70353316) -- RecentPartTool
table.insert(buildToolIds,70353319) -- ConfigTool
table.insert(buildToolIds,70353320) -- WiringTool
end
table.insert(buildToolIds,58921588) -- ClassicTool
table.insert(ownerToolIds, 65347268) -- OwnerCameraTool
-- next, create array of our tools
local buildTools = {}
local ownerTools = {}
getIds(buildToolIds, buildTools)
getIds(ownerToolIds, ownerTools)
storeInContainer("BuildToolsModel",buildTools)
storeInContainer("OwnerToolsModel",ownerTools)
toolsArray = container:FindFirstChild("BuildToolsModel")
ownerArray = container:FindFirstChild("OwnerToolsModel")
end
local localBuildTools = {}
function giveBuildTools()
if not hasBuildTools then
hasBuildTools = true
local theTools = toolsArray:GetChildren()
for i = 1, #theTools do
local toolClone = theTools[i]:clone()
if toolClone then
toolClone.Parent = player:findFirstChild("Backpack")
table.insert(localBuildTools,toolClone)
end
end
end
end
function giveOwnerTools()
local theOwnerTools = ownerArray:GetChildren()
for i = 1, #theOwnerTools do
local ownerToolClone = theOwnerTools[i]:clone()
if ownerToolClone then
ownerToolClone.Parent = player:findFirstChild("Backpack")
table.insert(localBuildTools,ownerToolClone)
end
end
end
function removeBuildTools()
if not hasBuildTools then return end
hasBuildTools = false
for k,v in pairs(localBuildTools) do
v:Destroy()
end localBuildTools = {}
end
if player.HasBuildTools then
giveBuildTools()
end
if player.PersonalServerRank >= 255 then
giveOwnerTools()
end
local debounce = false
player.Changed:connect(function(prop)
if prop == "HasBuildTools" then
while debounce do
wait(0.5)
end
debounce = true
if player.HasBuildTools then
giveBuildTools()
else
removeBuildTools()
end
if player.PersonalServerRank >= 255 then
giveOwnerTools()
end
debounce = false
elseif prop == "PersonalServerRank" then
if player.PersonalServerRank >= 255 then
giveOwnerTools()
elseif player.PersonalServerRank <= 0 then
player:Kick() -- you're banned, goodbye!
Game:SetMessage("You're banned from this PBS")
end
end
end)
player.CharacterAdded:connect(function()
hasBuildTools = false
if player.HasBuildTools then
giveBuildTools()
end
if player.PersonalServerRank >= 255 then
giveOwnerTools()
end
end)
@@ -0,0 +1,217 @@
-- This script is responsible for loading in all build tools for build mode
-- Script Globals
local buildTools = {}
local currentTools = {}
local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower()
if BaseUrl:find("www.watrbx.wtf") or BaseUrl:find("gametest1") then
DeleteToolID = 73089190
PartSelectionID = 73089166
CloneToolID = 73089204
RecentPartToolID = 73089229
RotateToolID = 73089214
ConfigToolID = 73089239
WiringToolID = 73089259
classicToolID = 58921588
elseif BaseUrl:find("gametest2") then
DeleteToolID = 70353317
PartSelectionID = 70353315
CloneToolID = 70353314
RecentPartToolID = 70353316
RotateToolID = 70353318
ConfigToolID = 70353319
WiringToolID = 70353320
classicToolID = 58921588
end
local player = nil
local backpack = nil
-- Basic Functions
local function waitForProperty(instance, name)
while not instance[name] do
instance.Changed:wait()
end
end
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
waitForProperty(game:GetService("Players"),"LocalPlayer")
waitForProperty(game:GetService("Players").LocalPlayer,"userId")
-- we aren't in a true build mode session, don't give build tools and delete this script
if game:GetService("Players").LocalPlayer.userId < 1 then
script:Destroy()
return -- this is probably not necessesary, doing it just in case
end
-- Functions
function getLatestPlayer()
waitForProperty(game:GetService("Players"),"LocalPlayer")
player = game:GetService("Players").LocalPlayer
waitForChild(player,"Backpack")
backpack = player.Backpack
end
function waitForCharacterLoad()
local startTick = tick()
local playerLoaded = false
local success = pcall(function() playerLoaded = player.AppearanceDidLoad end) --TODO: remove pcall once this in client on prod
if not success then return false end
while not playerLoaded do
player.Changed:wait()
playerLoaded = player.AppearanceDidLoad
end
return true
end
function showBuildToolsTutorial()
local tutorialKey = "BuildToolsTutorial"
if UserSettings().GameSettings:GetTutorialState(tutorialKey) == true then return end --already have shown tutorial
local RbxGui = LoadLibrary("RbxGuiFourTeen")
local frame, showTutorial, dismissTutorial, gotoPage = RbxGui.CreateTutorial("Build", tutorialKey, false)
local firstPage = RbxGui.CreateImageTutorialPage(" ", "http://www.watrbx.wtf/asset/?id=59162193", 359, 296, function() dismissTutorial() end, true)
RbxGui.AddTutorialPage(frame, firstPage)
frame.Parent = game:GetService("CoreGui"):FindFirstChild("RobloxGui")
game:GetService("GuiService"):AddCenterDialog(frame, Enum.CenterDialogType.UnsolicitedDialog,
--showFunction
function()
frame.Visible = true
showTutorial()
end,
--hideFunction
function()
frame.Visible = false
end
)
wait(1)
showTutorial()
end
function clearLoadout()
currentTools = {}
local backpackChildren = game:GetService("Players").LocalPlayer.Backpack:GetChildren()
for i = 1, #backpackChildren do
if backpackChildren[i]:IsA("Tool") or backpackChildren[i]:IsA("HopperBin") then
table.insert(currentTools,backpackChildren[i])
end
end
if game:GetService("Players").LocalPlayer["Character"] then
local characterChildren = game:GetService("Players").LocalPlayer.Character:GetChildren()
for i = 1, #characterChildren do
if characterChildren[i]:IsA("Tool") or characterChildren[i]:IsA("HopperBin") then
table.insert(currentTools,characterChildren[i])
end
end
end
for i = 1, #currentTools do
currentTools[i].Parent = nil
end
end
function giveToolsBack()
for i = 1, #currentTools do
currentTools[i].Parent = game:GetService("Players").LocalPlayer.Backpack
end
end
function backpackHasTool(tool)
local backpackChildren = backpack:GetChildren()
for i = 1, #backpackChildren do
if backpackChildren[i] == tool then
return true
end
end
return false
end
function getToolAssetID(assetID)
local newTool = game:GetService("InsertService"):LoadAsset(assetID)
local toolChildren = newTool:GetChildren()
for i = 1, #toolChildren do
if toolChildren[i]:IsA("Tool") then
return toolChildren[i]
end
end
return nil
end
-- remove legacy identifiers
-- todo: determine if we still need this
function removeBuildToolTag(tool)
if tool:FindFirstChild("RobloxBuildTool") then
tool.RobloxBuildTool:Destroy()
end
end
function giveAssetId(assetID,toolName)
local theTool = getToolAssetID(assetID,toolName)
if theTool and not backpackHasTool(theTool) then
removeBuildToolTag(theTool)
theTool.Parent = backpack
table.insert(buildTools,theTool)
end
end
function loadBuildTools()
giveAssetId(PartSelectionID)
giveAssetId(DeleteToolID)
giveAssetId(CloneToolID)
giveAssetId(RotateToolID)
giveAssetId(RecentPartToolID)
giveAssetId(WiringToolID)
giveAssetId(ConfigToolID)
-- deprecated tools
giveAssetId(classicToolID)
end
function givePlayerBuildTools()
getLatestPlayer()
clearLoadout()
loadBuildTools()
giveToolsBack()
end
function takePlayerBuildTools()
for k,v in ipairs(buildTools) do
v.Parent = nil
end
buildTools = {}
end
-- Script start
getLatestPlayer()
waitForCharacterLoad()
givePlayerBuildTools()
-- If player dies, we make sure to give them build tools again
player.CharacterAdded:connect(function()
takePlayerBuildTools()
givePlayerBuildTools()
end)
showBuildToolsTutorial()
@@ -0,0 +1,194 @@
-- Personal Server Script
-----------------
--| Constants |--
-----------------
local CHANGES_PER_PLAYER = 100 -- Saving also occurs every time the number of edits reaches this number times the number of players
local SAVE_CHECK_INTERVAL = 1800 -- should be set in seconds, this is how long we wait to force a save, as long as at least one change has been made
local MIN_SAVE_TIME = 900 -- At least this many seconds will pass before saving again
-----------------
--| Variables |--
-----------------
local ContentProviderService = Game:GetService('ContentProvider')
local PlayersService = Game:GetService('Players')
local RunService = Game:GetService("RunService")
local StartingPlayerRanks = {}
local RbxUtil = nil
local LastSaveTime = 0
local ChangeCount = 0
local TryingToSave = false
local NumberOfChangesBeforeSaveAbsolute = CHANGES_PER_PLAYER
local GameRunning = true
local WaitingToSave = false
local PlaceId = Game.PlaceId
local Url = ContentProviderService.BaseUrl
local UrlBase = Url:match('^http://www\.(.-)/?$') -- Turns "http://www.gametest1.pizzaboxer.fun/" into "gametest1.pizzaboxer.fun"
local ApiProxyUrl = 'https://api.' .. UrlBase
-----------------
--| Functions |--
-----------------
function GetRbxUtil()
if not RbxUtil then
RbxUtil = LoadLibrary("RbxUtility")
end
return RbxUtil
end
-- Checks the full hierarchy of an instance for archivability
local function IsArchivable(instance)
if instance == Workspace then
return true
elseif not instance.Archivable then
return false
else
return IsArchivable(instance.Parent)
end
end
local function UpdateSaveOnChangeAmount()
local players = PlayersService:GetPlayers()
NumberOfChangesBeforeSaveAbsolute = #players * CHANGES_PER_PLAYER
end
local function OnPlayerAdded(player)
if player:IsA('Player') then
local getRankUrl = ApiProxyUrl .. '/RoleSets/GetRoleSetForUser?placeId=' .. tostring(PlaceId) .. '&userId=' .. tostring(player.userId)
local serverRankTable = nil
pcall(function()
serverRankTable = GetRbxUtil().DecodeJSON(Game:HttpGetAsync(getRankUrl))
end)
local playerRank = 0
if serverRankTable and type(serverRankTable) == 'table' then
for k, v in pairs(serverRankTable) do
if k == "data" then
if v["Rank"] then
playerRank = v["Rank"]
end
end
end
end
player.PersonalServerRank = playerRank
StartingPlayerRanks[player] = playerRank
UpdateSaveOnChangeAmount()
end
end
local function OnPlayerRemoved(player)
if player:IsA('Player') then
UpdateSaveOnChangeAmount()
if StartingPlayerRanks[player] then
local playerRank = player.PersonalServerRank
if StartingPlayerRanks[player] ~= playerRank then -- Don't need to make web call if rank is the same
local setRankUrl = ApiProxyUrl .. '/RoleSets/PrivilegedSetUserRoleSetRank?placeId=' .. tostring(PlaceId) .. '&userId=' .. tostring(player.userId) .. '&newRank=' .. tostring(playerRank)
ypcall(function() Game:HttpPostAsync(setRankUrl, 'SetPersonalServerRank') end)
end
StartingPlayerRanks[player] = nil
end
end
end
local function DoSave()
if GameRunning then
ChangeCount = 0
LastSaveTime = tick()
Game:ServerSave()
end
end
local function TrySave()
if not TryingToSave then
TryingToSave = true
local now = tick()
if now - LastSaveTime >= MIN_SAVE_TIME then
DoSave()
elseif not WaitingToSave then -- Save after cooldown
WaitingToSave = true
Delay(LastSaveTime + MIN_SAVE_TIME - now, function()
DoSave()
WaitingToSave = false
end)
end
TryingToSave = false
end
end
-- Save based on number of edits to workspace
local function OnEdit(descendant)
if IsArchivable(descendant) then
ChangeCount = ChangeCount + 1
if ChangeCount >= NumberOfChangesBeforeSaveAbsolute then
TrySave()
end
end
end
-- Make sure we save every interval regardless of number of edits, so long as there is one
local function CheckForSaveOnInterval()
while true do
wait(SAVE_CHECK_INTERVAL)
if tick() - LastSaveTime >= SAVE_CHECK_INTERVAL and ChangeCount > 0 then
TrySave()
end
end
end
--------------------
--| Script Logic |--
--------------------
Game:WaitForChild('Workspace')
pcall(function()
Game.IsPersonalServer = true
if not Workspace:FindFirstChild("PSVariable") then
local psVar = Instance.new("BoolValue")
psVar.Name = "PSVariable"
psVar.Archivable = false
psVar.Parent = Workspace
end
end)
PlayersService.PlayerAdded:connect(OnPlayerAdded)
PlayersService.ChildRemoved:connect(OnPlayerRemoved)
for _, player in pairs(PlayersService:GetPlayers()) do
OnPlayerAdded(player)
end
if Url~=nil then
Game:SetServerSaveUrl(Url .. "Data/AutoSave.ashx?assetId=" .. PlaceId)
end
if pcall(function()
Game.Close:connect(
function()
GameRunning = false
Game:ServerSave()
end)
end) == false then
print("!Error in Game.Close:connect")
end
RunService:Run()
Game:GetService("Workspace").DescendantAdded:connect(OnEdit)
Game:GetService("Workspace").DescendantRemoving:connect(OnEdit)
Spawn(CheckForSaveOnInterval)
@@ -0,0 +1,981 @@
--[[
//FileName: ChatScript.LUA
//Written by: Sorcus
//Description: Code for lua side chat on ROBLOX. Supports Scrolling.
//NOTE: If you find any bugs or inaccuracies PM Sorcus on ROBLOX or @Canavus on Twitter
]]
local forceChatGUI = false
-- Utility functions + Globals
local function WaitForChild(parent, childName)
while parent:FindFirstChild(childName) == nil do
parent.ChildAdded:wait(0.03)
end
return parent[childName]
end
local function typedef(obj)
return obj
end
local function IsPhone()
local cGui = Game:GetService('CoreGui')
local rGui = WaitForChild(cGui, 'RobloxGui')
if rGui.AbsoluteSize.Y < 600 then
return true
end
return false
end
-- Users can use enough white spaces to spoof chatting as other players
-- This function removes trailing and leading white spaces
-- AFAIK, there is no reason for spam white spaces
local function StringTrim(str,nstr)
-- %s+ stands whitespaces
-- We yank out any whitespaces at the begin and end of the string
-- After that, we put a tab behind newlines
-- That way people can't fake messages on a new line
return str:match("^%s*(.-)%s*$"):gsub("\n","\n"..nstr)
end
while Game:GetService("Players").LocalPlayer == nil do wait(0.03) end
local Player = Game:GetService("Players").LocalPlayer
while Player.Character == nil do wait(0.03) end
local RbxUtility = LoadLibrary('RbxUtility')
local Gui = typedef(RbxUtility)
local Camera = Game:GetService("Workspace").CurrentCamera
-- Services
local CoreGuiService = Game:GetService('CoreGui')
local PlayersService = Game:GetService('Players')
local DebrisService= Game:GetService('Debris')
local GuiService = Game:GetService('GuiService')
local inputService = game:GetService("UserInputService")
-- Lua Enums
local Enums do
Enums = {}
local EnumName = {} -- used as unique key for enum name
local enum_mt = {
__call = function(self,value)
return self[value] or self[tonumber(value)]
end;
__index = {
GetEnumItems = function(self)
local t = {}
for i,item in pairs(self) do
if type(i) == 'number' then
t[#t+1] = item
end
end
table.sort(t,function(a,b) return a.Value < b.Value end)
return t
end;
};
__tostring = function(self)
return "Enum." .. self[EnumName]
end;
}
local item_mt = {
__call = function(self,value)
return value == self or value == self.Name or value == self.Value
end;
__tostring = function(self)
return "Enum." .. self[EnumName] .. "." .. self.Name
end;
}
function CreateEnum(enumName)
return function(t)
local e = {[EnumName] = enumName}
for i,name in pairs(t) do
local item = setmetatable({Name=name,Value=i,Enum=e,[EnumName]=enumName},item_mt)
e[i] = item
e[name] = item
e[item] = item
end
Enums[enumName] = e
return setmetatable(e, enum_mt)
end
end
end
---------------------------------------------------
------------------ Input class --------------------
local Input = {
Mouse = Player:GetMouse(),
Speed = 0,
Simulating = false,
Configuration = {
DefaultSpeed = 1
},
UserIsScrolling = false
}
---------------------------------------------------
------------------ Chat class --------------------
local Chat = {
ChatColors = {
BrickColor.new("Bright red"),
BrickColor.new("Bright blue"),
BrickColor.new("Earth green"),
BrickColor.new("Bright violet"),
BrickColor.new("Bright orange"),
BrickColor.new("Bright yellow"),
BrickColor.new("Light reddish violet"),
BrickColor.new("Brick yellow"),
},
Gui = nil,
Frame = nil,
RenderFrame = nil,
TapToChatLabel = nil,
ClickToChatButton = nil,
ScrollingLock = false,
EventListener = nil,
-- This is actually a ring buffer
-- Meaning at hitting the historyLength it wraps around
-- Reuses the text objects, so chat atmost uses 100 text objects
MessageQueue = {},
-- Stores all the values for configuring chat
Configuration = {
FontSize = Enum.FontSize.Size18, -- 10 is good
-- Also change this when you are changing the above, this is suboptimal but so is our interface to find FontSize
NumFontSize = 12,
HistoryLength = 20, -- stores up to 50 of the last chat messages for you to scroll through,
Size = UDim2.new(0.38, 0, 0.20, 0),
MessageColor = Color3.new(1, 1, 1),
AdminMessageColor = Color3.new(1, 215/255, 0),
XScale = 0.025,
LifeTime = 45,
Position = UDim2.new(0, 2, 0.05, 0),
DefaultTweenSpeed = 0.15,
HaltTime = 1/15, -- Why would people need to be chatting faster than every 1/15th of a second?
},
PreviousMessage = tick(), -- Timestamp of previous message
-- This could be redone by just using the previous and next fields of the Queue
-- But the iterators cause issues, will be optimized later
SlotPositions_List = {},
-- To precompute and store all player null strings since its an expensive process
CachedSpaceStrings_List = {},
MouseOnFrame = false,
GotFocus = false,
Messages_List = {},
MessageThread = nil,
Admins_List = {
'watrbx', 'watrabi', 'VMware', 'Frantic', 'SolidSoirb', 'MugMan', 'Sword',
},
TempSpaceLabel = nil
}
---------------------------------------------------
local function GetNameValue(pName)
local value = 0
for index = 1, #pName do
local cValue = string.byte(string.sub(pName, index, index))
local reverseIndex = #pName - index + 1
if #pName%2 == 1 then
reverseIndex = reverseIndex - 1
end
if reverseIndex%4 >= 2 then
cValue = -cValue
end
value = value + cValue
end
return value%8
end
function Chat:ComputeChatColor(pName)
return self.ChatColors[GetNameValue(pName) + 1].Color
end
-- This is context based scrolling
function Chat:EnableScrolling(toggle)
-- Genius idea gone to fail, if we switch the camera type we can effectively lock the
-- camera and do no click scrolling
self.MouseOnFrame = false
if self.RenderFrame then
self.RenderFrame.MouseEnter:connect(function()
local character = Player.Character
local torso = WaitForChild(character, 'Torso')
local humanoid = WaitForChild(character, 'Humanoid')
local head = WaitForChild(character, 'Head')
if toggle then
self.MouseOnFrame = true
Camera.CameraType = 'Scriptable'
-- Get relative position of camera and keep to it
Spawn(function()
local currentRelativePos = Camera.CoordinateFrame.p - torso.Position
while Chat.MouseOnFrame do
Camera.CoordinateFrame = CFrame.new(torso.Position + currentRelativePos, head.Position)
wait(0.015)
end
end)
end
end)
self.RenderFrame.MouseLeave:connect(function()
Camera.CameraType = 'Custom'
self.MouseOnFrame = false
end)
end
end
-- TODO: Scrolling using Mouse wheel
function Chat:OnScroll(speed)
if self.MouseOnFrame then
--
end
end
-- Check if we are running on a touch device
function Chat:IsTouchDevice()
local touchEnabled = false
pcall(function() touchEnabled = inputService.TouchEnabled end)
return touchEnabled
end
-- Scrolling
function Chat:ScrollQueue(value)
--[[for i = 1, #self.MessageQueue do
if self.MessageQueue[i] then
for _, label in pairs(self.MessageQueue[i]) do
local next = self.MessageQueue[i].Next
local previous = self.MessageQueue[i].Previous
if label and label:IsA('TextLabel') or label:IsA('TextButton') then
if value > 0 and previous and previous['Message'] then
label.Position = previous['Message'].Position
elseif value < 1 and next['Message'] then
label.Position = previous['Message'].Position
end
end
end
end
end ]]
end
-- Handles the rendering of the text objects in their appropriate places
function Chat:UpdateQueue(field, diff)
-- Have to do some sort of correction here
for i = #self.MessageQueue, 1, -1 do
if self.MessageQueue[i] then
for _, label in pairs(self.MessageQueue[i]) do
if label and type(label) ~= 'table' and type(label) ~= 'number' then
if label:IsA('TextLabel') or label:IsA('TextButton') or label:IsA('ImageLabel') then
if diff then
label.Position = label.Position - UDim2.new(0, 0, diff, 0)
else
local yOffset = 0
local xOffset = 20
if label:IsA('ImageLabel') then
yOffset = 4
xOffset = 0
end
if field == self.MessageQueue[i] then
label.Position = UDim2.new(self.Configuration.XScale, xOffset, label.Position.Y.Scale - field['Message'].Size.Y.Scale , yOffset)
-- Just to show up popping effect for the latest message in chat
if label:IsA('TextLabel') or label:IsA('TextButton') then
Spawn(function()
wait(0.05)
while label.TextTransparency > 0 do
label.TextTransparency = label.TextTransparency - 0.2
wait(0.03)
end
if label == field['Message'] then
label.TextStrokeTransparency = 0.6
else
label.TextStrokeTransparency = 1.0
end
end)
else
Spawn(function()
wait(0.05)
while label.ImageTransparency > 0 do
label.ImageTransparency = label.ImageTransparency - 0.2
wait(0.03)
end
end)
end
else
label.Position = UDim2.new(self.Configuration.XScale, xOffset, label.Position.Y.Scale - field['Message'].Size.Y.Scale, yOffset)
end
if label.Position.Y.Scale < -0.01 then
-- NOTE: Remove this fix when Textbounds is fixed
label.Visible = false
label:Destroy()
end
end
end
end
end
end
end
end
function Chat:CreateScrollBar()
-- Code for scrolling is in here, partially, but scroll bar drawing isn't drawn
-- TODO: Implement
end
-- For scrolling, to see if we hit the bounds so that we can stop it from scrolling anymore
function Chat:CheckIfInBounds(value)
if #Chat.MessageQueue < 3 then
return true
end
if value > 0 and Chat.MessageQueue[1] and Chat.MessageQueue[1]['Player'] and Chat.MessageQueue[1]['Player'].Position.Y.Scale == 0 then
return true
elseif value < 0 and Chat.MessageQueue[1] and Chat.MessageQueue[1]['Player'] and Chat.MessageQueue[1]['Player'].Position.Y.Scale < 0 then
return true
else
return false
end
return false
end
-- This is to precompute all playerName space strings
-- This is used to offset the message by exactly this + 2 spacestrings
function Chat:ComputeSpaceString(pLabel)
local nString = " "
if not self.TempSpaceLabel then
self.TempSpaceLabel = Gui.Create'TextButton'
{
Size = UDim2.new(0, pLabel.AbsoluteSize.X, 0, pLabel.AbsoluteSize.Y);
FontSize = self.Configuration.FontSize;
Parent = self.RenderFrame;
BackgroundTransparency = 1.0;
Text = nString;
Name = 'SpaceButton'
};
else
self.TempSpaceLabel.Text = nString
end
while self.TempSpaceLabel.TextBounds.X < pLabel.TextBounds.X do
nString = nString .. " "
self.TempSpaceLabel.Text = nString
end
nString = nString .. " "
self.CachedSpaceStrings_List[pLabel.Text] = nString
self.TempSpaceLabel.Text = ""
return nString
end
-- When the playerChatted event fires
-- The message is what the player chatted
function Chat:UpdateChat(cPlayer, message)
local messageField = {
['Player'] = cPlayer,
['Message'] = message
}
if coroutine.status(Chat.MessageThread) == 'dead' then
--Chat.Messages_List = {}
table.insert(Chat.Messages_List, messageField)
Chat.MessageThread = coroutine.create(function()
for i = 1, #Chat.Messages_List do
local field = Chat.Messages_List[i]
Chat:CreateMessage(field['Player'], field['Message'])
end
Chat.Messages_List = {}
end)
coroutine.resume(Chat.MessageThread)
else
table.insert(Chat.Messages_List, messageField)
end
end
function Chat:RecalculateSpacing()
--[[for i = 1, #self.MessageQueue do
local pLabel = self.MessageQueue[i]['Player']
local mLabel = self.MessageQueue[i]['Message']
local prevYScale = mLabel.Size.Y.Scale
local prevText = mLabel.Text
mLabel.Text = prevText
local heightField = mLabel.TextBounds.Y
mLabel.Size = UDim2.new(1, 0, heightField/self.RenderFrame.AbsoluteSize.Y, 0)
pLabel.Size = mLabel.Size
local diff = mLabel.Size.Y.Scale - prevYScale
Chat:UpdateQueue(self.MessageQueue[i], diff)
end ]]
end
function Chat:ApplyFilter(str)
--[[for _, word in pair(self.Filter_List) do
if string.find(str, word) then
str:gsub(word, '@#$^')
end
end ]]
end
-- NOTE: Temporarily disabled ring buffer to allow for chat to always wrap around
function Chat:CreateMessage(cPlayer, message)
local pName
if not cPlayer then
pName = ''
else
pName = cPlayer.Name
end
local pLabel,mLabel
-- Our history stores upto 50 messages that is 100 textlabels
-- If we ever hit the mark, which would be in every popular game btw
-- we wrap around and reuse the labels
if #self.MessageQueue > self.Configuration.HistoryLength then
--[[pLabel = self.MessageQueue[#self.MessageQueue]['Player']
mLabel = self.MessageQueue[#self.MessageQueue]['Message']
pLabel.Text = pName .. ':'
pLabel.Name = pName
local pColor
if cPlayer.Neutral then
pLabel.TextColor3 = Chat:ComputeChatColor(pName)
else
pLabel.TextColor3 = cPlayer.TeamColor.Color
end
local nString
if not self.CachedSpaceStrings_List[pName] then
nString = Chat:ComputeSpaceString(pLabel)
else
nString = self.CachedSpaceStrings_List[pName]
end
mLabel.Text = ""
mLabel.Name = pName .. " - message"
mLabel.Text = nString .. message;
mLabel.Parent = nil
mLabel.Parent = self.RenderFrame
mLabel.Position = UDim2.new(0, 0, 1, 0);
pLabel.Position = UDim2.new(0, 0, 1, 0);]]
-- Reinserted at the beginning, ring buffer
self.MessageQueue[#self.MessageQueue] = nil
end
--else
-- Haven't hit the mark yet, so keep creating
local nString = ""
pLabel = Gui.Create'ImageLabel'
{
Name = pName;
Parent = self.RenderFrame;
Size = UDim2.new(0, 14, 0, 14);
BackgroundTransparency = 1.0;
Position = UDim2.new(0, 0, 1, -10);
BorderSizePixel = 0.0;
Image = "rbxasset://textures/ui/chat_teamButton.png";
ImageTransparency = 1.0;
};
local pColor
if cPlayer.Neutral then
pLabel.ImageColor3 = Chat:ComputeChatColor(pName)
else
pLabel.ImageColor3 = cPlayer.TeamColor.Color
end
mLabel = Gui.Create'TextLabel'
{
Name = pName .. ' - message';
-- Max is 3 lines
Size = UDim2.new(1, 0, 0.5, 0);
TextColor3 = Chat.Configuration.MessageColor;
Font = Enum.Font.SourceSans;
FontSize = Chat.Configuration.FontSize;
TextXAlignment = Enum.TextXAlignment.Left;
TextYAlignment = Enum.TextYAlignment.Top;
Text = ""; -- this is to stop when the engine reverts the swear words to default, which is button, ugh
Parent = self.RenderFrame;
TextWrapped = true;
BackgroundTransparency = 1.0;
TextTransparency = 1.0;
Position = UDim2.new(0, 40, 1, 0);
BorderSizePixel = 0.0;
TextStrokeColor3 = Color3.new(0, 0, 0);
TextStrokeTransparency = 0.6;
--Active = false;
};
mLabel.Text = nString .. pName .. ": " .. message;
if not pName then
mLabel.TextColor3 = Color3.new(0, 0.4, 1.0)
end
--end
for _, adminName in pairs(self.Admins_List) do
if string.lower(adminName) == string.lower(pName) then
mLabel.TextColor3 = self.Configuration.AdminMessageColor
end
end
pLabel.Visible = true
mLabel.Visible = true
-- This will give beautiful multilines as well
local heightField = mLabel.TextBounds.Y
mLabel.Size = UDim2.new(1, 0, heightField/self.RenderFrame.AbsoluteSize.Y, 0)
local yPixels = self.RenderFrame.AbsoluteSize.Y
local yFieldSize = mLabel.TextBounds.Y
local queueField = {}
queueField['Player'] = pLabel
queueField['Message'] = mLabel
queueField['SpawnTime'] = tick() -- Used for identifying when to make the message invisible
table.insert(self.MessageQueue, 1, queueField)
Chat:UpdateQueue(queueField)
end
function Chat:ScreenSizeChanged()
wait()
while self.Frame.AbsoluteSize.Y > 120 do
self.Frame.Size = self.Frame.Size - UDim2.new(0, 0, 0.005, 0)
end
Chat:RecalculateSpacing()
end
function Chat:FocusOnChatBar()
if self.ClickToChatButton then
self.ClickToChatButton.Visible = false
end
self.GotFocus = true
if self.Frame['Background'] then
self.Frame.Background.Visible = false
end
self.ChatBar:CaptureFocus()
end
-- For touch devices we create a button instead
function Chat:CreateTouchButton()
self.ChatTouchFrame = Gui.Create'Frame'
{
Name = 'ChatTouchFrame';
Size = UDim2.new(0, 128, 0, 32);
Position = UDim2.new(0, 88, 0, 0);
BackgroundTransparency = 1.0;
Parent = self.Gui;
Gui.Create'ImageButton'
{
Name = 'ChatLabel';
Size = UDim2.new(0, 74, 0, 28);
Position = UDim2.new(0, 0, 0, 0);
BackgroundTransparency = 1.0;
ZIndex = 2.0;
};
Gui.Create'ImageLabel'
{
Name = 'Background';
Size = UDim2.new(1, 0, 1, 0);
Position = UDim2.new(0, 0, 0, 0);
BackgroundTransparency = 1.0;
Image = 'http://www.watrbx.wtf/asset/?id=97078724'
};
}
self.TapToChatLabel = self.ChatTouchFrame.ChatLabel
self.TouchLabelBackground = self.ChatTouchFrame.Background
self.ChatBar = Gui.Create'TextBox'
{
Name = 'ChatBar';
Size = UDim2.new(1, 0, 0.2, 0);
Position = UDim2.new(0, 0, 0.8, 800);
Text = "";
ZIndex = 1.0;
BackgroundTransparency = 1.0;
Parent = self.Frame;
TextXAlignment = Enum.TextXAlignment.Left;
TextColor3 = Color3.new(1, 1, 1);
ClearTextOnFocus = false;
};
self.TapToChatLabel.MouseButton1Click:connect(function()
self.TapToChatLabel.Visible = false
--self.ChatBar.Visible = true
--self.Frame.Background.Visible = true
self.ChatBar:CaptureFocus()
self.GotFocus = true
if self.TouchLabelBackground then
self.TouchLabelBackground.Visible = false
end
end)
end
-- Non touch devices, create the bottom chat bar
function Chat:CreateChatBar()
-- okay now we do
local status, result = pcall(function() return GuiService.UseLuaChat end)
if forceChatGUI or (status and result) then
self.ClickToChatButton = Gui.Create'TextButton'
{
Name = 'ClickToChat';
Size = UDim2.new(1, 0, 0, 20);
BackgroundTransparency = 1.0;
ZIndex = 2.0;
Parent = self.Gui;
Text = "To chat click here or press \"/\" key";
TextColor3 = Color3.new(1, 1, 0.9);
Position = UDim2.new(0, 0, 1, 0);
TextXAlignment = Enum.TextXAlignment.Left;
FontSize = Enum.FontSize.Size12;
}
self.ChatBar = Gui.Create'TextBox'
{
Name = 'ChatBar';
Size = UDim2.new(1, 0, 0, 20);
Position = UDim2.new(0, 0, 1, 0);
Text = "";
ZIndex = 1.0;
BackgroundColor3 = Color3.new(0, 0, 0);
BackgroundTransparency = 0.25;
Parent = self.Gui;
TextXAlignment = Enum.TextXAlignment.Left;
TextColor3 = Color3.new(1, 1, 1);
FontSize = Enum.FontSize.Size12;
ClearTextOnFocus = false;
Text = '';
};
-- Engine has code to offset the entire world, so if we do it by -20 pixels nothing gets in our chat's way
--GuiService:SetGlobalSizeOffsetPixel(0, -20)
local success, error = pcall(function() GuiService:SetGlobalGuiInset(0, 0, 0, 20) end)
if not success then
pcall(function() GuiService:SetGlobalSizeOffsetPixel(0, -20) end) -- Doesn't hurt to throw a non-existent function into a pcall
end
-- ChatHotKey is '/'
GuiService:AddSpecialKey(Enum.SpecialKey.ChatHotkey)
GuiService.SpecialKeyPressed:connect(function(key)
if key == Enum.SpecialKey.ChatHotkey then
Chat:FocusOnChatBar()
end
end)
self.ClickToChatButton.MouseButton1Click:connect(function()
Chat:FocusOnChatBar()
end)
end
end
-- Create the initial Chat stuff
-- Done only once
function Chat:CreateGui()
self.Gui = WaitForChild(CoreGuiService, 'RobloxGui')
self.Frame = Gui.Create'Frame'
{
Name = 'ChatFrame';
--Size = self.Configuration.Size;
Size = UDim2.new(0, 500, 0, 120);
Position = UDim2.new(0, 0, 0, 5);
BackgroundTransparency = 1.0;
--ClipsDescendants = true;
ZIndex = 0.0;
Parent = self.Gui;
Active = false;
Gui.Create'ImageLabel'
{
Name = 'Background';
Image = 'http://www.watrbx.wtf/asset/?id=97120937'; --96551212';
Size = UDim2.new(1.3, 0, 1.64, 0);
Position = UDim2.new(0, 0, 0, 0);
BackgroundTransparency = 1.0;
ZIndex = 0.0;
Visible = false
};
Gui.Create'Frame'
{
Name = 'Border';
Size = UDim2.new(1, 0, 0, 1);
Position = UDim2.new(0, 0, 0.8, 0);
BackgroundTransparency = 0.0;
BackgroundColor3 = Color3.new(236/255, 236/255, 236/255);
BorderSizePixel = 0.0;
Visible = false;
};
Gui.Create'Frame'
{
Name = 'ChatRenderFrame';
Size = UDim2.new(1.02, 0, 1.01, 0);
Position = UDim2.new(0, 0, 0, 0);
BackgroundTransparency = 1.0;
--ClipsDescendants = true;
ZIndex = 0.0;
Active = false;
};
};
Spawn(function()
wait(0.5)
if IsPhone() then
self.Frame.Size = UDim2.new(0, 280, 0, 120)
end
-- leave space for the settings button on touch devices
-- better use the exact same test it uses for its position
if game:GetService("UserInputService").TouchEnabled then
self.Frame.Position = UDim2.new(0, 0, 0, 55)
end
end)
self.RenderFrame = self.Frame.ChatRenderFrame
if Chat:IsTouchDevice() then
self.Frame.Position = self.Configuration.Position;
self.RenderFrame.Size = UDim2.new(1, 0, 1, 0)
elseif self.Frame.AbsoluteSize.Y > 120 then
Chat:ScreenSizeChanged()
self.Gui.Changed:connect(function(property)
if property == 'AbsoluteSize' then
Chat:ScreenSizeChanged()
end
end)
end
if forceChatGUI or Player.ChatMode == Enum.ChatMode.TextAndMenu then
if Chat:IsTouchDevice() then
Chat:CreateTouchButton()
else
Chat:CreateChatBar()
end
if self.ChatBar then
self.ChatBar.FocusLost:connect(function(enterPressed)
Chat.GotFocus = false
if Chat:IsTouchDevice() then
self.ChatBar.Visible = false
self.TapToChatLabel.Visible = true
if self.TouchLabelBackground then
self.TouchLabelBackground.Visible = true
end
end
if enterPressed and self.ChatBar.Text ~= "" then
if tick() - Chat.PreviousMessage > Chat.Configuration.HaltTime then -- Make sure that the user isn't deliberately spamming the chat
Chat.PreviousMessage = tick()
local cText = self.ChatBar.Text
if string.sub(self.ChatBar.Text, 1, 1) == '%' then
cText = '(TEAM) ' .. string.sub(cText, 2, #cText)
pcall(function() PlayersService:TeamChat(cText) end)
else
pcall(function() PlayersService:Chat(cText) end)
end
if self.ClickToChatButton then
self.ClickToChatButton.Visible = true
end
self.ChatBar.Text = ""
end
end
Spawn(function()
wait(5.0)
if not Chat.GotFocus then
Chat.Frame.Background.Visible = false
end
end)
end)
-- Make the escape key clear the chat box (like it used to)
inputService.InputBegan:connect(function(input)
if (input.KeyCode == Enum.KeyCode.Escape) then
if self.ClickToChatButton then
self.ClickToChatButton.Visible = true
end
self.ChatBar.Text = ""
end
end)
end
end
end
-- Scrolling function
-- Applies a speed(velocity) to have nice scrolling effect
function Input:OnMouseScroll()
Spawn(function()
-- How long should the speed last?
while Input.Speed ~=0 do
if Input.Speed > 1 then
while Input.Speed > 0 do
Input.Speed = Input.Speed - 1
wait(0.25)
end
elseif Input.Speed < 0 then
while Input.Speed < 0 do
Input.Speed = Input.Speed + 1
wait(0.25)
end
end
wait(0.03)
end
end)
if Chat:CheckIfInBounds(Input.Speed) then
return
end
Chat:ScrollQueue()
end
function Input:ApplySpeed(value)
Input.Speed = Input.Speed + value
if not self.Simulating then
Input:OnMouseScroll()
end
end
function Input:Initialize()
self.Mouse.WheelBackward:connect(function()
Input:ApplySpeed(self.Configuration.DefaultSpeed)
end)
self.Mouse.WheelForward:connect(function()
Input:ApplySpeed(self.Configuration.DefaultSpeed)
end)
end
-- Just a wrapper around our PlayerChatted event
function Chat:PlayerChatted(...)
local args = {...}
local argCount = select('#', ...)
local player
local message
-- This doesn't look very good, but what else to do?
if args[2] then
player = args[2]
end
if args[3] then
message = args[3]
if string.sub(message, 1, 1) == '%' then
message = '(TEAM) ' .. string.sub(message, 2, #message)
end
end
if PlayersService.ClassicChat then
if string.sub(message, 1, 3) == '/e ' or string.sub(message, 1, 7) == '/emote ' then
-- don't do anything right now
elseif forceChatGUI or Player.ChatMode == Enum.ChatMode.TextAndMenu then
Chat:UpdateChat(player, message)
elseif Player.ChatMode == Enum.ChatMode.Menu and string.sub(message, 1, 3) == '/sc' then
Chat:UpdateChat(player, message)
end
end
end
-- After Chat.Configuration.Lifetime seconds of existence, the labels become invisible
-- Runs only every 5 seconds and has to loop through 50 values
-- Shouldn't be too expensive
function Chat:CullThread()
while true do
if #self.MessageQueue > 0 then
for _, field in pairs(self.MessageQueue) do
if field['SpawnTime'] and field['Player'] and field['Message'] and tick() - field['SpawnTime'] > self.Configuration.LifeTime then
field['Player'].Visible = false
field['Message'].Visible = false
end
end
end
wait(5.0)
end
end
-- RobloxLock everything so users can't delete them(?)
function Chat:LockAllFields(gui)
local children = gui:GetChildren()
for i = 1, #children do
children[i].RobloxLocked = true
if #children[i]:GetChildren() > 0 then
Chat:LockAllFields(children[i])
end
end
end
function Chat:CoreGuiChanged(coreGuiType,enabled)
if coreGuiType == Enum.CoreGuiType.Chat or coreGuiType == Enum.CoreGuiType.All then
if self.Frame then self.Frame.Visible = enabled end
if self.TapToChatLabel then self.TapToChatLabel.Visible = enabled end
if not Chat:IsTouchDevice() and self.ChatBar then
self.ChatBar.Visible = enabled
if enabled then
GuiService:SetGlobalGuiInset(0, 0, 0, 20)
else
GuiService:SetGlobalGuiInset(0, 0, 0, 0)
end
end
end
end
-- Constructor
-- This function initializes everything
function Chat:Initialize()
Chat:CreateGui()
pcall(function()
Chat:CoreGuiChanged(Enum.CoreGuiType.Chat, Game:GetService("StarterGui"):GetCoreGuiEnabled(Enum.CoreGuiType.Chat))
Game:GetService("StarterGui").CoreGuiChangedSignal:connect(function(coreGuiType,enabled) Chat:CoreGuiChanged(coreGuiType,enabled) end)
end)
self.EventListener = PlayersService.PlayerChatted:connect(function(...)
-- This event has 4 callback arguments
-- Enum.PlayerChatType.All, chatPlayer, message, targetPlayer
Chat:PlayerChatted(...)
end)
self.MessageThread = coroutine.create(function() end)
coroutine.resume(self.MessageThread)
-- Initialize input for us
Input:Initialize()
-- Eww, everytime a player is added, you have to redo the connection
-- Seems this is not automatic
-- NOTE: PlayerAdded only fires on the server, hence ChildAdded is used here
PlayersService.ChildAdded:connect(function()
Chat.EventListener:disconnect()
self.EventListener = PlayersService.PlayerChatted:connect(function(...)
-- This event has 4 callback arguments
-- Enum.PlayerChatType.All, chatPlayer, message, targetPlayer
Chat:PlayerChatted(...)
end)
end)
Spawn(function()
Chat:CullThread()
end)
self.Frame.RobloxLocked = true
Chat:LockAllFields(self.Frame)
self.Frame.DescendantAdded:connect(function(descendant)
Chat:LockAllFields(descendant)
end)
end
Chat:Initialize()
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,264 @@
-- ContextActionTouch.lua
-- Copyright ROBLOX 2014, created by Ben Tkacheff
-- this script controls ui and firing of lua functions that are bound in ContextActionService for touch inputs
-- Essentially a user can bind a lua function to a key code, input type (mousebutton1 etc.) and this
-- Variables
local contextActionService = Game:GetService("ContextActionService")
local isTouchDevice = Game:GetService("UserInputService").TouchEnabled
local functionTable = {}
local buttonVector = {}
local buttonScreenGui = nil
local buttonFrame = nil
local ContextDownImage = "http://www.watrbx.wtf/asset/?id=97166756"
local ContextUpImage = "http://www.watrbx.wtf/asset/?id=97166444"
local oldTouches = {}
local buttonPositionTable = {
[1] = UDim2.new(0,123,0,70),
[2] = UDim2.new(0,30,0,60),
[3] = UDim2.new(0,180,0,160),
[4] = UDim2.new(0,85,0,-25),
[5] = UDim2.new(0,185,0,-25),
[6] = UDim2.new(0,185,0,260),
[7] = UDim2.new(0,216,0,65)
}
local maxButtons = #buttonPositionTable
-- Preload images
Game:GetService("ContentProvider"):Preload(ContextDownImage)
Game:GetService("ContentProvider"):Preload(ContextUpImage)
while not Game:GetService("Players") do
wait()
end
while not Game:GetService("Players").LocalPlayer do
wait()
end
function createContextActionGui()
if not buttonScreenGui and isTouchDevice then
buttonScreenGui = Instance.new("ScreenGui")
buttonScreenGui.Name = "ContextActionGui"
buttonFrame = Instance.new("Frame")
buttonFrame.BackgroundTransparency = 1
buttonFrame.Size = UDim2.new(0.3,0,0.5,0)
buttonFrame.Position = UDim2.new(0.7,0,0.5,0)
buttonFrame.Name = "ContextButtonFrame"
buttonFrame.Parent = buttonScreenGui
end
end
-- functions
function setButtonSizeAndPosition(object)
local buttonSize = 55
local xOffset = 10
local yOffset = 95
-- todo: better way to determine mobile sized screens
local onSmallScreen = (game:GetService("CoreGui").RobloxGui.AbsoluteSize.X < 600)
if not onSmallScreen then
buttonSize = 85
xOffset = 40
end
object.Size = UDim2.new(0,buttonSize,0,buttonSize)
end
function contextButtonDown(button, inputObject, actionName)
if inputObject.UserInputType == Enum.UserInputType.Touch then
button.Image = ContextDownImage
contextActionService:CallFunction(actionName, Enum.UserInputState.Begin, inputObject)
end
end
function contextButtonMoved(button, inputObject, actionName)
if inputObject.UserInputType == Enum.UserInputType.Touch then
button.Image = ContextDownImage
contextActionService:CallFunction(actionName, Enum.UserInputState.Change, inputObject)
end
end
function contextButtonUp(button, inputObject, actionName)
button.Image = ContextUpImage
if inputObject.UserInputType == Enum.UserInputType.Touch and inputObject.UserInputState == Enum.UserInputState.End then
contextActionService:CallFunction(actionName, Enum.UserInputState.End, inputObject)
end
end
function isSmallScreenDevice()
return Game:GetService("GuiService"):GetScreenResolution().y <= 320
end
function createNewButton(actionName, functionInfoTable)
local contextButton = Instance.new("ImageButton")
contextButton.Name = "ContextActionButton"
contextButton.BackgroundTransparency = 1
contextButton.Size = UDim2.new(0,90,0,90)
contextButton.Active = true
if isSmallScreenDevice() then
contextButton.Size = UDim2.new(0,70,0,70)
end
contextButton.Image = ContextUpImage
contextButton.Parent = buttonFrame
local currentButtonTouch = nil
Game:GetService("UserInputService").InputEnded:connect(function ( inputObject )
oldTouches[inputObject] = nil
end)
contextButton.InputBegan:connect(function(inputObject)
if oldTouches[inputObject] then return end
if inputObject.UserInputState == Enum.UserInputState.Begin and currentButtonTouch == nil then
currentButtonTouch = inputObject
contextButtonDown(contextButton, inputObject, actionName)
end
end)
contextButton.InputChanged:connect(function(inputObject)
if oldTouches[inputObject] then return end
if currentButtonTouch ~= inputObject then return end
contextButtonMoved(contextButton, inputObject, actionName)
end)
contextButton.InputEnded:connect(function(inputObject)
if oldTouches[inputObject] then return end
if currentButtonTouch ~= inputObject then return end
currentButtonTouch = nil
oldTouches[inputObject] = true
contextButtonUp(contextButton, inputObject, actionName)
end)
local actionIcon = Instance.new("ImageLabel")
actionIcon.Name = "ActionIcon"
actionIcon.Position = UDim2.new(0.175, 0, 0.175, 0)
actionIcon.Size = UDim2.new(0.65, 0, 0.65, 0)
actionIcon.BackgroundTransparency = 1
if functionInfoTable["image"] and type(functionInfoTable["image"]) == "string" then
actionIcon.Image = functionInfoTable["image"]
end
actionIcon.Parent = contextButton
local actionTitle = Instance.new("TextLabel")
actionTitle.Name = "ActionTitle"
actionTitle.Size = UDim2.new(1,0,1,0)
actionTitle.BackgroundTransparency = 1
actionTitle.Font = Enum.Font.SourceSansBold
actionTitle.TextColor3 = Color3.new(1,1,1)
actionTitle.TextStrokeTransparency = 0
actionTitle.FontSize = Enum.FontSize.Size18
actionTitle.TextWrapped = true
actionTitle.Text = ""
if functionInfoTable["title"] and type(functionInfoTable["title"]) == "string" then
actionTitle.Text = functionInfoTable["title"]
end
actionTitle.Parent = contextButton
return contextButton
end
function createButton( actionName, functionInfoTable )
local button = createNewButton(actionName, functionInfoTable)
local position = nil
for i = 1,#buttonVector do
if buttonVector[i] == "empty" then
position = i
break
end
end
if not position then
position = #buttonVector + 1
end
if position > maxButtons then
return -- todo: let user know we have too many buttons already?
end
buttonVector[position] = button
functionTable[actionName]["button"] = button
button.Position = buttonPositionTable[position]
button.Parent = buttonFrame
if buttonScreenGui and buttonScreenGui.Parent == nil then
buttonScreenGui.Parent = Game:GetService("Players").LocalPlayer.PlayerGui
end
end
function removeAction(actionName)
if not functionTable[actionName] then return end
local actionButton = functionTable[actionName]["button"]
if actionButton then
actionButton.Parent = nil
for i = 1,#buttonVector do
if buttonVector[i] == actionButton then
buttonVector[i] = "empty"
break
end
end
actionButton:Destroy()
end
functionTable[actionName] = nil
end
function addAction(actionName,createTouchButton,functionInfoTable)
if functionTable[actionName] then
removeAction(actionName)
end
functionTable[actionName] = {functionInfoTable}
if createTouchButton and isTouchDevice then
createContextActionGui()
createButton(actionName, functionInfoTable)
end
end
-- Connections
contextActionService.BoundActionChanged:connect( function(actionName, changeName, changeTable)
if functionTable[actionName] and changeTable then
local button = functionTable[actionName]["button"]
if button then
if changeName == "image" then
button.ActionIcon.Image = changeTable[changeName]
elseif changeName == "title" then
button.ActionTitle.Text = changeTable[changeName]
elseif changeName == "description" then
-- todo: add description to menu
elseif changeName == "position" then
button.Position = changeTable[changeName]
end
end
end
end)
contextActionService.BoundActionAdded:connect( function(actionName, createTouchButton, functionInfoTable)
addAction(actionName, createTouchButton, functionInfoTable)
end)
contextActionService.BoundActionRemoved:connect( function(actionName, functionInfoTable)
removeAction(actionName)
end)
contextActionService.GetActionButtonEvent:connect( function(actionName)
if functionTable[actionName] then
contextActionService:FireActionButtonFoundSignal(actionName, functionTable[actionName]["button"])
end
end)
-- make sure any bound data before we setup connections is handled
local boundActions = contextActionService:GetAllBoundActionInfo()
for actionName, actionData in pairs(boundActions) do
addAction(actionName,actionData["createTouchButton"],actionData)
end
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,34 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.watrbx.wtf/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="Script" referent="RBX0">
<Properties>
<bool name="Disabled">true</bool>
<Content name="LinkedSource"><null></null></Content>
<string name="Name">ReenableDialogScript</string>
<ProtectedString name="Source">wait(5)
local dialog = script.Parent
if dialog:IsA(&quot;Dialog&quot;) then
dialog.InUse = false
end
script:Remove()
</ProtectedString>
<bool name="archivable">true</bool>
</Properties>
</Item>
<Item class="Script" referent="RBX1">
<Properties>
<bool name="Disabled">true</bool>
<Content name="LinkedSource"><null></null></Content>
<string name="Name">TimeoutScript</string>
<ProtectedString name="Source">wait(15)
local dialog = script.Parent
if dialog:IsA(&quot;Dialog&quot;) then
dialog.InUse = false
end
script:Remove()
</ProtectedString>
<bool name="archivable">true</bool>
</Properties>
</Item>
</roblox>
@@ -0,0 +1,316 @@
--[[
This script controls the gui the player sees in regards to his or her health.
Can be turned with Game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Health,false)
Copyright ROBLOX 2014. Written by Ben Tkacheff.
--]]
---------------------------------------------------------------------
-- Initialize/Variables
while not Game do
wait(1/60)
end
while not Game:GetService("Players") do
wait(1/60)
end
local useCoreHealthBar = false
local success = pcall(function() useCoreHealthBar = Game:GetService("Players"):GetUseCoreScriptHealthBar() end)
if not success or not useCoreHealthBar then
return
end
local currentHumanoid = nil
local HealthGui = nil
local lastHealth = 100
local HealthPercentageForOverlay = 5
local maxBarTweenTime = 0.3
local greenColor = Color3.new(0.2, 1, 0.2)
local redColor = Color3.new(1, 0.2, 0.2)
local yellowColor = Color3.new(1, 1, 0.2)
local guiEnabled = false
local healthChangedConnection = nil
local humanoidDiedConnection = nil
local characterAddedConnection = nil
local greenBarImage = "rbxasset://textures/ui/Health-BKG-Center.png"
local greenBarImageLeft = "rbxasset://textures/ui/Health-BKG-Left-Cap.png"
local greenBarImageRight = "rbxasset://textures/ui/Health-BKG-Right-Cap.png"
local hurtOverlayImage = "http://www.watrbx.wtf/asset/?id=34854607"
Game:GetService("ContentProvider"):Preload(greenBarImage)
Game:GetService("ContentProvider"):Preload(hurtOverlayImage)
while not Game:GetService("Players").LocalPlayer do
wait(1/60)
end
---------------------------------------------------------------------
-- Functions
local capHeight = 15
local capWidth = 7
function CreateGui()
if HealthGui and #HealthGui:GetChildren() > 0 then
HealthGui.Parent = Game:GetService("CoreGui").RobloxGui
return
end
local hurtOverlay = Instance.new("ImageLabel")
hurtOverlay.Name = "HurtOverlay"
hurtOverlay.BackgroundTransparency = 1
hurtOverlay.Image = hurtOverlayImage
hurtOverlay.Position = UDim2.new(-10,0,-10,0)
hurtOverlay.Size = UDim2.new(20,0,20,0)
hurtOverlay.Visible = false
hurtOverlay.Parent = HealthGui
local healthFrame = Instance.new("Frame")
healthFrame.Name = "HealthFrame"
healthFrame.BackgroundTransparency = 1
healthFrame.BackgroundColor3 = Color3.new(1,1,1)
healthFrame.BorderColor3 = Color3.new(0,0,0)
healthFrame.BorderSizePixel = 0
healthFrame.Position = UDim2.new(0.5,-85,1,-20)
healthFrame.Size = UDim2.new(0,170,0,capHeight)
healthFrame.Parent = HealthGui
local healthBarBackCenter = Instance.new("ImageLabel")
healthBarBackCenter.Name = "healthBarBackCenter"
healthBarBackCenter.BackgroundTransparency = 1
healthBarBackCenter.Image = greenBarImage
healthBarBackCenter.Size = UDim2.new(1,-capWidth*2,1,0)
healthBarBackCenter.Position = UDim2.new(0,capWidth,0,0)
healthBarBackCenter.Parent = healthFrame
healthBarBackCenter.ImageColor3 = Color3.new(1,1,1)
local healthBarBackLeft = Instance.new("ImageLabel")
healthBarBackLeft.Name = "healthBarBackLeft"
healthBarBackLeft.BackgroundTransparency = 1
healthBarBackLeft.Image = greenBarImageLeft
healthBarBackLeft.Size = UDim2.new(0,capWidth,1,0)
healthBarBackLeft.Position = UDim2.new(0,0,0,0)
healthBarBackLeft.Parent = healthFrame
healthBarBackLeft.ImageColor3 = Color3.new(1,1,1)
local healthBarBackRight = Instance.new("ImageLabel")
healthBarBackRight.Name = "healthBarBackRight"
healthBarBackRight.BackgroundTransparency = 1
healthBarBackRight.Image = greenBarImageRight
healthBarBackRight.Size = UDim2.new(0,capWidth,1,0)
healthBarBackRight.Position = UDim2.new(1,-capWidth,0,0)
healthBarBackRight.Parent = healthFrame
healthBarBackRight.ImageColor3 = Color3.new(1,1,1)
local healthBar = Instance.new("Frame")
healthBar.Name = "HealthBar"
healthBar.BackgroundTransparency = 1
healthBar.BackgroundColor3 = Color3.new(1,1,1)
healthBar.BorderColor3 = Color3.new(0,0,0)
healthBar.BorderSizePixel = 0
healthBar.ClipsDescendants = true
healthBar.Position = UDim2.new(0, 0, 0, 0)
healthBar.Size = UDim2.new(1,0,1,0)
healthBar.Parent = healthFrame
local healthBarCenter = Instance.new("ImageLabel")
healthBarCenter.Name = "healthBarCenter"
healthBarCenter.BackgroundTransparency = 1
healthBarCenter.Image = greenBarImage
healthBarCenter.Size = UDim2.new(1,-capWidth*2,1,0)
healthBarCenter.Position = UDim2.new(0,capWidth,0,0)
healthBarCenter.Parent = healthBar
healthBarCenter.ImageColor3 = greenColor
local healthBarLeft = Instance.new("ImageLabel")
healthBarLeft.Name = "healthBarLeft"
healthBarLeft.BackgroundTransparency = 1
healthBarLeft.Image = greenBarImageLeft
healthBarLeft.Size = UDim2.new(0,capWidth,1,0)
healthBarLeft.Position = UDim2.new(0,0,0,0)
healthBarLeft.Parent = healthBar
healthBarLeft.ImageColor3 = greenColor
local healthBarRight = Instance.new("ImageLabel")
healthBarRight.Name = "healthBarRight"
healthBarRight.BackgroundTransparency = 1
healthBarRight.Image = greenBarImageRight
healthBarRight.Size = UDim2.new(0,capWidth,1,0)
healthBarRight.Position = UDim2.new(1,-capWidth,0,0)
healthBarRight.Parent = healthBar
healthBarRight.ImageColor3 = greenColor
HealthGui.Parent = Game:GetService("CoreGui").RobloxGui
end
function UpdateGui(health)
if not HealthGui then return end
local healthFrame = HealthGui:FindFirstChild("HealthFrame")
if not healthFrame then return end
local healthBar = healthFrame:FindFirstChild("HealthBar")
if not healthBar then return end
-- If more than 1/4 health, bar = green. Else, bar = red.
local percentHealth = (health/currentHumanoid.MaxHealth)
if percentHealth ~= percentHealth then
percentHealth = 1
healthBar.healthBarCenter.ImageColor3 = yellowColor
healthBar.healthBarRight.ImageColor3 = yellowColor
healthBar.healthBarLeft.ImageColor3 = yellowColor
elseif percentHealth > 0.25 then
healthBar.healthBarCenter.ImageColor3 = greenColor
healthBar.healthBarRight.ImageColor3 = greenColor
healthBar.healthBarLeft.ImageColor3 = greenColor
else
healthBar.healthBarCenter.ImageColor3 = redColor
healthBar.healthBarRight.ImageColor3 = redColor
healthBar.healthBarLeft.ImageColor3 = redColor
end
local width = (health / currentHumanoid.MaxHealth)
width = math.max(math.min(width,1),0) -- make sure width is between 0 and 1
if width ~= width then width = 1 end
local healthDelta = lastHealth - health
lastHealth = health
local percentOfTotalHealth = math.abs(healthDelta/currentHumanoid.MaxHealth)
percentOfTotalHealth = math.max(math.min(percentOfTotalHealth,1),0) -- make sure percentOfTotalHealth is between 0 and 1
if percentOfTotalHealth ~= percentOfTotalHealth then percentOfTotalHealth = 1 end
local newHealthSize = UDim2.new(width,0,1,0)
healthBar.Size = newHealthSize
local sizeX = healthBar.AbsoluteSize.X
if sizeX < capWidth then
healthBar.healthBarCenter.Visible = false
healthBar.healthBarRight.Visible = false
elseif sizeX < (2*capWidth + 1) then
healthBar.healthBarCenter.Visible = true
healthBar.healthBarCenter.Size = UDim2.new(0,sizeX - capWidth,1,0)
healthBar.healthBarRight.Visible = false
else
healthBar.healthBarCenter.Visible = true
healthBar.healthBarCenter.Size = UDim2.new(1,-capWidth*2,1,0)
healthBar.healthBarRight.Visible = true
end
local thresholdForHurtOverlay = currentHumanoid.MaxHealth * (HealthPercentageForOverlay/100)
if healthDelta >= thresholdForHurtOverlay then
AnimateHurtOverlay()
end
end
function AnimateHurtOverlay()
if not HealthGui then return end
local overlay = HealthGui:FindFirstChild("HurtOverlay")
if not overlay then return end
local newSize = UDim2.new(20, 0, 20, 0)
local newPos = UDim2.new(-10, 0, -10, 0)
if overlay:IsDescendantOf(Game) then
-- stop any tweens on overlay
overlay:TweenSizeAndPosition(newSize,newPos,Enum.EasingDirection.Out,Enum.EasingStyle.Linear,0,true,function()
-- show the gui
overlay.Size = UDim2.new(1,0,1,0)
overlay.Position = UDim2.new(0,0,0,0)
overlay.Visible = true
-- now tween the hide
if overlay:IsDescendantOf(Game) then
overlay:TweenSizeAndPosition(newSize,newPos,Enum.EasingDirection.Out,Enum.EasingStyle.Quad,10,false,function()
overlay.Visible = false
end)
else
overlay.Size = newSize
overlay.Position = newPos
end
end)
else
overlay.Size = newSize
overlay.Position = newPos
end
end
function humanoidDied()
UpdateGui(0)
end
function disconnectPlayerConnections()
if characterAddedConnection then characterAddedConnection:disconnect() end
if humanoidDiedConnection then humanoidDiedConnection:disconnect() end
if healthChangedConnection then healthChangedConnection:disconnect() end
end
function newPlayerCharacter()
disconnectPlayerConnections()
startGui()
end
function startGui()
characterAddedConnection = Game:GetService("Players").LocalPlayer.CharacterAdded:connect(newPlayerCharacter)
local character = Game:GetService("Players").LocalPlayer.Character
if not character then
return
end
currentHumanoid = character:WaitForChild("Humanoid")
if not currentHumanoid then
return
end
if not Game:GetService("StarterGui"):GetCoreGuiEnabled(Enum.CoreGuiType.Health) then
return
end
healthChangedConnection = currentHumanoid.HealthChanged:connect(UpdateGui)
humanoidDiedConnection = currentHumanoid.Died:connect(humanoidDied)
UpdateGui(currentHumanoid.Health)
CreateGui()
end
---------------------------------------------------------------------
-- Start Script
HealthGui = Instance.new("Frame")
HealthGui.Name = "HealthGui"
HealthGui.BackgroundTransparency = 1
HealthGui.Size = UDim2.new(1,0,1,0)
Game:GetService("StarterGui").CoreGuiChangedSignal:connect(function(coreGuiType,enabled)
if coreGuiType == Enum.CoreGuiType.Health or coreGuiType == Enum.CoreGuiType.All then
if guiEnabled and not enabled then
if HealthGui then
HealthGui.Parent = nil
end
disconnectPlayerConnections()
elseif not guiEnabled and enabled then
startGui()
end
guiEnabled = enabled
end
end)
if Game:GetService("StarterGui"):GetCoreGuiEnabled(Enum.CoreGuiType.Health) then
guiEnabled = true
startGui()
end
@@ -0,0 +1,876 @@
-- Creates the generic "ROBLOX" loading screen on startup
-- Written by ArceusInator & Ben Tkacheff, 2014
--
-- Constants
local PLACEID = Game.PlaceId
local MPS = Game:GetService 'MarketplaceService'
local CP = Game:GetService 'ContentProvider'
local function countBricks(object)
local count = 0
local children = object:GetChildren()
for _, child in ipairs(children) do
if child:IsA("BasePart") then
count = count + 1
end
count = count + countBricks(child)
end
return count
end
local function countInstances(object)
local count = 1
local children = object:GetChildren()
for _, child in ipairs(children) do
count = count + countInstances(child)
end
return count
end
local connectorTypes = {
["Weld"] = true,
["ManualWeld"] = true,
["Motor"] = true,
["Motor6D"] = true,
["Snap"] = true,
["Glue"] = true,
["RotateP"] = true,
}
local function countConnectors(object)
local count = 0
local children = object:GetChildren()
for _, child in ipairs(children) do
if connectorTypes[child.ClassName] then
count = count + 1
end
count = count + countConnectors(child)
end
return count
end
-- I don't think its possible to count voxels in this version, might need to implement a function for it later on.
local COLORS = {
BLACK = Color3.new(0, 0, 0),
DARK = Color3.new(35/255, 35/255, 38/255),
DARKMED = Color3.new(61/255, 61/255, 67/255),
DARKMED2 = Color3.new(75/255, 76/255, 85/255),
MED = Color3.new(118/255, 118/255, 129/255),
LIGHTMED = Color3.new(190/255, 192/255, 212/255),
LIGHT = Color3.new(217/255, 218/255, 231/255),
ERROR = Color3.new(253/255,68/255,72/255)
}
local IMAGES = {
BACKGROUND_THUMBNAIL_VIGNETTE = 'rbxasset://textures/loading/loadingvignette.png',
ROBLOX_LOGO_256 = 'rbxasset://textures/loading/robloxlogo.png',
GAME_THUMBNAIL = 'http://www.watrbx.wtf/Thumbs/Asset.ashx?format=png&width=420&height=230&assetId=',
GAME_BACKGROUND = 'rbxasset://textures/loading/loadingTexture.png'
}
local VALID_TEXT_SIZES = {
12,
14,
18,
24,
36,
48
}
--
-- Variables
local GameAssetInfo -- loaded by InfoProvider:LoadAssets()
local currScreenGui = nil
local renderSteppedConnection = nil
--
-- Utility functions
local create = function(className, defaultParent)
return function(propertyList)
local object = Instance.new(className)
for index, value in next, propertyList do
if type(index) == 'string' then
object[index] = value
else
if type(value) == 'function' then
value(object)
elseif type(value) == 'userdata' then
value.Parent = object
end
end
end
if object.Parent == nil then
object.Parent = defaultParent
end
return object
end
end
--
-- Create objects
local MainGui = {}
local InfoProvider = {}
function InfoProvider:GetGameName()
if GameAssetInfo ~= nil then
return GameAssetInfo.Name
else
return ''
end
end
function InfoProvider:GetCreatorName()
if GameAssetInfo ~= nil then
return GameAssetInfo.Creator.Name
else
return ''
end
end
function InfoProvider:LoadAssets()
Spawn(function()
if PLACEID <= 0 then
while Game.PlaceId <= 0 do
wait()
end
PLACEID = Game.PlaceId
end
IMAGES.GAME_THUMBNAIL = IMAGES.GAME_THUMBNAIL .. tostring(PLACEID)
-- load game asset info
coroutine.resume(coroutine.create(function() GameAssetInfo = MPS:GetProductInfo(PLACEID) end))
currScreenGui.ThumbnailContainer.Thumbnail.Image = IMAGES.GAME_THUMBNAIL
-- load images
for imageName, imageContent in next, IMAGES do
CP:Preload(imageContent)
end
end)
end
--
-- Declare member functions
function MainGui:GenerateMain()
local screenGui = create 'ScreenGui' {
Name = 'RobloxLoadingGui'
}
--
-- create descendant frames
local mainBackgroundContainer = create 'Frame' {
Name = 'MainBackgroundContainer',
BackgroundColor3 = COLORS.DARK,
Size = UDim2.new(1, 0, 1, 0),
Active = true,
create 'Frame' {
Name = 'TopBar',
BackgroundColor3 = COLORS.DARKMED,
BorderColor3 = COLORS.MED,
BorderSizePixel = 3,
Position = UDim2.new(0, -220, 0, -205),
Rotation = -10,
Size = UDim2.new(0, 1000, 0, 220),
ZIndex = 5,
create 'ImageLabel' {
Name = 'RobloxLogo',
BackgroundTransparency = 1,
Image = IMAGES.ROBLOX_LOGO_256,
Position = UDim2.new(0, 214, 1, -80),
Rotation = 2,
Size = UDim2.new(0, 128, 0, 128),
ZIndex = 6,
create 'TextLabel' {
Name = 'PoweredBy',
BackgroundTransparency = 1,
Position = UDim2.new(0.5, -60, 0, 30),
Size = UDim2.new(0, 80, 0, 18),
Font = Enum.Font.SourceSans,
FontSize = Enum.FontSize.Size18,
TextColor3 = Color3.new(1,1,1),
Text = "Powered By",
ZIndex = 6
}
}
},
create 'ImageButton' {
Name = 'CloseButton',
Image = 'rbxasset://textures/ui/CloseButton.png',
BackgroundTransparency = 1,
Position = UDim2.new(1, -27, 0, 5),
Size = UDim2.new(0, 22, 0, 22),
Active = true,
ZIndex = 10
},
create 'Frame' {
Name = 'ErrorFrame',
BackgroundColor3 = COLORS.ERROR,
BorderSizePixel = 0,
Position = UDim2.new(0.25,0,0,0),
Size = UDim2.new(0.5, 0, 0, 80),
ZIndex = 5,
Visible = false,
create 'TextLabel' {
Name = "ErrorText",
BackgroundTransparency = 1,
ZIndex = 6,
Position = UDim2.new(0,5,0,5),
Size = UDim2.new(1,-10,1,-10),
Font = Enum.Font.SourceSans,
FontSize = Enum.FontSize.Size18,
Text = "",
TextColor3 = Color3.new(1,1,1),
TextXAlignment = Enum.TextXAlignment.Center,
TextYAlignment = Enum.TextYAlignment.Center,
TextWrap = true
}
},
create 'Frame' {
Name = 'BottomBar',
BorderSizePixel = 0,
BackgroundTransparency = 1,
Position = UDim2.new(0, 0, 1, -150),
Size = UDim2.new(1, 0, 0, 300),
ZIndex = 5,
create 'Frame' {
Name = 'BottomBarActual',
BackgroundColor3 = COLORS.DARKMED,
BorderColor3 = COLORS.MED,
BorderSizePixel = 3,
Position = UDim2.new(0, 0, 0, 0),
Size = UDim2.new(1, 0, 1, 0),
ZIndex = 5,
create 'Frame' {
Name = 'TextContainer',
BackgroundTransparency = 1,
Position = UDim2.new(0, -5, 0, 5),
Size = UDim2.new(1, 0, 1, 0),
ZIndex = 8,
create 'TextLabel' {
Name = 'CreatorName',
BackgroundTransparency = 1,
Position = UDim2.new(0, 0, 0, 70),
Size = UDim2.new(1, 0, 1, 0),
ZIndex = 9,
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size48,
Text = InfoProvider:GetCreatorName(),
TextColor3 = COLORS.LIGHT,
TextStrokeColor3 = COLORS.DARKMED2,
TextStrokeTransparency = 0,
TextXAlignment = Enum.TextXAlignment.Right,
TextYAlignment = Enum.TextYAlignment.Top
},
create 'TextLabel' {
Name = 'GameName',
BackgroundTransparency = 1,
Position = UDim2.new(0, 0, 0, 30),
Size = UDim2.new(1, 0, 1, 0),
ZIndex = 9,
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size48,
Text = InfoProvider:GetGameName(),
TextColor3 = COLORS.LIGHT,
TextStrokeColor3 = COLORS.DARKMED2,
TextStrokeTransparency = 0,
TextXAlignment = Enum.TextXAlignment.Right,
TextYAlignment = Enum.TextYAlignment.Top
},
create 'TextLabel' {
Name = 'CreatorNamePrefix',
BackgroundTransparency = 1,
Size = UDim2.new(1, 0, 1, 0),
ZIndex = 9,
Font = Enum.Font.SourceSans,
FontSize = Enum.FontSize.Size48,
Text = 'By',
TextColor3 = COLORS.LIGHTMED,
TextStrokeColor3 = COLORS.DARKMED2,
TextStrokeTransparency = 0,
TextXAlignment = Enum.TextXAlignment.Right,
TextYAlignment = Enum.TextYAlignment.Top
},
create 'TextLabel' {
Name = 'OnYourWay',
BackgroundTransparency = 1,
Size = UDim2.new(1, 0, 1, 0),
ZIndex = 9,
Font = Enum.Font.SourceSans,
FontSize = Enum.FontSize.Size36,
Text = 'You\'re on your way to',
TextColor3 = COLORS.LIGHTMED,
TextStrokeColor3 = COLORS.DARKMED2,
TextStrokeTransparency = 0,
TextXAlignment = Enum.TextXAlignment.Right,
TextYAlignment = Enum.TextYAlignment.Top
}
}
}
},
create 'ImageLabel' {
Name = 'BackgroundThumbnailVignette',
BackgroundTransparency = 1,
Image = IMAGES.BACKGROUND_THUMBNAIL_VIGNETTE,
Size = UDim2.new(1, 0, 1, 0),
ZIndex = 3
},
create 'ImageLabel' {
Name = 'BackgroundThumbnail',
BackgroundTransparency = 1,
Image = IMAGES.GAME_BACKGROUND,
Size = UDim2.new(1.5, 0, 1.5, 0),
Position = UDim2.new(-0.5,0,0,0),
ZIndex = 2
},
Parent = screenGui
}
local thumbnailContainer = create 'Frame' {
Name = 'ThumbnailContainer',
BackgroundColor3 = COLORS.BLACK,
BorderColor3 = COLORS.MED,
BorderSizePixel = 4,
Position = UDim2.new(0.5, -210, 0.5, -115),
Size = UDim2.new(0, 420, 0, 230),
ZIndex = 8,
create 'ImageLabel' {
Name = 'Thumbnail',
BorderColor3 = COLORS.DARKMED2,
BorderSizePixel = 3,
Image = "",
Size = UDim2.new(1, 0, 1, 0),
ZIndex = 8
},
create 'Frame' {
Name = 'LoadingInfoContainer',
BorderColor3 = COLORS.MED,
BackgroundColor3 = COLORS.DARKMED,
BorderSizePixel = 2,
Position = UDim2.new(0,20,1,0),
Size = UDim2.new(1,-40,0,40),
ZIndex = 7,
create 'TextLabel' {
Name = 'InstancesLabel',
BackgroundTransparency = 1,
Position = UDim2.new(0,0,0,5),
Size = UDim2.new(0.25, 0, 1, -10),
ZIndex = 9,
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size14,
Text = 'Instances',
TextColor3 = COLORS.LIGHTMED,
TextStrokeColor3 = COLORS.DARKMED2,
TextStrokeTransparency = 0,
TextXAlignment = Enum.TextXAlignment.Center,
TextYAlignment = Enum.TextYAlignment.Top
},
create 'TextLabel' {
Name = 'InstancesValue',
BackgroundTransparency = 1,
Position = UDim2.new(0,0,0,5),
Size = UDim2.new(0.25, 0, 1, -10),
ZIndex = 9,
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size14,
Text = '0',
TextColor3 = COLORS.LIGHTMED,
TextStrokeColor3 = COLORS.DARKMED2,
TextStrokeTransparency = 0,
TextXAlignment = Enum.TextXAlignment.Center,
TextYAlignment = Enum.TextYAlignment.Bottom
},
create 'TextLabel' {
Name = 'VoxelsLabel',
BackgroundTransparency = 1,
Position = UDim2.new(0.75,0,0,5),
Size = UDim2.new(0.25, 0, 1, -10),
ZIndex = 9,
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size14,
Text = 'Voxels',
TextColor3 = COLORS.LIGHTMED,
TextStrokeColor3 = COLORS.DARKMED2,
TextStrokeTransparency = 0,
TextXAlignment = Enum.TextXAlignment.Center,
TextYAlignment = Enum.TextYAlignment.Top
},
create 'TextLabel' {
Name = 'VoxelsValue',
BackgroundTransparency = 1,
Position = UDim2.new(0.75,0,0,5),
Size = UDim2.new(0.25, 0, 1, -10),
ZIndex = 9,
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size14,
Text = '0',
TextColor3 = COLORS.LIGHTMED,
TextStrokeColor3 = COLORS.DARKMED2,
TextStrokeTransparency = 0,
TextXAlignment = Enum.TextXAlignment.Center,
TextYAlignment = Enum.TextYAlignment.Bottom
},
create 'TextLabel' {
Name = 'ConnectorsLabel',
BackgroundTransparency = 1,
Position = UDim2.new(0.5,0,0,5),
Size = UDim2.new(0.25, 0, 1, -10),
ZIndex = 9,
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size14,
Text = 'Connectors',
TextColor3 = COLORS.LIGHTMED,
TextStrokeColor3 = COLORS.DARKMED2,
TextStrokeTransparency = 0,
TextXAlignment = Enum.TextXAlignment.Center,
TextYAlignment = Enum.TextYAlignment.Top
},
create 'TextLabel' {
Name = 'ConnectorsValue',
BackgroundTransparency = 1,
Position = UDim2.new(0.5,0,0,5),
Size = UDim2.new(0.25, 0, 1, -10),
ZIndex = 9,
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size14,
Text = '0',
TextColor3 = COLORS.LIGHTMED,
TextStrokeColor3 = COLORS.DARKMED2,
TextStrokeTransparency = 0,
TextXAlignment = Enum.TextXAlignment.Center,
TextYAlignment = Enum.TextYAlignment.Bottom
},
create 'TextLabel' {
Name = 'BricksLabel',
BackgroundTransparency = 1,
Position = UDim2.new(0.25,0,0,5),
Size = UDim2.new(0.25, 0, 1, -10),
ZIndex = 9,
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size14,
Text = 'Bricks',
TextColor3 = COLORS.LIGHTMED,
TextStrokeColor3 = COLORS.DARKMED2,
TextStrokeTransparency = 0,
TextXAlignment = Enum.TextXAlignment.Center,
TextYAlignment = Enum.TextYAlignment.Top
},
create 'TextLabel' {
Name = 'BricksValue',
BackgroundTransparency = 1,
Position = UDim2.new(0.25,0,0,5),
Size = UDim2.new(0.25, 0, 1, -10),
ZIndex = 9,
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size14,
Text = '0',
TextColor3 = COLORS.LIGHTMED,
TextStrokeColor3 = COLORS.DARKMED2,
TextStrokeTransparency = 0,
TextXAlignment = Enum.TextXAlignment.Center,
TextYAlignment = Enum.TextYAlignment.Bottom
},
},
Parent = screenGui
}
--
-- recalculate everything
while not Game:GetService("CoreGui") do
wait()
end
screenGui.Parent = Game.CoreGui
MainGui:RecalculateSizes(screenGui)
--
-- return generated gui
return screenGui
end
function MainGui:RecalculateTextSize(screenGui)
local screenSize = screenGui.AbsoluteSize
local textSizeScale = math.min(screenSize.y/800, 1)
local closestValidSizePrevIndex = math.floor(textSizeScale*#VALID_TEXT_SIZES)-1
local closestValidSizePrevIndex2 = closestValidSizePrevIndex-1
local closestValidTextSize
local closestValidTextSizePrev
-- next can't take a 0 because it's a total wuss
if closestValidSizePrevIndex > 0 then
_, closestValidTextSize = next(VALID_TEXT_SIZES, closestValidSizePrevIndex)
if closestValidSizePrevIndex2 > 0 then
_, closestValidTextSizePrev = next(VALID_TEXT_SIZES, closestValidSizePrevIndex2)
else
_, closestValidTextSizePrev = next(VALID_TEXT_SIZES) -- not doing t[1] because this looks cleaner
end
else
_, closestValidTextSize = next(VALID_TEXT_SIZES)
_, closestValidTextSizePrev = next(VALID_TEXT_SIZES)
end
local textSizeEnum = Enum.FontSize['Size'..closestValidTextSize]
local textSizePrevEnum = Enum.FontSize['Size'..closestValidTextSizePrev]
if not screenGui:FindFirstChild("MainBackgroundContainer") then return end
local TextContainer = screenGui.MainBackgroundContainer.BottomBar.BottomBarActual.TextContainer
local currentYBumpDistance = 0
TextContainer.OnYourWay.FontSize = textSizePrevEnum
currentYBumpDistance = currentYBumpDistance + closestValidTextSizePrev*(40/48)
TextContainer.GameName.Position = UDim2.new(0, 0, 0, currentYBumpDistance)
TextContainer.GameName.FontSize = textSizeEnum
currentYBumpDistance = currentYBumpDistance + closestValidTextSize*(40/48)
TextContainer.CreatorName.Position = UDim2.new(0, 0, 0, currentYBumpDistance)
TextContainer.CreatorName.FontSize = textSizeEnum
local currentXBumpDistance = -(TextContainer.CreatorName.TextBounds.X+5)
TextContainer.CreatorNamePrefix.Position = UDim2.new(0, currentXBumpDistance, 0, currentYBumpDistance)
TextContainer.CreatorNamePrefix.FontSize = textSizeEnum
-- recalculate bottom bar size
local sizeScale = closestValidTextSize/48
screenGui.MainBackgroundContainer.BottomBar.Size = UDim2.new(1, 0, 0, 300 * sizeScale)
screenGui.MainBackgroundContainer.BottomBar.Position = UDim2.new(0, 0, 1, -150 * sizeScale)
screenGui.MainBackgroundContainer.BottomBar.BottomBarActual.Position = UDim2.new(0, -130 * sizeScale,0,0)
end
function MainGui:RecalculateSizes(screenGui)
local screenSize = screenGui.AbsoluteSize
-- recalculate thumbnail size
local thumbnailSizeScale = math.min(math.max(screenSize.y/630, 50/230), 1)
local thumbnailSize = UDim2.new(0, thumbnailSizeScale*420, 0, thumbnailSizeScale*230)
local thumbnailPosition = UDim2.new(0.5, -thumbnailSizeScale*420/2, 0.5, -20 - thumbnailSizeScale*230/2 )
screenGui.ThumbnailContainer.Size = thumbnailSize
screenGui.ThumbnailContainer.Position = thumbnailPosition
screenGui.ThumbnailContainer.LoadingInfoContainer.Visible = (screenSize.Y > 500)
-- update names
-- if we don't have a name yet, keep trying!
if InfoProvider:GetCreatorName() == '' or InfoProvider:GetGameName() == '' then
Spawn(function()
while InfoProvider and InfoProvider:GetCreatorName() == '' or InfoProvider:GetGameName() == '' do
wait()
end
if screenGui and screenGui:FindFirstChild("MainBackgroundContainer") then
screenGui.MainBackgroundContainer.BottomBar.BottomBarActual.TextContainer.CreatorName.Text = InfoProvider:GetCreatorName()
screenGui.MainBackgroundContainer.BottomBar.BottomBarActual.TextContainer.GameName.Text = InfoProvider:GetGameName()
end
MainGui:RecalculateTextSize(screenGui)
end)
else
screenGui.MainBackgroundContainer.BottomBar.BottomBarActual.TextContainer.CreatorName.Text = InfoProvider:GetCreatorName()
screenGui.MainBackgroundContainer.BottomBar.BottomBarActual.TextContainer.GameName.Text = InfoProvider:GetGameName()
end
MainGui:RecalculateTextSize(screenGui)
end
function MainGui:Show()
currScreenGui = MainGui:GenerateMain()
currScreenGui.MainBackgroundContainer.Visible = true
currScreenGui.ThumbnailContainer.Visible = true
currScreenGui.Changed:connect(function(prop)
if prop == "AbsoluteSize" then
MainGui:RecalculateSizes(currScreenGui)
end
end)
end
---------------------------------------------------------
-- Main Script (show something now + setup connections)
-- start loading assets asap
InfoProvider:LoadAssets()
MainGui:Show()
local guiService = Game:GetService("GuiService")
local instanceCount = 0
local voxelCount = 0
local brickCount = 0
local connectorCount = 0
local setVerb = true
renderSteppedConnection = Game:GetService("RunService").RenderStepped:connect(function()
instanceCount = countInstances(game.Workspace) --guiService:GetInstanceCount()
voxelCount = 0 --guiService:GetVoxelCount()
brickCount = countBricks(game.Workspace) --game:SetMessageBrickCount()
connectorCount = countConnectors(game.Workspace) --guiService:GetConnectorCount()
if not currScreenGui then return end
if setVerb then
currScreenGui.MainBackgroundContainer.CloseButton:SetVerb("Exit")
setVerb = false
end
currScreenGui.ThumbnailContainer.LoadingInfoContainer.InstancesValue.Text = tostring(instanceCount)
currScreenGui.ThumbnailContainer.LoadingInfoContainer.BricksValue.Text = tostring(brickCount)
currScreenGui.ThumbnailContainer.LoadingInfoContainer.ConnectorsValue.Text = tostring(connectorCount)
if voxelCount <= 0 then
currScreenGui.ThumbnailContainer.LoadingInfoContainer.VoxelsValue.Text = "0"
else
currScreenGui.ThumbnailContainer.LoadingInfoContainer.VoxelsValue.Text = tostring(voxelCount) .." million"
end
end)
guiService.ErrorMessageChanged:connect(function()
if guiService:GetErrorMessage() ~= '' then
currScreenGui.MainBackgroundContainer.ErrorFrame.ErrorText.Text = guiService:GetErrorMessage()
currScreenGui.MainBackgroundContainer.ErrorFrame.Visible = true
else
currScreenGui.MainBackgroundContainer.ErrorFrame.Visible = false
end
end)
if guiService:GetErrorMessage() ~= '' then
currScreenGui.MainBackgroundContainer.ErrorFrame.ErrorText.Text = guiService:GetErrorMessage()
currScreenGui.MainBackgroundContainer.ErrorFrame.Visible = true
end
local forceRemovalTime = 5
local destroyed = false
function removeLoadingScreen()
wait(3)
if renderSteppedConnection then
renderSteppedConnection:disconnect()
end
if currScreenGui then
currScreenGui:Destroy()
currScreenGui = nil
end
if script then script:Destroy() end
destroyed = true
end
function startForceLoadingDoneTimer()
wait(forceRemovalTime)
removeLoadingScreen()
end
function gameIsLoaded()
if Game.ReplicatedFirst:IsDefaultLoadingGuiRemoved() then
removeLoadingScreen()
else
startForceLoadingDoneTimer()
end
end
Game.ReplicatedFirst.RemoveDefaultLoadingGuiSignal:connect(function()
removeLoadingScreen()
end)
if Game.ReplicatedFirst:IsDefaultLoadingGuiRemoved() then
removeLoadingScreen()
return
end
Game.Loaded:connect(function()
gameIsLoaded()
end)
if Game:IsLoaded() then
gameIsLoaded()
end
--------------------------------------------------------------------------
--
-- Animation (make the stuff we are showing look cool)
local blockSize = 10
local blockColor = Color3.new(33/255,66/255,209/255)
local yPosScale = 0
local yPosOffset = -blockSize * 3.5
local tweenStyle = Enum.EasingStyle.Sine
local tweenVelocity = 1500
local tweenTime = (currScreenGui.AbsoluteSize.X/2)/tweenVelocity
function createBlock()
local initBlock = Instance.new("Frame")
initBlock.ZIndex = 5
initBlock.Size = UDim2.new(0,blockSize,0,blockSize)
initBlock.BackgroundColor3 = COLORS.DARK
initBlock.BorderSizePixel = 0
initBlock.Position = UDim2.new(0,-blockSize,yPosScale,yPosOffset)
initBlock.Parent = currScreenGui.MainBackgroundContainer.BottomBar
return initBlock
end
local blocks = {}
for i = 1,6 do
blocks[i] = createBlock()
end
function getYOffset(newSize)
return yPosOffset - (newSize/3)
end
function rightScreenExit()
wait(tweenTime * 3)
if not currScreenGui then return end
local regSize = blocks[6].Size
local regPos = blocks[6].Position
blocks[6].Size = blocks[1].Size
blocks[6].Position = blocks[1].Position
blocks[1].Size = regSize
blocks[1].Position = regPos
for i = 1,6 do
local delayTime = tweenTime * (i - 1) * 0.5
Delay(delayTime, function()
if not currScreenGui then return end
local blockIndex = i
local blockSizeMultiplier = 4 - (i * 0.5)
blocks[blockIndex]:TweenPosition(UDim2.new(1,0,yPosScale,yPosOffset),
Enum.EasingDirection.Out,tweenStyle,
tweenTime,true)
if i == 6 then
blocks[6]:TweenSizeAndPosition(UDim2.new(0,blockSize,0,blockSize),
UDim2.new(1,0,yPosScale,yPosOffset),
Enum.EasingDirection.InOut,tweenStyle,
tweenTime,true)
wait(tweenTime * 1.1)
leftScreenEntrance()
else
local newSize = blockSize * blockSizeMultiplier
blocks[6]:TweenSizeAndPosition(UDim2.new(0,newSize,0,newSize),
UDim2.new(0.5,-newSize/2,yPosScale,getYOffset(newSize)),
Enum.EasingDirection.InOut,tweenStyle,
tweenTime * 0.75,true)
end
end)
end
end
function leftScreenEntrance()
if not currScreenGui then return end
for i = 1,6 do
blocks[i].Size = UDim2.new(0,blockSize,0,blockSize)
blocks[i].Position = UDim2.new(0,-blockSize,yPosScale,yPosOffset)
end
blocks[1]:TweenPosition(UDim2.new(0.5,-blockSize/2,yPosScale,yPosOffset),Enum.EasingDirection.Out,tweenStyle,tweenTime,true,function()
for i = 1, 6 do
local delayTime = tweenTime * (i - 1) * 0.5
Delay(delayTime, function()
if not currScreenGui then return end
local blockIndex = i
local blockSizeMultiplier = 1 + (i * 0.5)
blocks[blockIndex]:TweenPosition(UDim2.new(0.5,-blockSize/2,yPosScale,yPosOffset),
Enum.EasingDirection.Out,tweenStyle,
tweenTime,true)
local newSize = blockSize * blockSizeMultiplier
blocks[1]:TweenSizeAndPosition(UDim2.new(0,newSize,0,newSize),
UDim2.new(0.5,-newSize/2,yPosScale,getYOffset(newSize)),
Enum.EasingDirection.InOut,tweenStyle,
tweenTime * 0.75,true)
if i == 4 then
rightScreenExit()
end
end)
end
end)
end
function startLoadingAnimation()
currScreenGui.MainBackgroundContainer.BackgroundThumbnail:TweenPosition(UDim2.new(0,0,0,0),Enum.EasingDirection.InOut,Enum.EasingStyle.Linear,20,true)
leftScreenEntrance()
end
----------------------------------
-- Animation Begin
startLoadingAnimation()
@@ -0,0 +1,557 @@
function waitForProperty(instance, name)
while not instance[name] do
instance.Changed:wait()
end
end
function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local mainFrame
local choices = {}
local lastChoice
local choiceMap = {}
local currentConversationDialog
local currentConversationPartner
local currentAbortDialogScript
local tooFarAwayMessage = "You are too far away to chat!"
local tooFarAwaySize = 300
local characterWanderedOffMessage = "Chat ended because you walked away"
local characterWanderedOffSize = 350
local conversationTimedOut = "Chat ended because you didn't reply"
local conversationTimedOutSize = 350
local player
local screenGui
local chatNotificationGui
local messageDialog
local timeoutScript
local reenableDialogScript
local dialogMap = {}
local dialogConnections = {}
local gui = nil
waitForChild(game,"CoreGui")
waitForChild(game:GetService("CoreGui"),"RobloxGui")
if game:GetService("CoreGui").RobloxGui:FindFirstChild("ControlFrame") then
gui = game:GetService("CoreGui").RobloxGui.ControlFrame
else
gui = game:GetService("CoreGui").RobloxGui
end
function currentTone()
if currentConversationDialog then
return currentConversationDialog.Tone
else
return Enum.DialogTone.Neutral
end
end
function createChatNotificationGui()
chatNotificationGui = Instance.new("BillboardGui")
chatNotificationGui.Name = "ChatNotificationGui"
chatNotificationGui.ExtentsOffset = Vector3.new(0,1,0)
chatNotificationGui.Size = UDim2.new(4, 0, 5.42857122, 0)
chatNotificationGui.SizeOffset = Vector2.new(0,0)
chatNotificationGui.StudsOffset = Vector3.new(0.4, 4.3, 0)
chatNotificationGui.Enabled = true
chatNotificationGui.RobloxLocked = true
chatNotificationGui.Active = true
local image = Instance.new("ImageLabel")
image.Name = "Image"
image.Active = false
image.BackgroundTransparency = 1
image.Position = UDim2.new(0,0,0,0)
image.Size = UDim2.new(1.0,0,1.0,0)
image.Image = ""
image.RobloxLocked = true
image.Parent = chatNotificationGui
local button = Instance.new("ImageButton")
button.Name = "Button"
button.AutoButtonColor = false
button.Position = UDim2.new(0.0879999995, 0, 0.0529999994, 0)
button.Size = UDim2.new(0.829999983, 0, 0.460000008, 0)
button.Image = ""
button.BackgroundTransparency = 1
button.RobloxLocked = true
button.Parent = image
end
function getChatColor(tone)
if tone == Enum.DialogTone.Neutral then
return Enum.ChatColor.Blue
elseif tone == Enum.DialogTone.Friendly then
return Enum.ChatColor.Green
elseif tone == Enum.DialogTone.Enemy then
return Enum.ChatColor.Red
end
end
function styleChoices(tone)
for i, obj in pairs(choices) do
resetColor(obj, tone)
end
resetColor(lastChoice, tone)
end
function styleMainFrame(tone)
if tone == Enum.DialogTone.Neutral then
mainFrame.Style = Enum.FrameStyle.ChatBlue
mainFrame.Tail.Image = "rbxasset://textures/chatBubble_botBlue_tailRight.png"
elseif tone == Enum.DialogTone.Friendly then
mainFrame.Style = Enum.FrameStyle.ChatGreen
mainFrame.Tail.Image = "rbxasset://textures/chatBubble_botGreen_tailRight.png"
elseif tone == Enum.DialogTone.Enemy then
mainFrame.Style = Enum.FrameStyle.ChatRed
mainFrame.Tail.Image = "rbxasset://textures/chatBubble_botRed_tailRight.png"
end
styleChoices(tone)
end
function setChatNotificationTone(gui, purpose, tone)
if tone == Enum.DialogTone.Neutral then
gui.Image.Image = "rbxasset://textures/chatBubble_botBlue_notify_bkg.png"
elseif tone == Enum.DialogTone.Friendly then
gui.Image.Image = "rbxasset://textures/chatBubble_botGreen_notify_bkg.png"
elseif tone == Enum.DialogTone.Enemy then
gui.Image.Image = "rbxasset://textures/chatBubble_botRed_notify_bkg.png"
end
if purpose == Enum.DialogPurpose.Quest then
gui.Image.Button.Image = "rbxasset://textures/chatBubble_bot_notify_bang.png"
elseif purpose == Enum.DialogPurpose.Help then
gui.Image.Button.Image = "rbxasset://textures/chatBubble_bot_notify_question.png"
elseif purpose == Enum.DialogPurpose.Shop then
gui.Image.Button.Image = "rbxasset://textures/chatBubble_bot_notify_money.png"
end
end
function createMessageDialog()
messageDialog = Instance.new("Frame");
messageDialog.Name = "DialogScriptMessage"
messageDialog.Style = Enum.FrameStyle.RobloxRound
messageDialog.Visible = false
local text = Instance.new("TextLabel")
text.Name = "Text"
text.Position = UDim2.new(0,0,0,-1)
text.Size = UDim2.new(1,0,1,0)
text.FontSize = Enum.FontSize.Size14
text.BackgroundTransparency = 1
text.TextColor3 = Color3.new(1,1,1)
text.RobloxLocked = true
text.Parent = messageDialog
end
function showMessage(msg, size)
messageDialog.Text.Text = msg
messageDialog.Size = UDim2.new(0,size,0,40)
messageDialog.Position = UDim2.new(0.5, -size/2, 0.5, -40)
messageDialog.Visible = true
wait(2)
messageDialog.Visible = false
end
function variableDelay(str)
local length = math.min(string.len(str), 100)
wait(0.75 + ((length/75) * 1.5))
end
function resetColor(frame, tone)
if tone == Enum.DialogTone.Neutral then
frame.BackgroundColor3 = Color3.new(0/255, 0/255, 179/255)
frame.Number.TextColor3 = Color3.new(45/255, 142/255, 245/255)
elseif tone == Enum.DialogTone.Friendly then
frame.BackgroundColor3 = Color3.new(0/255, 77/255, 0/255)
frame.Number.TextColor3 = Color3.new(0/255, 190/255, 0/255)
elseif tone == Enum.DialogTone.Enemy then
frame.BackgroundColor3 = Color3.new(140/255, 0/255, 0/255)
frame.Number.TextColor3 = Color3.new(255/255,88/255, 79/255)
end
end
function highlightColor(frame, tone)
if tone == Enum.DialogTone.Neutral then
frame.BackgroundColor3 = Color3.new(2/255, 108/255, 255/255)
frame.Number.TextColor3 = Color3.new(1, 1, 1)
elseif tone == Enum.DialogTone.Friendly then
frame.BackgroundColor3 = Color3.new(0/255, 128/255, 0/255)
frame.Number.TextColor3 = Color3.new(1, 1, 1)
elseif tone == Enum.DialogTone.Enemy then
frame.BackgroundColor3 = Color3.new(204/255, 0/255, 0/255)
frame.Number.TextColor3 = Color3.new(1, 1, 1)
end
end
function wanderDialog()
mainFrame.Visible = false
endDialog()
showMessage(characterWanderedOffMessage, characterWanderedOffSize)
end
function timeoutDialog()
mainFrame.Visible = false
endDialog()
showMessage(conversationTimedOut, conversationTimedOutSize)
end
function normalEndDialog()
endDialog()
end
function endDialog()
if currentAbortDialogScript then
currentAbortDialogScript:Remove()
currentAbortDialogScript = nil
end
local dialog = currentConversationDialog
currentConversationDialog = nil
if dialog and dialog.InUse then
local reenableScript = reenableDialogScript:Clone()
reenableScript.archivable = false
reenableScript.Disabled = false
reenableScript.Parent = dialog
end
for dialog, gui in pairs(dialogMap) do
if dialog and gui then
gui.Enabled = not dialog.InUse
end
end
currentConversationPartner = nil
end
function sanitizeMessage(msg)
if string.len(msg) == 0 then
return "..."
else
return msg
end
end
function selectChoice(choice)
renewKillswitch(currentConversationDialog)
--First hide the Gui
mainFrame.Visible = false
if choice == lastChoice then
game:GetService("Chat"):Chat(game:GetService("Players").LocalPlayer.Character, "Goodbye!", getChatColor(currentTone()))
normalEndDialog()
else
local dialogChoice = choiceMap[choice]
game:GetService("Chat"):Chat(game:GetService("Players").LocalPlayer.Character, sanitizeMessage(dialogChoice.UserDialog), getChatColor(currentTone()))
wait(1)
currentConversationDialog:SignalDialogChoiceSelected(player, dialogChoice)
game:GetService("Chat"):Chat(currentConversationPartner, sanitizeMessage(dialogChoice.ResponseDialog), getChatColor(currentTone()))
variableDelay(dialogChoice.ResponseDialog)
presentDialogChoices(currentConversationPartner, dialogChoice:GetChildren())
end
end
function newChoice(numberText)
local frame = Instance.new("TextButton")
frame.BackgroundColor3 = Color3.new(0/255, 0/255, 179/255)
frame.AutoButtonColor = false
frame.BorderSizePixel = 0
frame.Text = ""
frame.MouseEnter:connect(function() highlightColor(frame, currentTone()) end)
frame.MouseLeave:connect(function() resetColor(frame, currentTone()) end)
frame.MouseButton1Click:connect(function() selectChoice(frame) end)
frame.RobloxLocked = true
local number = Instance.new("TextLabel")
number.Name = "Number"
number.TextColor3 = Color3.new(127/255, 212/255, 255/255)
number.Text = numberText
number.FontSize = Enum.FontSize.Size14
number.BackgroundTransparency = 1
number.Position = UDim2.new(0,4,0,2)
number.Size = UDim2.new(0,20,0,24)
number.TextXAlignment = Enum.TextXAlignment.Left
number.TextYAlignment = Enum.TextYAlignment.Top
number.RobloxLocked = true
number.Parent = frame
local prompt = Instance.new("TextLabel")
prompt.Name = "UserPrompt"
prompt.BackgroundTransparency = 1
prompt.TextColor3 = Color3.new(1,1,1)
prompt.FontSize = Enum.FontSize.Size14
prompt.Position = UDim2.new(0,28, 0, 2)
prompt.Size = UDim2.new(1,-32, 1, -4)
prompt.TextXAlignment = Enum.TextXAlignment.Left
prompt.TextYAlignment = Enum.TextYAlignment.Top
prompt.TextWrap = true
prompt.RobloxLocked = true
prompt.Parent = frame
return frame
end
function initialize(parent)
choices[1] = newChoice("1)")
choices[2] = newChoice("2)")
choices[3] = newChoice("3)")
choices[4] = newChoice("4)")
lastChoice = newChoice("5)")
lastChoice.UserPrompt.Text = "Goodbye!"
lastChoice.Size = UDim2.new(1,0,0,28)
mainFrame = Instance.new("Frame")
mainFrame.Name = "UserDialogArea"
mainFrame.Size = UDim2.new(0, 350, 0, 200)
mainFrame.Style = Enum.FrameStyle.ChatBlue
mainFrame.Visible = false
imageLabel = Instance.new("ImageLabel")
imageLabel.Name = "Tail"
imageLabel.Size = UDim2.new(0,62,0,53)
imageLabel.Position = UDim2.new(1,8,0.25)
imageLabel.Image = "rbxasset://textures/chatBubble_botBlue_tailRight.png"
imageLabel.BackgroundTransparency = 1
imageLabel.RobloxLocked = true
imageLabel.Parent = mainFrame
for n, obj in pairs(choices) do
obj.RobloxLocked = true
obj.Parent = mainFrame
end
lastChoice.RobloxLocked = true
lastChoice.Parent = mainFrame
mainFrame.RobloxLocked = true
mainFrame.Parent = parent
end
function presentDialogChoices(talkingPart, dialogChoices)
if not currentConversationDialog then
return
end
currentConversationPartner = talkingPart
sortedDialogChoices = {}
for n, obj in pairs(dialogChoices) do
if obj:IsA("DialogChoice") then
table.insert(sortedDialogChoices, obj)
end
end
table.sort(sortedDialogChoices, function(a,b) return a.Name < b.Name end)
if #sortedDialogChoices == 0 then
normalEndDialog()
return
end
local pos = 1
local yPosition = 0
choiceMap = {}
for n, obj in pairs(choices) do
obj.Visible = false
end
for n, obj in pairs(sortedDialogChoices) do
if pos <= #choices then
--3 lines is the maximum, set it to that temporarily
choices[pos].Size = UDim2.new(1, 0, 0, 24*3)
choices[pos].UserPrompt.Text = obj.UserDialog
local height = math.ceil(choices[pos].UserPrompt.TextBounds.Y/24)*24
choices[pos].Position = UDim2.new(0, 0, 0, yPosition)
choices[pos].Size = UDim2.new(1, 0, 0, height)
choices[pos].Visible = true
choiceMap[choices[pos]] = obj
yPosition = yPosition + height
pos = pos + 1
end
end
lastChoice.Position = UDim2.new(0,0,0,yPosition)
lastChoice.Number.Text = pos .. ")"
mainFrame.Size = UDim2.new(0, 350, 0, yPosition+24+32)
mainFrame.Position = UDim2.new(0,20,0.0, -mainFrame.Size.Y.Offset-20)
styleMainFrame(currentTone())
mainFrame.Visible = true
end
function doDialog(dialog)
while not Instance.Lock(dialog, player) do
wait()
end
if dialog.InUse then
Instance.Unlock(dialog)
return
else
dialog.InUse = true
Instance.Unlock(dialog)
end
currentConversationDialog = dialog
game:GetService("Chat"):Chat(dialog.Parent, dialog.InitialPrompt, getChatColor(dialog.Tone))
variableDelay(dialog.InitialPrompt)
presentDialogChoices(dialog.Parent, dialog:GetChildren())
end
function renewKillswitch(dialog)
if currentAbortDialogScript then
currentAbortDialogScript:Remove()
currentAbortDialogScript = nil
end
currentAbortDialogScript = timeoutScript:Clone()
currentAbortDialogScript.archivable = false
currentAbortDialogScript.Disabled = false
currentAbortDialogScript.Parent = dialog
end
function checkForLeaveArea()
while currentConversationDialog do
if currentConversationDialog.Parent and (player:DistanceFromCharacter(currentConversationDialog.Parent.Position) >= currentConversationDialog.ConversationDistance) then
wanderDialog()
end
wait(1)
end
end
function startDialog(dialog)
if dialog.Parent and dialog.Parent:IsA("BasePart") then
if player:DistanceFromCharacter(dialog.Parent.Position) >= dialog.ConversationDistance then
showMessage(tooFarAwayMessage, tooFarAwaySize)
return
end
for dialog, gui in pairs(dialogMap) do
if dialog and gui then
gui.Enabled = false
end
end
renewKillswitch(dialog)
delay(1, checkForLeaveArea)
doDialog(dialog)
end
end
function removeDialog(dialog)
if dialogMap[dialog] then
dialogMap[dialog]:Remove()
dialogMap[dialog] = nil
end
if dialogConnections[dialog] then
dialogConnections[dialog]:disconnect()
dialogConnections[dialog] = nil
end
end
function addDialog(dialog)
if dialog.Parent then
if dialog.Parent:IsA("BasePart") then
local chatGui = chatNotificationGui:clone()
chatGui.Enabled = not dialog.InUse
chatGui.Adornee = dialog.Parent
chatGui.RobloxLocked = true
chatGui.Parent = game:GetService("CoreGui")
chatGui.Image.Button.MouseButton1Click:connect(function() startDialog(dialog) end)
setChatNotificationTone(chatGui, dialog.Purpose, dialog.Tone)
dialogMap[dialog] = chatGui
dialogConnections[dialog] = dialog.Changed:connect(function(prop)
if prop == "Parent" and dialog.Parent then
--This handles the reparenting case, seperate from removal case
removeDialog(dialog)
addDialog(dialog)
elseif prop == "InUse" then
chatGui.Enabled = not currentConversationDialog and not dialog.InUse
if dialog == currentConversationDialog then
timeoutDialog()
end
elseif prop == "Tone" or prop == "Purpose" then
setChatNotificationTone(chatGui, dialog.Purpose, dialog.Tone)
end
end)
else -- still need to listen to parent changes even if current parent is not a BasePart
dialogConnections[dialog] = dialog.Changed:connect(function(prop)
if prop == "Parent" and dialog.Parent then
--This handles the reparenting case, seperate from removal case
removeDialog(dialog)
addDialog(dialog)
end
end)
end
end
end
function fetchScripts()
local model = game:GetService("InsertService"):LoadAsset(39226062)
if type(model) == "string" then -- load failed, lets try again
wait(0.1)
model = game:GetService("InsertService"):LoadAsset(39226062)
end
if type(model) == "string" then -- not going to work, lets bail
return
end
waitForChild(model,"TimeoutScript")
timeoutScript = model.TimeoutScript
waitForChild(model,"ReenableDialogScript")
reenableDialogScript = model.ReenableDialogScript
end
function onLoad()
waitForProperty(game:GetService("Players"), "LocalPlayer")
player = game:GetService("Players").LocalPlayer
waitForProperty(player, "Character")
--print("Fetching Scripts")
fetchScripts()
--print("Creating Guis")
createChatNotificationGui()
--print("Creating MessageDialog")
createMessageDialog()
messageDialog.RobloxLocked = true
messageDialog.Parent = gui
--print("Waiting for BottomLeftControl")
waitForChild(gui, "BottomLeftControl")
--print("Initializing Frame")
local frame = Instance.new("Frame")
frame.Name = "DialogFrame"
frame.Position = UDim2.new(0,0,0,0)
frame.Size = UDim2.new(0,0,0,0)
frame.BackgroundTransparency = 1
frame.RobloxLocked = true
frame.Parent = gui.BottomLeftControl
initialize(frame)
--print("Adding Dialogs")
game:GetService("CollectionService").ItemAdded:connect(function(obj) if obj:IsA("Dialog") then addDialog(obj) end end)
game:GetService("CollectionService").ItemRemoved:connect(function(obj) if obj:IsA("Dialog") then removeDialog(obj) end end)
for i, obj in pairs(game:GetService("CollectionService"):GetCollection("Dialog")) do
if obj:IsA("Dialog") then
addDialog(obj)
end
end
end
onLoad()
@@ -0,0 +1,328 @@
function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
waitForProperty(game:GetService("Players"),"LocalPlayer")
waitForChild(script.Parent,"Popup")
waitForChild(script.Parent.Popup,"AcceptButton")
script.Parent.Popup.AcceptButton.Modal = true
local localPlayer = game:GetService("Players").LocalPlayer
local teleportUI = nil
local acceptedTeleport = Instance.new("IntValue")
local friendRequestBlacklist = {}
local teleportEnabled = true
local makePopupInvisible = function()
if script.Parent.Popup then script.Parent.Popup.Visible = false end
end
function makeFriend(fromPlayer,toPlayer)
local popup = script.Parent:FindFirstChild("Popup")
if popup == nil then return end -- there is no popup!
if popup.Visible then return end -- currently popping something, abort!
if friendRequestBlacklist[fromPlayer] then return end -- previously cancelled friend request, we don't want it!
popup.PopupText.Text = "Accept Friend Request from " .. tostring(fromPlayer.Name) .. "?"
popup.PopupImage.Image = "http://www.watrbx.wtf/thumbs/avatar.ashx?userId="..tostring(fromPlayer.userId).."&x=352&y=352"
showTwoButtons()
popup.Visible = true
popup.AcceptButton.Text = "Accept"
popup.DeclineButton.Text = "Decline"
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
local yesCon, noCon
yesCon = popup.AcceptButton.MouseButton1Click:connect(function()
popup.Visible = false
toPlayer:RequestFriendship(fromPlayer)
if yesCon then yesCon:disconnect() end
if noCon then noCon:disconnect() end
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
noCon = popup.DeclineButton.MouseButton1Click:connect(function()
popup.Visible = false
toPlayer:RevokeFriendship(fromPlayer)
friendRequestBlacklist[fromPlayer] = true
if yesCon then yesCon:disconnect() end
if noCon then noCon:disconnect() end
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
end
game:GetService("Players").FriendRequestEvent:connect(function(fromPlayer,toPlayer,event)
-- if this doesn't involve me, then do nothing
if fromPlayer ~= localPlayer and toPlayer ~= localPlayer then return end
if fromPlayer == localPlayer then
if event == Enum.FriendRequestEvent.Accept then
game:GetService("GuiService"):SendNotification("You are Friends",
"With " .. toPlayer.Name .. "!",
"http://www.watrbx.wtf/thumbs/avatar.ashx?userId="..tostring(toPlayer.userId).."&x=512&y=512",
5,
function()
end)
end
elseif toPlayer == localPlayer then
if event == Enum.FriendRequestEvent.Issue then
if friendRequestBlacklist[fromPlayer] then return end -- previously cancelled friend request, we don't want it!
game:GetService("GuiService"):SendNotification("Friend Request",
"From " .. fromPlayer.Name,
"http://www.watrbx.wtf/thumbs/avatar.ashx?userId="..tostring(fromPlayer.userId).."&x=512&y=512",
8,
function()
makeFriend(fromPlayer,toPlayer)
end)
elseif event == Enum.FriendRequestEvent.Accept then
game:GetService("GuiService"):SendNotification("You are Friends",
"With " .. fromPlayer.Name .. "!",
"http://www.watrbx.wtf/thumbs/avatar.ashx?userId="..tostring(fromPlayer.userId).."&x=512&y=512",
5,
function()
end)
end
end
end)
function showOneButton()
local popup = script.Parent:FindFirstChild("Popup")
if popup then
popup.OKButton.Visible = true
popup.DeclineButton.Visible = false
popup.AcceptButton.Visible = false
end
end
function showTwoButtons()
local popup = script.Parent:FindFirstChild("Popup")
if popup then
popup.OKButton.Visible = false
popup.DeclineButton.Visible = true
popup.AcceptButton.Visible = true
end
end
function onTeleport(teleportState, placeId, spawnName)
if game:GetService("TeleportService").CustomizedTeleportUI == false then
if teleportState == Enum.TeleportState.Started then
showTeleportUI("Teleport started...", 0)
elseif teleportState == Enum.TeleportState.WaitingForServer then
showTeleportUI("Requesting server...", 0)
elseif teleportState == Enum.TeleportState.InProgress then
showTeleportUI("Teleporting...", 0)
elseif teleportState == Enum.TeleportState.Failed then
showTeleportUI("Teleport failed. Insufficient privileges or target place does not exist.", 3)
end
end
end
function showTeleportUI(message, timer)
if teleportUI ~= nil then
teleportUI:Remove()
end
waitForChild(localPlayer, "PlayerGui")
teleportUI = Instance.new("Message", localPlayer.PlayerGui)
teleportUI.Text = message
if timer > 0 then
wait(timer)
teleportUI:Remove()
end
end
if teleportEnabled then
localPlayer.OnTeleport:connect(onTeleport)
game:GetService("TeleportService").ErrorCallback = function(message)
local popup = script.Parent:FindFirstChild("Popup")
showOneButton()
popup.PopupText.Text = message
local clickCon
clickCon = popup.OKButton.MouseButton1Click:connect(function()
game:GetService("TeleportService"):TeleportCancel()
if clickCon then clickCon:disconnect() end
game:GetService("GuiService"):RemoveCenterDialog(script.Parent:FindFirstChild("Popup"))
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
game:GetService("GuiService"):AddCenterDialog(script.Parent:FindFirstChild("Popup"), Enum.CenterDialogType.QuitDialog,
--ShowFunction
function()
showOneButton()
script.Parent:FindFirstChild("Popup").Visible = true
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end,
--HideFunction
function()
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
end
game:GetService("TeleportService").ConfirmationCallback = function(message, placeId, spawnName)
local popup = script.Parent:FindFirstChild("Popup")
popup.PopupText.Text = message
popup.PopupImage.Image = ""
local yesCon, noCon
local function killCons()
if yesCon then yesCon:disconnect() end
if noCon then noCon:disconnect() end
game:GetService("GuiService"):RemoveCenterDialog(script.Parent:FindFirstChild("Popup"))
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end
yesCon = popup.AcceptButton.MouseButton1Click:connect(function()
killCons()
local success, err = pcall(function() game:GetService("TeleportService"):TeleportImpl(placeId,spawnName) end)
if not success then
showOneButton()
popup.PopupText.Text = err
local clickCon
clickCon = popup.OKButton.MouseButton1Click:connect(function()
if clickCon then clickCon:disconnect() end
game:GetService("GuiService"):RemoveCenterDialog(script.Parent:FindFirstChild("Popup"))
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
game:GetService("GuiService"):AddCenterDialog(script.Parent:FindFirstChild("Popup"), Enum.CenterDialogType.QuitDialog,
--ShowFunction
function()
showOneButton()
script.Parent:FindFirstChild("Popup").Visible = true
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end,
--HideFunction
function()
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
end
end)
noCon = popup.DeclineButton.MouseButton1Click:connect(function()
killCons()
local success = pcall(function() game:GetService("TeleportService"):TeleportCancel() end)
end)
local centerDialogSuccess = pcall(function() game:GetService("GuiService"):AddCenterDialog(script.Parent:FindFirstChild("Popup"), Enum.CenterDialogType.QuitDialog,
--ShowFunction
function()
showTwoButtons()
popup.AcceptButton.Text = "Leave"
popup.DeclineButton.Text = "Stay"
script.Parent:FindFirstChild("Popup").Visible = true
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end,
--HideFunction
function()
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
end)
if centerDialogSuccess == false then
script.Parent:FindFirstChild("Popup").Visible = true
popup.AcceptButton.Text = "Leave"
popup.DeclineButton.Text = "Stay"
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end
return true
end
end
game:GetService("MarketplaceService").ClientLuaDialogRequested:connect(function(message, accept, decline)
local popup = script.Parent:FindFirstChild("Popup")
popup.PopupText.Text = message
popup.PopupImage.Image = ""
local yesCon, noCon
local function killCons()
if yesCon then yesCon:disconnect() end
if noCon then noCon:disconnect() end
game:GetService("GuiService"):RemoveCenterDialog(script.Parent:FindFirstChild("Popup"))
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end
yesCon = popup.AcceptButton.MouseButton1Click:connect(function()
killCons()
game:GetService("MarketplaceService"):SignalServerLuaDialogClosed(true);
end)
noCon = popup.DeclineButton.MouseButton1Click:connect(function()
killCons()
game:GetService("MarketplaceService"):SignalServerLuaDialogClosed(false);
end)
local centerDialogSuccess = pcall(function() game:GetService("GuiService"):AddCenterDialog(script.Parent:FindFirstChild("Popup"), Enum.CenterDialogType.QuitDialog,
function()
showTwoButtons()
popup.AcceptButton.Text = accept
popup.DeclineButton.Text = decline
script.Parent:FindFirstChild("Popup").Visible = true
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end,
function()
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
end)
if centerDialogSuccess == false then
script.Parent:FindFirstChild("Popup").Visible = true
popup.AcceptButton.Text = accept
popup.DeclineButton.Text = decline
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end
return true
end)
local noOptFunc = function ()
-- do nothing
end
Game:GetService("PointsService").PointsAwarded:connect( function(userId, pointsAwarded, userBalanceInGame, userTotalBalance)
if userId == Game:GetService("Players").LocalPlayer.userId then
if pointsAwarded > 0 then
game:GetService("GuiService"):SendNotification("Points Awarded!",
"You received " ..tostring(pointsAwarded) .. " points!",
"http://www.watrbx.wtf/asset?id=155363793",
5,
noOptFunc)
elseif pointsAwarded < 0 then
game:GetService("GuiService"):SendNotification("Points Lost!",
"You lost " ..tostring(-pointsAwarded) .. " points!",
"http://www.watrbx.wtf/asset?id=155363793",
5,
noOptFunc)
end
end
end)
-- Since we can't get the image right, let's just use a nice notification icon
Game:GetService("BadgeService").BadgeAwarded:connect( function(message, userId, badgeId)
if userId == Game:GetService("Players").LocalPlayer.userId then
game:GetService("GuiService"):SendNotification("Badge Awarded!",
message,
"http://www.watrbx.wtf/asset?id=177200377",
5,
noOptFunc)
end
end)
@@ -0,0 +1,349 @@
-- a couple neccessary functions
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local function waitForProperty(instance, prop)
while not instance[prop] do
instance.Changed:wait()
end
end
function securityCheck()
local allowedUserIds = {--[[game.CreatorId,]]7210880}
local canUsePanel = false
local localUserId = game.Players.LocalPlayer.userId
for i = 1, #allowedUserIds do
if localUserId == allowedUserIds[i] then
canUsePanel = true
break
end
end
if not canUsePanel then
script:remove()
end
end
function createGui()
local adminStatsFrame = Instance.new("Frame")
adminStatsFrame.RobloxLocked = true
adminStatsFrame.Name = "AdminStatsFrame"
adminStatsFrame.Active = true
adminStatsFrame.Draggable = true
adminStatsFrame.Position = UDim2.new(0.2,20,0,0)
adminStatsFrame.Size = UDim2.new(0.6,-40,1,0)
adminStatsFrame.Style = Enum.FrameStyle.RobloxRound
adminStatsFrame.Parent = script.Parent
-- AdminStatsFrame Children
local adminStatsTextLabel = Instance.new("TextLabel")
adminStatsTextLabel.RobloxLocked = true
adminStatsTextLabel.Name = "AdminStatsTextLabel"
adminStatsTextLabel.BackgroundTransparency = 1
adminStatsTextLabel.Font = Enum.Font.ArialBold
adminStatsTextLabel.FontSize = Enum.FontSize.Size24
adminStatsTextLabel.Size = UDim2.new(1,0,0,24)
adminStatsTextLabel.Text = "Place Console"
adminStatsTextLabel.TextColor3 = Color3.new(1,1,1)
adminStatsTextLabel.TextYAlignment = Enum.TextYAlignment.Center
adminStatsTextLabel.Parent = adminStatsFrame
local errorPanel = Instance.new("Frame")
errorPanel.RobloxLocked = true
errorPanel.Name = "ErrorPanel"
errorPanel.Position = UDim2.new(0,0,0.5,0)
errorPanel.Size = UDim2.new(1,0,0.5,0)
errorPanel.Style = Enum.FrameStyle.RobloxRound
errorPanel.Parent = adminStatsFrame
-- ErrorPanel Children
local textPanel = Instance.new("Frame")
textPanel.RobloxLocked = true
textPanel.Name = "TextPanel"
textPanel.Position = UDim2.new(0,0,0,18)
textPanel.Size = UDim2.new(1,0,1,-18)
textPanel.BackgroundTransparency = 1
textPanel.Parent = errorPanel
local errorPanelTextLabel = Instance.new("TextLabel")
errorPanelTextLabel.RobloxLocked = true
errorPanelTextLabel.Name = "ErrorPanelTextLabel"
errorPanelTextLabel.Font = Enum.Font.ArialBold
errorPanelTextLabel.FontSize = Enum.FontSize.Size18
errorPanelTextLabel.Size = UDim2.new(1,0,0,18)
errorPanelTextLabel.BackgroundTransparency = 1
errorPanelTextLabel.TextColor3 = Color3.new(1,1,1)
errorPanelTextLabel.Text = "Lua Errors"
errorPanelTextLabel.Parent = errorPanel
local sampleError = Instance.new("TextLabel")
sampleError.RobloxLocked = true
sampleError.Name = "SampleError"
sampleError.Font = Enum.Font.Arial
sampleError.FontSize = Enum.FontSize.Size12
sampleError.Size = UDim2.new(1,0,0,12)
sampleError.BackgroundTransparency = 0.5
sampleError.TextColor3 = Color3.new(1,1,1)
sampleError.Text = "Thu May 19 12:37:09 2011 - Players.Player.Backpack.StamperTool.GuiScript:1199: attempt to index field '?' (a nil value)"
sampleError.TextWrap = true
sampleError.TextXAlignment = Enum.TextXAlignment.Left
sampleError.TextYAlignment = Enum.TextYAlignment.Top
sampleError.Visible = false
sampleError.Parent = errorPanel
local playerStatsFrame = Instance.new("Frame")
playerStatsFrame.RobloxLocked = true
playerStatsFrame.Name = "PlayerStatsFrame"
playerStatsFrame.BackgroundTransparency = 1
playerStatsFrame.Position = UDim2.new(0,0,0,24)
playerStatsFrame.Size = UDim2.new(0,200,0,100)
playerStatsFrame.Style = Enum.FrameStyle.RobloxRound
playerStatsFrame.Parent = adminStatsFrame
local playerStatsTextInfo = Instance.new("TextLabel")
playerStatsTextInfo.Name = "PlayerStatsTextInfo"
playerStatsTextInfo.BackgroundTransparency = 1
playerStatsTextInfo.Font = Enum.Font.ArialBold
playerStatsTextInfo.FontSize = Enum.FontSize.Size14
playerStatsTextInfo.Size = UDim2.new(1,0,1,0)
playerStatsTextInfo.Text = ""
playerStatsTextInfo.TextColor3 = Color3.new(1,1,1)
playerStatsTextInfo.TextYAlignment = Enum.TextYAlignment.Top
local smallFrame = Instance.new("Frame")
smallFrame.BackgroundTransparency = 1
smallFrame.Size = UDim2.new(1,0,0,14)
-- PlayerStatsFrame Children
local avgPlayerTimeFrame = smallFrame:clone()
avgPlayerTimeFrame.RobloxLocked = true
avgPlayerTimeFrame.Name = "AvgPlayerTimeFrame"
avgPlayerTimeFrame.Position = UDim2.new(0,0,0,46)
local newTextInfo = playerStatsTextInfo:clone()
newTextInfo.RobloxLocked = true
newTextInfo.Text = "Avg. Play Time: 0"
newTextInfo.Parent = avgPlayerTimeFrame
avgPlayerTimeFrame.Parent = playerStatsFrame
local joinFrame = smallFrame:clone()
joinFrame.RobloxLocked = true
joinFrame.Name = "JoinFrame"
joinFrame.Position = UDim2.new(0,0,0,18)
local newTextInfo = playerStatsTextInfo:clone()
newTextInfo.RobloxLocked = true
newTextInfo.Text = "# of Joins: 0"
newTextInfo.Parent = joinFrame
joinFrame.Parent = playerStatsFrame
local leaveFrame = smallFrame:clone()
leaveFrame.RobloxLocked = true
leaveFrame.Name = "LeaveFrame"
leaveFrame.Position = UDim2.new(0,0,0,32)
local newTextInfo = playerStatsTextInfo:clone()
newTextInfo.RobloxLocked = true
newTextInfo.Text = "# of Leaves: 0"
newTextInfo.Parent = leaveFrame
leaveFrame.Parent = playerStatsFrame
local uniqueVisitorsFrame = smallFrame:clone()
uniqueVisitorsFrame.RobloxLocked = true
uniqueVisitorsFrame.Name = "UniqueVisitorsFrame"
uniqueVisitorsFrame.Position = UDim2.new(0,0,0,60)
local newTextInfo = playerStatsTextInfo:clone()
newTextInfo.RobloxLocked = true
newTextInfo.Text = "# of Unique Visits: 0"
newTextInfo.Parent = uniqueVisitorsFrame
uniqueVisitorsFrame.Parent = playerStatsFrame
local textHeader = playerStatsTextInfo:clone()
textHeader.Name = "PlayerStatsTextLabel"
textHeader.RobloxLocked = true
textHeader.FontSize = Enum.FontSize.Size18
textHeader.Size = UDim2.new(1,0,0,18)
textHeader.Text = "Player Stats"
textHeader.TextYAlignment = Enum.TextYAlignment.Center
textHeader.Parent = playerStatsFrame
-- Script Stats Frame
local scriptStatsFrame = playerStatsFrame:clone()
scriptStatsFrame.RobloxLocked = true
scriptStatsFrame.Name = "ScriptStatsFrame"
scriptStatsFrame.Position = UDim2.new(0,0,0,126)
scriptStatsFrame.PlayerStatsTextLabel.Name = "ScriptStatsTextLabel"
scriptStatsFrame.ScriptStatsTextLabel.Text = "Lua Stats"
scriptStatsFrame.JoinFrame.Name = "ScriptErrorsFrame"
scriptStatsFrame.ScriptErrorsFrame.PlayerStatsTextInfo.Name = "ScriptErrorsTextInfo"
scriptStatsFrame.ScriptErrorsFrame.ScriptErrorsTextInfo.Text = "# of Lua Errors: 0"
scriptStatsFrame.LeaveFrame.Name = "ScriptWarningFrame"
scriptStatsFrame.ScriptWarningFrame.PlayerStatsTextInfo.Name = "ScriptWarningTextInfo"
scriptStatsFrame.ScriptWarningFrame.ScriptWarningTextInfo.Text = "# of Lua Warnings: 0"
scriptStatsFrame.AvgPlayerTimeFrame.Name = "ScriptsRunningFrame"
scriptStatsFrame.ScriptsRunningFrame.PlayerStatsTextInfo.Name = "ScriptsRunningInfo"
scriptStatsFrame.ScriptsRunningFrame.ScriptsRunningInfo.Text = "# Scripts Running: 0"
scriptStatsFrame.UniqueVisitorsFrame:remove()
scriptStatsFrame.Parent = adminStatsFrame
-- UptimeFrame
local upTimeFrame = Instance.new("Frame")
upTimeFrame.RobloxLocked = true
upTimeFrame.Name = "UptimeFrame"
upTimeFrame.BackgroundTransparency = 1
upTimeFrame.Position = UDim2.new(1,-200,0,24)
upTimeFrame.Size = UDim2.new(0,200,0,100)
upTimeFrame.Style = Enum.FrameStyle.RobloxRound
upTimeFrame.Parent = adminStatsFrame
-- UptimeFrame Children
local secondsUpTimeTextInfo = Instance.new("TextLabel")
secondsUpTimeTextInfo.RobloxLocked = true
secondsUpTimeTextInfo.Name = "SecondsUptimeTextInfo"
secondsUpTimeTextInfo.Font = Enum.Font.ArialBold
secondsUpTimeTextInfo.FontSize = Enum.FontSize.Size14
secondsUpTimeTextInfo.Position = UDim2.new(0,0,0.5,18)
secondsUpTimeTextInfo.Size = UDim2.new(1,0,0.5,-18)
secondsUpTimeTextInfo.Text = "0 Total Seconds"
secondsUpTimeTextInfo.BackgroundTransparency = 1
secondsUpTimeTextInfo.TextColor3 = Color3.new(1,1,1)
secondsUpTimeTextInfo.TextYAlignment = Enum.TextYAlignment.Top
secondsUpTimeTextInfo.Parent = upTimeFrame
local uptimeTextInfo = secondsUpTimeTextInfo:clone()
uptimeTextInfo.RobloxLocked = true
uptimeTextInfo.Name = "UptimeTextInfo"
uptimeTextInfo.Position = UDim2.new(0,0,0,18)
uptimeTextInfo.Size = UDim2.new(1,0,0.5,0)
uptimeTextInfo.TextWrap = true
uptimeTextInfo.Text = "0 Days, 0 Hours, 0 Minutes, 0 Seconds"
uptimeTextInfo.Parent = upTimeFrame
local upTimeTextLabel = uptimeTextInfo:clone()
upTimeTextLabel.RobloxLocked = true
upTimeTextLabel.Name = "UptimeTextLabel"
upTimeTextLabel.FontSize = Enum.FontSize.Size18
upTimeTextLabel.Size = UDim2.new(1,0,0,18)
upTimeTextLabel.Position = UDim2.new(0,0,0,0)
upTimeTextLabel.Text = "Instance Uptime"
upTimeTextLabel.TextYAlignment = Enum.TextYAlignment.Center
upTimeTextLabel.Parent = upTimeFrame
end
-- functions
function initLocals()
-- Top Gui Layer
adminGui = script.Parent
adminFrame = adminGui.AdminStatsFrame
-- Second Gui Layer
upTimeFrame = adminFrame.UptimeFrame
errorFrame = adminFrame.ErrorPanel
playerStatsFrame = adminFrame.PlayerStatsFrame
scriptStatsFrame = adminFrame.ScriptStatsFrame
-- UptimeFrame Children
upTimeFormattedText = upTimeFrame.UptimeTextInfo
upTimeSecondsText = upTimeFrame.SecondsUptimeTextInfo
-- PlayerStatsFrame Children
avgPlayTimeText = playerStatsFrame.AvgPlayerTimeFrame.PlayerStatsTextInfo
joinText = playerStatsFrame.JoinFrame.PlayerStatsTextInfo
leaveText = playerStatsFrame.LeaveFrame.PlayerStatsTextInfo
uniqueVisitorText = playerStatsFrame.UniqueVisitorsFrame.PlayerStatsTextInfo
uniqueUserIds = {}
playTimes = {}
avgPlayTime = 0
placeVisits = 0
placeLeaves = 0
end
function updateUptime()
local currentTime = game.Workspace.DistributedGameTime
upTimeSecondsText.Text = tostring(math.floor(currentTime)) .. " Total Seconds"
local days = math.floor(currentTime/86400)
currentTime = currentTime - (days * 86400)
local hours = math.floor(currentTime/3600)
currentTime = currentTime - (hours * 3600)
local minutes = math.floor(currentTime/60)
currentTime = currentTime - (minutes * 60)
currentTime = math.floor(currentTime)
upTimeFormattedText.Text = tostring(days) .. " Days, " .. tostring(hours) .. " Hours, " .. tostring(minutes) .. " Minutes, " .. tostring(currentTime) .. (" Seconds")
end
function playerJoined(addedPlayer)
placeVisits = placeVisits + 1
joinText.Text = "# of Joins: " .. tostring(placeVisits)
if uniqueUserIds[addedPlayer] == nil then
uniqueUserIds[addedPlayer] = addedPlayer.userId
uniqueVisitorText.Text = "#of Unique Visits: " .. tostring(#uniqueUserIds)
end
playTimes[addedPlayer] = game.Workspace.DistributedGameTime
end
function recalculateAvgPlayTime(removedPlayer)
if playTimes[removedPlayer] then
local playerPlayTime = game.Workspace.DistributedGameTime - playTimes[removedPlayer]
avgPlayTime = ( ((placesLeaves - 1)/placeLeaves) * avgPlayTime ) + ( (1/placeLeaves) * playerPlayTime )
avgPlayTimeText.Text = "Avg. Play Time: " .. tostring(math.floor(avgPlayTime))
end
end
function playerLeft(removedPlayer)
placeLeaves = placeLeaves + 1
leaveText.Text = "# of Leaves: " .. tostring(placeLeaves)
recalculateAvgPlayTime(removedPlayer)
end
function uptimeLoop()
while true do
updateUptime()
wait(1)
end
end
function playerAddedFunction(player)
if player == game.Players.LocalPlayer then
securityCheck()
createGui()
initLocals()
adminFrame.Visible = true
uptimeLoop()
end
playerJoined(addedPlayer)
end
-- Script Start
-- Check to see if we already have players
local playersChildren = game.Players:GetChildren()
for i = 1, #playersChildren do
if playersChildren[i]:IsA("Player") then
playerAddedFunction(playersChildren[i])
end
end
-- Listen for players now
game.Players.PlayerAdded:connect(function(addedPlayer) playerAddedFunction(addedPlayer) end)
game.Players.PlayerRemoving:connect(function(removedPlayer) playerLeft(removedPlayer) end)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,72 @@
--build our gui
local popupFrame = Instance.new("Frame")
popupFrame.Position = UDim2.new(0.5,-165,0.5,-175)
popupFrame.Size = UDim2.new(0,330,0,350)
popupFrame.Style = Enum.FrameStyle.DropShadow
popupFrame.ZIndex = 4
popupFrame.Name = "Popup"
popupFrame.Visible = false
popupFrame.Parent = script.Parent
local darken = popupFrame:clone()
darken.Size = UDim2.new(1,16,1,16)
darken.Position = UDim2.new(0,-8,0,-8)
darken.Name = "Darken"
darken.ZIndex = 1
darken.Parent = popupFrame
local acceptButton = Instance.new("TextButton")
acceptButton.Position = UDim2.new(0,20,0,270)
acceptButton.Size = UDim2.new(0,100,0,50)
acceptButton.Font = Enum.Font.ArialBold
acceptButton.FontSize = Enum.FontSize.Size24
acceptButton.Style = Enum.ButtonStyle.RobloxRoundButton
acceptButton.TextColor3 = Color3.new(248/255,248/255,248/255)
acceptButton.Text = "Yes"
acceptButton.ZIndex = 5
acceptButton.Name = "AcceptButton"
acceptButton.Parent = popupFrame
local declineButton = acceptButton:clone()
declineButton.Position = UDim2.new(1,-120,0,270)
declineButton.Text = "No"
declineButton.Name = "DeclineButton"
declineButton.Parent = popupFrame
local okButton = acceptButton:clone()
okButton.Name = "OKButton"
okButton.Text = "OK"
okButton.Position = UDim2.new(0.5,-50,0,270)
okButton.Visible = false
okButton.Parent = popupFrame
local popupImage = Instance.new("ImageLabel")
popupImage.BackgroundTransparency = 1
popupImage.Position = UDim2.new(0.5,-140,0,10)
popupImage.Size = UDim2.new(0,280,0,280)
popupImage.ZIndex = 3
popupImage.Name = "PopupImage"
popupImage.Parent = popupFrame
local backing = Instance.new("ImageLabel")
backing.BackgroundTransparency = 1
backing.Size = UDim2.new(1,0,1,0)
backing.Image = "http://www.watrbx.wtf/asset/?id=47574181"
backing.Name = "Backing"
backing.ZIndex = 2
backing.Parent = popupImage
local popupText = Instance.new("TextLabel")
popupText.Name = "PopupText"
popupText.Size = UDim2.new(1,0,0.8,0)
popupText.Font = Enum.Font.ArialBold
popupText.FontSize = Enum.FontSize.Size36
popupText.BackgroundTransparency = 1
popupText.Text = "Hello I'm a popup"
popupText.TextColor3 = Color3.new(248/255,248/255,248/255)
popupText.TextWrap = true
popupText.ZIndex = 5
popupText.Parent = popupFrame
script:remove()
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,134 @@
local vChar = script.Parent
local vPlayer = game.Players:GetPlayerFromCharacter(vChar)
playerGui = vPlayer.PlayerGui
local config = vChar:FindFirstChild("PlayerStats")
while config == nil do
config = vChar:FindFirstChild("PlayerStats")
wait()
end
buffGui = Instance.new("ScreenGui")
buffGui.Parent = playerGui
buffGui.Name = "BuffGUI"
tray = Instance.new("Frame")
tray.BackgroundTransparency = 1.0
tray.Parent = buffGui
tray.Name = "Tray"
tray.Position = UDim2.new(0.40, 0.0, 0.95, 0.0)
tray.Size = UDim2.new(0.0, 300.0, 0.0, 30.0)
tray.BorderColor3 = Color3.new(0, 0, 0)
tray.Visible = true
local iceLabel = Instance.new("ImageLabel")
iceLabel.Name = "Ice"
iceLabel.Size = UDim2.new(0.1, 0.0, 0.8, 0.0)
iceLabel.BackgroundTransparency = 1.0
iceLabel.Image = "http://www.watrbx.wtf/asset/?id=47522829"
iceLabel.Visible = true
local poisonLabel = Instance.new("ImageLabel")
poisonLabel.Name = "Poison"
poisonLabel.Size = UDim2.new(0.1, 0.0, 0.8, 0.0)
poisonLabel.BackgroundTransparency = 1.0
poisonLabel.Image = "http://www.watrbx.wtf/asset/?id=47525343"
poisonLabel.Visible = true
local fireLabel = Instance.new("ImageLabel")
fireLabel.Name = "Fire"
fireLabel.Size = UDim2.new(0.1, 0.0, 0.8, 0.0)
fireLabel.BackgroundTransparency = 1.0
fireLabel.Image = "http://www.watrbx.wtf/asset/?id=47522853"
fireLabel.Visible = true
local stunLabel = Instance.new("ImageLabel")
stunLabel.Name = "Stun"
stunLabel.Size = UDim2.new(0.1, 0.0, 0.8, 0.0)
stunLabel.BackgroundTransparency = 1.0
stunLabel.Image = "http://www.watrbx.wtf/asset/?id= 47522868"
stunLabel.Visible = true
-- The table that contains the list of all the status buff images
local labels = {poisonLabel, iceLabel, fireLabel, stunLabel}
-- Contains the list of active Labels to draw them
local activeLabels = {}
-- Copies the necessary labels
local buffsGuiTable = {
["Speed"] = function ()
end,
["MaxHealth"] = function ()
end,
["Poison"] = function ()
table.insert(activeLabels, labels[1])
end,
["Ice"] = function()
table.insert(activeLabels, labels[2])
end,
["Fire"] = function()
table.insert(activeLabels, labels[3])
end,
["Stun"] = function()
table.insert(activeLabels, labels[4])
end
}
function statusBuffGui()
activeLabels = {}
for a = 1, #labels do
labels[a].Active = false
labels[a].Visible = false
end
activeBuffs = config:GetChildren()
print(#buffsGuiTable)
print(#activeBuffs)
if #activeBuffs > 2 then
for i = 1, #activeBuffs do
print(activeBuffs[i].Name)
buffsGuiTable[activeBuffs[i].Name]()
end
print(#activeLabels)
if #activeLabels > 0 then
count = 0
parity = 1
median = 0.45
if #activeLabels%2 == 0 then median = .5 end
for j = 1, #activeLabels do
activeLabels[j].Position = UDim2.new(median + parity*count, 0.0, 0.0, 0.0)
if j%2 == 1 then count = count + .1 end
parity = parity * -1
activeLabels[j].Parent = tray
activeLabels.Active = true
end
end
end
end
-- Blinking Labels
function blinkGui()
while true do
for n = 1, #activeLabels do
activeLabels[n].Visible = not activeLabels[n].Visible
end
wait(0.5)
end
end
blink = coroutine.create(blinkGui)
coroutine.resume(blink)
-- Event Listeners
config.ChildAdded:connect(statusBuffGui)
config.ChildRemoved:connect(statusBuffGui)
@@ -0,0 +1,3 @@
settings().FastLogSettings:SetGroupEnable("Network", 1, true)
settings().FastLogSettings:SetGroupEnable("MegaClusterNetwork", 1, true)
settings().FastLogSettings:SetGroupEnable("MegaClusterNetworkInit", 1, true)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,96 @@
-- Creates all neccessary scripts for the gui on initial load, everything except build tools
-- Created by Ben T. 10/29/10
-- Please note that these are loaded in a specific order to diminish errors/perceived load time by user
local scriptContext = game:GetService("ScriptContext")
local touchEnabled = game:GetService("UserInputService").TouchEnabled
Game:GetService("CoreGui"):WaitForChild("RobloxGui")
local screenGui = Game:GetService("CoreGui"):FindFirstChild("RobloxGui")
-- SettingsScript
scriptContext:AddCoreScriptLocal("CoreScripts/2014/Settings", screenGui)
local luaControlsSuccess, luaControlsFlagValue = pcall(function() return settings():GetFFlag("UsePlayerScripts") end)
if not touchEnabled then
-- ToolTipper (creates tool tips for gui)
scriptContext:AddCoreScriptLocal("CoreScripts/2014/ToolTip", screenGui)
else
if not luaControlsSuccess or luaControlsFlagValue == false then
scriptContext:AddCoreScriptLocal("CoreScripts/2014/TouchControls", screenGui)
end
end
-- MainBotChatScript
scriptContext:AddCoreScriptLocal("CoreScripts/2014/MainBotChatScript", screenGui)
-- Developer Console Script
scriptContext:AddCoreScriptLocal("CoreScripts/2014/DeveloperConsole", screenGui)
-- Popup Script
scriptContext:AddCoreScriptLocal("CoreScripts/2014/PopupScript", screenGui)
-- Friend Notification Script (probably can use this script to expand out to other notifications)
scriptContext:AddCoreScriptLocal("CoreScripts/2014/NotificationScript", screenGui)
-- Chat script
local success, chatFlagValue = pcall(function() return settings():GetFFlag("NewLuaChatScript") end)
if success and chatFlagValue == true then
scriptContext:AddCoreScriptLocal("CoreScripts/2014/ChatScript2", screenGui)
else
scriptContext:AddCoreScriptLocal("CoreScripts/2014/ChatScript", screenGui)
end
-- Purchase Prompt Script
scriptContext:AddCoreScriptLocal("CoreScripts/2014/PurchasePromptScript", screenGui)
-- Health Script
scriptContext:AddCoreScriptLocal("CoreScripts/2014/HealthScript", screenGui)
local playerListSuccess, playerListFlagValue = pcall(function() return settings():GetFFlag("NewPlayerListScript") end)
if not touchEnabled then
-- New Player List
if playerListSuccess and playerListFlagValue == true then
scriptContext:AddCoreScriptLocal("CoreScripts/2014/PlayerListScript2", screenGui)
else
scriptContext:AddCoreScriptLocal("CoreScripts/2014/PlayerListScript", screenGui)
end
elseif Game:GetService("GuiService"):GetScreenResolution().Y >= 500 then
-- New Player List
if playerListSuccess and playerListFlagValue == true then
scriptContext:AddCoreScriptLocal("CoreScripts/2014/PlayerListScript2", screenGui)
else
scriptContext:AddCoreScriptLocal("CoreScripts/2014/PlayerListScript", screenGui)
end
end
do -- Backpack!
local useNewBackpack = false
local success, errorMsg = pcall(function()
useNewBackpack = settings():GetFFlag("NewBackpackScript")
end)
if useNewBackpack then
scriptContext:AddCoreScriptLocal("CoreScripts/2014/BackpackScript", screenGui)
else
-- Backpack Builder, creates most of the backpack gui
scriptContext:AddCoreScriptLocal("CoreScripts/2014/BackpackScripts/BackpackBuilder", screenGui)
screenGui:WaitForChild("CurrentLoadout")
screenGui:WaitForChild("Backpack")
local Backpack = screenGui.Backpack
-- Manager handles all big backpack state changes, other scripts subscribe to this and do things accordingly
scriptContext:AddCoreScriptLocal("CoreScripts/2014/BackpackScripts/BackpackManager", Backpack)
-- Backpack Gear (handles all backpack gear tab stuff)
scriptContext:AddCoreScriptLocal("CoreScripts/2014/BackpackScripts/BackpackGear", Backpack)
-- Loadout Script, used for gear hotkeys
scriptContext:AddCoreScriptLocal("CoreScripts/2014/BackpackScripts/LoadoutScript", screenGui.CurrentLoadout)
end
end
if touchEnabled then -- touch devices don't use same control frame
-- only used for touch device button generation
scriptContext:AddCoreScriptLocal("CoreScripts/2014/ContextActionTouch", screenGui)
screenGui:WaitForChild("ControlFrame")
screenGui.ControlFrame:WaitForChild("BottomLeftControl")
screenGui.ControlFrame.BottomLeftControl.Visible = false
end
@@ -0,0 +1,288 @@
-- creates the in-game gui sub menus for property tools
-- written 9/27/2010 by Ben (jeditkacheff)
local gui = script.Parent
if gui:FindFirstChild("ControlFrame") then
gui = gui:FindFirstChild("ControlFrame")
end
local currentlySelectedButton = nil
local localAssetBase = "rbxasset://textures/ui/"
local selectedButton = Instance.new("ObjectValue")
selectedButton.RobloxLocked = true
selectedButton.Name = "SelectedButton"
selectedButton.Parent = gui.BuildTools
local closeButton = Instance.new("ImageButton")
closeButton.Name = "CloseButton"
closeButton.RobloxLocked = true
closeButton.BackgroundTransparency = 1
closeButton.Image = localAssetBase .. "CloseButton.png"
closeButton.ZIndex = 2
closeButton.Size = UDim2.new(0.2,0,0.05,0)
closeButton.AutoButtonColor = false
closeButton.Position = UDim2.new(0.75,0,0.01,0)
function setUpCloseButtonState(button)
button.MouseEnter:connect(function()
button.Image = localAssetBase .. "CloseButton_dn.png"
end)
button.MouseLeave:connect(function()
button.Image = localAssetBase .. "CloseButton.png"
end)
button.MouseButton1Click:connect(function()
button.ClosedState.Value = true
button.Image = localAssetBase .. "CloseButton.png"
end)
end
-- nice selection animation
function fadeInButton(button)
if currentlySelectedButton ~= nil then
currentlySelectedButton.Selected = false
currentlySelectedButton.ZIndex = 2
currentlySelectedButton.Frame.BackgroundTransparency = 1
end
local speed = 0.1
button.ZIndex = 3
while button.Frame.BackgroundTransparency > 0 do
button.Frame.BackgroundTransparency = button.Frame.BackgroundTransparency - speed
wait()
end
button.Selected = true
currentlySelectedButton = button
selectedButton.Value = currentlySelectedButton
end
------------------------------- create the color selection sub menu -----------------------------------
local paintMenu = Instance.new("ImageLabel")
local paintTool = gui.BuildTools.Frame.PropertyTools.PaintTool
paintMenu.Name = "PaintMenu"
paintMenu.RobloxLocked = true
paintMenu.Parent = paintTool
paintMenu.Position = UDim2.new(-2.7,0,-3,0)
paintMenu.Size = UDim2.new(2.5,0,10,0)
paintMenu.BackgroundTransparency = 1
paintMenu.ZIndex = 2
paintMenu.Image = localAssetBase .. "PaintMenu.png"
local paintColorButton = Instance.new("ImageButton")
paintColorButton.RobloxLocked = true
paintColorButton.BorderSizePixel = 0
paintColorButton.ZIndex = 2
paintColorButton.Size = UDim2.new(0.200000003, 0,0.0500000007, 0)
local selection = Instance.new("Frame")
selection.RobloxLocked = true
selection.BorderSizePixel = 0
selection.BackgroundColor3 = Color3.new(1,1,1)
selection.BackgroundTransparency = 1
selection.ZIndex = 2
selection.Size = UDim2.new(1.1,0,1.1,0)
selection.Position = UDim2.new(-0.05,0,-0.05,0)
selection.Parent = paintColorButton
local header = 0.08
local spacing = 18
local count = 1
function findNextColor()
colorName = tostring(BrickColor.new(count))
while colorName == "Medium stone grey" do
count = count + 1
colorName = tostring(BrickColor.new(count))
end
return count
end
for i = 0,15 do
for j = 1, 4 do
newButton = paintColorButton:clone()
newButton.RobloxLocked = true
newButton.BackgroundColor3 = BrickColor.new(findNextColor()).Color
newButton.Name = tostring(BrickColor.new(count))
count = count + 1
if j == 1 then newButton.Position = UDim2.new(0.08,0,i/spacing + header,0)
elseif j == 2 then newButton.Position = UDim2.new(0.29,0,i/spacing + header,0)
elseif j == 3 then newButton.Position = UDim2.new(0.5,0,i/spacing + header,0)
elseif j == 4 then newButton.Position = UDim2.new(0.71,0,i/spacing + header,0) end
newButton.Parent = paintMenu
end
end
local paintButtons = paintMenu:GetChildren()
for i = 1, #paintButtons do
paintButtons[i].MouseButton1Click:connect(function()
fadeInButton(paintButtons[i])
end)
end
local paintCloseButton = closeButton:clone()
paintCloseButton.RobloxLocked = true
paintCloseButton.Parent = paintMenu
local closedState = Instance.new("BoolValue")
closedState.RobloxLocked = true
closedState.Name = "ClosedState"
closedState.Parent = paintCloseButton
setUpCloseButtonState(paintCloseButton)
------------------------------- create the material selection sub menu -----------------------------------
local materialMenu = Instance.new("ImageLabel")
local materialTool = gui.BuildTools.Frame.PropertyTools.MaterialSelector
materialMenu.RobloxLocked = true
materialMenu.Name = "MaterialMenu"
materialMenu.Position = UDim2.new(-4,0,-3,0)
materialMenu.Size = UDim2.new(2.5,0,6.5,0)
materialMenu.BackgroundTransparency = 1
materialMenu.ZIndex = 2
materialMenu.Image = localAssetBase .. "MaterialMenu.png"
materialMenu.Parent = materialTool
local textures = {"Plastic","Wood","Slate","CorrodedMetal","Ice","Grass","Foil","DiamondPlate","Concrete"}
local materialButtons = {}
local materialButton = Instance.new("ImageButton")
materialButton.RobloxLocked = true
materialButton.BackgroundTransparency = 1
materialButton.Size = UDim2.new(0.400000003, 0,0.16, 0)
materialButton.ZIndex = 2
selection.Parent = materialButton
local current = 1
function getTextureAndName(button)
if current > #textures then
button:remove()
return false
end
button.Image = localAssetBase .. textures[current] .. ".png"
button.Name = textures[current]
current = current + 1
return true
end
local ySpacing = 0.10
local xSpacing = 0.07
for i = 1,5 do
for j = 1,2 do
local button = materialButton:clone()
button.RobloxLocked = true
button.Position = UDim2.new((j -1)/2.2 + xSpacing,0,ySpacing + (i - 1)/5.5,0)
if getTextureAndName(button) then button.Parent = materialMenu else button:remove() end
table.insert(materialButtons,button)
end
end
for i = 1, #materialButtons do
materialButtons[i].MouseButton1Click:connect(function()
fadeInButton(materialButtons[i])
end)
end
local materialCloseButton = closeButton:clone()
materialCloseButton.RobloxLocked = true
materialCloseButton.Size = UDim2.new(0.2,0,0.08,0)
materialCloseButton.Parent = materialMenu
local closedState = Instance.new("BoolValue")
closedState.RobloxLocked = true
closedState.Name = "ClosedState"
closedState.Parent = materialCloseButton
setUpCloseButtonState(materialCloseButton)
------------------------------- create the surface selection sub menu -----------------------------------
local surfaceMenu = Instance.new("ImageLabel")
local surfaceTool = gui.BuildTools.Frame.PropertyTools.InputSelector
surfaceMenu.RobloxLocked = true
surfaceMenu.Name = "SurfaceMenu"
surfaceMenu.Position = UDim2.new(-2.6,0,-4,0)
surfaceMenu.Size = UDim2.new(2.5,0,5.5,0)
surfaceMenu.BackgroundTransparency = 1
surfaceMenu.ZIndex = 2
surfaceMenu.Image = localAssetBase .. "SurfaceMenu.png"
surfaceMenu.Parent = surfaceTool
textures = {"Smooth", "Studs", "Inlets", "Universal", "Glue", "Weld", "Hinge", "Motor"}
current = 1
local surfaceButtons = {}
local surfaceButton = Instance.new("ImageButton")
surfaceButton.RobloxLocked = true
surfaceButton.BackgroundTransparency = 1
surfaceButton.Size = UDim2.new(0.400000003, 0,0.19, 0)
surfaceButton.ZIndex = 2
selection.Parent = surfaceButton
local ySpacing = 0.14
local xSpacing = 0.07
for i = 1,4 do
for j = 1,2 do
local button = surfaceButton:clone()
button.RobloxLocked = true
button.Position = UDim2.new((j -1)/2.2 + xSpacing,0,ySpacing + (i - 1)/4.6,0)
getTextureAndName(button)
button.Parent = surfaceMenu
table.insert(surfaceButtons,button)
end
end
for i = 1, #surfaceButtons do
surfaceButtons[i].MouseButton1Click:connect(function()
fadeInButton(surfaceButtons[i])
end)
end
local surfaceMenuCloseButton = closeButton:clone()
surfaceMenuCloseButton.RobloxLocked = true
surfaceMenuCloseButton.Size = UDim2.new(0.2,0,0.09,0)
surfaceMenuCloseButton.Parent = surfaceMenu
local closedState = Instance.new("BoolValue")
closedState.RobloxLocked = true
closedState.Name = "ClosedState"
closedState.Parent = surfaceMenuCloseButton
setUpCloseButtonState(surfaceMenuCloseButton)
local function setupTweenTransition(button, menu, outXScale, inXScale)
button.Changed:connect(
function(property)
if property ~= "Selected" then
return
end
if button.Selected then
menu:TweenPosition(UDim2.new(inXScale, menu.Position.X.Offset, menu.Position.Y.Scale, menu.Position.Y.Offset),
Enum.EasingDirection.Out, Enum.EasingStyle.Quart, 1, true)
else
menu:TweenPosition(UDim2.new(outXScale, menu.Position.X.Offset, menu.Position.Y.Scale, menu.Position.Y.Offset),
Enum.EasingDirection.In, Enum.EasingStyle.Quart, 0.5, true)
end
end)
end
setupTweenTransition(paintTool, paintMenu, -2.7, 2.6)
setupTweenTransition(surfaceTool, surfaceMenu, -2.6, 2.6)
setupTweenTransition(materialTool, materialMenu, -4, 1.4)
@@ -0,0 +1,36 @@
-- this script is responsible for moving the surface menu in and out when selected/deselected
local button = script.Parent
local activated = false
function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
waitForChild(script.Parent,"SurfaceMenu")
local menu = script.Parent:FindFirstChild("SurfaceMenu")
local speed = 0.35
local moving = false
button.Changed:connect(function(property)
if property ~= "Selected" then return end
if moving then return end
moving = true
activated = button.Selected
if activated then
while menu.Position.X.Scale < 2.6 do
menu.Position = UDim2.new(menu.Position.X.Scale + speed,menu.Position.X.Offset,menu.Position.Y.Scale,menu.Position.Y.Offset)
wait()
end
else
while menu.Position.X.Scale > -2.6 do
menu.Position = UDim2.new(menu.Position.X.Scale - speed,menu.Position.X.Offset,menu.Position.Y.Scale,menu.Position.Y.Offset)
wait()
end
end
moving = false end)
@@ -0,0 +1,109 @@
local controlFrame = script.Parent:FindFirstChild("ControlFrame")
if not controlFrame then return end
local topLeftControl = controlFrame:FindFirstChild("TopLeftControl")
local bottomLeftControl = controlFrame:FindFirstChild("BottomLeftControl")
local bottomRightControl = controlFrame:FindFirstChild("BottomRightControl")
local frameTip = Instance.new("TextLabel")
frameTip.Name = "ToolTip"
frameTip.Text = ""
frameTip.Font = Enum.Font.ArialBold
frameTip.FontSize = Enum.FontSize.Size12
frameTip.TextColor3 = Color3.new(1,1,1)
frameTip.BorderSizePixel = 0
frameTip.ZIndex = 10
frameTip.Size = UDim2.new(2,0,1,0)
frameTip.Position = UDim2.new(1,0,0,0)
frameTip.BackgroundColor3 = Color3.new(0,0,0)
frameTip.BackgroundTransparency = 1
frameTip.TextTransparency = 1
frameTip.TextWrap = true
local inside = Instance.new("BoolValue")
inside.Name = "inside"
inside.Value = false
inside.Parent = frameTip
function setUpListeners(frameToListen)
local fadeSpeed = 0.1
frameToListen.Parent.MouseEnter:connect(function()
if frameToListen:FindFirstChild("inside") then
frameToListen.inside.Value = true
wait(1.2)
if frameToListen.inside.Value then
while frameToListen.inside.Value and frameToListen.BackgroundTransparency > 0 do
frameToListen.BackgroundTransparency = frameToListen.BackgroundTransparency - fadeSpeed
frameToListen.TextTransparency = frameToListen.TextTransparency - fadeSpeed
wait()
end
end
end
end)
function killTip(killFrame)
killFrame.inside.Value = false
killFrame.BackgroundTransparency = 1
killFrame.TextTransparency = 1
end
frameToListen.Parent.MouseLeave:connect(function() killTip(frameToListen) end)
frameToListen.Parent.MouseButton1Click:connect(function() killTip(frameToListen) end)
end
function createSettingsButtonTip(parent)
if parent == nil then
parent = bottomLeftControl:FindFirstChild("SettingsButton")
end
local toolTip = frameTip:clone()
toolTip.RobloxLocked = true
toolTip.Text = "Settings/Leave Game"
toolTip.Position = UDim2.new(0,0,0,-18)
toolTip.Size = UDim2.new(0,120,0,20)
toolTip.Parent = parent
setUpListeners(toolTip)
end
wait(5) -- make sure we are loaded in, won't need tool tips for first 5 seconds anyway
---------------- set up Bottom Left Tool Tips -------------------------
local bottomLeftChildren = bottomLeftControl:GetChildren()
local hasSettingsTip = false
for i = 1, #bottomLeftChildren do
if bottomLeftChildren[i].Name == "Exit" then
local exitTip = frameTip:clone()
exitTip.RobloxLocked = true
exitTip.Text = "Leave Place"
exitTip.Position = UDim2.new(0,0,-1,0)
exitTip.Size = UDim2.new(1,0,1,0)
exitTip.Parent = bottomLeftChildren[i]
setUpListeners(exitTip)
elseif bottomLeftChildren[i].Name == "SettingsButton" then
hasSettingsTip = true
createSettingsButtonTip(bottomLeftChildren[i])
end
end
---------------- set up Bottom Right Tool Tips -------------------------
local bottomRightChildren = bottomRightControl:GetChildren()
for i = 1, #bottomRightChildren do
if bottomRightChildren[i].Name:find("Camera") ~= nil then
local cameraTip = frameTip:clone()
cameraTip.RobloxLocked = true
cameraTip.Text = "Camera View"
if bottomRightChildren[i].Name:find("Zoom") then
cameraTip.Position = UDim2.new(-1,0,-1.5)
else
cameraTip.Position = UDim2.new(0,0,-1.5,0)
end
cameraTip.Size = UDim2.new(2,0,1.25,0)
cameraTip.Parent = bottomRightChildren[i]
setUpListeners(cameraTip)
end
end
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,4 @@
settings().FastLogSettings.ViewRbxBase = true
settings().FastLogSettings.DeviceLost = true
settings().FastLogSettings.Network = true
settings().FastLogSettings.RenderBreakdown = true