Write more corescripts in Yuescript
This commit is contained in:
parent
a98951aca6
commit
58df0a7c90
|
|
@ -0,0 +1,391 @@
|
|||
local t = { }
|
||||
local assert = assert
|
||||
local Null
|
||||
Null = function()
|
||||
return Null
|
||||
end
|
||||
local StringBuilder = {
|
||||
buffer = { }
|
||||
}
|
||||
StringBuilder.New = function(self)
|
||||
local o = setmetatable({ }, self)
|
||||
self.__index = self
|
||||
o.buffer = { }
|
||||
return o
|
||||
end
|
||||
StringBuilder.Append = function(self, s)
|
||||
do
|
||||
local _obj_0 = self.buffer
|
||||
_obj_0[#_obj_0 + 1] = s
|
||||
end
|
||||
end
|
||||
StringBuilder.ToString = function(self)
|
||||
return table.concat(self.buffer)
|
||||
end
|
||||
local JsonWriter = {
|
||||
backslashes = {
|
||||
["\b"] = "\\b",
|
||||
["\t"] = "\\t",
|
||||
["\n"] = "\\n",
|
||||
["\f"] = "\\f",
|
||||
["\r"] = "\\r",
|
||||
['"'] = '\\"',
|
||||
["\\"] = "\\\\",
|
||||
["/"] = "\\/"
|
||||
}
|
||||
}
|
||||
JsonWriter.New = function(self)
|
||||
local o = setmetatable({ }, self)
|
||||
o.writer = StringBuilder:New()
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
JsonWriter.Append = function(self, s)
|
||||
return self.writer:Append(s)
|
||||
end
|
||||
JsonWriter.ToString = function(self)
|
||||
return self.writer:ToString()
|
||||
end
|
||||
JsonWriter.Write = function(self, o)
|
||||
local _exp_0 = type(o)
|
||||
if "nil" == _exp_0 then
|
||||
return self:WriteNil()
|
||||
elseif "boolean" == _exp_0 or "number" == _exp_0 then
|
||||
return self:WriteString(o)
|
||||
elseif "string" == _exp_0 then
|
||||
return self:ParseString(o)
|
||||
elseif "table" == _exp_0 then
|
||||
return self:WriteTable(o)
|
||||
elseif "function" == _exp_0 then
|
||||
return self:WriteFunction(o)
|
||||
elseif "thread" == _exp_0 or "userdata" == _exp_0 then
|
||||
return self:WriteError(o)
|
||||
end
|
||||
end
|
||||
JsonWriter.WriteNil = function(self)
|
||||
return self:Append("null")
|
||||
end
|
||||
JsonWriter.WriteString = function(self, o)
|
||||
return self:Append(tostring(o))
|
||||
end
|
||||
JsonWriter.ParseString = function(self, s)
|
||||
self:Append('"')
|
||||
self:Append(string.gsub(s, '[%z%c\\"/]', function(n)
|
||||
local c = self.backslashes[n]
|
||||
if c then
|
||||
return c
|
||||
end
|
||||
return string.format("\\u%.4X", string.byte(n))
|
||||
end))
|
||||
return self:Append('"')
|
||||
end
|
||||
JsonWriter.IsArray = function(self, t)
|
||||
local count = 0
|
||||
local isindex
|
||||
isindex = function(k)
|
||||
if type(k) == "number" and k > 0 and math.floor(k) == k then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
for k, _ in pairs(t) do
|
||||
if not isindex(k) then
|
||||
return false, "{", "}"
|
||||
else
|
||||
count = math.max(count, k)
|
||||
end
|
||||
end
|
||||
return true, "[", "]", count
|
||||
end
|
||||
JsonWriter.WriteTable = function(self, t)
|
||||
local ba, st, et, n = self:IsArray(t)
|
||||
self:Append(st)
|
||||
if ba then
|
||||
for i = 1, n do
|
||||
self:Write(t[i])
|
||||
if i < n then
|
||||
self:Append(",")
|
||||
end
|
||||
end
|
||||
else
|
||||
local first = true
|
||||
for k, v in pairs(t) do
|
||||
if not first then
|
||||
self:Append(",")
|
||||
end
|
||||
first = false
|
||||
self:ParseString(k)
|
||||
self:Append(":")
|
||||
self:Write(v)
|
||||
end
|
||||
end
|
||||
return self:Append(et)
|
||||
end
|
||||
JsonWriter.WriteError = function(self, o)
|
||||
return error(string.format("Encoding of %s unsupported", tostring(o)))
|
||||
end
|
||||
JsonWriter.WriteFunction = function(self, o)
|
||||
if o == Null then
|
||||
return self:WriteNil()
|
||||
else
|
||||
return self:WriteError(o)
|
||||
end
|
||||
end
|
||||
local StringReader = {
|
||||
s = "",
|
||||
i = 0
|
||||
}
|
||||
StringReader.New = function(self, s)
|
||||
local o = setmetatable({ }, self)
|
||||
self.__index = self
|
||||
o.s = s or o.s
|
||||
return o
|
||||
end
|
||||
StringReader.Peek = function(self)
|
||||
local i = self.i + 1
|
||||
if i <= #self.s then
|
||||
return string.sub(self.s, i, i)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
StringReader.Next = function(self)
|
||||
self.i = self.i + 1
|
||||
if self.i <= #self.s then
|
||||
return string.sub(self.s, self.i, self.i)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
StringReader.All = function(self)
|
||||
return self.s
|
||||
end
|
||||
local JsonReader = {
|
||||
escapes = {
|
||||
["t"] = "\t",
|
||||
["n"] = "\n",
|
||||
["f"] = "\f",
|
||||
["r"] = "\r",
|
||||
["b"] = "\b"
|
||||
}
|
||||
}
|
||||
JsonReader.New = function(self, s)
|
||||
local o = setmetatable({ }, self)
|
||||
o.reader = StringReader:New(s)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
JsonReader.Read = function(self)
|
||||
self:SkipWhiteSpace()
|
||||
local peek = self:Peek()
|
||||
if not (peek ~= nil) then
|
||||
return error(string.format("Nil string: '%s'", self:All()))
|
||||
elseif peek == "{" then
|
||||
return self:ReadObject()
|
||||
elseif peek == "[" then
|
||||
return self:ReadArray()
|
||||
elseif peek == '"' then
|
||||
return self:ReadString()
|
||||
elseif string.find(peek, "[%+%-%d]") then
|
||||
return self:ReadNumber()
|
||||
elseif peek == "t" then
|
||||
return self:ReadTrue()
|
||||
elseif peek == "f" then
|
||||
return self:ReadFalse()
|
||||
elseif peek == "n" then
|
||||
return self:ReadNull()
|
||||
elseif peek == "/" then
|
||||
self:ReadComment()
|
||||
return self:Read()
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
JsonReader.ReadTrue = function(self)
|
||||
self:TestReservedWord({
|
||||
"t",
|
||||
"r",
|
||||
"u",
|
||||
"e"
|
||||
})
|
||||
return true
|
||||
end
|
||||
JsonReader.ReadFalse = function(self)
|
||||
self:TestReservedWord({
|
||||
"f",
|
||||
"a",
|
||||
"l",
|
||||
"s",
|
||||
"e"
|
||||
})
|
||||
return false
|
||||
end
|
||||
JsonReader.ReadNull = function(self)
|
||||
self:TestReservedWord({
|
||||
"n",
|
||||
"u",
|
||||
"l",
|
||||
"l"
|
||||
})
|
||||
return nil
|
||||
end
|
||||
JsonReader.TestReservedWord = function(self, t)
|
||||
for _, v in ipairs(t) do
|
||||
if self:Next() ~= v then
|
||||
error(string.format("Error reading '%s': %s", table.concat(t), self:All()))
|
||||
end
|
||||
end
|
||||
end
|
||||
JsonReader.ReadNumber = function(self)
|
||||
local result = self:Next()
|
||||
local peek = self:Peek()
|
||||
while (peek ~= nil) and string.find(peek, "[%+%-%d%.eE]") do
|
||||
result = result .. self:Next()
|
||||
peek = self:Peek()
|
||||
end
|
||||
result = tonumber(result)
|
||||
if not (result ~= nil) then
|
||||
return error(string.format("Invalid number: '%s'", result))
|
||||
else
|
||||
return result
|
||||
end
|
||||
end
|
||||
JsonReader.ReadString = function(self)
|
||||
local result = ""
|
||||
assert(self:Next() == '"')
|
||||
while self:Peek() ~= '"' do
|
||||
local ch = self:Next()
|
||||
if ch == "\\" then
|
||||
ch = self:Next()
|
||||
if self.escapes[ch] then
|
||||
ch = self.escapes[ch]
|
||||
end
|
||||
end
|
||||
result = result .. ch
|
||||
end
|
||||
assert(self:Next() == '"')
|
||||
local fromunicode
|
||||
fromunicode = function(m)
|
||||
return string.char(tonumber(m, 16))
|
||||
end
|
||||
return string.gsub(result, "u%x%x(%x%x)", fromunicode)
|
||||
end
|
||||
JsonReader.ReadComment = function(self)
|
||||
assert(self:Next() == "/")
|
||||
local second = self:Next()
|
||||
if second == "/" then
|
||||
return self:ReadSingleLineComment()
|
||||
elseif second == "*" then
|
||||
return self:ReadBlockComment()
|
||||
else
|
||||
return error(string.format("Invalid comment: %s", self:All()))
|
||||
end
|
||||
end
|
||||
JsonReader.ReadBlockComment = function(self)
|
||||
local done = false
|
||||
while not done do
|
||||
local ch = self:Next()
|
||||
if ch == "*" and self:Peek() == "/" then
|
||||
done = true
|
||||
end
|
||||
if not done and ch == "/" and self:Peek() == "*" then
|
||||
error(string.format("Invalid comment: %s, '/*' illegal.", self:All()))
|
||||
end
|
||||
end
|
||||
return self:Next()
|
||||
end
|
||||
JsonReader.ReadSingleLineComment = function(self)
|
||||
local ch = self:Next()
|
||||
while ch ~= "\r" and ch ~= "\n" do
|
||||
ch = self:Next()
|
||||
end
|
||||
end
|
||||
JsonReader.ReadArray = function(self)
|
||||
local result = { }
|
||||
assert(self:Next() == "[")
|
||||
local done = false
|
||||
if self:Peek() == "]" then
|
||||
done = true
|
||||
end
|
||||
while not done do
|
||||
local item = self:Read()
|
||||
result[#result + 1] = item
|
||||
self:SkipWhiteSpace()
|
||||
if self:Peek() == "]" then
|
||||
done = true
|
||||
end
|
||||
if not done then
|
||||
local ch = self:Next()
|
||||
if ch ~= "," then
|
||||
error(string.format("Invalid array: '%s' due to: '%s'", self:All(), ch))
|
||||
end
|
||||
end
|
||||
end
|
||||
assert("]" == self:Next())
|
||||
return result
|
||||
end
|
||||
JsonReader.ReadObject = function(self)
|
||||
local result = { }
|
||||
assert(self:Next() == "{")
|
||||
local done = false
|
||||
if self:Peek() == "}" then
|
||||
done = true
|
||||
end
|
||||
while not done do
|
||||
local key = self:Read()
|
||||
if type(key) ~= "string" then
|
||||
error(string.format("Invalid non-string object key: %s", key))
|
||||
end
|
||||
self:SkipWhiteSpace()
|
||||
local ch = self:Next()
|
||||
if ch ~= ":" then
|
||||
error(string.format("Invalid object: '%s' due to: '%s'", self:All(), ch))
|
||||
end
|
||||
self:SkipWhiteSpace()
|
||||
local val = self:Read()
|
||||
result[key] = val
|
||||
self:SkipWhiteSpace()
|
||||
if self:Peek() == "}" then
|
||||
done = true
|
||||
end
|
||||
if not done then
|
||||
ch = self:Next()
|
||||
if ch ~= "," then
|
||||
error(string.format("Invalid array: '%s' near: '%s'", self:All(), ch))
|
||||
end
|
||||
end
|
||||
end
|
||||
assert(self:Next() == "}")
|
||||
return result
|
||||
end
|
||||
JsonReader.SkipWhiteSpace = function(self)
|
||||
local p = self:Peek()
|
||||
while (p ~= nil) and string.find(p, "[%s/]") do
|
||||
if p == "/" then
|
||||
self:ReadComment()
|
||||
else
|
||||
self:Next()
|
||||
end
|
||||
p = self:Peek()
|
||||
end
|
||||
end
|
||||
JsonReader.Peek = function(self)
|
||||
return self.reader:Peek()
|
||||
end
|
||||
JsonReader.Next = function(self)
|
||||
return self.reader:Next()
|
||||
end
|
||||
JsonReader.All = function(self)
|
||||
return self.reader:All()
|
||||
end
|
||||
local Encode
|
||||
Encode = function(o)
|
||||
local _with_0 = JsonWriter:New()
|
||||
_with_0:Write(o)
|
||||
_with_0:ToString()
|
||||
return _with_0
|
||||
end
|
||||
local Decode
|
||||
Decode = function(s)
|
||||
local _with_0 = JsonReader:New(s)
|
||||
_with_0:Read()
|
||||
return _with_0
|
||||
end
|
||||
383
yue/60595411.yue
383
yue/60595411.yue
|
|
@ -0,0 +1,383 @@
|
|||
t = {}
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
------------------------------------------------JSON Functions Begin----------------------------------------------------
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--JSON Encoder and Parser for Lua 5.1
|
||||
--
|
||||
--2007 Shaun Brown (http://www.chipmunkav.com)
|
||||
|
||||
assert = assert
|
||||
Null = -> Null
|
||||
|
||||
StringBuilder = {
|
||||
buffer: {}
|
||||
}
|
||||
|
||||
StringBuilder.New ==>
|
||||
o = <>: @
|
||||
@__index = @
|
||||
o.buffer = {}
|
||||
o
|
||||
|
||||
|
||||
StringBuilder.Append = (s) =>
|
||||
@buffer[] = s
|
||||
|
||||
|
||||
StringBuilder.ToString ==> table.concat @buffer
|
||||
|
||||
|
||||
JsonWriter =
|
||||
backslashes:
|
||||
["\b"]: "\\b",
|
||||
["\t"]: "\\t",
|
||||
["\n"]: "\\n",
|
||||
["\f"]: "\\f",
|
||||
["\r"]: "\\r",
|
||||
['"']: '\\"',
|
||||
["\\"]: "\\\\",
|
||||
["/"]: "\\/",
|
||||
|
||||
JsonWriter.New ==>
|
||||
o = <>: @
|
||||
o.writer = StringBuilder\New!
|
||||
@__index = @
|
||||
o
|
||||
|
||||
|
||||
JsonWriter.Append = (s) =>
|
||||
@writer\Append s
|
||||
|
||||
|
||||
JsonWriter.ToString ==> @writer\ToString!
|
||||
|
||||
|
||||
JsonWriter.Write = (o) =>
|
||||
switch type o
|
||||
when "nil"
|
||||
@\WriteNil!
|
||||
when "boolean", "number"
|
||||
@\WriteString o
|
||||
when "string"
|
||||
@\ParseString o
|
||||
when "table"
|
||||
@\WriteTable o
|
||||
when "function"
|
||||
@\WriteFunction o
|
||||
when "thread", "userdata"
|
||||
@\WriteError o
|
||||
|
||||
JsonWriter.WriteNil ==> @\Append "null"
|
||||
JsonWriter.WriteString = (o) => @\Append "#{o}"
|
||||
|
||||
|
||||
JsonWriter.ParseString = (s) =>
|
||||
@\Append '"'
|
||||
@\Append string.gsub s, '[%z%c\\"/]', (n) ->
|
||||
c = @backslashes[n]
|
||||
if c
|
||||
return c
|
||||
|
||||
return string.format "\\u%.4X", string.byte n
|
||||
|
||||
@\Append '"'
|
||||
|
||||
|
||||
JsonWriter.IsArray = (t) =>
|
||||
count = 0
|
||||
isindex = (k) ->
|
||||
if type(k) == "number" and
|
||||
k > 0 and
|
||||
math.floor(k) == k
|
||||
|
||||
return true
|
||||
return false
|
||||
|
||||
for k, _ in pairs t
|
||||
if not isindex k
|
||||
return false, "{", "}"
|
||||
else
|
||||
count = math.max count, k
|
||||
|
||||
|
||||
return true, "[", "]", count
|
||||
|
||||
|
||||
JsonWriter.WriteTable = (t) =>
|
||||
ba, st, et, n = @\IsArray t
|
||||
@\Append st
|
||||
if ba
|
||||
for i = 1, n
|
||||
@\Write t[i]
|
||||
if i < n
|
||||
@\Append ","
|
||||
|
||||
else
|
||||
first = true
|
||||
for k, v in pairs t
|
||||
if not first
|
||||
@\Append ","
|
||||
|
||||
first = false
|
||||
@\ParseString k
|
||||
@\Append ":"
|
||||
@\Write v
|
||||
|
||||
|
||||
@\Append et
|
||||
|
||||
|
||||
JsonWriter.WriteError = (o) =>
|
||||
error string.format "Encoding of %s unsupported", "#{o}"
|
||||
|
||||
|
||||
JsonWriter.WriteFunction = (o) =>
|
||||
if o == Null
|
||||
@\WriteNil!
|
||||
else
|
||||
@\WriteError o
|
||||
|
||||
|
||||
|
||||
StringReader =
|
||||
s: "",
|
||||
i: 0,
|
||||
|
||||
StringReader.New = (s) =>
|
||||
o = <>: @
|
||||
@__index = @
|
||||
o.s = s or o.s
|
||||
o
|
||||
|
||||
|
||||
StringReader.Peek ==>
|
||||
i = @i + 1
|
||||
if i <= #@s
|
||||
return string.sub @s, i, i
|
||||
nil
|
||||
|
||||
StringReader.Next ==>
|
||||
@i = @i + 1
|
||||
if @i <= #@s
|
||||
return string.sub @s, @i, @i
|
||||
nil
|
||||
|
||||
|
||||
StringReader.All ==> @s
|
||||
|
||||
|
||||
JsonReader =
|
||||
escapes:
|
||||
["t"]: "\t",
|
||||
["n"]: "\n",
|
||||
["f"]: "\f",
|
||||
["r"]: "\r",
|
||||
["b"]: "\b",
|
||||
|
||||
JsonReader.New = (s) =>
|
||||
o = <>: @
|
||||
o.reader = StringReader\New s
|
||||
@__index = @
|
||||
o
|
||||
|
||||
|
||||
JsonReader.Read ==>
|
||||
@\SkipWhiteSpace!
|
||||
peek = @\Peek!
|
||||
return if not peek?
|
||||
error string.format "Nil string: '%s'", @\All!
|
||||
elseif peek == "{"
|
||||
@\ReadObject!
|
||||
elseif peek == "["
|
||||
@\ReadArray!
|
||||
elseif peek == '"'
|
||||
@\ReadString!
|
||||
elseif string.find peek, "[%+%-%d]"
|
||||
@\ReadNumber!
|
||||
elseif peek == "t"
|
||||
@\ReadTrue!
|
||||
elseif peek == "f"
|
||||
@\ReadFalse!
|
||||
elseif peek == "n"
|
||||
@\ReadNull!
|
||||
elseif peek == "/"
|
||||
@\ReadComment!
|
||||
@\Read!
|
||||
else
|
||||
nil
|
||||
|
||||
JsonReader.ReadTrue ==>
|
||||
@\TestReservedWord { "t", "r", "u", "e" }
|
||||
true
|
||||
|
||||
JsonReader.ReadFalse ==>
|
||||
@\TestReservedWord { "f", "a", "l", "s", "e" }
|
||||
false
|
||||
|
||||
JsonReader.ReadNull ==>
|
||||
@\TestReservedWord { "n", "u", "l", "l" }
|
||||
nil
|
||||
|
||||
JsonReader.TestReservedWord = (t) =>
|
||||
for _, v in ipairs t
|
||||
if @\Next! ~= v
|
||||
error string.format "Error reading '%s': %s", table.concat(t), @\All!
|
||||
|
||||
|
||||
JsonReader.ReadNumber ==>
|
||||
result = @\Next!
|
||||
peek = @\Peek!
|
||||
while peek? and string.find peek, "[%+%-%d%.eE]"
|
||||
result ..= @\Next!
|
||||
peek = @\Peek!
|
||||
|
||||
result = tonumber result
|
||||
if not result?
|
||||
error string.format "Invalid number: '%s'", result
|
||||
else
|
||||
return result
|
||||
|
||||
|
||||
|
||||
JsonReader.ReadString ==>
|
||||
result = ""
|
||||
assert @\Next! == '"'
|
||||
while @\Peek! ~= '"'
|
||||
ch = @\Next!
|
||||
if ch == "\\"
|
||||
ch = @\Next!
|
||||
if @escapes[ch]
|
||||
ch = @escapes[ch]
|
||||
|
||||
result ..= ch
|
||||
|
||||
assert @\Next! == '"'
|
||||
fromunicode = (m) -> string.char tonumber m, 16
|
||||
|
||||
string.gsub result, "u%x%x(%x%x)", fromunicode
|
||||
|
||||
|
||||
JsonReader.ReadComment ==>
|
||||
assert @\Next! == "/"
|
||||
second = @\Next!
|
||||
if second == "/"
|
||||
@\ReadSingleLineComment!
|
||||
elseif second == "*"
|
||||
@\ReadBlockComment!
|
||||
else
|
||||
error string.format "Invalid comment: %s", @\All!
|
||||
|
||||
|
||||
JsonReader.ReadBlockComment ==>
|
||||
done = false
|
||||
until done
|
||||
ch = @\Next!
|
||||
if ch == "*" and @\Peek! == "/"
|
||||
done = true
|
||||
|
||||
if not done and ch == "/" and @\Peek! == "*"
|
||||
error string.format "Invalid comment: %s, '/*' illegal.", @\All!
|
||||
|
||||
|
||||
@\Next!
|
||||
|
||||
|
||||
JsonReader.ReadSingleLineComment ==>
|
||||
ch = @\Next!
|
||||
while ch ~= "\r" and ch ~= "\n"
|
||||
ch = @\Next!
|
||||
|
||||
|
||||
JsonReader.ReadArray ==>
|
||||
result = {}
|
||||
assert @\Next! == "["
|
||||
done = false
|
||||
if @\Peek! == "]"
|
||||
done = true
|
||||
|
||||
until done
|
||||
item = @\Read!
|
||||
result[] = item
|
||||
@\SkipWhiteSpace!
|
||||
if @\Peek! == "]"
|
||||
done = true
|
||||
|
||||
if not done
|
||||
ch = @\Next!
|
||||
if ch ~= ","
|
||||
error string.format "Invalid array: '%s' due to: '%s'", @\All!, ch
|
||||
|
||||
|
||||
assert "]" == @\Next!
|
||||
result
|
||||
|
||||
|
||||
JsonReader.ReadObject ==>
|
||||
result = {}
|
||||
assert @\Next! == "{"
|
||||
done = false
|
||||
if @\Peek! == "}"
|
||||
done = true
|
||||
|
||||
until done
|
||||
key = @\Read!
|
||||
if type(key) ~= "string"
|
||||
error string.format "Invalid non-string object key: %s", key
|
||||
|
||||
@\SkipWhiteSpace!
|
||||
ch = @\Next!
|
||||
if ch ~= ":"
|
||||
error string.format "Invalid object: '%s' due to: '%s'", @\All!, ch
|
||||
|
||||
@\SkipWhiteSpace!
|
||||
val = @\Read!
|
||||
result[key] = val
|
||||
@\SkipWhiteSpace!
|
||||
if @\Peek! == "}"
|
||||
done = true
|
||||
|
||||
if not done
|
||||
ch = @\Next!
|
||||
if ch ~= ","
|
||||
error string.format "Invalid array: '%s' near: '%s'", @\All!, ch
|
||||
|
||||
|
||||
|
||||
assert @\Next! == "}"
|
||||
result
|
||||
|
||||
|
||||
JsonReader.SkipWhiteSpace ==>
|
||||
p = @\Peek!
|
||||
while p? and string.find p, "[%s/]"
|
||||
if p == "/"
|
||||
@\ReadComment!
|
||||
else
|
||||
@\Next!
|
||||
|
||||
p = @\Peek!
|
||||
|
||||
|
||||
JsonReader.Peek ==> @reader\Peek!
|
||||
JsonReader.Next ==> @reader\Next!
|
||||
JsonReader.All ==> @reader\All!
|
||||
|
||||
Encode = (o) ->
|
||||
with JsonWriter\New!
|
||||
\Write o
|
||||
\ToString!
|
||||
|
||||
|
||||
Decode = (s) ->
|
||||
with JsonReader\New s
|
||||
\Read!
|
||||
|
||||
-------------------- End JSON Parser ------------------------
|
||||
|
||||
-- TODO
|
||||
|
|
@ -0,0 +1,863 @@
|
|||
local New
|
||||
New = function(className, name, props)
|
||||
if not (props ~= nil) then
|
||||
props = name
|
||||
name = nil
|
||||
end
|
||||
local obj = New(className)
|
||||
if name then
|
||||
obj.Name = name
|
||||
end
|
||||
local parent
|
||||
for k, v in pairs(props) do
|
||||
if type(k) == "string" then
|
||||
if k == "Parent" then
|
||||
parent = v
|
||||
else
|
||||
obj[k] = v
|
||||
end
|
||||
elseif type(k) == "number" and type(v) == "userdata" then
|
||||
v.Parent = obj
|
||||
end
|
||||
end
|
||||
obj.Parent = parent
|
||||
return obj
|
||||
end
|
||||
local waitForChild
|
||||
waitForChild = function(instance, name)
|
||||
assert(instance)
|
||||
assert(name)
|
||||
while not instance:FindFirstChild(name) do
|
||||
print("Waiting for ...", instance, name)
|
||||
instance.ChildAdded:wait()
|
||||
end
|
||||
return instance:FindFirstChild(name)
|
||||
end
|
||||
local waitForProperty
|
||||
waitForProperty = function(instance, property)
|
||||
assert(instance)
|
||||
assert(property)
|
||||
while not instance[property] do
|
||||
instance.Changed:wait()
|
||||
end
|
||||
end
|
||||
local IsTouchDevice
|
||||
IsTouchDevice = function()
|
||||
local touchEnabled = false
|
||||
pcall(function()
|
||||
touchEnabled = Game:GetService("UserInputService").TouchEnabled
|
||||
end)
|
||||
return touchEnabled
|
||||
end
|
||||
waitForChild(game, "Players")
|
||||
waitForProperty(game.Players, "LocalPlayer")
|
||||
local player = game.Players.LocalPlayer
|
||||
local RbxGui, _
|
||||
RbxGui, _ = LoadLibrary("RbxGui")
|
||||
if not RbxGui then
|
||||
print("could not find RbxGui!")
|
||||
return
|
||||
end
|
||||
local StaticTabName = "gear"
|
||||
local backpack = script.Parent
|
||||
local backpackItems = { }
|
||||
local buttons = { }
|
||||
local debounce = false
|
||||
local browsingMenu = false
|
||||
local mouseEnterCons = { }
|
||||
local mouseClickCons = { }
|
||||
local characterChildAddedCon
|
||||
local characterChildRemovedCon
|
||||
local backpackAddCon
|
||||
local playerBackpack = waitForChild(player, "Backpack")
|
||||
waitForChild(backpack, "Tabs")
|
||||
waitForChild(backpack, "Gear")
|
||||
local gearPreview = waitForChild(backpack.Gear, "GearPreview")
|
||||
local scroller = waitForChild(backpack.Gear, "GearGridScrollingArea")
|
||||
local currentLoadout = waitForChild(backpack.Parent, "CurrentLoadout")
|
||||
local grid = waitForChild(backpack.Gear, "GearGrid")
|
||||
local gearButton = waitForChild(grid, "GearButton")
|
||||
local swapSlot = waitForChild(script.Parent, "SwapSlot")
|
||||
local backpackManager = waitForChild(script.Parent, "CoreScripts/BackpackScripts/BackpackManager")
|
||||
local backpackOpenEvent = waitForChild(backpackManager, "BackpackOpenEvent")
|
||||
local backpackCloseEvent = waitForChild(backpackManager, "BackpackCloseEvent")
|
||||
local tabClickedEvent = waitForChild(backpackManager, "TabClickedEvent")
|
||||
local resizeEvent = waitForChild(backpackManager, "ResizeEvent")
|
||||
local searchRequestedEvent = waitForChild(backpackManager, "SearchRequestedEvent")
|
||||
local tellBackpackReadyFunc = waitForChild(backpackManager, "BackpackReady")
|
||||
local scrollFrame, scrollUp, scrollDown, recalculateScroll
|
||||
scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil, "grid", Vector2.new(6, 6))
|
||||
scrollFrame.Position = UDim2.new(0, 0, 0, 30)
|
||||
scrollFrame.Size = UDim2.new(1, 0, 1, -30)
|
||||
scrollFrame.Parent = backpack.Gear.GearGrid
|
||||
local scrollBar = New("Frame", "ScrollBar", {
|
||||
BackgroundTransparency = 0.9,
|
||||
BackgroundColor3 = Color3.new(1, 1, 1),
|
||||
BorderSizePixel = 0,
|
||||
Size = UDim2.new(0, 17, 1, -36),
|
||||
Position = UDim2.new(0, 0, 0, 18),
|
||||
Parent = scroller
|
||||
})
|
||||
scrollDown.Position = UDim2.new(0, 0, 1, -17)
|
||||
scrollUp.Parent = scroller
|
||||
scrollDown.Parent = scroller
|
||||
local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout
|
||||
scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame()
|
||||
scrollFrameLoadout.Position = UDim2.new(0, 0, 0, 0)
|
||||
scrollFrameLoadout.Size = UDim2.new(1, 0, 1, 0)
|
||||
scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList
|
||||
local LoadoutButton = New("TextButton", "LoadoutButton", {
|
||||
RobloxLocked = true,
|
||||
Font = Enum.Font.ArialBold,
|
||||
FontSize = Enum.FontSize.Size14,
|
||||
Position = UDim2.new(0, 0, 0, 0),
|
||||
Size = UDim2.new(1, 0, 0, 32),
|
||||
Style = Enum.ButtonStyle.RobloxButton,
|
||||
Text = "Loadout #1",
|
||||
TextColor3 = Color3.new(1, 1, 1),
|
||||
Parent = scrollFrameLoadout
|
||||
})
|
||||
do
|
||||
local _with_0 = LoadoutButton:clone()
|
||||
_with_0.Text = "Loadout #2"
|
||||
_with_0.Parent = scrollFrameLoadout
|
||||
end
|
||||
do
|
||||
local _with_0 = LoadoutButton:clone()
|
||||
_with_0.Text = "Loadout #3"
|
||||
_with_0.Parent = scrollFrameLoadout
|
||||
end
|
||||
do
|
||||
local _with_0 = LoadoutButton:clone()
|
||||
_with_0.Text = "Loadout #4"
|
||||
_with_0.Parent = scrollFrameLoadout
|
||||
end
|
||||
New("Frame", "ScrollBarLoadout", {
|
||||
BackgroundTransparency = 0.9,
|
||||
BackgroundColor3 = Color3.new(1, 1, 1),
|
||||
BorderSizePixel = 0,
|
||||
Size = UDim2.new(0, 17, 1, -36),
|
||||
Position = UDim2.new(0, 0, 0, 18),
|
||||
Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
|
||||
})
|
||||
scrollDownLoadout.Position = UDim2.new(0, 0, 1, -17)
|
||||
scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
|
||||
scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
|
||||
local removeFromMap
|
||||
removeFromMap = function(map, object)
|
||||
for i = 1, #map do
|
||||
if map[i] == object then
|
||||
table.remove(map, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
local robloxLock
|
||||
robloxLock = function(instance)
|
||||
instance.RobloxLocked = true
|
||||
local children = instance:GetChildren()
|
||||
if children then
|
||||
for _, child in ipairs(children) do
|
||||
robloxLock(child)
|
||||
end
|
||||
end
|
||||
end
|
||||
local clearPreview
|
||||
clearPreview = function()
|
||||
gearPreview.GearImage.Image = ""
|
||||
gearPreview.GearStats.GearName.Text = ""
|
||||
end
|
||||
local clearHighlight
|
||||
clearHighlight = function(button)
|
||||
button.TextColor3 = Color3.new(1, 1, 1)
|
||||
button.BackgroundColor3 = Color3.new(0, 0, 0)
|
||||
end
|
||||
local inLoadout
|
||||
inLoadout = function(gear)
|
||||
local children = currentLoadout:GetChildren()
|
||||
for i = 1, #children do
|
||||
if children[i]:IsA("Frame") then
|
||||
local button = children[i]:GetChildren()
|
||||
if #button > 0 and button[1].GearReference.Value and button[1].GearReference.Value == gear then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
local updateGridActive
|
||||
updateGridActive = function()
|
||||
for _, v in pairs(backpackItems) do
|
||||
if buttons[v] then
|
||||
local gear
|
||||
local gearRef = buttons[v]:FindFirstChild("GearReference")
|
||||
if gearRef then
|
||||
gear = gearRef.Value
|
||||
end
|
||||
if (not gear) or inLoadout(gear) then
|
||||
buttons[v].Active = false
|
||||
else
|
||||
buttons[v].Active = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local swapGearSlot
|
||||
swapGearSlot = function(slot, gearButton)
|
||||
if not swapSlot.Value then
|
||||
swapSlot.Slot.Value = slot
|
||||
swapSlot.GearButton.Value = gearButton
|
||||
swapSlot.Value = true
|
||||
return updateGridActive()
|
||||
end
|
||||
end
|
||||
local unequipGear
|
||||
unequipGear = function(physGear)
|
||||
physGear.Parent = playerBackpack
|
||||
return updateGridActive()
|
||||
end
|
||||
local UnequipGearMenuClick
|
||||
UnequipGearMenuClick = function(element, menu)
|
||||
if type(element.Action) ~= "number" then
|
||||
return
|
||||
end
|
||||
local num = element.Action
|
||||
if num == 1 then
|
||||
unequipGear(menu.Parent.GearReference.Value)
|
||||
local inventoryButton = menu.Parent
|
||||
local gearToUnequip = inventoryButton.GearReference.Value
|
||||
local loadoutChildren = currentLoadout:GetChildren()
|
||||
local slot = -1
|
||||
for i = 1, #loadoutChildren do
|
||||
if loadoutChildren[i]:IsA("Frame") then
|
||||
local button = loadoutChildren[i]:GetChildren()
|
||||
if button[1] and button[1].GearReference.Value == gearToUnequip then
|
||||
slot = button[1].SlotNumber.Text
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return swapGearSlot(slot, nil)
|
||||
end
|
||||
end
|
||||
local highlight
|
||||
highlight = function(button)
|
||||
button.TextColor3 = Color3.new(0, 0, 0)
|
||||
button.BackgroundColor3 = Color3.new(0.8, 0.8, 0.8)
|
||||
end
|
||||
local getGearContextMenu
|
||||
getGearContextMenu = function()
|
||||
local gearContextMenu = New("Frame", "UnequipContextMenu", {
|
||||
Active = true,
|
||||
Size = UDim2.new(0, 115, 0, 70),
|
||||
Position = UDim2.new(0, -16, 0, -16),
|
||||
BackgroundTransparency = 1,
|
||||
Visible = false
|
||||
})
|
||||
local gearContextMenuButton = New("TextButton", "UnequipContextMenuButton", {
|
||||
Text = "",
|
||||
Style = Enum.ButtonStyle.RobloxButtonDefault,
|
||||
ZIndex = 8,
|
||||
Size = UDim2.new(1, 0, 1, -20),
|
||||
Visible = true,
|
||||
Parent = gearContextMenu
|
||||
})
|
||||
local elementHeight = 12
|
||||
local contextMenuElements = { }
|
||||
local contextMenuElementsName = {
|
||||
"Remove Hotkey"
|
||||
}
|
||||
for i = 1, #contextMenuElementsName do
|
||||
local element = { }
|
||||
element.Type = "Button"
|
||||
element.Text = contextMenuElementsName[i]
|
||||
element.Action = i
|
||||
element.DoIt = UnequipGearMenuClick
|
||||
table.insert(contextMenuElements, element)
|
||||
end
|
||||
for i, contextElement in ipairs(contextMenuElements) do
|
||||
local element = contextElement
|
||||
if element.Type == "Button" then
|
||||
local button = New("TextButton", "UnequipContextButton" .. tostring(i), {
|
||||
BackgroundColor3 = Color3.new(0, 0, 0),
|
||||
BorderSizePixel = 0,
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
Text = " " .. tostring(contextElement.Text),
|
||||
Font = Enum.Font.Arial,
|
||||
FontSize = Enum.FontSize.Size14,
|
||||
Size = UDim2.new(1, 8, 0, elementHeight),
|
||||
Position = UDim2.new(0, 0, 0, elementHeight * i),
|
||||
TextColor3 = Color3.new(1, 1, 1),
|
||||
ZIndex = 9,
|
||||
Parent = gearContextMenuButton
|
||||
})
|
||||
if not IsTouchDevice() then
|
||||
button.MouseButton1Click:connect(function()
|
||||
if button.Active and not gearContextMenu.Parent.Active then
|
||||
pcall(function()
|
||||
return element.DoIt(element, gearContextMenu)
|
||||
end)
|
||||
browsingMenu = false
|
||||
gearContextMenu.Visible = false
|
||||
clearHighlight(button)
|
||||
return clearPreview()
|
||||
end
|
||||
end)
|
||||
button.MouseEnter:connect(function()
|
||||
if button.Active and gearContextMenu.Parent.Active then
|
||||
return highlight(button)
|
||||
end
|
||||
end)
|
||||
button.MouseLeave:connect(function()
|
||||
if button.Active and gearContextMenu.Parent.Active then
|
||||
return clearHighlight(button)
|
||||
end
|
||||
end)
|
||||
end
|
||||
contextElement.Button = button
|
||||
contextElement.Element = button
|
||||
elseif element.Type == "Label" then
|
||||
local frame = New("Frame", "ContextLabel" .. tostring(i), {
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.new(1, 8, 0, elementHeight),
|
||||
New("TextLabel", "Text1", {
|
||||
BackgroundTransparency = 1,
|
||||
BackgroundColor3 = Color3.new(1, 1, 1),
|
||||
BorderSizePixel = 0,
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
Font = Enum.Font.ArialBold,
|
||||
FontSize = Enum.FontSize.Size14,
|
||||
Position = UDim2.new(0, 0, 0, 0),
|
||||
Size = UDim2.new(0.5, 0, 1, 0),
|
||||
TextColor3 = Color3.new(1, 1, 1),
|
||||
ZIndex = 9
|
||||
})
|
||||
})
|
||||
element.Label1 = frame.Text1
|
||||
if element.GetText2 then
|
||||
element.Label2 = New("TextLabel", "Text2", {
|
||||
BackgroundTransparency = 1,
|
||||
BackgroundColor3 = Color3.new(1, 1, 1),
|
||||
BorderSizePixel = 0,
|
||||
TextXAlignment = Enum.TextXAlignment.Right,
|
||||
Font = Enum.Font.Arial,
|
||||
FontSize = Enum.FontSize.Size14,
|
||||
Position = UDim2.new(0.5, 0, 0, 0),
|
||||
Size = UDim2.new(0.5, 0, 1, 0),
|
||||
TextColor3 = Color3.new(1, 1, 1),
|
||||
ZIndex = 9,
|
||||
Parent = frame
|
||||
})
|
||||
end
|
||||
frame.Parent = gearContextMenuButton
|
||||
element.Label = frame
|
||||
element.Element = frame
|
||||
end
|
||||
end
|
||||
gearContextMenu.ZIndex = 4
|
||||
gearContextMenu.MouseLeave:connect(function()
|
||||
browsingMenu = false
|
||||
gearContextMenu.Visible = false
|
||||
return clearPreview()
|
||||
end)
|
||||
robloxLock(gearContextMenu)
|
||||
return gearContextMenu
|
||||
end
|
||||
local findEmptySlot
|
||||
findEmptySlot = function()
|
||||
local smallestNum
|
||||
local loadout = currentLoadout:GetChildren()
|
||||
for i = 1, #loadout do
|
||||
if loadout[i]:IsA("Frame") and #loadout[i]:GetChildren() <= 0 then
|
||||
local frameNum = tonumber(string.sub(loadout[i].Name, 5))
|
||||
if frameNum == 0 then
|
||||
frameNum = 10
|
||||
end
|
||||
if not smallestNum or (smallestNum > frameNum) then
|
||||
smallestNum = frameNum
|
||||
end
|
||||
end
|
||||
end
|
||||
if smallestNum == 10 then
|
||||
smallestNum = 0
|
||||
end
|
||||
return smallestNum
|
||||
end
|
||||
local checkForSwap
|
||||
checkForSwap = function(button, x, y)
|
||||
local loadoutChildren = currentLoadout:GetChildren()
|
||||
for i = 1, #loadoutChildren do
|
||||
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name, "Slot") then
|
||||
if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then
|
||||
if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then
|
||||
local slot = tonumber(string.sub(loadoutChildren[i].Name, 5))
|
||||
swapGearSlot(slot, button)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
local previewGear
|
||||
previewGear = function(button)
|
||||
if not browsingMenu then
|
||||
gearPreview.Visible = false
|
||||
gearPreview.GearImage.Image = button.Image
|
||||
gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name
|
||||
end
|
||||
end
|
||||
local buttonClick
|
||||
buttonClick = function(button)
|
||||
if button:FindFirstChild("UnequipContextMenu" and not button.Active) then
|
||||
button.UnequipContextMenu.Visible = true
|
||||
browsingMenu = true
|
||||
end
|
||||
end
|
||||
local resizeGrid
|
||||
resizeGrid = function()
|
||||
for _, v in pairs(backpackItems) do
|
||||
if not v:FindFirstChild("RobloxBuildTool") then
|
||||
if not buttons[v] then
|
||||
local buttonClone = gearButton:clone()
|
||||
buttonClone.Parent = grid.ScrollingFrame
|
||||
buttonClone.Visible = true
|
||||
buttonClone.Image = v.TextureId
|
||||
if buttonClone.Image == "" then
|
||||
buttonClone.GearText.Text = v.Name
|
||||
end
|
||||
buttonClone.GearReference.Value = v
|
||||
buttonClone.Draggable = true
|
||||
buttons[v] = buttonClone
|
||||
if not IsTouchDevice() then
|
||||
local unequipMenu = getGearContextMenu()
|
||||
unequipMenu.Visible = false
|
||||
unequipMenu.Parent = buttonClone
|
||||
end
|
||||
local beginPos
|
||||
buttonClone.DragBegin:connect(function(value)
|
||||
waitForChild(buttonClone, "Background")
|
||||
buttonClone["Background"].ZIndex = 10
|
||||
buttonClone.ZIndex = 10
|
||||
beginPos = value
|
||||
end)
|
||||
buttonClone.DragStopped:connect(function(x, y)
|
||||
waitForChild(buttonClone, "Background")
|
||||
buttonClone["Background"].ZIndex = 1
|
||||
buttonClone.ZIndex = 2
|
||||
if beginPos ~= buttonClone.Position then
|
||||
if not checkForSwap(buttonClone, x, y) then
|
||||
buttonClone:TweenPosition(beginPos, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true)
|
||||
buttonClone.Draggable = false
|
||||
return delay(0.5, function()
|
||||
buttonClone.Draggable = true
|
||||
end)
|
||||
else
|
||||
buttonClone.Position = beginPos
|
||||
end
|
||||
end
|
||||
end)
|
||||
local clickTime = tick()
|
||||
mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function()
|
||||
return previewGear(buttonClone)
|
||||
end)
|
||||
mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function()
|
||||
local newClickTime = tick()
|
||||
if buttonClone.Active and (newClickTime - clickTime) < 0.5 then
|
||||
local slot = findEmptySlot()
|
||||
if slot then
|
||||
buttonClone.ZIndex = 1
|
||||
swapGearSlot(slot, buttonClone)
|
||||
end
|
||||
else
|
||||
buttonClick(buttonClone)
|
||||
end
|
||||
clickTime = newClickTime
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
return recalculateScroll()
|
||||
end
|
||||
local resize
|
||||
resize = function()
|
||||
local size = 0.75 * (function()
|
||||
if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then
|
||||
return gearPreview.AbsoluteSize.X
|
||||
else
|
||||
return gearPreview.AbsoluteSize.Y
|
||||
end
|
||||
end)()
|
||||
waitForChild(gearPreview, "GearImage")
|
||||
gearPreview.GearImage.Size = UDim2.new(0, size, 0, size)
|
||||
gearPreview.GearImage.Position = UDim2.new(0, gearPreview.AbsoluteSize.X / 2 - size / 2, 0.75, -size)
|
||||
return resizeGrid()
|
||||
end
|
||||
local addToGrid
|
||||
addToGrid = function(child)
|
||||
if not child:IsA("Tool") and not child:IsA("HopperBin") then
|
||||
return
|
||||
end
|
||||
if child:FindFirstChild("RobloxBuildTool") then
|
||||
return
|
||||
end
|
||||
for _, v in pairs(backpackItems) do
|
||||
if v == child then
|
||||
return
|
||||
end
|
||||
end
|
||||
table.insert(backpackItems, child)
|
||||
local changeCon = child.Changed:connect(function(prop)
|
||||
if prop == "Name" and buttons[child] and buttons[child].Image == "" then
|
||||
buttons[child].GearText.Text = child.Name
|
||||
end
|
||||
end)
|
||||
local ancestryCon = child.AncestryChanged:connect(function(_, _)
|
||||
local thisObject
|
||||
for _, v in pairs(backpackItems) do
|
||||
if v == child then
|
||||
thisObject = v
|
||||
break
|
||||
end
|
||||
end
|
||||
waitForProperty(player, "Character")
|
||||
waitForChild(player, "Backpack")
|
||||
if child.Parent ~= player.Backpack and child.Parent ~= player.Character then
|
||||
do
|
||||
local _obj_0 = ancestryCon
|
||||
if _obj_0 ~= nil then
|
||||
_obj_0:disconnect()
|
||||
end
|
||||
end
|
||||
if changeCon ~= nil then
|
||||
changeCon:disconnect()
|
||||
end
|
||||
for _, v in pairs(backpackItems) do
|
||||
if v == thisObject then
|
||||
do
|
||||
local _obj_0 = mouseEnterCons[buttons[v]]
|
||||
if _obj_0 ~= nil then
|
||||
_obj_0:disconnect()
|
||||
end
|
||||
end
|
||||
do
|
||||
local _obj_0 = mouseClickCons[buttons[v]]
|
||||
if _obj_0 ~= nil then
|
||||
_obj_0:disconnect()
|
||||
end
|
||||
end
|
||||
buttons[v].Parent = nil
|
||||
buttons[v] = nil
|
||||
break
|
||||
end
|
||||
end
|
||||
removeFromMap(backpackItems, thisObject)
|
||||
resizeGrid()
|
||||
else
|
||||
resizeGrid()
|
||||
end
|
||||
return updateGridActive()
|
||||
end)
|
||||
return resizeGrid()
|
||||
end
|
||||
local showPartialGrid
|
||||
showPartialGrid = function(subset)
|
||||
for _, v in pairs(buttons) do
|
||||
v.Parent = nil
|
||||
end
|
||||
if subset then
|
||||
for _, v in pairs(subset) do
|
||||
v.Parent = grid.ScrollingFrame
|
||||
end
|
||||
end
|
||||
return recalculateScroll()
|
||||
end
|
||||
local showEntireGrid
|
||||
showEntireGrid = function()
|
||||
for _, v in pairs(buttons) do
|
||||
v.Parent = grid.ScrollingFrame
|
||||
end
|
||||
return recalculateScroll()
|
||||
end
|
||||
local centerGear
|
||||
centerGear = function(loadoutChildren)
|
||||
local gearButtons = { }
|
||||
local lastSlotAdd
|
||||
for i = 1, #loadoutChildren do
|
||||
if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then
|
||||
if loadoutChildren[i].Name == "Slot0" then
|
||||
lastSlotAdd = loadoutChildren[i]
|
||||
else
|
||||
table.insert(gearButtons, loadoutChildren[i])
|
||||
end
|
||||
end
|
||||
end
|
||||
if lastSlotAdd then
|
||||
table.insert(gearButtons, lastSlotAdd)
|
||||
end
|
||||
local startPos = (1 - (#gearButtons * 0.1)) / 2
|
||||
for i = 1, #gearButtons do
|
||||
gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1), 0, 0, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
|
||||
end
|
||||
end
|
||||
local backpackOpenHandler
|
||||
backpackOpenHandler = function(currentTab)
|
||||
if currentTab and currentTab ~= StaticTabName then
|
||||
backpack.Gear.Visible = false
|
||||
return
|
||||
end
|
||||
backpack.Gear.Visible = true
|
||||
updateGridActive()
|
||||
resizeGrid()
|
||||
resize()
|
||||
return tellBackpackReadyFunc:Invoke()
|
||||
end
|
||||
local backpackCloseHandler
|
||||
backpackCloseHandler = function(currentTab)
|
||||
if currentTab and currentTab ~= StaticTabName then
|
||||
backpack.Gear.Visible = false
|
||||
return
|
||||
end
|
||||
backpack.Gear.Visible = false
|
||||
resizeGrid()
|
||||
resize()
|
||||
return tellBackpackReadyFunc:Invoke()
|
||||
end
|
||||
local tabClickHandler
|
||||
tabClickHandler = function(tabName)
|
||||
if tabName == StaticTabName then
|
||||
return backpackOpenHandler(tabName)
|
||||
else
|
||||
return backpackCloseHandler(tabName)
|
||||
end
|
||||
end
|
||||
local loadoutCheck
|
||||
loadoutCheck = function(child, selectState)
|
||||
if not child:IsA("ImageButton") then
|
||||
return
|
||||
end
|
||||
for _, v in pairs(backpackItems) do
|
||||
if buttons[v] then
|
||||
if child:FindFirstChild("GearReference" and buttons[v]:FindFirstChild("GearReference")) then
|
||||
if buttons[v].GearReference.Value == child.GearReference.Value then
|
||||
buttons[v].Active = selectState
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local setupCharacterConnections
|
||||
setupCharacterConnections = function()
|
||||
if backpackAddCon ~= nil then
|
||||
backpackAddCon:disconnect()
|
||||
end
|
||||
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child)
|
||||
return addToGrid(child)
|
||||
end)
|
||||
local backpackChildren = game.Players.LocalPlayer.Backpack:GetChildren()
|
||||
for i = 1, #backpackChildren do
|
||||
addToGrid(backpackChildren[i])
|
||||
end
|
||||
if characterChildAddedCon ~= nil then
|
||||
characterChildAddedCon:disconnect()
|
||||
end
|
||||
characterChildAddedCon = game.Players.LocalPlayer.Character.ChildAdded:connect(function(child)
|
||||
addToGrid(child)
|
||||
return updateGridActive()
|
||||
end)
|
||||
if characterChildRemovedCon ~= nil then
|
||||
characterChildRemovedCon:disconnect()
|
||||
end
|
||||
characterChildRemovedCon = game.Players.LocalPlayer.Character.ChildRemoved:connect(function(_)
|
||||
return updateGridActive()
|
||||
end)
|
||||
wait()
|
||||
return centerGear(currentLoadout:GetChildren())
|
||||
end
|
||||
local removeCharacterConnections
|
||||
removeCharacterConnections = function()
|
||||
if characterChildAddedCon ~= nil then
|
||||
characterChildAddedCon:disconnect()
|
||||
end
|
||||
if characterChildRemovedCon ~= nil then
|
||||
characterChildRemovedCon:disconnect()
|
||||
end
|
||||
if backpackAddCon ~= nil then
|
||||
return backpackAddCon:disconnect()
|
||||
end
|
||||
return nil
|
||||
end
|
||||
local trim
|
||||
trim = function(s)
|
||||
return s:gsub("^%s*(.-)%s*$", "%1")
|
||||
end
|
||||
local filterGear
|
||||
filterGear = function(terms)
|
||||
local filteredGear = { }
|
||||
for _, v in pairs(backpackItems) do
|
||||
if buttons[v] then
|
||||
local gearString = string.lower(buttons[v].GearReference.Value.Name)
|
||||
gearString = trim(gearString)
|
||||
for i = 1, #terms do
|
||||
if string.match(gearString, terms[i]) then
|
||||
table.insert(filteredGear, buttons[v])
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return filteredGear
|
||||
end
|
||||
local splitByWhitespace
|
||||
splitByWhitespace = function(text)
|
||||
if type(text) ~= "string" then
|
||||
return
|
||||
end
|
||||
local terms = { }
|
||||
for token in string.gmatch(text, "[^%s]+") do
|
||||
if string.len(token) > 0 then
|
||||
table.insert(terms, token)
|
||||
end
|
||||
end
|
||||
return terms
|
||||
end
|
||||
local showSearchGear
|
||||
showSearchGear = function(searchTerms)
|
||||
if not backpack.Gear.Visible then
|
||||
return
|
||||
end
|
||||
local searchTermTable = splitByWhitespace(searchTerms)
|
||||
local currSearchTerms
|
||||
if searchTermTable and (#searchTermTable > 0) then
|
||||
currSearchTerms = searchTermTable
|
||||
else
|
||||
currSearchTerms = nil
|
||||
end
|
||||
if not (searchTermTable ~= nil) then
|
||||
showEntireGrid()
|
||||
return
|
||||
end
|
||||
local filteredButtons = filterGear(currSearchTerms)
|
||||
return showPartialGrid(filteredButtons)
|
||||
end
|
||||
local nukeBackpack
|
||||
nukeBackpack = function()
|
||||
while #buttons > 0 do
|
||||
table.remove(buttons)
|
||||
end
|
||||
buttons = { }
|
||||
while #backpackItems > 0 do
|
||||
table.remove(backpackItems)
|
||||
end
|
||||
backpackItems = { }
|
||||
local scrollingFrameChildren = grid.ScrollingFrame:GetChildren()
|
||||
for i = 1, #scrollingFrameChildren do
|
||||
scrollingFrameChildren[i]:remove()
|
||||
end
|
||||
end
|
||||
local coreGuiChanged
|
||||
coreGuiChanged = function(coreGuiType, enabled)
|
||||
if coreGuiType == Enum.CoreGuiType.Backpack or coreGuiType == Enum.CoreGuiType.All then
|
||||
if not enabled then
|
||||
backpack.Gear.Visible = false
|
||||
end
|
||||
end
|
||||
end
|
||||
local backpackChildren = player.Backpack:GetChildren()
|
||||
for i = 1, #backpackChildren do
|
||||
addToGrid(backpackChildren[i])
|
||||
end
|
||||
resizeEvent.Event:connect(function(_)
|
||||
if debounce then
|
||||
return
|
||||
end
|
||||
debounce = true
|
||||
wait()
|
||||
resize()
|
||||
resizeGrid()
|
||||
debounce = false
|
||||
end)
|
||||
currentLoadout.ChildAdded:connect(function(child)
|
||||
return loadoutCheck(child, false)
|
||||
end)
|
||||
currentLoadout.ChildRemoved:connect(function(child)
|
||||
return loadoutCheck(child, true)
|
||||
end)
|
||||
currentLoadout.DescendantAdded:connect(function(descendant)
|
||||
if not backpack.Visible and (descendant:IsA("ImageButton") or descendant:IsA("TextButton")) then
|
||||
return centerGear(currentLoadout:GetChildren())
|
||||
end
|
||||
end)
|
||||
currentLoadout.DescendantRemoving:connect(function(descendant)
|
||||
if not backpack.Visible and (descendant:IsA("ImageButton") or descendant:IsA("TextButton")) then
|
||||
wait()
|
||||
return centerGear(currentLoadout:GetChildren())
|
||||
end
|
||||
end)
|
||||
grid.MouseEnter:connect(function()
|
||||
return clearPreview()
|
||||
end)
|
||||
grid.MouseLeave:connect(function()
|
||||
return clearPreview()
|
||||
end)
|
||||
player.CharacterRemoving:connect(function()
|
||||
removeCharacterConnections()
|
||||
return nukeBackpack()
|
||||
end)
|
||||
player.CharacterAdded:connect(function()
|
||||
return setupCharacterConnections()
|
||||
end)
|
||||
player.ChildAdded:connect(function(child)
|
||||
if child:IsA("Backpack") then
|
||||
playerBackpack = child
|
||||
if backpackAddCon ~= nil then
|
||||
backpackAddCon:disconnect()
|
||||
end
|
||||
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child)
|
||||
return addToGrid(child)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
swapSlot.Changed:connect(function()
|
||||
if not swapSlot.Value then
|
||||
return updateGridActive()
|
||||
end
|
||||
end)
|
||||
local loadoutChildren = currentLoadout:GetChildren()
|
||||
for i = 1, #loadoutChildren do
|
||||
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name, "Slot") then
|
||||
loadoutChildren[i].ChildRemoved:connect(function()
|
||||
return updateGridActive()
|
||||
end)
|
||||
loadoutChildren[i].ChildAdded:connect(function()
|
||||
return updateGridActive()
|
||||
end)
|
||||
end
|
||||
end
|
||||
pcall(function()
|
||||
coreGuiChanged(Enum.CoreGuiType.Backpack, Game.StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType.Backpack))
|
||||
return Game.StarterGui.CoreGuiChangedSignal:connect(coreGuiChanged)
|
||||
end)
|
||||
resize()
|
||||
resizeGrid()
|
||||
loadoutChildren = currentLoadout:GetChildren()
|
||||
for i = 1, #loadoutChildren do
|
||||
loadoutCheck(loadoutChildren[i], false)
|
||||
end
|
||||
if not backpack.Visible then
|
||||
centerGear(currentLoadout:GetChildren())
|
||||
end
|
||||
if not (characterChildAddedCon ~= nil) and game.Players.LocalPlayer["Character"] then
|
||||
setupCharacterConnections()
|
||||
end
|
||||
if not backpackAddCon then
|
||||
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child)
|
||||
return addToGrid(child)
|
||||
end)
|
||||
end
|
||||
backpackOpenEvent.Event:connect(backpackOpenHandler)
|
||||
backpackCloseEvent.Event:connect(backpackCloseHandler)
|
||||
tabClickedEvent.Event:connect(tabClickHandler)
|
||||
searchRequestedEvent.Event:connect(showSearchGear)
|
||||
return recalculateScrollLoadout()
|
||||
826
yue/89449008.yue
826
yue/89449008.yue
|
|
@ -0,0 +1,826 @@
|
|||
-- Heliodex's basic New function (basically a simplified version of melt)
|
||||
New = (className, name, props) ->
|
||||
if not props? -- no name was provided
|
||||
props = name
|
||||
name = nil
|
||||
|
||||
obj = New className
|
||||
obj.Name = name if name
|
||||
local parent
|
||||
|
||||
for k, v in pairs props
|
||||
if type(k) == "string"
|
||||
if k == "Parent"
|
||||
parent = v
|
||||
else
|
||||
obj[k] = v
|
||||
|
||||
elseif type(k) == "number" and type(v) == "userdata"
|
||||
v.Parent = obj
|
||||
|
||||
obj.Parent = parent
|
||||
obj
|
||||
--
|
||||
|
||||
-- A couple of necessary functions
|
||||
waitForChild = (instance, name) ->
|
||||
assert instance
|
||||
assert name
|
||||
while not instance\FindFirstChild name
|
||||
print "Waiting for ...", instance, name
|
||||
instance.ChildAdded\wait!
|
||||
|
||||
instance\FindFirstChild name
|
||||
|
||||
waitForProperty = (instance, property) ->
|
||||
assert instance
|
||||
assert property
|
||||
while not instance[property]
|
||||
instance.Changed\wait!
|
||||
|
||||
|
||||
local IsTouchDevice = ->
|
||||
touchEnabled = false
|
||||
try
|
||||
touchEnabled = Game\GetService"UserInputService".TouchEnabled
|
||||
touchEnabled
|
||||
|
||||
|
||||
waitForChild game, "Players"
|
||||
waitForProperty game.Players, "LocalPlayer"
|
||||
player = game.Players.LocalPlayer
|
||||
|
||||
local RbxGui, _ = LoadLibrary "RbxGui"
|
||||
if not RbxGui
|
||||
print "could not find RbxGui!"
|
||||
return
|
||||
|
||||
--- Begin Locals
|
||||
StaticTabName = "gear"
|
||||
|
||||
backpack = script.Parent
|
||||
|
||||
backpackItems = {}
|
||||
buttons = {}
|
||||
|
||||
debounce = false
|
||||
browsingMenu = false
|
||||
|
||||
mouseEnterCons = {}
|
||||
mouseClickCons = {}
|
||||
|
||||
local characterChildAddedCon
|
||||
local characterChildRemovedCon
|
||||
local backpackAddCon
|
||||
|
||||
playerBackpack = waitForChild player, "Backpack"
|
||||
|
||||
waitForChild backpack, "Tabs"
|
||||
|
||||
waitForChild backpack, "Gear"
|
||||
gearPreview = waitForChild backpack.Gear, "GearPreview"
|
||||
|
||||
scroller = waitForChild backpack.Gear, "GearGridScrollingArea"
|
||||
|
||||
currentLoadout = waitForChild backpack.Parent, "CurrentLoadout"
|
||||
|
||||
grid = waitForChild backpack.Gear, "GearGrid"
|
||||
gearButton = waitForChild grid, "GearButton"
|
||||
|
||||
swapSlot = waitForChild script.Parent, "SwapSlot"
|
||||
|
||||
backpackManager = waitForChild script.Parent, "CoreScripts/BackpackScripts/BackpackManager"
|
||||
backpackOpenEvent = waitForChild backpackManager, "BackpackOpenEvent"
|
||||
backpackCloseEvent = waitForChild backpackManager, "BackpackCloseEvent"
|
||||
tabClickedEvent = waitForChild backpackManager, "TabClickedEvent"
|
||||
resizeEvent = waitForChild backpackManager, "ResizeEvent"
|
||||
searchRequestedEvent = waitForChild backpackManager, "SearchRequestedEvent"
|
||||
tellBackpackReadyFunc = waitForChild backpackManager, "BackpackReady"
|
||||
|
||||
-- creating scroll bar early as to make sure items get placed correctly
|
||||
local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame nil, "grid", Vector2.new 6, 6
|
||||
|
||||
scrollFrame.Position = UDim2.new 0, 0, 0, 30
|
||||
scrollFrame.Size = UDim2.new 1, 0, 1, -30
|
||||
scrollFrame.Parent = backpack.Gear.GearGrid
|
||||
|
||||
scrollBar = New "Frame", "ScrollBar"
|
||||
BackgroundTransparency: 0.9
|
||||
BackgroundColor3: Color3.new 1, 1, 1
|
||||
BorderSizePixel: 0
|
||||
Size: UDim2.new 0, 17, 1, -36
|
||||
Position: UDim2.new 0, 0, 0, 18
|
||||
Parent: scroller
|
||||
|
||||
scrollDown.Position = UDim2.new 0, 0, 1, -17
|
||||
|
||||
scrollUp.Parent = scroller
|
||||
scrollDown.Parent = scroller
|
||||
|
||||
local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame!
|
||||
|
||||
scrollFrameLoadout.Position = UDim2.new 0, 0, 0, 0
|
||||
scrollFrameLoadout.Size = UDim2.new 1, 0, 1, 0
|
||||
scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList
|
||||
|
||||
LoadoutButton = New "TextButton", "LoadoutButton"
|
||||
RobloxLocked: true
|
||||
Font: Enum.Font.ArialBold
|
||||
FontSize: Enum.FontSize.Size14
|
||||
Position: UDim2.new 0, 0, 0, 0
|
||||
Size: UDim2.new 1, 0, 0, 32
|
||||
Style: Enum.ButtonStyle.RobloxButton
|
||||
Text: "Loadout #1"
|
||||
TextColor3: Color3.new 1, 1, 1
|
||||
Parent: scrollFrameLoadout
|
||||
|
||||
with LoadoutButton\clone!
|
||||
.Text = "Loadout #2"
|
||||
.Parent = scrollFrameLoadout
|
||||
|
||||
with LoadoutButton\clone!
|
||||
.Text = "Loadout #3"
|
||||
.Parent = scrollFrameLoadout
|
||||
|
||||
with LoadoutButton\clone!
|
||||
.Text = "Loadout #4"
|
||||
.Parent = scrollFrameLoadout
|
||||
|
||||
New "Frame", "ScrollBarLoadout"
|
||||
BackgroundTransparency: 0.9
|
||||
BackgroundColor3: Color3.new 1, 1, 1
|
||||
BorderSizePixel: 0
|
||||
Size: UDim2.new 0, 17, 1, -36
|
||||
Position: UDim2.new 0, 0, 0, 18
|
||||
Parent: backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
|
||||
|
||||
scrollDownLoadout.Position = UDim2.new 0, 0, 1, -17
|
||||
|
||||
scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
|
||||
scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
|
||||
|
||||
-- Begin Functions
|
||||
removeFromMap = (map, object) ->
|
||||
for i = 1, #map
|
||||
if map[i] == object
|
||||
table.remove map, i
|
||||
break
|
||||
|
||||
robloxLock = (instance) ->
|
||||
instance.RobloxLocked = true
|
||||
children = instance\GetChildren!
|
||||
if children
|
||||
for _, child in ipairs children
|
||||
robloxLock child
|
||||
|
||||
|
||||
clearPreview = ->
|
||||
gearPreview.GearImage.Image = ""
|
||||
gearPreview.GearStats.GearName.Text = ""
|
||||
|
||||
clearHighlight = (button) ->
|
||||
button.TextColor3 = Color3.new 1, 1, 1
|
||||
button.BackgroundColor3 = Color3.new 0, 0, 0
|
||||
|
||||
inLoadout = (gear) ->
|
||||
children = currentLoadout\GetChildren!
|
||||
for i = 1, #children
|
||||
if children[i]\IsA "Frame"
|
||||
button = children[i]\GetChildren!
|
||||
if #button > 0 and
|
||||
button[1].GearReference.Value and
|
||||
button[1].GearReference.Value == gear
|
||||
return true
|
||||
|
||||
false
|
||||
|
||||
updateGridActive = ->
|
||||
for _, v in pairs backpackItems
|
||||
if buttons[v]
|
||||
local gear
|
||||
gearRef = buttons[v]\FindFirstChild "GearReference"
|
||||
|
||||
if gearRef
|
||||
gear = gearRef.Value
|
||||
|
||||
buttons[v].Active = if (not gear) or inLoadout gear
|
||||
false
|
||||
else
|
||||
true
|
||||
|
||||
swapGearSlot = (slot, gearButton) ->
|
||||
if not swapSlot.Value -- signal loadout to swap a gear out
|
||||
swapSlot.Slot.Value = slot
|
||||
swapSlot.GearButton.Value = gearButton
|
||||
swapSlot.Value = true
|
||||
updateGridActive!
|
||||
|
||||
unequipGear = (physGear) ->
|
||||
physGear.Parent = playerBackpack
|
||||
updateGridActive!
|
||||
|
||||
UnequipGearMenuClick = (element, menu) ->
|
||||
return if type(element.Action) ~= "number"
|
||||
|
||||
num = element.Action
|
||||
if num == 1 -- remove from loadout
|
||||
unequipGear menu.Parent.GearReference.Value
|
||||
inventoryButton = menu.Parent
|
||||
gearToUnequip = inventoryButton.GearReference.Value
|
||||
loadoutChildren = currentLoadout\GetChildren!
|
||||
slot = -1
|
||||
for i = 1, #loadoutChildren
|
||||
if loadoutChildren[i]\IsA "Frame"
|
||||
button = loadoutChildren[i]\GetChildren!
|
||||
if button[1] and button[1].GearReference.Value == gearToUnequip
|
||||
slot = button[1].SlotNumber.Text
|
||||
break
|
||||
|
||||
swapGearSlot slot, nil
|
||||
|
||||
|
||||
highlight = (button) ->
|
||||
button.TextColor3 = Color3.new 0, 0, 0
|
||||
button.BackgroundColor3 = Color3.new 0.8, 0.8, 0.8
|
||||
|
||||
getGearContextMenu = ->
|
||||
gearContextMenu = New "Frame", "UnequipContextMenu"
|
||||
Active: true
|
||||
Size: UDim2.new 0, 115, 0, 70
|
||||
Position: UDim2.new 0, -16, 0, -16
|
||||
BackgroundTransparency: 1
|
||||
Visible: false
|
||||
|
||||
gearContextMenuButton = New "TextButton", "UnequipContextMenuButton"
|
||||
Text: ""
|
||||
Style: Enum.ButtonStyle.RobloxButtonDefault
|
||||
ZIndex: 8
|
||||
Size: UDim2.new 1, 0, 1, -20
|
||||
Visible: true
|
||||
Parent: gearContextMenu
|
||||
|
||||
elementHeight = 12
|
||||
|
||||
contextMenuElements = {}
|
||||
contextMenuElementsName = { "Remove Hotkey" }
|
||||
|
||||
for i = 1, #contextMenuElementsName
|
||||
element = {}
|
||||
element.Type = "Button"
|
||||
element.Text = contextMenuElementsName[i]
|
||||
element.Action = i
|
||||
element.DoIt = UnequipGearMenuClick
|
||||
table.insert contextMenuElements, element
|
||||
|
||||
|
||||
for i, contextElement in ipairs contextMenuElements
|
||||
element = contextElement
|
||||
if element.Type == "Button"
|
||||
button = New "TextButton", "UnequipContextButton#{i}"
|
||||
BackgroundColor3: Color3.new 0, 0, 0
|
||||
BorderSizePixel: 0
|
||||
TextXAlignment: Enum.TextXAlignment.Left
|
||||
Text: " #{contextElement.Text}"
|
||||
Font: Enum.Font.Arial
|
||||
FontSize: Enum.FontSize.Size14
|
||||
Size: UDim2.new 1, 8, 0, elementHeight
|
||||
Position: UDim2.new 0, 0, 0, elementHeight * i
|
||||
TextColor3: Color3.new 1, 1, 1
|
||||
ZIndex: 9
|
||||
Parent: gearContextMenuButton
|
||||
|
||||
if not IsTouchDevice!
|
||||
button.MouseButton1Click\connect ->
|
||||
if button.Active and not gearContextMenu.Parent.Active
|
||||
try
|
||||
element.DoIt element, gearContextMenu
|
||||
|
||||
browsingMenu = false
|
||||
gearContextMenu.Visible = false
|
||||
clearHighlight button
|
||||
clearPreview!
|
||||
|
||||
|
||||
button.MouseEnter\connect ->
|
||||
if button.Active and gearContextMenu.Parent.Active
|
||||
highlight button
|
||||
|
||||
|
||||
button.MouseLeave\connect ->
|
||||
if button.Active and gearContextMenu.Parent.Active
|
||||
clearHighlight button
|
||||
|
||||
|
||||
contextElement.Button = button
|
||||
contextElement.Element = button
|
||||
elseif element.Type == "Label"
|
||||
frame = New "Frame", "ContextLabel#{i}"
|
||||
BackgroundTransparency: 1
|
||||
Size: UDim2.new 1, 8, 0, elementHeight
|
||||
|
||||
* New "TextLabel", "Text1"
|
||||
BackgroundTransparency: 1
|
||||
BackgroundColor3: Color3.new 1, 1, 1
|
||||
BorderSizePixel: 0
|
||||
TextXAlignment: Enum.TextXAlignment.Left
|
||||
Font: Enum.Font.ArialBold
|
||||
FontSize: Enum.FontSize.Size14
|
||||
Position: UDim2.new 0, 0, 0, 0
|
||||
Size: UDim2.new 0.5, 0, 1, 0
|
||||
TextColor3: Color3.new 1, 1, 1
|
||||
ZIndex: 9
|
||||
|
||||
element.Label1 = frame.Text1
|
||||
|
||||
if element.GetText2
|
||||
element.Label2 = New "TextLabel", "Text2"
|
||||
BackgroundTransparency: 1
|
||||
BackgroundColor3: Color3.new 1, 1, 1
|
||||
BorderSizePixel: 0
|
||||
TextXAlignment: Enum.TextXAlignment.Right
|
||||
Font: Enum.Font.Arial
|
||||
FontSize: Enum.FontSize.Size14
|
||||
Position: UDim2.new 0.5, 0, 0, 0
|
||||
Size: UDim2.new 0.5, 0, 1, 0
|
||||
TextColor3: Color3.new 1, 1, 1
|
||||
ZIndex: 9
|
||||
Parent: frame
|
||||
|
||||
frame.Parent = gearContextMenuButton
|
||||
element.Label = frame
|
||||
element.Element = frame
|
||||
|
||||
|
||||
gearContextMenu.ZIndex = 4
|
||||
gearContextMenu.MouseLeave\connect ->
|
||||
browsingMenu = false
|
||||
gearContextMenu.Visible = false
|
||||
clearPreview!
|
||||
|
||||
robloxLock gearContextMenu
|
||||
|
||||
gearContextMenu
|
||||
|
||||
findEmptySlot = ->
|
||||
local smallestNum
|
||||
loadout = currentLoadout\GetChildren!
|
||||
for i = 1, #loadout
|
||||
if loadout[i]\IsA"Frame" and #loadout[i]\GetChildren! <= 0
|
||||
frameNum = tonumber string.sub loadout[i].Name, 5
|
||||
if frameNum == 0
|
||||
frameNum = 10
|
||||
|
||||
if not smallestNum or (smallestNum > frameNum)
|
||||
smallestNum = frameNum
|
||||
|
||||
if smallestNum == 10
|
||||
smallestNum = 0
|
||||
|
||||
smallestNum
|
||||
|
||||
checkForSwap = (button, x, y) ->
|
||||
loadoutChildren = currentLoadout\GetChildren!
|
||||
for i = 1, #loadoutChildren
|
||||
if loadoutChildren[i]\IsA"Frame" and string.find loadoutChildren[i].Name, "Slot"
|
||||
if x >= loadoutChildren[i].AbsolutePosition.x and
|
||||
x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x)
|
||||
|
||||
if y >= loadoutChildren[i].AbsolutePosition.y and
|
||||
y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y)
|
||||
|
||||
slot = tonumber string.sub loadoutChildren[i].Name, 5
|
||||
swapGearSlot slot, button
|
||||
return true
|
||||
false
|
||||
|
||||
|
||||
previewGear = (button) ->
|
||||
if not browsingMenu
|
||||
gearPreview.Visible = false
|
||||
gearPreview.GearImage.Image = button.Image
|
||||
gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name
|
||||
|
||||
buttonClick = (button) ->
|
||||
if button\FindFirstChild "UnequipContextMenu" and not button.Active
|
||||
button.UnequipContextMenu.Visible = true
|
||||
browsingMenu = true
|
||||
|
||||
resizeGrid = ->
|
||||
for _, v in pairs backpackItems
|
||||
if not v\FindFirstChild "RobloxBuildTool"
|
||||
if not buttons[v]
|
||||
buttonClone = gearButton\clone!
|
||||
|
||||
with buttonClone
|
||||
.Parent = grid.ScrollingFrame
|
||||
.Visible = true
|
||||
.Image = v.TextureId
|
||||
if .Image == ""
|
||||
.GearText.Text = v.Name
|
||||
.GearReference.Value = v
|
||||
.Draggable = true
|
||||
buttons[v] = buttonClone
|
||||
|
||||
if not IsTouchDevice!
|
||||
unequipMenu = getGearContextMenu!
|
||||
|
||||
unequipMenu.Visible = false
|
||||
unequipMenu.Parent = buttonClone
|
||||
|
||||
|
||||
local beginPos
|
||||
buttonClone.DragBegin\connect (value) ->
|
||||
waitForChild buttonClone, "Background"
|
||||
buttonClone["Background"].ZIndex = 10
|
||||
buttonClone.ZIndex = 10
|
||||
beginPos = value
|
||||
|
||||
buttonClone.DragStopped\connect (x, y) ->
|
||||
waitForChild buttonClone, "Background"
|
||||
buttonClone["Background"].ZIndex = 1
|
||||
buttonClone.ZIndex = 2
|
||||
if beginPos ~= buttonClone.Position
|
||||
if not checkForSwap buttonClone, x, y
|
||||
buttonClone\TweenPosition(
|
||||
beginPos,
|
||||
Enum.EasingDirection.Out,
|
||||
Enum.EasingStyle.Quad,
|
||||
0.5,
|
||||
true
|
||||
)
|
||||
buttonClone.Draggable = false
|
||||
delay 0.5, ->
|
||||
buttonClone.Draggable = true
|
||||
|
||||
else
|
||||
buttonClone.Position = beginPos
|
||||
|
||||
|
||||
|
||||
clickTime = tick!
|
||||
mouseEnterCons[buttonClone] = buttonClone.MouseEnter\connect ->
|
||||
previewGear buttonClone
|
||||
|
||||
mouseClickCons[buttonClone] = buttonClone.MouseButton1Click\connect ->
|
||||
newClickTime = tick!
|
||||
if buttonClone.Active and (newClickTime - clickTime) < 0.5
|
||||
slot = findEmptySlot!
|
||||
if slot
|
||||
buttonClone.ZIndex = 1
|
||||
swapGearSlot slot, buttonClone
|
||||
|
||||
else
|
||||
buttonClick buttonClone
|
||||
|
||||
clickTime = newClickTime
|
||||
|
||||
recalculateScroll!
|
||||
|
||||
resize = ->
|
||||
size = 0.75 * if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X
|
||||
gearPreview.AbsoluteSize.X
|
||||
else
|
||||
gearPreview.AbsoluteSize.Y
|
||||
|
||||
|
||||
waitForChild gearPreview, "GearImage"
|
||||
gearPreview.GearImage.Size = UDim2.new 0, size, 0, size
|
||||
gearPreview.GearImage.Position = UDim2.new 0, gearPreview.AbsoluteSize.X / 2 - size / 2, 0.75, -size
|
||||
|
||||
resizeGrid!
|
||||
|
||||
|
||||
addToGrid = (child) ->
|
||||
return if not child\IsA"Tool" and
|
||||
not child\IsA "HopperBin"
|
||||
|
||||
return if child\FindFirstChild "RobloxBuildTool"
|
||||
|
||||
|
||||
for _, v in pairs backpackItems -- check to see if we already have this gear registered
|
||||
return if v == child
|
||||
|
||||
table.insert backpackItems, child
|
||||
|
||||
changeCon = child.Changed\connect (prop) ->
|
||||
if prop == "Name" and
|
||||
buttons[child] and
|
||||
buttons[child].Image == ""
|
||||
|
||||
buttons[child].GearText.Text = child.Name
|
||||
|
||||
ancestryCon = child.AncestryChanged\connect (_, _) ->
|
||||
local thisObject
|
||||
for _, v in pairs backpackItems
|
||||
if v == child
|
||||
thisObject = v
|
||||
break
|
||||
|
||||
waitForProperty player, "Character"
|
||||
waitForChild player, "Backpack"
|
||||
if child.Parent ~= player.Backpack and child.Parent ~= player.Character
|
||||
|
||||
ancestryCon?\disconnect!
|
||||
changeCon?\disconnect!
|
||||
|
||||
for _, v in pairs backpackItems
|
||||
if v == thisObject
|
||||
mouseEnterCons[buttons[v]]?\disconnect!
|
||||
mouseClickCons[buttons[v]]?\disconnect!
|
||||
|
||||
buttons[v].Parent = nil
|
||||
buttons[v] = nil
|
||||
break
|
||||
|
||||
removeFromMap backpackItems, thisObject
|
||||
|
||||
resizeGrid!
|
||||
else
|
||||
resizeGrid!
|
||||
updateGridActive!
|
||||
resizeGrid!
|
||||
|
||||
showPartialGrid = (subset) ->
|
||||
for _, v in pairs buttons
|
||||
v.Parent = nil
|
||||
|
||||
if subset
|
||||
for _, v in pairs subset
|
||||
v.Parent = grid.ScrollingFrame
|
||||
|
||||
|
||||
recalculateScroll!
|
||||
|
||||
|
||||
showEntireGrid = ->
|
||||
for _, v in pairs buttons
|
||||
v.Parent = grid.ScrollingFrame
|
||||
|
||||
recalculateScroll!
|
||||
|
||||
centerGear = (loadoutChildren) ->
|
||||
gearButtons = {}
|
||||
local lastSlotAdd
|
||||
for i = 1, #loadoutChildren
|
||||
if loadoutChildren[i]\IsA"Frame" and #loadoutChildren[i]\GetChildren! > 0
|
||||
if loadoutChildren[i].Name == "Slot0"
|
||||
lastSlotAdd = loadoutChildren[i]
|
||||
else
|
||||
table.insert gearButtons, loadoutChildren[i]
|
||||
|
||||
if lastSlotAdd
|
||||
table.insert gearButtons, lastSlotAdd
|
||||
|
||||
|
||||
startPos = (1 - (#gearButtons * 0.1)) / 2
|
||||
for i = 1, #gearButtons
|
||||
gearButtons[i]\TweenPosition(
|
||||
UDim2.new(startPos + ((i - 1) * 0.1), 0, 0, 0),
|
||||
Enum.EasingDirection.Out,
|
||||
Enum.EasingStyle.Quad,
|
||||
0.25,
|
||||
true
|
||||
)
|
||||
|
||||
backpackOpenHandler = (currentTab) ->
|
||||
if currentTab and currentTab ~= StaticTabName
|
||||
backpack.Gear.Visible = false
|
||||
return
|
||||
|
||||
backpack.Gear.Visible = true
|
||||
updateGridActive!
|
||||
|
||||
resizeGrid!
|
||||
resize!
|
||||
tellBackpackReadyFunc\Invoke!
|
||||
|
||||
backpackCloseHandler = (currentTab) ->
|
||||
if currentTab and currentTab ~= StaticTabName
|
||||
backpack.Gear.Visible = false
|
||||
return
|
||||
|
||||
|
||||
backpack.Gear.Visible = false
|
||||
|
||||
resizeGrid!
|
||||
resize!
|
||||
tellBackpackReadyFunc\Invoke!
|
||||
|
||||
tabClickHandler = (tabName) ->
|
||||
if tabName == StaticTabName
|
||||
backpackOpenHandler tabName
|
||||
else
|
||||
backpackCloseHandler tabName
|
||||
|
||||
loadoutCheck = (child, selectState) ->
|
||||
return if not child\IsA "ImageButton"
|
||||
|
||||
for _, v in pairs backpackItems
|
||||
if buttons[v]
|
||||
if child\FindFirstChild "GearReference" and buttons[v]\FindFirstChild "GearReference"
|
||||
if buttons[v].GearReference.Value == child.GearReference.Value
|
||||
buttons[v].Active = selectState
|
||||
break
|
||||
|
||||
|
||||
-- removeAllEquippedGear = (physGear) ->
|
||||
-- stuff = player.Character\GetChildren!
|
||||
-- for i = 1, #stuff
|
||||
-- if (stuff[i]\IsA"Tool" or stuff[i]\IsA"HopperBin") and stuff[i] ~= physGear
|
||||
-- stuff[i].Parent = playerBackpack
|
||||
|
||||
-- equipGear = (physGear) ->
|
||||
-- removeAllEquippedGear physGear
|
||||
-- physGear.Parent = player.Character
|
||||
-- updateGridActive!
|
||||
|
||||
setupCharacterConnections = ->
|
||||
backpackAddCon?\disconnect!
|
||||
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded\connect (child) ->
|
||||
addToGrid child
|
||||
|
||||
|
||||
-- make sure we get all the children
|
||||
backpackChildren = game.Players.LocalPlayer.Backpack\GetChildren!
|
||||
for i = 1, #backpackChildren
|
||||
addToGrid backpackChildren[i]
|
||||
|
||||
|
||||
characterChildAddedCon?\disconnect!
|
||||
characterChildAddedCon = game.Players.LocalPlayer.Character.ChildAdded\connect (child) ->
|
||||
addToGrid child
|
||||
updateGridActive!
|
||||
|
||||
characterChildRemovedCon?\disconnect!
|
||||
characterChildRemovedCon = game.Players.LocalPlayer.Character.ChildRemoved\connect (_) ->
|
||||
updateGridActive!
|
||||
|
||||
wait!
|
||||
centerGear currentLoadout\GetChildren!
|
||||
|
||||
removeCharacterConnections = ->
|
||||
characterChildAddedCon?\disconnect!
|
||||
characterChildRemovedCon?\disconnect!
|
||||
backpackAddCon?\disconnect!
|
||||
|
||||
trim = (s) -> s\gsub "^%s*(.-)%s*$", "%1"
|
||||
|
||||
filterGear = (terms) ->
|
||||
filteredGear = {}
|
||||
for _, v in pairs backpackItems
|
||||
if buttons[v]
|
||||
gearString = string.lower buttons[v].GearReference.Value.Name
|
||||
gearString = trim gearString
|
||||
for i = 1, #terms
|
||||
if string.match gearString, terms[i]
|
||||
table.insert filteredGear, buttons[v]
|
||||
break
|
||||
|
||||
filteredGear
|
||||
|
||||
splitByWhitespace = (text) ->
|
||||
return if type(text) ~= "string"
|
||||
|
||||
terms = {}
|
||||
for token in string.gmatch text, "[^%s]+"
|
||||
if string.len(token) > 0
|
||||
table.insert terms, token
|
||||
terms
|
||||
|
||||
showSearchGear = (searchTerms) ->
|
||||
return if not backpack.Gear.Visible
|
||||
|
||||
-- currently not active tab
|
||||
|
||||
searchTermTable = splitByWhitespace searchTerms
|
||||
local currSearchTerms
|
||||
currSearchTerms = if searchTermTable and (#searchTermTable > 0)
|
||||
searchTermTable
|
||||
else
|
||||
nil
|
||||
|
||||
if not searchTermTable?
|
||||
showEntireGrid!
|
||||
return
|
||||
|
||||
filteredButtons = filterGear currSearchTerms
|
||||
showPartialGrid filteredButtons
|
||||
|
||||
|
||||
nukeBackpack = ->
|
||||
while #buttons > 0
|
||||
table.remove buttons
|
||||
|
||||
buttons = {}
|
||||
while #backpackItems > 0
|
||||
table.remove backpackItems
|
||||
|
||||
backpackItems = {}
|
||||
scrollingFrameChildren = grid.ScrollingFrame\GetChildren!
|
||||
for i = 1, #scrollingFrameChildren
|
||||
scrollingFrameChildren[i]\remove!
|
||||
|
||||
coreGuiChanged = (coreGuiType, enabled) ->
|
||||
if coreGuiType == Enum.CoreGuiType.Backpack or coreGuiType == Enum.CoreGuiType.All
|
||||
if not enabled
|
||||
backpack.Gear.Visible = false
|
||||
|
||||
|
||||
|
||||
|
||||
backpackChildren = player.Backpack\GetChildren!
|
||||
for i = 1, #backpackChildren
|
||||
addToGrid backpackChildren[i]
|
||||
|
||||
|
||||
------------------------- Start Lifelong Connections -----------------------
|
||||
|
||||
resizeEvent.Event\connect (_) ->
|
||||
return if debounce
|
||||
|
||||
debounce = true
|
||||
wait!
|
||||
resize!
|
||||
resizeGrid!
|
||||
debounce = false
|
||||
|
||||
|
||||
currentLoadout.ChildAdded\connect (child) -> loadoutCheck child, false
|
||||
currentLoadout.ChildRemoved\connect (child) -> loadoutCheck child, true
|
||||
|
||||
|
||||
currentLoadout.DescendantAdded\connect (descendant) ->
|
||||
if not backpack.Visible and (descendant\IsA"ImageButton" or descendant\IsA "TextButton")
|
||||
centerGear currentLoadout\GetChildren!
|
||||
|
||||
|
||||
currentLoadout.DescendantRemoving\connect (descendant) ->
|
||||
if not backpack.Visible and (descendant\IsA"ImageButton" or descendant\IsA "TextButton")
|
||||
wait!
|
||||
centerGear currentLoadout\GetChildren!
|
||||
|
||||
|
||||
grid.MouseEnter\connect -> clearPreview!
|
||||
grid.MouseLeave\connect -> clearPreview!
|
||||
|
||||
|
||||
player.CharacterRemoving\connect ->
|
||||
removeCharacterConnections!
|
||||
nukeBackpack!
|
||||
|
||||
player.CharacterAdded\connect ->
|
||||
setupCharacterConnections!
|
||||
|
||||
|
||||
player.ChildAdded\connect (child) ->
|
||||
if child\IsA "Backpack"
|
||||
playerBackpack = child
|
||||
backpackAddCon?\disconnect!
|
||||
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded\connect (child) ->
|
||||
addToGrid child
|
||||
|
||||
|
||||
swapSlot.Changed\connect ->
|
||||
if not swapSlot.Value
|
||||
updateGridActive!
|
||||
|
||||
loadoutChildren = currentLoadout\GetChildren!
|
||||
for i = 1, #loadoutChildren
|
||||
if loadoutChildren[i]\IsA"Frame" and string.find loadoutChildren[i].Name, "Slot"
|
||||
loadoutChildren[i].ChildRemoved\connect -> updateGridActive!
|
||||
loadoutChildren[i].ChildAdded\connect -> updateGridActive!
|
||||
|
||||
|
||||
------------------------- End Lifelong Connections -----------------------
|
||||
|
||||
try
|
||||
coreGuiChanged Enum.CoreGuiType.Backpack, Game.StarterGui\GetCoreGuiEnabled Enum.CoreGuiType.Backpack
|
||||
Game.StarterGui.CoreGuiChangedSignal\connect coreGuiChanged
|
||||
|
||||
|
||||
resize!
|
||||
resizeGrid!
|
||||
|
||||
-- make sure any items in the loadout are accounted for in inventory
|
||||
loadoutChildren = currentLoadout\GetChildren!
|
||||
for i = 1, #loadoutChildren
|
||||
loadoutCheck loadoutChildren[i], false
|
||||
|
||||
if not backpack.Visible
|
||||
centerGear currentLoadout\GetChildren!
|
||||
|
||||
|
||||
-- make sure that inventory is listening to gear reparenting
|
||||
if not characterChildAddedCon? and game.Players.LocalPlayer["Character"]
|
||||
setupCharacterConnections!
|
||||
|
||||
if not backpackAddCon
|
||||
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded\connect (child) ->
|
||||
addToGrid child
|
||||
|
||||
backpackOpenEvent.Event\connect backpackOpenHandler
|
||||
backpackCloseEvent.Event\connect backpackCloseHandler
|
||||
tabClickedEvent.Event\connect tabClickHandler
|
||||
searchRequestedEvent.Event\connect showSearchGear
|
||||
|
||||
recalculateScrollLoadout!
|
||||
Loading…
Reference in New Issue