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