This commit is contained in:
watrabi
2025-09-18 17:55:52 -04:00
commit 977f1ff4b8
15030 changed files with 17324420 additions and 0 deletions
@@ -0,0 +1,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,214 @@
-- 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
RotateToolID = 73089214
ConfigToolID = 73089239
WiringToolID = 73089259
classicToolID = 58921588
elseif BaseUrl:find("gametest2") then
DeleteToolID = 70353317
PartSelectionID = 70353315
CloneToolID = 70353314
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("RbxGuiThirteen")
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(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)
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,265 @@
--[[ SERVICES ]]
local GuiService = game:GetService('GuiService')
local CoreGuiService = game:GetService('CoreGui')
local InputService = game:GetService('UserInputService')
local ContextActionService = game:GetService('ContextActionService')
local StarterGui = game:GetService('StarterGui')
--[[ END OF SERVICES ]]
local GuiRoot = CoreGuiService:WaitForChild('RobloxGui')
local Util = {}
do
function Util.Create(instanceType)
return function(data)
local obj = Instance.new(instanceType)
for k, v in pairs(data) do
if type(k) == 'number' then
v.Parent = obj
else
obj[k] = v
end
end
return obj
end
end
end
local gamepadSettingsFrame = nil
local function createGamepadMenuGui()
gamepadSettingsFrame = Util.Create'Frame'{
Name = "GamepadSettingsFrame";
BorderSizePixel = 2;
Position = UDim2.new(0.5,0,0.5,0);
BackgroundTransparency = 1;
BorderSizePixel = 0;
Size = UDim2.new(0,1,0,1);
Visible = false;
Parent = GuiRoot;
}
local backpackGamepad = Util.Create'TextButton'{
Name = "Backpack";
Position = UDim2.new(0,100,0,-50);
Size = UDim2.new(0,100,0,100);
Font = Enum.Font.SourceSansBold;
FontSize = Enum.FontSize.Size24;
BackgroundColor3 = Color3.new(1,1,1);
Text = "Backpack";
Parent = gamepadSettingsFrame;
}
local settingsGamepad = Util.Create'TextButton'{
Name = "Settings";
Position = UDim2.new(0,-50,0,-200);
Size = UDim2.new(0,100,0,100);
Font = Enum.Font.SourceSansBold;
FontSize = Enum.FontSize.Size24;
BackgroundColor3 = Color3.new(1,1,1);
Text = "Settings";
Parent = gamepadSettingsFrame;
}
local playerListGamepad = Util.Create'TextButton'{
Name = "PlayerList";
Position = UDim2.new(0,-200,0,-50);
Size = UDim2.new(0,100,0,100);
Font = Enum.Font.SourceSansBold;
FontSize = Enum.FontSize.Size24;
BackgroundColor3 = Color3.new(1,1,1);
Text = "Player List";
Parent = gamepadSettingsFrame;
}
local chatGamepad = Util.Create'TextButton'{
Name = "Chat";
Position = UDim2.new(0,-50,0,100);
Size = UDim2.new(0,100,0,100);
Font = Enum.Font.SourceSansBold;
FontSize = Enum.FontSize.Size24;
BackgroundColor3 = Color3.new(1,1,1);
Text = "Chat";
Parent = gamepadSettingsFrame;
}
--todo: notications!
local closeHintImage = Util.Create'ImageLabel'{
Name = "CloseHint";
Position = UDim2.new(0,200,0,200);
Size = UDim2.new(0,40,0,40);
BackgroundTransparency = 1;
Image = "http://www.watrbx.wtf/asset?id=238273272";
Parent = gamepadSettingsFrame;
}
local closeHintText = Util.Create'TextLabel'{
Name = "closeHintText";
Position = UDim2.new(1,0,0,0);
Size = UDim2.new(0,80,0,40);
Font = Enum.Font.SourceSans;
FontSize = Enum.FontSize.Size18;
BackgroundTransparency = 1;
Text = " Close";
TextColor3 = Color3.new(1,1,1);
TextStrokeTransparency = 0;
TextXAlignment = Enum.TextXAlignment.Left;
Parent = closeHintImage;
}
game.GuiService:AddSelectionParent("CoreUIMainGroup", gamepadSettingsFrame)
settingsGamepad.MouseButton1Click:connect(function()
gamepadSettingsFrame.Visible = false
local MenuModule = require(game.CoreGui.RobloxGui.Modules.Settings2)
MenuModule:ToggleVisibility(true)
end)
backpackGamepad.MouseButton1Click:connect(function()
gamepadSettingsFrame.Visible = false
local BackpackModule = require(GuiRoot.Modules.BackpackScript)
BackpackModule:OpenClose()
end)
playerListGamepad.MouseButton1Click:connect(function()
gamepadSettingsFrame.Visible = false
local PlayerlistModule = require(GuiRoot.Modules.PlayerlistModule)
PlayerlistModule.ToggleVisibility()
end)
chatGamepad.MouseButton1Click:connect(function()
gamepadSettingsFrame.Visible = false
local ChatModule = require(GuiRoot.Modules.Chat)
ChatModule:ToggleVisibility()
end)
gamepadSettingsFrame.Changed:connect(function(prop)
if prop == "Visible" then
if not gamepadSettingsFrame.Visible then
unbindAllRadialActions()
end
end
end)
end
local function isCoreGuiDisabled()
for _, enumItem in pairs(Enum.CoreGuiType:GetEnumItems()) do
if StarterGui:GetCoreGuiEnabled(enumItem) then
return false
end
end
return true
end
local function setupGamepadControls()
local freezeControllerActionName = "doNothingAction"
local radialSelectActionName = "RadialSelectAction"
local radialCancelActionName = "RadialSelectCancel"
local noOptFunc = function() end
function unbindAllRadialActions()
ContextActionService:UnbindCoreAction(radialSelectActionName)
ContextActionService:UnbindCoreAction(radialCancelActionName)
ContextActionService:UnbindCoreAction(freezeControllerActionName)
end
local radialSelect = function(name, state, input)
local inputVector = Vector2.new(0,0)
if input.KeyCode == Enum.KeyCode.Thumbstick1 then
inputVector = Vector2.new(input.Position.x, -input.Position.y)
elseif state == Enum.UserInputState.Begin then
if input.KeyCode == Enum.KeyCode.DPadLeft then
inputVector = Vector2.new(-1,0)
elseif input.KeyCode == Enum.KeyCode.DPadRight then
inputVector = Vector2.new(1,0)
elseif input.KeyCode == Enum.KeyCode.DPadUp then
inputVector = Vector2.new(0,-1)
elseif input.KeyCode == Enum.KeyCode.DPadDown then
inputVector = Vector2.new(0,1)
end
end
local selectedObject = nil
-- get input direction gui
if inputVector.magnitude > 0.5 then
if math.abs(inputVector.x) > math.abs(inputVector.y) then
if inputVector.x < 0 then
selectedObject = gamepadSettingsFrame.PlayerList
else
selectedObject = gamepadSettingsFrame.Backpack
end
else
if inputVector.y < 0 then
selectedObject = gamepadSettingsFrame.Settings
else
selectedObject = gamepadSettingsFrame.Chat
end
end
GuiService.SelectedObject = selectedObject
end
end
local radialSelectCancel = function(name, state, input)
if state == Enum.UserInputState.Begin then
if gamepadSettingsFrame.Visible then
toggleCoreGuiRadial()
end
end
end
function toggleCoreGuiRadial()
gamepadSettingsFrame.Visible = not gamepadSettingsFrame.Visible
if gamepadSettingsFrame.Visible then
game.GuiService.SelectedObject = nil
ContextActionService:BindCoreAction(freezeControllerActionName, noOptFunc, false, Enum.KeyCode.Thumbstick2,
Enum.KeyCode.ButtonA,Enum.KeyCode.ButtonX, Enum.KeyCode.ButtonY, Enum.KeyCode.ButtonSelect,
Enum.KeyCode.ButtonL1, Enum.KeyCode.ButtonL2, Enum.KeyCode.ButtonL3,
Enum.KeyCode.ButtonR1, Enum.KeyCode.ButtonR2, Enum.KeyCode.ButtonR3)
ContextActionService:BindCoreAction(radialCancelActionName, radialSelectCancel, false, Enum.KeyCode.ButtonB)
ContextActionService:BindCoreAction(radialSelectActionName, radialSelect, false, Enum.KeyCode.Thumbstick1,
Enum.KeyCode.DPadLeft, Enum.KeyCode.DPadRight, Enum.KeyCode.DPadUp, Enum.KeyCode.DPadDown)
else
unbindAllRadialActions()
end
return gamepadSettingsFrame.Visible
end
local doGamepadMenuButton = function(name, state, input)
if input.UserInputType ~= Enum.UserInputType.Gamepad1 then return end
if state ~= Enum.UserInputState.Begin then return end
ContextActionService:BindCoreAction(freezeControllerActionName, noOptFunc, false, Enum.KeyCode.Thumbstick1, Enum.KeyCode.Thumbstick2,
Enum.KeyCode.ButtonA, Enum.KeyCode.ButtonB, Enum.KeyCode.ButtonX, Enum.KeyCode.ButtonY, Enum.KeyCode.ButtonSelect,
Enum.KeyCode.ButtonL1, Enum.KeyCode.ButtonL2, Enum.KeyCode.ButtonL3, Enum.KeyCode.ButtonR1, Enum.KeyCode.ButtonR2, Enum.KeyCode.ButtonR3,
Enum.KeyCode.DPadLeft, Enum.KeyCode.DPadRight, Enum.KeyCode.DPadUp, Enum.KeyCode.DPadDown)
if isCoreGuiDisabled() then
local shouldKillGamepadInput = toggleSettings()
if not shouldKillGamepadInput then
unbindAllRadialActions()
end
else
local radialIsShown = toggleCoreGuiRadial()
if not radialIsShown then
unbindAllRadialActions()
end
end
end
if InputService:GetGamepadConnected(Enum.UserInputType.Gamepad1) then
createGamepadMenuGui()
else
InputService.GamepadConnected:connect(function(gamepadEnum)
if gamepadEnum == Enum.UserInputType.Gamepad1 then
createGamepadMenuGui()
end
end)
end
ContextActionService:BindCoreAction("RBXToggleMenuAction", doGamepadMenuButton, false, Enum.KeyCode.ButtonStart)
end
-- hook up gamepad stuff
setupGamepadControls()
@@ -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,668 @@
-- 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 startTime = tick()
local COLORS = {
BLACK = Color3.new(0, 0, 0),
WHITE = Color3.new(1, 1, 1),
ERROR = Color3.new(253/255,68/255,72/255)
}
local function countBricks()
local count = 0
local children = game.Workspace:GetChildren()
for _, child in ipairs(children) do
wait()
if child:IsA("BasePart") then
count = count + 1
end
count = count + countBricks(child)
end
return count
end
local function countInstances()
local count = 1
local children = game.Workspace: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()
local count = 0
local children = game.Workspace:GetChildren()
for _, child in ipairs(children) do
if connectorTypes[child.ClassName] then
count = count + 1
end
count = count + countConnectors(child)
end
return count
end
--
-- Variables
local GameAssetInfo -- loaded by InfoProvider:LoadAssets()
local currScreenGui = nil
local renderSteppedConnection = nil
local fadingBackground = false
local destroyedLoadingGui = false
local hasReplicatedFirstElements = false
-- Fast Flags
local topbarSuccess, topbarFlagValue = pcall(function() return settings():GetFFlag("UseInGameTopBar") end)
local useTopBar = (topbarSuccess and topbarFlagValue == true)
local bgFrameOffset = useTopBar and 36 or 20
local offsetPosition = useTopBar and UDim2.new(0, 0, 0, -36) or UDim2.new(0, 0, 0, 0)
--
-- 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
-- load game asset info
coroutine.resume(coroutine.create(function()
local success, result = pcall(function()
GameAssetInfo = MPS:GetProductInfo(PLACEID)
end)
if not success then
print("LoadingScript->InfoProvider:LoadAssets:", result)
end
end))
end)
end
--
-- Declare member functions
function MainGui:GenerateMain()
local screenGui = create 'ScreenGui' {
Name = 'RobloxLoadingGui'
}
--
-- create descendant frames
local mainBackgroundContainer = create 'Frame' {
Name = 'BlackFrame',
BackgroundColor3 = COLORS.BLACK,
Size = UDim2.new(1, 0, 1, bgFrameOffset),
Position = offsetPosition,
Active = true,
create 'ImageButton' {
Name = 'CloseButton',
Image = 'rbxasset://textures/ui/CloseButton_dn.png',
ImageColor3=Color3.new(0.9,0.9,0.9),
ImageTransparency = 1,
BackgroundTransparency = 1,
Position = UDim2.new(1, -37, 0, 5),
Size = UDim2.new(0, 32, 0, 32),
Active = false,
ZIndex = 10
},
create 'Frame' {
Name = 'GraphicsFrame',
BorderSizePixel = 0,
BackgroundTransparency = 1,
Position = UDim2.new(1, -125, 1, -125),
Size = UDim2.new(0, 120, 0, 120),
ZIndex = 2,
create 'ImageLabel' {
Name = 'LoadingImage',
BackgroundTransparency = 1,
Image = 'rbxasset://textures/Roblox-loading-glow.png',
Position = UDim2.new(0, 0, 0, 0),
Size = UDim2.new(1, 0, 1, 0),
ZIndex = 2
},
create 'ImageLabel' {
Name = 'LogoImage',
BackgroundTransparency = 1,
Image = 'rbxasset://textures/Roblox-loading.png',
Position = UDim2.new(0.125, 0, 0.125, 0),
Size = UDim2.new(0.75, 0, 0.75, 0),
ZIndex = 2
}
},
create 'Frame' {
Name = 'UiMessageFrame',
BackgroundTransparency = 1,
Position = UDim2.new(0.25, 0, 1, -120),
Size = UDim2.new(0.5, 0, 0, 80),
ZIndex = 2,
create 'TextLabel' {
Name = 'UiMessage',
BackgroundTransparency = 1,
Size = UDim2.new(1, 0, 1, 0),
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size18,
TextWrapped = true,
TextColor3 = COLORS.WHITE,
Text = "",
ZIndex = 2
},
},
create 'Frame' {
Name = 'CountFrame',
BackgroundTransparency = 1,
Position = UDim2.new(0, 0, 1, -120),
Size = UDim2.new(0.3, 0, 0, 120),
ZIndex = 2,
create 'TextLabel' {
Name = 'PlaceLabel',
BackgroundTransparency = 1,
Size = UDim2.new(1, -5, 0, 18),
Position = UDim2.new(0, 5, 0, 0),
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size14,
TextWrapped = true,
TextScaled = true,
TextColor3 = COLORS.WHITE,
TextStrokeTransparency = 0,
Text = "",
TextXAlignment = Enum.TextXAlignment.Left,
ZIndex = 2
},
create 'TextLabel' {
Name = 'CreatorLabel',
BackgroundTransparency = 1,
Position = UDim2.new(0,5,0,18),
Size = UDim2.new(1, -5, 0, 18),
Font = Enum.Font.SourceSans,
FontSize = Enum.FontSize.Size12,
TextWrapped = true,
TextScaled = true,
TextColor3 = COLORS.WHITE,
TextStrokeTransparency = 0,
Text = "",
TextXAlignment = Enum.TextXAlignment.Left,
ZIndex = 2
},
create 'TextLabel' {
Name = 'BrickLabel',
BackgroundTransparency = 1,
Position = UDim2.new(0, 5, 0, 63),
Size = UDim2.new(0, 85, 0, 18),
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size18,
TextScaled = true,
TextColor3 = COLORS.WHITE,
TextStrokeTransparency = 0,
Text = "Bricks:",
TextXAlignment = Enum.TextXAlignment.Right,
ZIndex = 2
},
create 'TextLabel' {
Name = 'ConnectorLabel',
BackgroundTransparency = 1,
Position = UDim2.new(0, 5, 0, 81),
Size = UDim2.new(0, 85, 0, 18),
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size18,
TextScaled = true,
TextColor3 = COLORS.WHITE,
TextStrokeTransparency = 0,
Text = "Connectors:",
TextXAlignment = Enum.TextXAlignment.Right,
ZIndex = 2
},
create 'TextLabel' {
Name = 'InstanceLabel',
BackgroundTransparency = 1,
Position = UDim2.new(0, 5, 0, 45),
Size = UDim2.new(0, 85, 0, 18),
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size18,
TextScaled = true,
TextColor3 = COLORS.WHITE,
TextStrokeTransparency = 0,
Text = "Instances:",
TextXAlignment = Enum.TextXAlignment.Right,
ZIndex = 2
},
create 'TextLabel' {
Name = 'VoxelLabel',
BackgroundTransparency = 1,
Position = UDim2.new(0, 5, 0, 99),
Size = UDim2.new(0, 85, 0, 18),
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size18,
TextScaled = true,
TextColor3 = COLORS.WHITE,
TextStrokeTransparency = 0,
Text = "Voxels:",
TextXAlignment = Enum.TextXAlignment.Right,
ZIndex = 2
},
create 'TextLabel' {
Name = 'BrickCount',
BackgroundTransparency = 1,
Position = UDim2.new(0, 95, 0, 63),
Size = UDim2.new(0.5, -5, 0, 18),
Font = Enum.Font.SourceSans,
FontSize = Enum.FontSize.Size18,
TextScaled = true,
TextColor3 = COLORS.WHITE,
TextStrokeTransparency = 0,
Text = "",
TextXAlignment = Enum.TextXAlignment.Left,
ZIndex = 2
},
create 'TextLabel' {
Name = 'ConnectorCount',
BackgroundTransparency = 1,
Position = UDim2.new(0, 95, 0, 81),
Size = UDim2.new(0.5, -5, 0, 18),
Font = Enum.Font.SourceSans,
FontSize = Enum.FontSize.Size18,
TextScaled = true,
TextColor3 = COLORS.WHITE,
TextStrokeTransparency = 0,
Text = "",
TextXAlignment = Enum.TextXAlignment.Left,
ZIndex = 2
},
create 'TextLabel' {
Name = 'InstanceCount',
BackgroundTransparency = 1,
Position = UDim2.new(0, 95, 0, 45),
Size = UDim2.new(0.5, -5, 0, 18),
Font = Enum.Font.SourceSans,
FontSize = Enum.FontSize.Size18,
TextScaled = true,
TextColor3 = COLORS.WHITE,
TextStrokeTransparency = 0,
Text = "",
TextXAlignment = Enum.TextXAlignment.Left,
ZIndex = 2
},
create 'TextLabel' {
Name = 'VoxelCount',
BackgroundTransparency = 1,
Position = UDim2.new(0, 95, 0, 99),
Size = UDim2.new(0.5, -5, 0, 18),
Font = Enum.Font.SourceSans,
FontSize = Enum.FontSize.Size18,
TextScaled = true,
TextColor3 = COLORS.WHITE,
TextStrokeTransparency = 0,
Text = "",
TextXAlignment = Enum.TextXAlignment.Left,
ZIndex = 2
},
},
Parent = screenGui
}
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 = 8,
Visible = false,
create 'TextLabel' {
Name = "ErrorText",
BackgroundTransparency = 1,
Size = UDim2.new(1, 0, 1, 0),
Font = Enum.Font.SourceSansBold,
FontSize = Enum.FontSize.Size14,
TextWrapped = true,
TextColor3 = COLORS.WHITE,
Text = "",
ZIndex = 8
},
Parent = screenGui
}
while not Game:GetService("CoreGui") do
wait()
end
screenGui.Parent = Game:GetService("CoreGui")
currScreenGui = screenGui
end
function round(num, idp)
local mult = 10^(idp or 0)
return math.floor(num * mult + 0.5) / mult
end
---------------------------------------------------------
-- Main Script (show something now + setup connections)
-- start loading assets asap
InfoProvider:LoadAssets()
MainGui:GenerateMain()
local guiService = Game:GetService("GuiService")
local removedLoadingScreen = false
local instanceCount = 0
local voxelCount = 0
local brickCount = 0
local connectorCount = 0
local setVerb = true
local fadeDown = true
local lastRenderTime = nil
local fadeCycleTime = 1.7
renderSteppedConnection = Game:GetService("RunService").RenderStepped:connect(function()
if not currScreenGui then return end
if not currScreenGui:FindFirstChild("BlackFrame") then return end
if setVerb then
currScreenGui.BlackFrame.CloseButton:SetVerb("Exit")
setVerb = false
end
if currScreenGui.BlackFrame.CountFrame.PlaceLabel.Text == "" then
currScreenGui.BlackFrame.CountFrame.PlaceLabel.Text = InfoProvider:GetGameName()
end
if currScreenGui.BlackFrame.CountFrame.CreatorLabel.Text == "" then
local creatorName = InfoProvider:GetCreatorName()
if creatorName ~= "" then
currScreenGui.BlackFrame.CountFrame.CreatorLabel.Text = "By " .. creatorName
end
end
wait(0.1)
instanceCount = countInstances() --guiService:GetInstanceCount()
voxelCount = 0 --guiService:GetVoxelCount()
brickCount = countBricks()
connectorCount = countConnectors() --guiService:GetConnectorCount()
currScreenGui.BlackFrame.CountFrame.InstanceCount.Text = tostring(instanceCount)
currScreenGui.BlackFrame.CountFrame.BrickCount.Text = tostring(brickCount)
currScreenGui.BlackFrame.CountFrame.ConnectorCount.Text = tostring(connectorCount)
if voxelCount <= 0 then
currScreenGui.BlackFrame.CountFrame.VoxelCount.Text = "0"
else
currScreenGui.BlackFrame.CountFrame.VoxelCount.Text = tostring(round(voxelCount,4)) .." million"
end
if not lastRenderTime then
lastRenderTime = tick()
return
end
local currentTime = tick()
local fadeAmount = (currentTime - lastRenderTime) * fadeCycleTime
lastRenderTime = currentTime
if fadeDown then
currScreenGui.BlackFrame.GraphicsFrame.LoadingImage.ImageTransparency = currScreenGui.BlackFrame.GraphicsFrame.LoadingImage.ImageTransparency - fadeAmount
if currScreenGui.BlackFrame.GraphicsFrame.LoadingImage.ImageTransparency <= 0 then
fadeDown = false
end
else
currScreenGui.BlackFrame.GraphicsFrame.LoadingImage.ImageTransparency = currScreenGui.BlackFrame.GraphicsFrame.LoadingImage.ImageTransparency + fadeAmount
if currScreenGui.BlackFrame.GraphicsFrame.LoadingImage.ImageTransparency >= 1 then
fadeDown = true
end
end
-- fade in close button after 5 seconds
if currentTime - startTime > 5 and currScreenGui.BlackFrame.CloseButton.ImageTransparency > 0 then
currScreenGui.BlackFrame.CloseButton.ImageTransparency = currScreenGui.BlackFrame.CloseButton.ImageTransparency - fadeAmount
if currScreenGui.BlackFrame.CloseButton.ImageTransparency <= 0 then
currScreenGui.BlackFrame.CloseButton.Active = true
end
end
end)
guiService.ErrorMessageChanged:connect(function()
if guiService:GetErrorMessage() ~= '' then
currScreenGui.ErrorFrame.ErrorText.Text = guiService:GetErrorMessage()
currScreenGui.ErrorFrame.Visible = true
local blackFrame = currScreenGui:FindFirstChild('BlackFrame')
if blackFrame then
blackFrame.CloseButton.ImageTransparency = 0
blackFrame.CloseButton.Active = true
end
else
currScreenGui.ErrorFrame.Visible = false
end
end)
guiService.UiMessageChanged:connect(function(type, newMessage)
if type == Enum.UiMessageType.UiMessageInfo then
local blackFrame = currScreenGui and currScreenGui:FindFirstChild('BlackFrame')
if blackFrame then
blackFrame.UiMessageFrame.UiMessage.Text = newMessage
if newMessage ~= '' then
blackFrame.UiMessageFrame.Visible = true
else
blackFrame.UiMessageFrame.Visible = false
end
end
end
end)
if guiService:GetErrorMessage() ~= '' then
currScreenGui.ErrorFrame.ErrorText.Text = guiService:GetErrorMessage()
currScreenGui.ErrorFrame.Visible = true
end
function stopListeningToRenderingStep()
if renderSteppedConnection then
renderSteppedConnection:disconnect()
renderSteppedConnection = nil
end
end
function fadeBackground()
if not currScreenGui then return end
if fadingBackground then return end
if not currScreenGui:findFirstChild("BlackFrame") then return end
fadingBackground = true
local lastTime = nil
local backgroundRemovalTime = 3.2
while currScreenGui and currScreenGui.BlackFrame and currScreenGui.BlackFrame.BackgroundTransparency < 1 do
if lastTime == nil then
currScreenGui.BlackFrame.Active = false
lastTime = tick()
else
local currentTime = tick()
local fadeAmount = (currentTime - lastTime) * backgroundRemovalTime
lastTime = currentTime
currScreenGui.BlackFrame.BackgroundTransparency = currScreenGui.BlackFrame.BackgroundTransparency + fadeAmount
end
wait()
end
end
function fadeAndDestroyBlackFrame(blackFrame)
Spawn(function()
local countFrame = blackFrame:FindFirstChild("CountFrame")
local graphicsFrame = blackFrame:FindFirstChild("GraphicsFrame")
local textChildren = countFrame:GetChildren()
local transparency = 0
local rateChange = 1.8
local lastUpdateTime = nil
while transparency < 1 do
if not lastUpdateTime then
lastUpdateTime = tick()
else
local newTime = tick()
transparency = transparency + rateChange * (newTime - lastUpdateTime)
for i =1, #textChildren do
textChildren[i].TextTransparency = transparency
textChildren[i].TextStrokeTransparency = transparency
end
graphicsFrame.LoadingImage.ImageTransparency = transparency
graphicsFrame.LogoImage.ImageTransparency = transparency
lastUpdateTime = newTime
end
wait()
end
blackFrame:Destroy()
end)
end
function destroyLoadingElements()
if not currScreenGui then return end
if destroyedLoadingGui then return end
destroyedLoadingGui = true
local guiChildren = currScreenGui:GetChildren()
for i=1, #guiChildren do
-- need to keep this around in case we get a connection error later
if guiChildren[i].Name ~= "ErrorFrame" then
if guiChildren[i].Name == "BlackFrame" then
fadeAndDestroyBlackFrame(guiChildren[i])
else
guiChildren[i]:Destroy()
end
end
end
end
function handleFinishedReplicating()
hasReplicatedFirstElements = (#Game:GetService("ReplicatedFirst"):GetChildren() > 0)
if not hasReplicatedFirstElements then
fadeBackground()
else
wait(20) -- make sure after 20 seconds we remove the default gui, even if the user doesn't
handleRemoveDefaultLoadingGui()
end
end
function handleRemoveDefaultLoadingGui()
fadeBackground()
destroyLoadingElements()
end
function handleGameLoaded()
if not hasReplicatedFirstElements then
destroyLoadingElements()
end
end
Game:GetService("ReplicatedFirst").FinishedReplicating:connect(handleFinishedReplicating)
if Game:GetService("ReplicatedFirst"):IsFinishedReplicating() then
handleFinishedReplicating()
end
Game:GetService("ReplicatedFirst").RemoveDefaultLoadingGuiSignal:connect(handleRemoveDefaultLoadingGui)
if Game:GetService("ReplicatedFirst"):IsDefaultLoadingGuiRemoved() then
handleRemoveDefaultLoadingGui()
return
end
Game.Loaded:connect(handleGameLoaded)
if Game:IsLoaded() then
handleGameLoaded()
end
@@ -0,0 +1,565 @@
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
local touchEnabled = game:GetService("UserInputService").TouchEnabled
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,1.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
if (touchEnabled) then
frame.Position = UDim2.new(0,20,0.5,0)
frame.Size = UDim2.new(0.25,0,0.1,0)
frame.Parent = gui
else
frame.Parent = gui.BottomLeftControl
end
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,533 @@
local PURPOSE_DATA = {
[Enum.DialogPurpose.Quest] = {"rbxasset://textures/ui/dialog_purpose_quest.png", Vector2.new(6, 22)},
[Enum.DialogPurpose.Help] = {"rbxasset://textures/ui/dialog_purpose_help.png", Vector2.new(12, 22)},
[Enum.DialogPurpose.Shop] = {"rbxasset://textures/ui/dialog_purpose_shop.png", Vector2.new(14, 27)},
}
local TEXT_HEIGHT = 24 -- Pixel height of one row
local BAR_THICKNESS = 6
local STYLE_PADDING = 17
local CHOICE_PADDING = 6 * 2 -- (Added to vertical height)
local PROMPT_SIZE = Vector2.new(80, 90)
local WIDTH_BONUS = (STYLE_PADDING * 2) - BAR_THICKNESS
local XPOS_OFFSET = -(STYLE_PADDING - BAR_THICKNESS)
local YPOS_OFFSET = -math.floor(STYLE_PADDING / 2)
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
local touchEnabled = game:GetService("UserInputService").TouchEnabled
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(PROMPT_SIZE.X / 31.5, 0, PROMPT_SIZE.Y / 31.5, 0)
chatNotificationGui.SizeOffset = Vector2.new(0,0)
chatNotificationGui.StudsOffset = Vector3.new(0, 3.7, 0)
chatNotificationGui.Enabled = true
chatNotificationGui.RobloxLocked = true
chatNotificationGui.Active = true
local button = Instance.new("ImageButton")
button.Name = "Background"
button.Active = false
button.BackgroundTransparency = 1
button.Position = UDim2.new(0, 0, 0, 0)
button.Size = UDim2.new(1, 0, 1, 0)
button.Image = ""
button.RobloxLocked = true
button.Parent = chatNotificationGui
local icon = Instance.new("ImageLabel")
icon.Name = "Icon"
icon.Position = UDim2.new(0, 0, 0, 0)
icon.Size = UDim2.new(1, 0, 1, 0)
icon.Image = ""
icon.BackgroundTransparency = 1
icon.RobloxLocked = true
icon.Parent = button
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()
for _, obj in pairs(choices) do
obj.BackgroundTransparency = 1
end
lastChoice.BackgroundTransparency = 1
end
function styleMainFrame(tone)
if tone == Enum.DialogTone.Neutral then
mainFrame.Style = Enum.FrameStyle.ChatBlue
elseif tone == Enum.DialogTone.Friendly then
mainFrame.Style = Enum.FrameStyle.ChatGreen
elseif tone == Enum.DialogTone.Enemy then
mainFrame.Style = Enum.FrameStyle.ChatRed
end
styleChoices()
end
function setChatNotificationTone(gui, purpose, tone)
if tone == Enum.DialogTone.Neutral then
gui.Background.Image = "rbxasset://textures/ui/chatBubble_blue_notify_bkg.png"
elseif tone == Enum.DialogTone.Friendly then
gui.Background.Image = "rbxasset://textures/ui/chatBubble_green_notify_bkg.png"
elseif tone == Enum.DialogTone.Enemy then
gui.Background.Image = "rbxasset://textures/ui/chatBubble_red_notify_bkg.png"
end
local newIcon, size = unpack(PURPOSE_DATA[purpose])
local relativeSize = size / PROMPT_SIZE
gui.Background.Icon.Size = UDim2.new(relativeSize.X, 0, relativeSize.Y, 0)
gui.Background.Icon.Position = UDim2.new(0.5 - (relativeSize.X / 2), 0, 0.4 - (relativeSize.Y / 2), 0)
gui.Background.Icon.Image = newIcon
end
function createMessageDialog()
messageDialog = Instance.new("Frame");
messageDialog.Name = "DialogScriptMessage"
messageDialog.Style = Enum.FrameStyle.Custom
messageDialog.BackgroundTransparency = 0.5
messageDialog.BackgroundColor3 = Color3.new(31/255, 31/255, 31/255)
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)
frame.BackgroundTransparency = 1
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()
local frame = Instance.new("TextButton")
frame.BackgroundColor3 = Color3.new(227/255, 227/255, 227/255)
frame.BackgroundTransparency = 1
frame.AutoButtonColor = false
frame.BorderSizePixel = 0
frame.Text = ""
frame.MouseEnter:connect(function() frame.BackgroundTransparency = 0 end)
frame.MouseLeave:connect(function() frame.BackgroundTransparency = 1 end)
frame.MouseButton1Click:connect(function() selectChoice(frame) end)
frame.RobloxLocked = true
local prompt = Instance.new("TextLabel")
prompt.Name = "UserPrompt"
prompt.BackgroundTransparency = 1
prompt.Font = Enum.Font.SourceSans
prompt.FontSize = Enum.FontSize.Size24
prompt.Position = UDim2.new(0, 28, 0, 0)
prompt.Size = UDim2.new(1, -32-28, 1, 0)
prompt.TextXAlignment = Enum.TextXAlignment.Left
prompt.TextYAlignment = Enum.TextYAlignment.Center
prompt.TextWrap = true
prompt.RobloxLocked = true
prompt.Parent = frame
return frame
end
function initialize(parent)
choices[1] = newChoice()
choices[2] = newChoice()
choices[3] = newChoice()
choices[4] = newChoice()
lastChoice = newChoice()
lastChoice.UserPrompt.Text = "Goodbye!"
lastChoice.Size = UDim2.new(1, WIDTH_BONUS, 0, TEXT_HEIGHT + CHOICE_PADDING)
mainFrame = Instance.new("Frame")
mainFrame.Name = "UserDialogArea"
mainFrame.Size = UDim2.new(0, 350, 0, 200)
mainFrame.Style = Enum.FrameStyle.ChatBlue
mainFrame.Visible = false
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, WIDTH_BONUS, 0, TEXT_HEIGHT * 3)
choices[pos].UserPrompt.Text = obj.UserDialog
local height = (math.ceil(choices[pos].UserPrompt.TextBounds.Y / TEXT_HEIGHT) * TEXT_HEIGHT) + CHOICE_PADDING
choices[pos].Position = UDim2.new(0, XPOS_OFFSET, 0, YPOS_OFFSET + yPosition)
choices[pos].Size = UDim2.new(1, WIDTH_BONUS, 0, height)
choices[pos].Visible = true
choiceMap[choices[pos]] = obj
yPosition = yPosition + height + 1 -- The +1 makes highlights not overlap
pos = pos + 1
end
end
lastChoice.Position = UDim2.new(0, XPOS_OFFSET, 0, YPOS_OFFSET + yPosition)
mainFrame.Size = UDim2.new(0, 350, 0, yPosition + lastChoice.AbsoluteSize.Y + (STYLE_PADDING * 2) + (YPOS_OFFSET * 2))
mainFrame.Position = UDim2.new(0,20,1.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.Background.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
if (touchEnabled) then
frame.Position = UDim2.new(0,20,0.5,0)
frame.Size = UDim2.new(0.25,0,0.1,0)
frame.Parent = gui
else
frame.Parent = gui.BottomLeftControl
end
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,474 @@
--[[
Filename: NotificationScript2.lua
Version 1.1
Written by: jmargh
Description: Handles notification gui for the following in game ROBLOX events
Badge Awarded
Player Points Awarded
Friend Request Recieved/New Friend
Graphics Quality Changed
Teleports
CreatePlaceInPlayerInventoryAsync
--]]
--[[ Services ]]--
local BadgeService = game:GetService('BadgeService')
local GuiService = game:GetService('GuiService')
local Players = game:GetService('Players')
local PointsService = game:GetService('PointsService')
local MarketplaceService = game:GetService('MarketplaceService')
local TeleportService = game:GetService('TeleportService')
local Settings = UserSettings()
local GameSettings = Settings.GameSettings
--[[ Script Variables ]]--
local LocalPlayer = nil
while not Players.LocalPlayer do
wait()
end
LocalPlayer = Players.LocalPlayer
local RbxGui = script.Parent
local NotificationQueue = {}
local OverflowQueue = {}
local FriendRequestBlacklist = {}
local CurrentGraphicsQualityLevel = GameSettings.SavedQualityLevel.Value
local BindableEvent_SendNotification = Instance.new('BindableFunction')
BindableEvent_SendNotification.Name = "SendNotification"
BindableEvent_SendNotification.Parent = RbxGui
--[[ Constants ]]--
local BG_TRANSPARENCY = 0.7
local MAX_NOTIFICATIONS = 3
local NOTIFICATION_Y_OFFSET = 64
local IMAGE_SIZE = 48
local EASE_DIR = Enum.EasingDirection.InOut
local EASE_STYLE = Enum.EasingStyle.Sine
local TWEEN_TIME = 0.35
local DEFAULT_NOTIFICATION_DURATION = 5
--[[ Images ]]--
local PLAYER_POINTS_IMG = 'http://www.watrbx.wtf/asset?id=206410433'
local BADGE_IMG = 'http://www.watrbx.wtf/asset?id=206410289'
local FRIEND_IMAGE = 'http://www.watrbx.wtf/thumbs/avatar.ashx?userId='
--[[ Gui Creation ]]--
local function createFrame(name, size, position, bgt)
local frame = Instance.new('Frame')
frame.Name = name
frame.Size = size
frame.Position = position
frame.BackgroundTransparency = bgt
return frame
end
local function createTextButton(name, text, position)
local button = Instance.new('TextButton')
button.Name = name
button.Size = UDim2.new(0.5, -2, 0.5, 0)
button.Position = position
button.BackgroundTransparency = BG_TRANSPARENCY
button.BackgroundColor3 = Color3.new(0, 0, 0)
button.Font = Enum.Font.SourceSansBold
button.FontSize = Enum.FontSize.Size18
button.TextColor3 = Color3.new(1, 1, 1)
button.Text = text
return button
end
local NotificationFrame = createFrame("NotificationFrame", UDim2.new(0, 200, 0.42, 0), UDim2.new(1, -204, 0.50, 0), 1)
NotificationFrame.Parent = RbxGui
local DefaultNotifcation = createFrame("Notifcation", UDim2.new(1, 0, 0, NOTIFICATION_Y_OFFSET), UDim2.new(0, 0, 0, 0), BG_TRANSPARENCY)
DefaultNotifcation.BackgroundColor3 = Color3.new(0, 0, 0)
DefaultNotifcation.BorderSizePixel = 0
local NotificationTitle = Instance.new('TextLabel')
NotificationTitle.Name = "NotificationTitle"
NotificationTitle.Size = UDim2.new(0, 0, 0, 0)
NotificationTitle.Position = UDim2.new(0.5, 0, 0.5, -12)
NotificationTitle.BackgroundTransparency = 1
NotificationTitle.Font = Enum.Font.SourceSansBold
NotificationTitle.FontSize = Enum.FontSize.Size18
NotificationTitle.TextColor3 = Color3.new(0.97, 0.97, 0.97)
local NotificationText = Instance.new('TextLabel')
NotificationText.Name = "NotificationText"
NotificationText.Size = UDim2.new(1, -20, 0, 28)
NotificationText.Position = UDim2.new(0, 10, 0.5, 1)
NotificationText.BackgroundTransparency = 1
NotificationText.Font = Enum.Font.SourceSans
NotificationText.FontSize = Enum.FontSize.Size14
NotificationText.TextColor3 = Color3.new(0.92, 0.92, 0.92)
NotificationText.TextWrap = true
NotificationText.TextYAlignment = Enum.TextYAlignment.Top
local NotificationImage = Instance.new('ImageLabel')
NotificationImage.Name = "NotificationImage"
NotificationImage.Size = UDim2.new(0, IMAGE_SIZE, 0, IMAGE_SIZE)
NotificationImage.Position = UDim2.new(0, 8, 0.5, -24)
NotificationImage.BackgroundTransparency = 1
NotificationImage.Image = ""
-- Would really like to get rid of this but some events still require this
local PopupFrame = createFrame("PopupFrame", UDim2.new(0, 360, 0, 160), UDim2.new(0.5, -180, 0.5, -50), 0)
PopupFrame.Style = Enum.FrameStyle.DropShadow
PopupFrame.ZIndex = 4
PopupFrame.Visible = false
PopupFrame.Parent = RbxGui
local PopupAcceptButton = Instance.new('TextButton')
PopupAcceptButton.Name = "PopupAcceptButton"
PopupAcceptButton.Size = UDim2.new(0, 100, 0, 50)
PopupAcceptButton.Position = UDim2.new(0.5, -102, 1, -58)
PopupAcceptButton.Style = Enum.ButtonStyle.RobloxRoundButton
PopupAcceptButton.Font = Enum.Font.SourceSansBold
PopupAcceptButton.FontSize = Enum.FontSize.Size24
PopupAcceptButton.TextColor3 = Color3.new(1, 1, 1)
PopupAcceptButton.Text = "Accept"
PopupAcceptButton.ZIndex = 5
PopupAcceptButton.Parent = PopupFrame
local PopupDeclineButton = PopupAcceptButton:Clone()
PopupDeclineButton.Name = "PopupDeclineButton"
PopupDeclineButton.Position = UDim2.new(0.5, 2, 1, -58)
PopupDeclineButton.Text = "Decline"
PopupDeclineButton.Parent = PopupFrame
local PopupOKButton = PopupAcceptButton:Clone()
PopupOKButton.Name = "PopupOKButton"
PopupOKButton.Position = UDim2.new(0.5, -50, 1, -58)
PopupOKButton.Text = "OK"
PopupOKButton.Visible = false
PopupOKButton.Parent = PopupFrame
local PopupText = Instance.new('TextLabel')
PopupText.Name = "PopupText"
PopupText.Size = UDim2.new(1, -16, 0.8, 0)
PopupText.Position = UDim2.new(0, 8, 0, 8)
PopupText.BackgroundTransparency = 1
PopupText.Font = Enum.Font.SourceSansBold
PopupText.FontSize = Enum.FontSize.Size36
PopupText.TextColor3 = Color3.new(0.97, 0.97, 0.97)
PopupText.TextWrap = true
PopupText.ZIndex = 5
PopupText.TextYAlignment = Enum.TextYAlignment.Top
PopupText.Text = "This is a popup"
PopupText.Parent = PopupFrame
--[[ Helper Functions ]]--
local insertNotifcation = nil
local removeNotification = nil
--
local function createNotification(title, text, image)
local notificationFrame = DefaultNotifcation:Clone()
notificationFrame.Position = UDim2.new(1, 4, 1, -NOTIFICATION_Y_OFFSET - 4)
--
local notificationTitle = NotificationTitle:Clone()
notificationTitle.Text = title
notificationTitle.Parent = notificationFrame
local notificationText = NotificationText:Clone()
notificationText.Text = text
notificationText.Parent = notificationFrame
if image and image ~= "" then
local notificationImage = NotificationImage:Clone()
notificationImage.Image = image
notificationImage.Parent = notificationFrame
--
notificationTitle.Position = UDim2.new(0, NotificationImage.Size.X.Offset + 16, 0.5, -12)
notificationTitle.TextXAlignment = Enum.TextXAlignment.Left
--
notificationText.Size = UDim2.new(1, -IMAGE_SIZE - 16, 0, 28)
notificationText.Position = UDim2.new(0, IMAGE_SIZE + 16, 0.5, 1)
notificationText.TextXAlignment = Enum.TextXAlignment.Left
end
return notificationFrame
end
local function findNotification(notification)
local index = nil
for i = 1, #NotificationQueue do
if NotificationQueue[i] == notification then
return i
end
end
end
local function updateNotifications()
local pos = 1
local yOffset = 0
for i = #NotificationQueue, 1, -1 do
local currentNotification = NotificationQueue[i]
if currentNotification then
local frame = currentNotification.Frame
if frame and frame.Parent then
local thisOffset = currentNotification.IsFriend and (NOTIFICATION_Y_OFFSET + 2) * 1.5 or NOTIFICATION_Y_OFFSET
yOffset = yOffset + thisOffset
frame:TweenPosition(UDim2.new(0, 0, 1, -yOffset - (pos * 4)), EASE_DIR, EASE_STYLE, TWEEN_TIME, true)
pos = pos + 1
end
end
end
end
local lastTimeInserted = 0
insertNotifcation = function(notification)
notification.IsActive = true
local size = #NotificationQueue
if size == MAX_NOTIFICATIONS then
OverflowQueue[#OverflowQueue + 1] = notification
return
end
--
NotificationQueue[size + 1] = notification
notification.Frame.Parent = NotificationFrame
delay(notification.Duration, function()
removeNotification(notification)
end)
while tick() - lastTimeInserted < TWEEN_TIME do
wait()
end
lastTimeInserted = tick()
--
updateNotifications()
end
removeNotification = function(notification)
if not notification then return end
--
local index = findNotification(notification)
table.remove(NotificationQueue, index)
local frame = notification.Frame
if frame and frame.Parent then
notification.IsActive = false
frame:TweenPosition(UDim2.new(1, 0, 1, frame.Position.Y.Offset), EASE_DIR, EASE_STYLE, TWEEN_TIME, true,
function()
frame:Destroy()
notification = nil
end)
end
if #OverflowQueue > 0 then
local nextNofication = OverflowQueue[1]
table.remove(OverflowQueue, 1)
insertNotifcation(nextNofication)
else
updateNotifications()
end
end
local function sendNotifcation(title, text, image, duration, callback)
local notification = {}
local notificationFrame = createNotification(title, text, image)
--
notification.Frame = notificationFrame
notification.Duration = duration
insertNotifcation(notification)
end
BindableEvent_SendNotification.OnInvoke = function(title, text, image, duration, callback)
sendNotifcation(title, text, image, duration, callback)
end
local function sendFriendNotification(fromPlayer)
local notification = {}
local notificationFrame = createNotification(fromPlayer.Name, "Sent you a friend request!",
FRIEND_IMAGE..tostring(fromPlayer.userId).."&x=512&y=512")
notificationFrame.Position = UDim2.new(1, 4, 1, -(NOTIFICATION_Y_OFFSET + 2) * 1.5 - 4)
--
local acceptButton = createTextButton("AcceptButton", "Accept", UDim2.new(0, 0, 1, 2))
acceptButton.Parent = notificationFrame
local declineButton = createTextButton("DeclineButton", "Decline", UDim2.new(0.5, 2, 1, 2))
declineButton.Parent = notificationFrame
acceptButton.MouseButton1Click:connect(function()
if not notification.IsActive then return end
if notification then
removeNotification(notification)
end
LocalPlayer:RequestFriendship(fromPlayer)
end)
declineButton.MouseButton1Click:connect(function()
if not notification.IsActive then return end
if notification then
removeNotification(notification)
end
LocalPlayer:RevokeFriendship(fromPlayer)
FriendRequestBlacklist[fromPlayer] = true
end)
notification.Frame = notificationFrame
notification.Duration = 8
notification.IsFriend = true
insertNotifcation(notification)
end
--[[ Friend Notifications ]]--
local function onFriendRequestEvent(fromPlayer, toPlayer, event)
if fromPlayer ~= LocalPlayer and toPlayer ~= LocalPlayer then return end
--
if fromPlayer == LocalPlayer then
if event == Enum.FriendRequestEvent.Accept then
sendNotifcation("New Friend", "You are now friends with "..toPlayer.Name.."!",
FRIEND_IMAGE..tostring(toPlayer.userId).."&x=512&y=512", DEFAULT_NOTIFICATION_DURATION, nil)
end
elseif toPlayer == LocalPlayer then
if event == Enum.FriendRequestEvent.Issue then
if FriendRequestBlacklist[fromPlayer] then return end
sendFriendNotification(fromPlayer)
elseif event == Enum.FriendRequestEvent.Accept then
sendNotifcation("New Friend", "You are now friends with "..fromPlayer.Name.."!",
FRIEND_IMAGE..tostring(fromPlayer.userId).."&x=512&y=512", DEFAULT_NOTIFICATION_DURATION, nil)
end
end
end
Players.FriendRequestEvent:connect(onFriendRequestEvent)
--[[ Player Points Notifications ]]--
local function onPointsAwarded(userId, pointsAwarded, userBalanceInGame, userTotalBalance)
if userId == LocalPlayer.userId then
if pointsAwarded == 1 then
sendNotifcation("Point Awarded", "You received "..tostring(pointsAwarded).." point!", PLAYER_POINTS_IMG, DEFAULT_NOTIFICATION_DURATION, nil)
elseif pointsAwarded > 0 then
sendNotifcation("Points Awarded", "You received "..tostring(pointsAwarded).." points!", PLAYER_POINTS_IMG, DEFAULT_NOTIFICATION_DURATION, nil)
elseif pointsAwarded < 0 then
sendNotifcation("Points Lost", "You lost "..tostring(-pointsAwarded).." points!", PLAYER_POINTS_IMG, DEFAULT_NOTIFICATION_DURATION, nil)
end
end
end
PointsService.PointsAwarded:connect(onPointsAwarded)
--[[ Badge Notification ]]--
local function onBadgeAwarded(message, userId, badgeId)
if userId == LocalPlayer.userId then
sendNotifcation("Badge Awarded", message, BADGE_IMG, DEFAULT_NOTIFICATION_DURATION, nil)
end
end
BadgeService.BadgeAwarded:connect(onBadgeAwarded)
--[[ Graphics Changes Notification ]]--
GameSettings.Changed:connect(function(property)
if property == "SavedQualityLevel" then
local level = GameSettings.SavedQualityLevel.Value
-- value of 0 is automatic, we do not want to send a notification in that case
if level > 0 and level ~= CurrentGraphicsQualityLevel then
if level > CurrentGraphicsQualityLevel then
sendNotifcation("Graphics Quality", "Increased to ("..tostring(level)..")", "", 2, nil)
else
sendNotifcation("Graphics Quality", "Decreased to ("..tostring(level)..")", "", 2, nil)
end
CurrentGraphicsQualityLevel = level
end
end
end)
--[[ Teleport Notifications ]]--
local TeleportMessage = nil
local function sendTeleportNotification(msg, time)
if TeleportMessage then
TeleportMessage:Destroy()
end
local playerGui = LocalPlayer:FindFirstChild('PlayerGui')
if playerGui then
TeleportMessage = Instance.new('Message')
TeleportMessage.Text = msg
TeleportMessage.Parent = playerGui
--
if time > 0 then
delay(time, function()
TeleportMessage:Destroy()
end)
end
end
end
local function onTeleport(state, placeId, spawnName)
if not TeleportService.CustomizedTeleportUI then
if state == Enum.TeleportState.Started then
sendTeleportNotification("Teleport Started...", 0)
elseif state == Enum.TeleportState.WaitingForServer then
sendTeleportNotification("Requesting Server...", 0)
elseif state == Enum.TeleportState.InProgress then
sendTeleportNotification("Teleporting...", 0)
elseif state == Enum.TeleportState.Failed then
sendTeleportNotification("Teleport failed. Insufficient privileges or target place does not exist.", 3)
end
end
end
LocalPlayer.OnTeleport:connect(onTeleport)
local function onTeleportErrorCallback(msg)
PopupAcceptButton.Visible = false
PopupDeclineButton.Visible = false
PopupOKButton.Visible = true
PopupText.Text = msg
--
local okCn = nil
okCn = PopupOKButton.MouseButton1Click:connect(function()
TeleportService:TeleportCancel()
if okCn then okCn:disconnect() end
--
GuiService:RemoveCenterDialog(PopupFrame)
PopupFrame.Visible = false
end)
GuiService:AddCenterDialog(PopupFrame, Enum.CenterDialogType.QuitDialog,
function()
PopupFrame.Visible = true
end,
function()
PopupFrame.Visible = false
end)
end
TeleportService.ErrorCallback = onTeleportErrorCallback
--[[ Market Place Events ]]--
-- This is used for when a player calls CreatePlaceInPlayerInventoryAsync
local function onClientLuaDialogRequested(msg, accept, decline)
PopupText.Text = msg
--
local acceptCn, declineCn = nil, nil
local function disconnectCns()
if acceptCn then acceptCn:disconnect() end
if declineCn then declineCn:disconnect() end
--
GuiService:RemoveCenterDialog(PopupFrame)
PopupFrame.Visible = false
end
acceptCn = PopupAcceptButton.MouseButton1Click:connect(function()
disconnectCns()
MarketplaceService:SignalServerLuaDialogClosed(true)
end)
declineCn = PopupDeclineButton.MouseButton1Click:connect(function()
disconnectCns()
MarketplaceService:SignalServerLuaDialogClosed(false)
end)
local centerDialogSuccess = pcall(
function()
GuiService:AddCenterDialog(PopupFrame, Enum.CenterDialogType.QuitDialog,
function()
PopupOKButton.Visible = false
PopupAcceptButton.Visible = true
PopupDeclineButton.Visible = true
PopupAcceptButton.Text = accept
PopupDeclineButton.Text = decline
PopupFrame.Visible = true
end,
function()
PopupFrame.Visible = false
end)
end)
if not centerDialogSuccess then
PopupFrame.Visible = true
PopupAcceptButton.Text = accept
PopupDeclineButton.Text = decline
end
return true
end
MarketplaceService.ClientLuaDialogRequested:connect(onClientLuaDialogRequested)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,103 @@
-- 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
local RobloxGui = Game:GetService("CoreGui"):WaitForChild("RobloxGui")
local screenGui = Game:GetService("CoreGui"):FindFirstChild("RobloxGui")
-- TopBar
local topbarSuccess, topbarFlagValue = pcall(function() return settings():GetFFlag("UseInGameTopBar") end)
local useTopBar = (topbarSuccess and topbarFlagValue == true)
if useTopBar then
scriptContext:AddCoreScriptLocal("CoreScripts/2015/Topbar", screenGui)
end
-- SettingsScript
local luaControlsSuccess, luaControlsFlagValue = pcall(function() return settings():GetFFlag("UseLuaCameraAndControl") end)
local newSettingsSuccess, newSettingsFlagValue = pcall(function() return settings():GetFFlag("NewMenuSettingsScript") end)
local useNewSettings = newSettingsSuccess and newSettingsFlagValue
if useNewSettings then
spawn(function() require(RobloxGui.Modules.Settings2) end)
else
scriptContext:AddCoreScriptLocal("CoreScripts/2015/Settings", screenGui)
end
-- Set up touch controls. TODO: Remove when new lua controls are stable.
if touchEnabled then
if not luaControlsSuccess or luaControlsFlagValue == false then
scriptContext:AddCoreScriptLocal("CoreScripts/2015/TouchControls", screenGui)
end
end
-- MainBotChatScript (the Lua part of Dialogs)
local useNewDialogLook = false
pcall(function() useNewDialogLook = settings():GetFFlag("UseNewBubbleSkin") end)
if useNewDialogLook then
scriptContext:AddCoreScriptLocal("CoreScripts/2015/MainBotChatScript2", screenGui)
else
scriptContext:AddCoreScriptLocal("CoreScripts/2015/MainBotChatScript", screenGui)
end
-- Developer Console Script
scriptContext:AddCoreScriptLocal("CoreScripts/2015/DeveloperConsole", screenGui)
-- In-game notifications script
scriptContext:AddCoreScriptLocal("CoreScripts/2015/NotificationScript2", screenGui)
-- Chat script
if useTopBar then
spawn(function() require(RobloxGui.Modules.Chat) end)
else
scriptContext:AddCoreScriptLocal("CoreScripts/2015/ChatScript2", screenGui)
end
-- Purchase Prompt Script
local newPurchaseSuccess, newPurchaseEnabled = pcall(function() return settings():GetFFlag("NewPurchaseScript") end)
local isNewPurchaseScript = newPurchaseSuccess and newPurchaseEnabled
if isNewPurchaseScript then
scriptContext:AddCoreScriptLocal("CoreScripts/2015/PurchasePromptScript2", screenGui)
else
scriptContext:AddCoreScriptLocal("CoreScripts/2015/PurchasePromptScript", screenGui)
end
-- Health Script
if not useTopBar then
scriptContext:AddCoreScriptLocal("CoreScripts/2015/HealthScript", screenGui)
end
local playerListSuccess, playerListFlagValue = pcall(function() return settings():GetFFlag("NewPlayerListScript") end)
local isNotSmallTouchDevice = not touchEnabled or Game:GetService("GuiService"):GetScreenResolution().Y >= 500
-- New Player List
if playerListSuccess and playerListFlagValue == true then
if useTopBar then
--spawn(function() require(RobloxGui.Modules.PlayerlistModule) end)
elseif isNotSmallTouchDevice then
--scriptContext:AddCoreScriptLocal("CoreScripts/2015/PlayerListScript2", screenGui)
end
elseif isNotSmallTouchDevice then
--scriptContext:AddCoreScriptLocal("CoreScripts/2015/PlayerListScript", screenGui)
end
do -- Backpack!
spawn(function() require(RobloxGui.Modules.BackpackScript) end)
end
local luaVehicleHudSuccess, luaVehicleHudEnabled = pcall(function() return settings():GetFFlag('NewVehicleHud') end)
if useTopBar and (luaVehicleHudSuccess and luaVehicleHudEnabled == true) then
scriptContext:AddCoreScriptLocal("CoreScripts/2015/VehicleHud", screenGui)
end
local gamepadSupportSuccess, gamepadSupportFlagValue = pcall(function() return settings():GetFFlag("TopbarGamepadSupport") end)
if gamepadSupportSuccess and gamepadSupportFlagValue then
scriptContext:AddCoreScriptLocal("CoreScripts/2015/GamepadMenu", screenGui)
end
if touchEnabled then -- touch devices don't use same control frame
-- only used for touch device button generation
scriptContext:AddCoreScriptLocal("CoreScripts/2015/ContextActionTouch", screenGui)
screenGui:WaitForChild("ControlFrame")
screenGui.ControlFrame:WaitForChild("BottomLeftControl")
screenGui.ControlFrame.BottomLeftControl.Visible = false
end
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,143 @@
--[[
// Filename: VehicleHud.lua
// Version 1.0
// Written by: jmargh
// Description: Implementation of the VehicleSeat HUD
// TODO:
Once this is live and stable, move to PlayerScripts as module
]]
local RunService = game:GetService('RunService')
local Players = game:GetService('Players')
while not Players.LocalPlayer do
wait()
end
local LocalPlayer = Players.LocalPlayer
local RobloxGui = script.Parent
local CurrentVehicleSeat = nil
local VehicleSeatRenderCn = nil
local VehicleSeatHUDChangedCn = nil
--[[ Images ]]--
local VEHICLE_HUD_BG = 'rbxasset://textures/ui/Vehicle/SpeedBarBKG.png'
local SPEED_BAR_EMPTY = 'rbxasset://textures/ui/Vehicle/SpeedBarEmpty.png'
local SPEED_BAR = 'rbxasset://textures/ui/Vehicle/SpeedBar.png'
--[[ Constants ]]--
local BOTTOM_OFFSET = 84
local MAX_SIZE = 142
--[[ Gui Creation ]]--
local function createImageLabel(name, size, position, image, parent)
local imageLabel = Instance.new('ImageLabel')
imageLabel.Name = name
imageLabel.Size = size
imageLabel.Position = position
imageLabel.BackgroundTransparency = 1
imageLabel.Image = image
imageLabel.Parent = parent
return imageLabel
end
local function createTextLabel(name, alignment, text, parent)
local textLabel = Instance.new('TextLabel')
textLabel.Name = name
textLabel.Size = UDim2.new(1, -4, 0, 20)
textLabel.Position = UDim2.new(0, 2, 0, -20)
textLabel.BackgroundTransparency = 1
textLabel.TextXAlignment = alignment
textLabel.Font = Enum.Font.SourceSans
textLabel.FontSize = Enum.FontSize.Size18
textLabel.TextColor3 = Color3.new(1, 1, 1)
textLabel.TextStrokeTransparency = 0.5
textLabel.TextStrokeColor3 = Color3.new(49/255, 49/255, 49/255)
textLabel.Text = text
textLabel.Parent = parent
return textLabel
end
local VehicleHudFrame = Instance.new('Frame')
VehicleHudFrame.Name = "VehicleHudFrame"
VehicleHudFrame.Size = UDim2.new(0, 158, 0, 14)
VehicleHudFrame.Position = UDim2.new(0.5, -79, 1, -BOTTOM_OFFSET)
VehicleHudFrame.BackgroundTransparency = 1
VehicleHudFrame.Visible = false
VehicleHudFrame.Parent = RobloxGui
local HudBG = createImageLabel("HudBG", UDim2.new(1, 0, 1, 0), UDim2.new(0, 0, 0, 1), VEHICLE_HUD_BG, VehicleHudFrame)
local SpeedBG = createImageLabel("SpeedBG", UDim2.new(0, 142, 0, 4), UDim2.new(0.5, -71, 0.5, -2), SPEED_BAR_EMPTY, VehicleHudFrame)
local SpeedBarImage = createImageLabel("SpeedBarImage", UDim2.new(0, 0, 0, 4), UDim2.new(0.5, -71, 0.5, -2), SPEED_BAR, VehicleHudFrame)
SpeedBarImage.ZIndex = 2
local SpeedLabel = createTextLabel("SpeedLabel", Enum.TextXAlignment.Left, "Speed", VehicleHudFrame)
local SpeedText = createTextLabel("SpeedText", Enum.TextXAlignment.Right, "0", VehicleHudFrame)
--[[ Local Functions ]]--
local function getHumanoid()
local character = LocalPlayer and LocalPlayer.Character
if character then
for _,child in pairs(character:GetChildren()) do
if child:IsA('Humanoid') then
return child
end
end
end
end
local function onRenderStepped()
if CurrentVehicleSeat then
local speed = CurrentVehicleSeat.Velocity.magnitude
SpeedText.Text = tostring(math.min(math.floor(speed), 9999))
local drawSize = math.floor((speed / CurrentVehicleSeat.MaxSpeed) * MAX_SIZE)
drawSize = math.min(drawSize, MAX_SIZE)
SpeedBarImage.Size = UDim2.new(0, drawSize, 0, 4)
SpeedBarImage.ImageRectSize = Vector2.new(drawSize, 0)
end
end
local function onVehicleSeatChanged(property)
if property == "HeadsUpDisplay" then
VehicleHudFrame.Visible = not VehicleHudFrame.Visible
end
end
local function onSeated(active)
if active then
-- TODO: Can we make an API change to get the seat that the humanoid is sitting in?
local camSubject = workspace.CurrentCamera.CameraSubject
if camSubject and camSubject:IsA('VehicleSeat') then
CurrentVehicleSeat = camSubject
VehicleHudFrame.Visible = CurrentVehicleSeat.HeadsUpDisplay
VehicleSeatRenderCn = RunService.RenderStepped:connect(onRenderStepped)
VehicleSeatHUDChangedCn = CurrentVehicleSeat.Changed:connect(onVehicleSeatChanged)
end
else
if CurrentVehicleSeat then
VehicleHudFrame.Visible = false
CurrentVehicleSeat = nil
if VehicleSeatRenderCn then
VehicleSeatRenderCn:disconnect()
VehicleSeatRenderCn = nil
end
if VehicleSeatHUDChangedCn then
VehicleSeatHUDChangedCn:disconnect()
VehicleSeatHUDChangedCn = nil
end
end
end
end
local function connectSeated()
local humanoid = getHumanoid()
while not humanoid do
wait()
humanoid = getHumanoid()
end
humanoid.Seated:connect(onSeated)
end
connectSeated()
LocalPlayer.CharacterAdded:connect(function(character)
connectSeated()
end)