mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-05 05:07:48 +00:00
GEEKING
This commit is contained in:
@@ -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("Dialog") 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("Dialog") 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
|
||||
Reference in New Issue
Block a user