Advertisement
fidelmena73

Untitled

Jul 3rd, 2015
1,337
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 486.32 KB | None | 0 0
  1. --[[
  2.  
  3. NotAshley's loadstring fix.
  4.  
  5. Credit to einsteinK, as well as the creators of LuLu for the parser. This parser now supports local variables.
  6.  
  7. Credit to Reinitialized and NecroBumpist for the VM and RBX.lua sandboxing scripts.
  8.  
  9. ]]
  10.  
  11. local luaZ = {}
  12.  
  13. ------------------------------------------------------------------------
  14. -- * reader() should return a string, or nil if nothing else to parse.
  15. -- Additional data can be set only during stream initialization
  16. -- * Readers are handled in lauxlib.c, see luaL_load(file|buffer|string)
  17. -- * LUAL_BUFFERSIZE=BUFSIZ=512 in make_getF() (located in luaconf.h)
  18. -- * Original Reader typedef:
  19. -- const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
  20. -- * This Lua chunk reader implementation:
  21. -- returns string or nil, no arguments to function
  22. ------------------------------------------------------------------------
  23.  
  24. ------------------------------------------------------------------------
  25. -- create a chunk reader from a source string
  26. ------------------------------------------------------------------------
  27. function luaZ:make_getS(buff)
  28. local b = buff
  29. return function() -- chunk reader anonymous function here
  30. if not b then return nil end
  31. local data = b
  32. b = nil
  33. return data
  34. end
  35. end
  36.  
  37. ------------------------------------------------------------------------
  38. -- create a chunk reader from a source file
  39. ------------------------------------------------------------------------
  40. function luaZ:make_getF(filename)
  41. local LUAL_BUFFERSIZE = 512
  42. local h = io.open(filename, "r")
  43. if not h then return nil end
  44. return function() -- chunk reader anonymous function here
  45. if not h or io.type(h) == "closed file" then return nil end
  46. local buff = h:read(LUAL_BUFFERSIZE)
  47. if not buff then h:close(); h = nil end
  48. return buff
  49. end
  50. end
  51.  
  52. ------------------------------------------------------------------------
  53. -- creates a zio input stream
  54. -- returns the ZIO structure, z
  55. ------------------------------------------------------------------------
  56. function luaZ:init(reader, data)
  57. if not reader then return end
  58. local z = {}
  59. z.reader = reader
  60. z.data = data or ""
  61. z.name = name
  62. -- set up additional data for reading
  63. if not data or data == "" then z.n = 0 else z.n = #data end
  64. z.p = 0
  65. return z
  66. end
  67.  
  68. ------------------------------------------------------------------------
  69. -- fill up input buffer
  70. ------------------------------------------------------------------------
  71. function luaZ:fill(z)
  72. local buff = z.reader()
  73. z.data = buff
  74. if not buff or buff == "" then return "EOZ" end
  75. z.n, z.p = #buff - 1, 1
  76. return string.sub(buff, 1, 1)
  77. end
  78.  
  79. ------------------------------------------------------------------------
  80. -- get next character from the input stream
  81. -- * local n, p are used to optimize code generation
  82. ------------------------------------------------------------------------
  83. function luaZ:zgetc(z)
  84. local n, p = z.n, z.p + 1
  85. if n > 0 then
  86. z.n, z.p = n - 1, p
  87. return string.sub(z.data, p, p)
  88. else
  89. return self:fill(z)
  90. end
  91. end
  92.  
  93. local luaZfunc = luaZ
  94.  
  95. --[[--------------------------------------------------------------------
  96.  
  97. llex.lua
  98. Lua lexical analyzer in Lua
  99. This file is part of Yueliang.
  100.  
  101. Copyright (c) 2005-2006 Kein-Hong Man <khman@users.sf.net>
  102. The COPYRIGHT file describes the conditions
  103. under which this software may be distributed.
  104.  
  105. See the ChangeLog for more information.
  106.  
  107. ----------------------------------------------------------------------]]
  108.  
  109. --[[--------------------------------------------------------------------
  110. -- Notes:
  111. -- * intended to 'imitate' llex.c code; performance is not a concern
  112. -- * tokens are strings; code structure largely retained
  113. -- * deleted stuff (compared to llex.c) are noted, comments retained
  114. -- * nextc() returns the currently read character to simplify coding
  115. -- here; next() in llex.c does not return anything
  116. -- * compatibility code is marked with "--Unknown command """, use #help to get a list
  117. --
  118. -- Added:
  119. -- * luaX:chunkid (function luaO_chunkid from lobject.c)
  120. -- * luaX:str2d (function luaO_str2d from lobject.c)
  121. -- * luaX.LUA_QS used in luaX:lexerror (from luaconf.h)
  122. -- * luaX.LUA_COMPAT_LSTR in luaX:read_long_string (from luaconf.h)
  123. -- * luaX.MAX_INT used in luaX:inclinenumber (from llimits.h)
  124. --
  125. -- To use the lexer:
  126. -- (1) luaX:init() to initialize the lexer
  127. -- (2) luaX:setinput() to set the input stream to lex
  128. -- (3) call luaX:next() or luaX:luaX:lookahead() to get tokens,
  129. -- until "TK_EOS": luaX:next()
  130. -- * since EOZ is returned as a string, be careful when regexp testing
  131. --
  132. -- Not implemented:
  133. -- * luaX_newstring: not required by this Lua implementation
  134. -- * buffer MAX_SIZET size limit (from llimits.h) test not implemented
  135. -- in the interest of performance
  136. -- * locale-aware number handling is largely redundant as Lua's
  137. -- tonumber() function is already capable of this
  138. --
  139. -- Changed in 5.1.x:
  140. -- * TK_NAME token order moved down
  141. -- * string representation for TK_NAME, TK_NUMBER, TK_STRING changed
  142. -- * token struct renamed to lower case (LS -> ls)
  143. -- * LexState struct: removed nestlevel, added decpoint
  144. -- * error message functions have been greatly simplified
  145. -- * token2string renamed to luaX_tokens, exposed in llex.h
  146. -- * lexer now handles all kinds of newlines, including CRLF
  147. -- * shbang first line handling removed from luaX:setinput;
  148. -- it is now done in lauxlib.c (luaL_loadfile)
  149. -- * next(ls) macro renamed to nextc(ls) due to new luaX_next function
  150. -- * EXTRABUFF and MAXNOCHECK removed due to lexer changes
  151. -- * checkbuffer(ls, len) macro deleted
  152. -- * luaX:read_numeral now has 3 support functions: luaX:trydecpoint,
  153. -- luaX:buffreplace and (luaO_str2d from lobject.c) luaX:str2d
  154. -- * luaX:read_numeral is now more promiscuous in slurping characters;
  155. -- hexadecimal numbers was added, locale-aware decimal points too
  156. -- * luaX:skip_sep is new; used by luaX:read_long_string
  157. -- * luaX:read_long_string handles new-style long blocks, with some
  158. -- optional compatibility code
  159. -- * luaX:llex: parts changed to support new-style long blocks
  160. -- * luaX:llex: readname functionality has been folded in
  161. -- * luaX:llex: removed test for control characters
  162. --
  163. --------------------------------------------------------------------]]
  164.  
  165. local luaZ = luaZfunc
  166.  
  167. local luaX = {}
  168.  
  169. -- FIRST_RESERVED is not required as tokens are manipulated as strings
  170. -- TOKEN_LEN deleted; maximum length of a reserved word not needed
  171.  
  172. ------------------------------------------------------------------------
  173. -- "ORDER RESERVED" deleted; enumeration in one place: luaX.RESERVED
  174. ------------------------------------------------------------------------
  175.  
  176. -- terminal symbols denoted by reserved words: TK_AND to TK_WHILE
  177. -- other terminal symbols: TK_NAME to TK_EOS
  178. luaX.RESERVED = [[
  179. TK_AND and
  180. TK_BREAK break
  181. TK_DO do
  182. TK_ELSE else
  183. TK_ELSEIF elseif
  184. TK_END end
  185. TK_FALSE false
  186. TK_FOR for
  187. TK_FUNCTION function
  188. TK_IF if
  189. TK_IN in
  190. TK_LOCAL local
  191. TK_NIL nil
  192. TK_NOT not
  193. TK_OR or
  194. TK_REPEAT repeat
  195. TK_RETURN return
  196. TK_THEN then
  197. TK_TRUE true
  198. TK_UNTIL until
  199. TK_WHILE while
  200. TK_CONCAT ..
  201. TK_DOTS ...
  202. TK_EQ ==
  203. TK_GE >=
  204. TK_LE <=
  205. TK_NE ~=
  206. TK_NAME <name>
  207. TK_NUMBER <number>
  208. TK_STRING <string>
  209. TK_EOS <eof>]]
  210.  
  211. -- NUM_RESERVED is not required; number of reserved words
  212.  
  213. --[[--------------------------------------------------------------------
  214. -- Instead of passing seminfo, the Token struct (e.g. ls.t) is passed
  215. -- so that lexer functions can use its table element, ls.t.seminfo
  216. --
  217. -- SemInfo (struct no longer needed, a mixed-type value is used)
  218. --
  219. -- Token (struct of ls.t and ls.lookahead):
  220. -- token -- token symbol
  221. -- seminfo -- semantics information
  222. --
  223. -- LexState (struct of ls; ls is initialized by luaX:setinput):
  224. -- current -- current character (charint)
  225. -- linenumber -- input line counter
  226. -- lastline -- line of last token 'consumed'
  227. -- t -- current token (table: struct Token)
  228. -- lookahead -- look ahead token (table: struct Token)
  229. -- fs -- 'FuncState' is private to the parser
  230. -- L -- LuaState
  231. -- z -- input stream
  232. -- buff -- buffer for tokens
  233. -- source -- current source name
  234. -- decpoint -- locale decimal point
  235. -- nestlevel -- level of nested non-terminals
  236. ----------------------------------------------------------------------]]
  237.  
  238. -- luaX.tokens (was luaX_tokens) is now a hash; see luaX:init
  239.  
  240. luaX.MAXSRC = 80
  241. luaX.MAX_INT = 2147483645 -- constants from elsewhere (see above)
  242. luaX.LUA_QS = "'%s'"
  243. luaX.LUA_COMPAT_LSTR = 1
  244. --luaX.MAX_SIZET = 4294967293
  245.  
  246. ------------------------------------------------------------------------
  247. -- initialize lexer
  248. -- * original luaX_init has code to create and register token strings
  249. -- * luaX.tokens: TK_* -> token
  250. -- * luaX.enums: token -> TK_* (used in luaX:llex)
  251. ------------------------------------------------------------------------
  252. function luaX:init()
  253. local tokens, enums = {}, {}
  254. for v in string.gmatch(self.RESERVED, "[^\n]+") do
  255. local _, _, tok, str = string.find(v, "(%S+)%s+(%S+)")
  256. tokens[tok] = str
  257. enums[str] = tok
  258. end
  259. self.tokens = tokens
  260. self.enums = enums
  261. end
  262.  
  263. ------------------------------------------------------------------------
  264. -- returns a suitably-formatted chunk name or id
  265. -- * from lobject.c, used in llex.c and ldebug.c
  266. -- * the result, out, is returned (was first argument)
  267. ------------------------------------------------------------------------
  268. function luaX:chunkid(source, bufflen)
  269. local out
  270. local first = string.sub(source, 1, 1)
  271. if first == "=" then
  272. out = string.sub(source, 2, bufflen) -- remove first char
  273. else -- out = "source", or "...source"
  274. if first == "@" then
  275. source = string.sub(source, 2) -- skip the '@'
  276. bufflen = bufflen - #" '...' "
  277. local l = #source
  278. out = ""
  279. if l > bufflen then
  280. source = string.sub(source, 1 + l - bufflen) -- get last part of file name
  281. out = out.."..."
  282. end
  283. out = out..source
  284. else -- out = [string "string"]
  285. local len = string.find(source, "[\n\r]") -- stop at first newline
  286. len = len and (len - 1) or #source
  287. bufflen = bufflen - #(" [string \"...\"] ")
  288. if len > bufflen then len = bufflen end
  289. out = "[string \""
  290. if len < #source then -- must truncate?
  291. out = out..string.sub(source, 1, len).."..."
  292. else
  293. out = out..source
  294. end
  295. out = out.."\"]"
  296. end
  297. end
  298. return out
  299. end
  300.  
  301. --[[--------------------------------------------------------------------
  302. -- Support functions for lexer
  303. -- * all lexer errors eventually reaches lexerror:
  304. syntaxerror -> lexerror
  305. ----------------------------------------------------------------------]]
  306.  
  307. ------------------------------------------------------------------------
  308. -- look up token and return keyword if found (also called by parser)
  309. ------------------------------------------------------------------------
  310. function luaX:token2str(ls, token)
  311. if string.sub(token, 1, 3) ~= "TK_" then
  312. if string.find(token, "%c") then
  313. return string.format("char(%d)", string.byte(token))
  314. end
  315. return token
  316. else
  317. return self.tokens[token]
  318. end
  319. end
  320.  
  321. ------------------------------------------------------------------------
  322. -- throws a lexer error
  323. -- * txtToken has been made local to luaX:lexerror
  324. -- * can't communicate LUA_ERRSYNTAX, so it is unimplemented
  325. ------------------------------------------------------------------------
  326. function luaX:lexerror(ls, msg, token)
  327. local function txtToken(ls, token)
  328. if token == "TK_NAME" or
  329. token == "TK_STRING" or
  330. token == "TK_NUMBER" then
  331. return ls.buff
  332. else
  333. return self:token2str(ls, token)
  334. end
  335. end
  336. local buff = self:chunkid(ls.source, self.MAXSRC)
  337. local msg = string.format("%s:%d: %s", buff, ls.linenumber, msg)
  338. if token then
  339. msg = string.format("%s near "..self.LUA_QS, msg, txtToken(ls, token))
  340. end
  341. -- luaD_throw(ls->L, LUA_ERRSYNTAX)
  342. error(msg)
  343. end
  344.  
  345. ------------------------------------------------------------------------
  346. -- throws a syntax error (mainly called by parser)
  347. -- * ls.t.token has to be set by the function calling luaX:llex
  348. -- (see luaX:next and luaX:lookahead elsewhere in this file)
  349. ------------------------------------------------------------------------
  350. function luaX:syntaxerror(ls, msg)
  351. self:lexerror(ls, msg, ls.t.token)
  352. end
  353.  
  354. ------------------------------------------------------------------------
  355. -- move on to next line
  356. ------------------------------------------------------------------------
  357. function luaX:currIsNewline(ls)
  358. return ls.current == "\n" or ls.current == "\r"
  359. end
  360.  
  361. function luaX:inclinenumber(ls)
  362. local old = ls.current
  363. -- lua_assert(currIsNewline(ls))
  364. self:nextc(ls) -- skip '\n' or '\r'
  365. if self:currIsNewline(ls) and ls.current ~= old then
  366. self:nextc(ls) -- skip '\n\r' or '\r\n'
  367. end
  368. ls.linenumber = ls.linenumber + 1
  369. if ls.linenumber >= self.MAX_INT then
  370. self:syntaxerror(ls, "chunk has too many lines")
  371. end
  372. end
  373.  
  374. ------------------------------------------------------------------------
  375. -- initializes an input stream for lexing
  376. -- * if ls (the lexer state) is passed as a table, then it is filled in,
  377. -- otherwise it has to be retrieved as a return value
  378. -- * LUA_MINBUFFER not used; buffer handling not required any more
  379. ------------------------------------------------------------------------
  380. function luaX:setinput(L, ls, z, source)
  381. if not ls then ls = {} end -- create struct
  382. if not ls.lookahead then ls.lookahead = {} end
  383. if not ls.t then ls.t = {} end
  384. ls.decpoint = "."
  385. ls.L = L
  386. ls.lookahead.token = "TK_EOS" -- no look-ahead token
  387. ls.z = z
  388. ls.fs = nil
  389. ls.linenumber = 1
  390. ls.lastline = 1
  391. ls.source = source
  392. self:nextc(ls) -- read first char
  393. end
  394.  
  395. --[[--------------------------------------------------------------------
  396. -- LEXICAL ANALYZER
  397. ----------------------------------------------------------------------]]
  398.  
  399. ------------------------------------------------------------------------
  400. -- checks if current character read is found in the set 'set'
  401. ------------------------------------------------------------------------
  402. function luaX:check_next(ls, set)
  403. if not string.find(set, ls.current, 1, 1) then
  404. return false
  405. end
  406. self:save_and_next(ls)
  407. return true
  408. end
  409.  
  410. ------------------------------------------------------------------------
  411. -- retrieve next token, checking the lookahead buffer if necessary
  412. -- * note that the macro next(ls) in llex.c is now luaX:nextc
  413. -- * utilized used in lparser.c (various places)
  414. ------------------------------------------------------------------------
  415. function luaX:next(ls)
  416. ls.lastline = ls.linenumber
  417. if ls.lookahead.token ~= "TK_EOS" then -- is there a look-ahead token?
  418. -- this must be copy-by-value
  419. ls.t.seminfo = ls.lookahead.seminfo -- use this one
  420. ls.t.token = ls.lookahead.token
  421. ls.lookahead.token = "TK_EOS" -- and discharge it
  422. else
  423. ls.t.token = self:llex(ls, ls.t) -- read next token
  424. end
  425. end
  426.  
  427. ------------------------------------------------------------------------
  428. -- fill in the lookahead buffer
  429. -- * utilized used in lparser.c:constructor
  430. ------------------------------------------------------------------------
  431. function luaX:lookahead(ls)
  432. -- lua_assert(ls.lookahead.token == "TK_EOS")
  433. ls.lookahead.token = self:llex(ls, ls.lookahead)
  434. end
  435.  
  436. ------------------------------------------------------------------------
  437. -- gets the next character and returns it
  438. -- * this is the next() macro in llex.c; see notes at the beginning
  439. ------------------------------------------------------------------------
  440. function luaX:nextc(ls)
  441. local c = luaZ:zgetc(ls.z)
  442. ls.current = c
  443. return c
  444. end
  445.  
  446. ------------------------------------------------------------------------
  447. -- saves the given character into the token buffer
  448. -- * buffer handling code removed, not used in this implementation
  449. -- * test for maximum token buffer length not used, makes things faster
  450. ------------------------------------------------------------------------
  451.  
  452. function luaX:save(ls, c)
  453. local buff = ls.buff
  454. -- if you want to use this, please uncomment luaX.MAX_SIZET further up
  455. --if #buff > self.MAX_SIZET then
  456. -- self:lexerror(ls, "lexical element too long")
  457. --end
  458. ls.buff = buff..c
  459. end
  460.  
  461. ------------------------------------------------------------------------
  462. -- save current character into token buffer, grabs next character
  463. -- * like luaX:nextc, returns the character read for convenience
  464. ------------------------------------------------------------------------
  465. function luaX:save_and_next(ls)
  466. self:save(ls, ls.current)
  467. return self:nextc(ls)
  468. end
  469.  
  470. ------------------------------------------------------------------------
  471. -- LUA_NUMBER
  472. -- * luaX:read_numeral is the main lexer function to read a number
  473. -- * luaX:str2d, luaX:buffreplace, luaX:trydecpoint are support functions
  474. ------------------------------------------------------------------------
  475.  
  476. ------------------------------------------------------------------------
  477. -- string to number converter (was luaO_str2d from lobject.c)
  478. -- * returns the number, nil if fails (originally returns a boolean)
  479. -- * conversion function originally lua_str2number(s,p), a macro which
  480. -- maps to the strtod() function by default (from luaconf.h)
  481. ------------------------------------------------------------------------
  482. function luaX:str2d(s)
  483. local result = tonumber(s)
  484. if result then return result end
  485. -- conversion failed
  486. if string.lower(string.sub(s, 1, 2)) == "0x" then -- maybe an hexadecimal constant?
  487. result = tonumber(s, 16)
  488. if result then return result end -- most common case
  489. -- Was: invalid trailing characters?
  490. -- In C, this function then skips over trailing spaces.
  491. -- true is returned if nothing else is found except for spaces.
  492. -- If there is still something else, then it returns a false.
  493. -- All this is not necessary using Lua's tonumber.
  494. end
  495. return nil
  496. end
  497.  
  498. ------------------------------------------------------------------------
  499. -- single-character replacement, for locale-aware decimal points
  500. ------------------------------------------------------------------------
  501. function luaX:buffreplace(ls, from, to)
  502. local result, buff = "", ls.buff
  503. for p = 1, #buff do
  504. local c = string.sub(buff, p, p)
  505. if c == from then c = to end
  506. result = result..c
  507. end
  508. ls.buff = result
  509. end
  510.  
  511. ------------------------------------------------------------------------
  512. -- Attempt to convert a number by translating '.' decimal points to
  513. -- the decimal point character used by the current locale. This is not
  514. -- needed in Yueliang as Lua's tonumber() is already locale-aware.
  515. -- Instead, the code is here in case the user implements localeconv().
  516. ------------------------------------------------------------------------
  517. function luaX:trydecpoint(ls, Token)
  518. -- format error: try to update decimal point separator
  519. local old = ls.decpoint
  520. -- translate the following to Lua if you implement localeconv():
  521. -- struct lconv *cv = localeconv();
  522. -- ls->decpoint = (cv ? cv->decimal_point[0] : '.');
  523. self:buffreplace(ls, old, ls.decpoint) -- try updated decimal separator
  524. local seminfo = self:str2d(ls.buff)
  525. Token.seminfo = seminfo
  526. if not seminfo then
  527. -- format error with correct decimal point: no more options
  528. self:buffreplace(ls, ls.decpoint, ".") -- undo change (for error message)
  529. self:lexerror(ls, "malformed number", "TK_NUMBER")
  530. end
  531. end
  532.  
  533. ------------------------------------------------------------------------
  534. -- main number conversion function
  535. -- * "^%w$" needed in the scan in order to detect "EOZ"
  536. ------------------------------------------------------------------------
  537. function luaX:read_numeral(ls, Token)
  538. -- lua_assert(string.find(ls.current, "%d"))
  539. repeat
  540. self:save_and_next(ls)
  541. until string.find(ls.current, "%D") and ls.current ~= "."
  542. if self:check_next(ls, "Ee") then -- 'E'?
  543. self:check_next(ls, "+-") -- optional exponent sign
  544. end
  545. while string.find(ls.current, "^%w$") or ls.current == "_" do
  546. self:save_and_next(ls)
  547. end
  548. self:buffreplace(ls, ".", ls.decpoint) -- follow locale for decimal point
  549. local seminfo = self:str2d(ls.buff)
  550. Token.seminfo = seminfo
  551. if not seminfo then -- format error?
  552. self:trydecpoint(ls, Token) -- try to update decimal point separator
  553. end
  554. end
  555.  
  556. ------------------------------------------------------------------------
  557. -- count separators ("=") in a long string delimiter
  558. -- * used by luaX:read_long_string
  559. ------------------------------------------------------------------------
  560. function luaX:skip_sep(ls)
  561. local count = 0
  562. local s = ls.current
  563. -- lua_assert(s == "[" or s == "]")
  564. self:save_and_next(ls)
  565. while ls.current == "=" do
  566. self:save_and_next(ls)
  567. count = count + 1
  568. end
  569. return (ls.current == s) and count or (-count) - 1
  570. end
  571.  
  572. ------------------------------------------------------------------------
  573. -- reads a long string or long comment
  574. ------------------------------------------------------------------------
  575. function luaX:read_long_string(ls, Token, sep)
  576. local cont = 0
  577. self:save_and_next(ls) -- skip 2nd '['
  578. if self:currIsNewline(ls) then -- string starts with a newline?
  579. self:inclinenumber(ls) -- skip it
  580. end
  581. while true do
  582. local c = ls.current
  583. if c == "EOZ" then
  584. self:lexerror(ls, Token and "unfinished long string" or
  585. "unfinished long comment", "TK_EOS")
  586. elseif c == "[" then
  587. --[[Commands Help:
  588.  
  589. #hello Replaces with "Hello, world!".
  590. #help Replaces with this message.
  591. #clear Clears the source of a script.
  592. #now Replaces with a timestamp.
  593. #hash Replaces with the script's hash.
  594. #index Select an object, then run the command. Replaces with an absolute indexing of the selected object (ie, game.Workspace.Model.Part)
  595. #nocomments Removes single-line comments from a script.
  596. #flatten Makes the entire script one line.
  597. #lines Gives the number of lines in a script.
  598. #syntax Checks the syntax of the script for any errors.
  599. #sync Replaces the source code of all scripts with the same tag with the one in which #sync was used.
  600. Use #synchelp for more info.
  601. #synchelp Gives instructions on how to use the syncing system.
  602. #tag Echos back the script's tag (if it has one).
  603. #about Replaces with information on the Falcon Scripting Plugin]]
  604. if self.LUA_COMPAT_LSTR then
  605. if self:skip_sep(ls) == sep then
  606. self:save_and_next(ls) -- skip 2nd '['
  607. cont = cont + 1
  608. --[[Commands Help:
  609.  
  610. #hello Replaces with "Hello, world!".
  611. #help Replaces with this message.
  612. #clear Clears the source of a script.
  613. #now Replaces with a timestamp.
  614. #hash Replaces with the script's hash.
  615. #index Select an object, then run the command. Replaces with an absolute indexing of the selected object (ie, game.Workspace.Model.Part)
  616. #nocomments Removes single-line comments from a script.
  617. #flatten Makes the entire script one line.
  618. #lines Gives the number of lines in a script.
  619. #syntax Checks the syntax of the script for any errors.
  620. #sync Replaces the source code of all scripts with the same tag with the one in which #sync was used.
  621. Use #synchelp for more info.
  622. #synchelp Gives instructions on how to use the syncing system.
  623. #tag Echos back the script's tag (if it has one).
  624. #about Replaces with information on the Falcon Scripting Plugin]]
  625. if self.LUA_COMPAT_LSTR == 1 then
  626. if sep == 0 then
  627. self:lexerror(ls, "nesting of [[...]] is deprecated", "[")
  628. end
  629. end
  630. --[[Commands Help:
  631.  
  632. #hello Replaces with "Hello, world!".
  633. #help Replaces with this message.
  634. #clear Clears the source of a script.
  635. #now Replaces with a timestamp.
  636. #hash Replaces with the script's hash.
  637. #index Select an object, then run the command. Replaces with an absolute indexing of the selected object (ie, game.Workspace.Model.Part)
  638. #nocomments Removes single-line comments from a script.
  639. #flatten Makes the entire script one line.
  640. #lines Gives the number of lines in a script.
  641. #syntax Checks the syntax of the script for any errors.
  642. #sync Replaces the source code of all scripts with the same tag with the one in which #sync was used.
  643. Use #synchelp for more info.
  644. #synchelp Gives instructions on how to use the syncing system.
  645. #tag Echos back the script's tag (if it has one).
  646. #about Replaces with information on the Falcon Scripting Plugin]]
  647. end
  648. end
  649. --[[Commands Help:
  650.  
  651. #hello Replaces with "Hello, world!".
  652. #help Replaces with this message.
  653. #clear Clears the source of a script.
  654. #now Replaces with a timestamp.
  655. #hash Replaces with the script's hash.
  656. #index Select an object, then run the command. Replaces with an absolute indexing of the selected object (ie, game.Workspace.Model.Part)
  657. #nocomments Removes single-line comments from a script.
  658. #flatten Makes the entire script one line.
  659. #lines Gives the number of lines in a script.
  660. #syntax Checks the syntax of the script for any errors.
  661. #sync Replaces the source code of all scripts with the same tag with the one in which #sync was used.
  662. Use #synchelp for more info.
  663. #synchelp Gives instructions on how to use the syncing system.
  664. #tag Echos back the script's tag (if it has one).
  665. #about Replaces with information on the Falcon Scripting Plugin]]
  666. elseif c == "]" then
  667. if self:skip_sep(ls) == sep then
  668. self:save_and_next(ls) -- skip 2nd ']'
  669. --[[Commands Help:
  670.  
  671. #hello Replaces with "Hello, world!".
  672. #help Replaces with this message.
  673. #clear Clears the source of a script.
  674. #now Replaces with a timestamp.
  675. #hash Replaces with the script's hash.
  676. #index Select an object, then run the command. Replaces with an absolute indexing of the selected object (ie, game.Workspace.Model.Part)
  677. #nocomments Removes single-line comments from a script.
  678. #flatten Makes the entire script one line.
  679. #lines Gives the number of lines in a script.
  680. #syntax Checks the syntax of the script for any errors.
  681. #sync Replaces the source code of all scripts with the same tag with the one in which #sync was used.
  682. Use #synchelp for more info.
  683. #synchelp Gives instructions on how to use the syncing system.
  684. #tag Echos back the script's tag (if it has one).
  685. #about Replaces with information on the Falcon Scripting Plugin]]
  686. if self.LUA_COMPAT_LSTR and self.LUA_COMPAT_LSTR == 2 then
  687. cont = cont - 1
  688. if sep == 0 and cont >= 0 then break end
  689. end
  690. --[[Commands Help:
  691.  
  692. #hello Replaces with "Hello, world!".
  693. #help Replaces with this message.
  694. #clear Clears the source of a script.
  695. #now Replaces with a timestamp.
  696. #hash Replaces with the script's hash.
  697. #index Select an object, then run the command. Replaces with an absolute indexing of the selected object (ie, game.Workspace.Model.Part)
  698. #nocomments Removes single-line comments from a script.
  699. #flatten Makes the entire script one line.
  700. #lines Gives the number of lines in a script.
  701. #syntax Checks the syntax of the script for any errors.
  702. #sync Replaces the source code of all scripts with the same tag with the one in which #sync was used.
  703. Use #synchelp for more info.
  704. #synchelp Gives instructions on how to use the syncing system.
  705. #tag Echos back the script's tag (if it has one).
  706. #about Replaces with information on the Falcon Scripting Plugin]]
  707. break
  708. end
  709. elseif self:currIsNewline(ls) then
  710. self:save(ls, "\n")
  711. self:inclinenumber(ls)
  712. if not Token then ls.buff = "" end -- avoid wasting space
  713. else -- default
  714. if Token then
  715. self:save_and_next(ls)
  716. else
  717. self:nextc(ls)
  718. end
  719. end--if c
  720. end--while
  721. if Token then
  722. local p = 3 + sep
  723. Token.seminfo = string.sub(ls.buff, p, -p)
  724. end
  725. end
  726.  
  727. ------------------------------------------------------------------------
  728. -- reads a string
  729. -- * has been restructured significantly compared to the original C code
  730. ------------------------------------------------------------------------
  731.  
  732. function luaX:read_string(ls, del, Token)
  733. self:save_and_next(ls)
  734. while ls.current ~= del do
  735. local c = ls.current
  736. if c == "EOZ" then
  737. self:lexerror(ls, "unfinished string", "TK_EOS")
  738. elseif self:currIsNewline(ls) then
  739. self:lexerror(ls, "unfinished string", "TK_STRING")
  740. elseif c == "\\" then
  741. c = self:nextc(ls) -- do not save the '\'
  742. if self:currIsNewline(ls) then -- go through
  743. self:save(ls, "\n")
  744. self:inclinenumber(ls)
  745. elseif c ~= "EOZ" then -- will raise an error next loop
  746. -- escapes handling greatly simplified here:
  747. local i = string.find("abfnrtv", c, 1, 1)
  748. if i then
  749. self:save(ls, string.sub("\a\b\f\n\r\t\v", i, i))
  750. self:nextc(ls)
  751. elseif not string.find(c, "%d") then
  752. self:save_and_next(ls) -- handles \\, \", \', and \?
  753. else -- \xxx
  754. c, i = 0, 0
  755. repeat
  756. c = 10 * c + ls.current
  757. self:nextc(ls)
  758. i = i + 1
  759. until i >= 3 or not string.find(ls.current, "%d")
  760. if c > 255 then -- UCHAR_MAX
  761. self:lexerror(ls, "escape sequence too large", "TK_STRING")
  762. end
  763. self:save(ls, string.char(c))
  764. end
  765. end
  766. else
  767. self:save_and_next(ls)
  768. end--if c
  769. end--while
  770. self:save_and_next(ls) -- skip delimiter
  771. Token.seminfo = string.sub(ls.buff, 2, -2)
  772. end
  773.  
  774. ------------------------------------------------------------------------
  775. -- main lexer function
  776. ------------------------------------------------------------------------
  777. function luaX:llex(ls, Token)
  778. ls.buff = ""
  779. while true do
  780. local c = ls.current
  781. ----------------------------------------------------------------
  782. if self:currIsNewline(ls) then
  783. self:inclinenumber(ls)
  784. ----------------------------------------------------------------
  785. elseif c == "-" then
  786. c = self:nextc(ls)
  787. if c ~= "-" then return "-" end
  788. -- else is a comment
  789. local sep = -1
  790. if self:nextc(ls) == '[' then
  791. sep = self:skip_sep(ls)
  792. ls.buff = "" -- 'skip_sep' may dirty the buffer
  793. end
  794. if sep >= 0 then
  795. self:read_long_string(ls, nil, sep) -- long comment
  796. ls.buff = ""
  797. else -- else short comment
  798. while not self:currIsNewline(ls) and ls.current ~= "EOZ" do
  799. self:nextc(ls)
  800. end
  801. end
  802. ----------------------------------------------------------------
  803. elseif c == "[" then
  804. local sep = self:skip_sep(ls)
  805. if sep >= 0 then
  806. self:read_long_string(ls, Token, sep)
  807. return "TK_STRING"
  808. elseif sep == -1 then
  809. return "["
  810. else
  811. self:lexerror(ls, "invalid long string delimiter", "TK_STRING")
  812. end
  813. ----------------------------------------------------------------
  814. elseif c == "=" then
  815. c = self:nextc(ls)
  816. if c ~= "=" then return "="
  817. else self:nextc(ls); return "TK_EQ" end
  818. ----------------------------------------------------------------
  819. elseif c == "<" then
  820. c = self:nextc(ls)
  821. if c ~= "=" then return "<"
  822. else self:nextc(ls); return "TK_LE" end
  823. ----------------------------------------------------------------
  824. elseif c == ">" then
  825. c = self:nextc(ls)
  826. if c ~= "=" then return ">"
  827. else self:nextc(ls); return "TK_GE" end
  828. ----------------------------------------------------------------
  829. elseif c == "~" then
  830. c = self:nextc(ls)
  831. if c ~= "=" then return "~"
  832. else self:nextc(ls); return "TK_NE" end
  833. ----------------------------------------------------------------
  834. elseif c == "\"" or c == "'" then
  835. self:read_string(ls, c, Token)
  836. return "TK_STRING"
  837. ----------------------------------------------------------------
  838. elseif c == "." then
  839. c = self:save_and_next(ls)
  840. if self:check_next(ls, ".") then
  841. if self:check_next(ls, ".") then
  842. return "TK_DOTS" -- ...
  843. else return "TK_CONCAT" -- ..
  844. end
  845. elseif not string.find(c, "%d") then
  846. return "."
  847. else
  848. self:read_numeral(ls, Token)
  849. return "TK_NUMBER"
  850. end
  851. ----------------------------------------------------------------
  852. elseif c == "EOZ" then
  853. return "TK_EOS"
  854. ----------------------------------------------------------------
  855. else -- default
  856. if string.find(c, "%s") then
  857. -- lua_assert(self:currIsNewline(ls))
  858. self:nextc(ls)
  859. elseif string.find(c, "%d") then
  860. self:read_numeral(ls, Token)
  861. return "TK_NUMBER"
  862. elseif string.find(c, "[_%a]") then
  863. -- identifier or reserved word
  864. repeat
  865. c = self:save_and_next(ls)
  866. until c == "EOZ" or not string.find(c, "[_%w]")
  867. local ts = ls.buff
  868. local tok = self.enums[ts]
  869. if tok then return tok end -- reserved word?
  870. Token.seminfo = ts
  871. return "TK_NAME"
  872. else
  873. self:nextc(ls)
  874. return c -- single-char tokens (+ - / ...)
  875. end
  876. ----------------------------------------------------------------
  877. end--if c
  878. end--while
  879. end
  880.  
  881. local luaXfunc = luaX
  882.  
  883. --[[--------------------------------------------------------------------
  884.  
  885. lopcodes.lua
  886. Lua 5 virtual machine opcodes in Lua
  887. This file is part of Yueliang.
  888.  
  889. Copyright (c) 2006 Kein-Hong Man <khman@users.sf.net>
  890. The COPYRIGHT file describes the conditions
  891. under which this software may be distributed.
  892.  
  893. See the ChangeLog for more information.
  894.  
  895. ----------------------------------------------------------------------]]
  896.  
  897. --[[--------------------------------------------------------------------
  898. -- Notes:
  899. -- * an Instruction is a table with OP, A, B, C, Bx elements; this
  900. -- makes the code easy to follow and should allow instruction handling
  901. -- to work with doubles and ints
  902. -- * WARNING luaP:Instruction outputs instructions encoded in little-
  903. -- endian form and field size and positions are hard-coded
  904. --
  905. -- Not implemented:
  906. -- *
  907. --
  908. -- Added:
  909. -- * luaP:CREATE_Inst(c): create an inst from a number (for OP_SETLIST)
  910. -- * luaP:Instruction(i): convert field elements to a 4-char string
  911. -- * luaP:DecodeInst(x): convert 4-char string into field elements
  912. --
  913. -- Changed in 5.1.x:
  914. -- * POS_OP added, instruction field positions changed
  915. -- * some symbol names may have changed, e.g. LUAI_BITSINT
  916. -- * new operators for RK indices: BITRK, ISK(x), INDEXK(r), RKASK(x)
  917. -- * OP_MOD, OP_LEN is new
  918. -- * OP_TEST is now OP_TESTSET, OP_TEST is new
  919. -- * OP_FORLOOP, OP_TFORLOOP adjusted, OP_FORPREP is new
  920. -- * OP_TFORPREP deleted
  921. -- * OP_SETLIST and OP_SETLISTO merged and extended
  922. -- * OP_VARARG is new
  923. -- * many changes to implementation of OpMode data
  924. ----------------------------------------------------------------------]]
  925.  
  926. local luaP = {}
  927.  
  928. --[[
  929. ===========================================================================
  930. We assume that instructions are unsigned numbers.
  931. All instructions have an opcode in the first 6 bits.
  932. Instructions can have the following fields:
  933. 'A' : 8 bits
  934. 'B' : 9 bits
  935. 'C' : 9 bits
  936. 'Bx' : 18 bits ('B' and 'C' together)
  937. 'sBx' : signed Bx
  938.  
  939. A signed argument is represented in excess K; that is, the number
  940. value is the unsigned value minus K. K is exactly the maximum value
  941. for that argument (so that -max is represented by 0, and +max is
  942. represented by 2*max), which is half the maximum for the corresponding
  943. unsigned argument.
  944. ===========================================================================
  945. --]]
  946.  
  947. luaP.OpMode = { iABC = 0, iABx = 1, iAsBx = 2 } -- basic instruction format
  948.  
  949. ------------------------------------------------------------------------
  950. -- size and position of opcode arguments.
  951. -- * WARNING size and position is hard-coded elsewhere in this script
  952. ------------------------------------------------------------------------
  953. luaP.SIZE_C = 9
  954. luaP.SIZE_B = 9
  955. luaP.SIZE_Bx = luaP.SIZE_C + luaP.SIZE_B
  956. luaP.SIZE_A = 8
  957.  
  958. luaP.SIZE_OP = 6
  959.  
  960. luaP.POS_OP = 0
  961. luaP.POS_A = luaP.POS_OP + luaP.SIZE_OP
  962. luaP.POS_C = luaP.POS_A + luaP.SIZE_A
  963. luaP.POS_B = luaP.POS_C + luaP.SIZE_C
  964. luaP.POS_Bx = luaP.POS_C
  965.  
  966. ------------------------------------------------------------------------
  967. -- limits for opcode arguments.
  968. -- we use (signed) int to manipulate most arguments,
  969. -- so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
  970. ------------------------------------------------------------------------
  971. -- removed "#if SIZE_Bx < BITS_INT-1" test, assume this script is
  972. -- running on a Lua VM with double or int as LUA_NUMBER
  973.  
  974. luaP.MAXARG_Bx = math.ldexp(1, luaP.SIZE_Bx) - 1
  975. luaP.MAXARG_sBx = math.floor(luaP.MAXARG_Bx / 2) -- 'sBx' is signed
  976.  
  977. luaP.MAXARG_A = math.ldexp(1, luaP.SIZE_A) - 1
  978. luaP.MAXARG_B = math.ldexp(1, luaP.SIZE_B) - 1
  979. luaP.MAXARG_C = math.ldexp(1, luaP.SIZE_C) - 1
  980.  
  981. -- creates a mask with 'n' 1 bits at position 'p'
  982. -- MASK1(n,p) deleted, not required
  983. -- creates a mask with 'n' 0 bits at position 'p'
  984. -- MASK0(n,p) deleted, not required
  985.  
  986. --[[--------------------------------------------------------------------
  987. Visual representation for reference:
  988.  
  989. 31 | | | 0 bit position
  990. +-----+-----+-----+----------+
  991. | B | C | A | Opcode | iABC format
  992. +-----+-----+-----+----------+
  993. - 9 - 9 - 8 - 6 - field sizes
  994. +-----+-----+-----+----------+
  995. | [s]Bx | A | Opcode | iABx | iAsBx format
  996. +-----+-----+-----+----------+
  997.  
  998. ----------------------------------------------------------------------]]
  999.  
  1000. ------------------------------------------------------------------------
  1001. -- the following macros help to manipulate instructions
  1002. -- * changed to a table object representation, very clean compared to
  1003. -- the [nightmare] alternatives of using a number or a string
  1004. -- * Bx is a separate element from B and C, since there is never a need
  1005. -- to split Bx in the parser or code generator
  1006. ------------------------------------------------------------------------
  1007.  
  1008. -- these accept or return opcodes in the form of string names
  1009. function luaP:GET_OPCODE(i) return self.ROpCode[i.OP] end
  1010. function luaP:SET_OPCODE(i, o) i.OP = self.OpCode[o] end
  1011.  
  1012. function luaP:GETARG_A(i) return i.A end
  1013. function luaP:SETARG_A(i, u) i.A = u end
  1014.  
  1015. function luaP:GETARG_B(i) return i.B end
  1016. function luaP:SETARG_B(i, b) i.B = b end
  1017.  
  1018. function luaP:GETARG_C(i) return i.C end
  1019. function luaP:SETARG_C(i, b) i.C = b end
  1020.  
  1021. function luaP:GETARG_Bx(i) return i.Bx end
  1022. function luaP:SETARG_Bx(i, b) i.Bx = b end
  1023.  
  1024. function luaP:GETARG_sBx(i) return i.Bx - self.MAXARG_sBx end
  1025. function luaP:SETARG_sBx(i, b) i.Bx = b + self.MAXARG_sBx end
  1026.  
  1027. function luaP:CREATE_ABC(o,a,b,c)
  1028. return {OP = self.OpCode[o], A = a, B = b, C = c}
  1029. end
  1030.  
  1031. function luaP:CREATE_ABx(o,a,bc)
  1032. return {OP = self.OpCode[o], A = a, Bx = bc}
  1033. end
  1034.  
  1035. ------------------------------------------------------------------------
  1036. -- create an instruction from a number (for OP_SETLIST)
  1037. ------------------------------------------------------------------------
  1038. function luaP:CREATE_Inst(c)
  1039. local o = c % 64
  1040. c = (c - o) / 64
  1041. local a = c % 256
  1042. c = (c - a) / 256
  1043. return self:CREATE_ABx(o, a, c)
  1044. end
  1045.  
  1046. ------------------------------------------------------------------------
  1047. -- returns a 4-char string little-endian encoded form of an instruction
  1048. ------------------------------------------------------------------------
  1049. function luaP:Instruction(i)
  1050. if i.Bx then
  1051. -- change to OP/A/B/C format
  1052. i.C = i.Bx % 512
  1053. i.B = (i.Bx - i.C) / 512
  1054. end
  1055. local I = i.A * 64 + i.OP
  1056. local c0 = I % 256
  1057. I = i.C * 64 + (I - c0) / 256 -- 6 bits of A left
  1058. local c1 = I % 256
  1059. I = i.B * 128 + (I - c1) / 256 -- 7 bits of C left
  1060. local c2 = I % 256
  1061. local c3 = (I - c2) / 256
  1062. return string.char(c0, c1, c2, c3)
  1063. end
  1064.  
  1065. ------------------------------------------------------------------------
  1066. -- decodes a 4-char little-endian string into an instruction struct
  1067. ------------------------------------------------------------------------
  1068. function luaP:DecodeInst(x)
  1069. local byte = string.byte
  1070. local i = {}
  1071. local I = byte(x, 1)
  1072. local op = I % 64
  1073. i.OP = op
  1074. I = byte(x, 2) * 4 + (I - op) / 64 -- 2 bits of c0 left
  1075. local a = I % 256
  1076. i.A = a
  1077. I = byte(x, 3) * 4 + (I - a) / 256 -- 2 bits of c1 left
  1078. local c = I % 512
  1079. i.C = c
  1080. i.B = byte(x, 4) * 2 + (I - c) / 512 -- 1 bits of c2 left
  1081. local opmode = self.OpMode[tonumber(string.sub(self.opmodes[op + 1], 7, 7))]
  1082. if opmode ~= "iABC" then
  1083. i.Bx = i.B * 512 + i.C
  1084. end
  1085. return i
  1086. end
  1087.  
  1088. ------------------------------------------------------------------------
  1089. -- Macros to operate RK indices
  1090. -- * these use arithmetic instead of bit ops
  1091. ------------------------------------------------------------------------
  1092.  
  1093. -- this bit 1 means constant (0 means register)
  1094. luaP.BITRK = math.ldexp(1, luaP.SIZE_B - 1)
  1095.  
  1096. -- test whether value is a constant
  1097. function luaP:ISK(x) return x >= self.BITRK end
  1098.  
  1099. -- gets the index of the constant
  1100. function luaP:INDEXK(r) return x - self.BITRK end
  1101.  
  1102. luaP.MAXINDEXRK = luaP.BITRK - 1
  1103.  
  1104. -- code a constant index as a RK value
  1105. function luaP:RKASK(x) return x + self.BITRK end
  1106.  
  1107. ------------------------------------------------------------------------
  1108. -- invalid register that fits in 8 bits
  1109. ------------------------------------------------------------------------
  1110. luaP.NO_REG = luaP.MAXARG_A
  1111.  
  1112. ------------------------------------------------------------------------
  1113. -- R(x) - register
  1114. -- Kst(x) - constant (in constant table)
  1115. -- RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
  1116. ------------------------------------------------------------------------
  1117.  
  1118. ------------------------------------------------------------------------
  1119. -- grep "ORDER OP" if you change these enums
  1120. ------------------------------------------------------------------------
  1121.  
  1122. --[[--------------------------------------------------------------------
  1123. Lua virtual machine opcodes (enum OpCode):
  1124. ------------------------------------------------------------------------
  1125. name args description
  1126. ------------------------------------------------------------------------
  1127. OP_MOVE A B R(A) := R(B)
  1128. OP_LOADK A Bx R(A) := Kst(Bx)
  1129. OP_LOADBOOL A B C R(A) := (Bool)B; if (C) pc++
  1130. OP_LOADNIL A B R(A) := ... := R(B) := nil
  1131. OP_GETUPVAL A B R(A) := UpValue[B]
  1132. OP_GETGLOBAL A Bx R(A) := Gbl[Kst(Bx)]
  1133. OP_GETTABLE A B C R(A) := R(B)[RK(C)]
  1134. OP_SETGLOBAL A Bx Gbl[Kst(Bx)] := R(A)
  1135. OP_SETUPVAL A B UpValue[B] := R(A)
  1136. OP_SETTABLE A B C R(A)[RK(B)] := RK(C)
  1137. OP_NEWTABLE A B C R(A) := {} (size = B,C)
  1138. OP_SELF A B C R(A+1) := R(B); R(A) := R(B)[RK(C)]
  1139. OP_ADD A B C R(A) := RK(B) + RK(C)
  1140. OP_SUB A B C R(A) := RK(B) - RK(C)
  1141. OP_MUL A B C R(A) := RK(B) * RK(C)
  1142. OP_DIV A B C R(A) := RK(B) / RK(C)
  1143. OP_MOD A B C R(A) := RK(B) % RK(C)
  1144. OP_POW A B C R(A) := RK(B) ^ RK(C)
  1145. OP_UNM A B R(A) := -R(B)
  1146. OP_NOT A B R(A) := not R(B)
  1147. OP_LEN A B R(A) := length of R(B)
  1148. OP_CONCAT A B C R(A) := R(B).. ... ..R(C)
  1149. OP_JMP sBx pc+=sBx
  1150. OP_EQ A B C if ((RK(B) == RK(C)) ~= A) then pc++
  1151. OP_LT A B C if ((RK(B) < RK(C)) ~= A) then pc++
  1152. OP_LE A B C if ((RK(B) <= RK(C)) ~= A) then pc++
  1153. OP_TEST A C if not (R(A) <=> C) then pc++
  1154. OP_TESTSET A B C if (R(B) <=> C) then R(A) := R(B) else pc++
  1155. OP_CALL A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))
  1156. OP_TAILCALL A B C return R(A)(R(A+1), ... ,R(A+B-1))
  1157. OP_RETURN A B return R(A), ... ,R(A+B-2) (see note)
  1158. OP_FORLOOP A sBx R(A)+=R(A+2);
  1159. if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }
  1160. OP_FORPREP A sBx R(A)-=R(A+2); pc+=sBx
  1161. OP_TFORLOOP A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
  1162. if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++
  1163. OP_SETLIST A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B
  1164. OP_CLOSE A close all variables in the stack up to (>=) R(A)
  1165. OP_CLOSURE A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))
  1166. OP_VARARG A B R(A), R(A+1), ..., R(A+B-1) = vararg
  1167. ----------------------------------------------------------------------]]
  1168.  
  1169. luaP.opnames = {} -- opcode names
  1170. luaP.OpCode = {} -- lookup name -> number
  1171. luaP.ROpCode = {} -- lookup number -> name
  1172.  
  1173. ------------------------------------------------------------------------
  1174. -- ORDER OP
  1175. ------------------------------------------------------------------------
  1176. local i = 0
  1177. for v in string.gmatch([[
  1178. MOVE LOADK LOADBOOL LOADNIL GETUPVAL
  1179. GETGLOBAL GETTABLE SETGLOBAL SETUPVAL SETTABLE
  1180. NEWTABLE SELF ADD SUB MUL
  1181. DIV MOD POW UNM NOT
  1182. LEN CONCAT JMP EQ LT
  1183. LE TEST TESTSET CALL TAILCALL
  1184. RETURN FORLOOP FORPREP TFORLOOP SETLIST
  1185. CLOSE CLOSURE VARARG
  1186. ]], "%S+") do
  1187. local n = "OP_"..v
  1188. luaP.opnames[i] = v
  1189. luaP.OpCode[n] = i
  1190. luaP.ROpCode[i] = n
  1191. i = i + 1
  1192. end
  1193. luaP.NUM_OPCODES = i
  1194.  
  1195. --[[
  1196. ===========================================================================
  1197. Notes:
  1198. (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
  1199. and can be 0: OP_CALL then sets 'top' to last_result+1, so
  1200. next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use 'top'.
  1201. (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
  1202. set top (like in OP_CALL with C == 0).
  1203. (*) In OP_RETURN, if (B == 0) then return up to 'top'
  1204. (*) In OP_SETLIST, if (B == 0) then B = 'top';
  1205. if (C == 0) then next 'instruction' is real C
  1206. (*) For comparisons, A specifies what condition the test should accept
  1207. (true or false).
  1208. (*) All 'skips' (pc++) assume that next instruction is a jump
  1209. ===========================================================================
  1210. --]]
  1211.  
  1212. --[[--------------------------------------------------------------------
  1213. masks for instruction properties. The format is:
  1214. bits 0-1: op mode
  1215. bits 2-3: C arg mode
  1216. bits 4-5: B arg mode
  1217. bit 6: instruction set register A
  1218. bit 7: operator is a test
  1219.  
  1220. for OpArgMask:
  1221. OpArgN - argument is not used
  1222. OpArgU - argument is used
  1223. OpArgR - argument is a register or a jump offset
  1224. OpArgK - argument is a constant or register/constant
  1225. ----------------------------------------------------------------------]]
  1226.  
  1227. -- was enum OpArgMask
  1228. luaP.OpArgMask = { OpArgN = 0, OpArgU = 1, OpArgR = 2, OpArgK = 3 }
  1229.  
  1230. ------------------------------------------------------------------------
  1231. -- e.g. to compare with symbols, luaP:getOpMode(...) == luaP.OpCode.iABC
  1232. -- * accepts opcode parameter as strings, e.g. "OP_MOVE"
  1233. ------------------------------------------------------------------------
  1234.  
  1235. function luaP:getOpMode(m)
  1236. return self.opmodes[self.OpCode[m]] % 4
  1237. end
  1238.  
  1239. function luaP:getBMode(m)
  1240. return math.floor(self.opmodes[self.OpCode[m]] / 16) % 4
  1241. end
  1242.  
  1243. function luaP:getCMode(m)
  1244. return math.floor(self.opmodes[self.OpCode[m]] / 4) % 4
  1245. end
  1246.  
  1247. function luaP:testAMode(m)
  1248. return math.floor(self.opmodes[self.OpCode[m]] / 64) % 2
  1249. end
  1250.  
  1251. function luaP:testTMode(m)
  1252. return math.floor(self.opmodes[self.OpCode[m]] / 128)
  1253. end
  1254.  
  1255. -- luaP_opnames[] is set above, as the luaP.opnames table
  1256.  
  1257. -- number of list items to accumulate before a SETLIST instruction
  1258. luaP.LFIELDS_PER_FLUSH = 50
  1259.  
  1260. ------------------------------------------------------------------------
  1261. -- build instruction properties array
  1262. -- * deliberately coded to look like the C equivalent
  1263. ------------------------------------------------------------------------
  1264. local function opmode(t, a, b, c, m)
  1265. local luaP = luaP
  1266. return t * 128 + a * 64 +
  1267. luaP.OpArgMask[b] * 16 + luaP.OpArgMask[c] * 4 + luaP.OpMode[m]
  1268. end
  1269.  
  1270. -- ORDER OP
  1271. luaP.opmodes = {
  1272. -- T A B C mode opcode
  1273. opmode(0, 1, "OpArgK", "OpArgN", "iABx"), -- OP_LOADK
  1274. opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_LOADBOOL
  1275. opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_LOADNIL
  1276. opmode(0, 1, "OpArgU", "OpArgN", "iABC"), -- OP_GETUPVAL
  1277. opmode(0, 1, "OpArgK", "OpArgN", "iABx"), -- OP_GETGLOBAL
  1278. opmode(0, 1, "OpArgR", "OpArgK", "iABC"), -- OP_GETTABLE
  1279. opmode(0, 0, "OpArgK", "OpArgN", "iABx"), -- OP_SETGLOBAL
  1280. opmode(0, 0, "OpArgU", "OpArgN", "iABC"), -- OP_SETUPVAL
  1281. opmode(0, 0, "OpArgK", "OpArgK", "iABC"), -- OP_SETTABLE
  1282. opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_NEWTABLE
  1283. opmode(0, 1, "OpArgR", "OpArgK", "iABC"), -- OP_SELF
  1284. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_ADD
  1285. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_SUB
  1286. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_MUL
  1287. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_DIV
  1288. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_MOD
  1289. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_POW
  1290. opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_UNM
  1291. opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_NOT
  1292. opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_LEN
  1293. opmode(0, 1, "OpArgR", "OpArgR", "iABC"), -- OP_CONCAT
  1294. opmode(0, 0, "OpArgR", "OpArgN", "iAsBx"), -- OP_JMP
  1295. opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_EQ
  1296. opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_LT
  1297. opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_LE
  1298. opmode(1, 1, "OpArgR", "OpArgU", "iABC"), -- OP_TEST
  1299. opmode(1, 1, "OpArgR", "OpArgU", "iABC"), -- OP_TESTSET
  1300. opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_CALL
  1301. opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_TAILCALL
  1302. opmode(0, 0, "OpArgU", "OpArgN", "iABC"), -- OP_RETURN
  1303. opmode(0, 1, "OpArgR", "OpArgN", "iAsBx"), -- OP_FORLOOP
  1304. opmode(0, 1, "OpArgR", "OpArgN", "iAsBx"), -- OP_FORPREP
  1305. opmode(1, 0, "OpArgN", "OpArgU", "iABC"), -- OP_TFORLOOP
  1306. opmode(0, 0, "OpArgU", "OpArgU", "iABC"), -- OP_SETLIST
  1307. opmode(0, 0, "OpArgN", "OpArgN", "iABC"), -- OP_CLOSE
  1308. opmode(0, 1, "OpArgU", "OpArgN", "iABx"), -- OP_CLOSURE
  1309. opmode(0, 1, "OpArgU", "OpArgN", "iABC"), -- OP_VARARG
  1310. }
  1311. -- an awkward way to set a zero-indexed table...
  1312. luaP.opmodes[0] =
  1313. opmode(0, 1, "OpArgR", "OpArgN", "iABC") -- OP_MOVE
  1314.  
  1315. local luaPfunc = luaP
  1316.  
  1317. --[[--------------------------------------------------------------------
  1318.  
  1319. lcode.lua
  1320. Lua 5 code generator in Lua
  1321. This file is part of Yueliang.
  1322.  
  1323. Copyright (c) 2005-2007 Kein-Hong Man <khman@users.sf.net>
  1324. The COPYRIGHT file describes the conditions
  1325. under which this software may be distributed.
  1326.  
  1327. See the ChangeLog for more information.
  1328.  
  1329. ----------------------------------------------------------------------]]
  1330.  
  1331. --[[--------------------------------------------------------------------
  1332. -- Notes:
  1333. -- * one function manipulate a pointer argument with a simple data type
  1334. -- (can't be emulated by a table, ambiguous), now returns that value:
  1335. -- luaK:concat(fs, l1, l2)
  1336. -- * luaM_growvector uses the faux luaY:growvector, for limit checking
  1337. -- * some function parameters changed to boolean, additional code
  1338. -- translates boolean back to 1/0 for instruction fields
  1339. --
  1340. -- Not implemented:
  1341. -- * NOTE there is a failed assert in luaK:addk, a porting problem
  1342. --
  1343. -- Added:
  1344. -- * constant MAXSTACK from llimits.h
  1345. -- * luaK:ttisnumber(o) (from lobject.h)
  1346. -- * luaK:nvalue(o) (from lobject.h)
  1347. -- * luaK:setnilvalue(o) (from lobject.h)
  1348. -- * luaK:setnvalue(o, x) (from lobject.h)
  1349. -- * luaK:setbvalue(o, x) (from lobject.h)
  1350. -- * luaK:sethvalue(o, x) (from lobject.h), parameter L deleted
  1351. -- * luaK:setsvalue(o, x) (from lobject.h), parameter L deleted
  1352. -- * luaK:numadd, luaK:numsub, luaK:nummul, luaK:numdiv, luaK:nummod,
  1353. -- luaK:numpow, luaK:numunm, luaK:numisnan (from luaconf.h)
  1354. -- * copyexp(e1, e2) added in luaK:posfix to copy expdesc struct
  1355. --
  1356. -- Changed in 5.1.x:
  1357. -- * enum BinOpr has a new entry, OPR_MOD
  1358. -- * enum UnOpr has a new entry, OPR_LEN
  1359. -- * binopistest, unused in 5.0.x, has been deleted
  1360. -- * macro setmultret is new
  1361. -- * functions isnumeral, luaK_ret, boolK are new
  1362. -- * funcion nilK was named nil_constant in 5.0.x
  1363. -- * function interface changed: need_value, patchtestreg, concat
  1364. -- * TObject now a TValue
  1365. -- * functions luaK_setreturns, luaK_setoneret are new
  1366. -- * function luaK:setcallreturns deleted, to be replaced by:
  1367. -- luaK:setmultret, luaK:ret, luaK:setreturns, luaK:setoneret
  1368. -- * functions constfolding, codearith, codecomp are new
  1369. -- * luaK:codebinop has been deleted
  1370. -- * function luaK_setlist is new
  1371. -- * OPR_MULT renamed to OPR_MUL
  1372. ----------------------------------------------------------------------]]
  1373.  
  1374. -- requires luaP, luaX, luaY
  1375. local luaK = {}
  1376. local luaP = luaPfunc
  1377.  
  1378. ------------------------------------------------------------------------
  1379. -- constants used by code generator
  1380. ------------------------------------------------------------------------
  1381. -- maximum stack for a Lua function
  1382. luaK.MAXSTACK = 250 -- (from llimits.h)
  1383.  
  1384. --[[--------------------------------------------------------------------
  1385. -- other functions
  1386. ----------------------------------------------------------------------]]
  1387.  
  1388. ------------------------------------------------------------------------
  1389. -- emulation of TValue macros (these are from lobject.h)
  1390. -- * TValue is a table since lcode passes references around
  1391. -- * tt member field removed, using Lua's type() instead
  1392. -- * for setsvalue, sethvalue, parameter L (deleted here) in lobject.h
  1393. -- is used in an assert for testing, see checkliveness(g,obj)
  1394. ------------------------------------------------------------------------
  1395. function luaK:ttisnumber(o)
  1396. if o then return type(o.value) == "number" else return false end
  1397. end
  1398. function luaK:nvalue(o) return o.value end
  1399. function luaK:setnilvalue(o) o.value = nil end
  1400. function luaK:setsvalue(o, x) o.value = x end
  1401. luaK.setnvalue = luaK.setsvalue
  1402. luaK.sethvalue = luaK.setsvalue
  1403. luaK.setbvalue = luaK.setsvalue
  1404.  
  1405. ------------------------------------------------------------------------
  1406. -- The luai_num* macros define the primitive operations over numbers.
  1407. -- * this is not the entire set of primitive operations from luaconf.h
  1408. -- * used in luaK:constfolding()
  1409. ------------------------------------------------------------------------
  1410. function luaK:numadd(a, b) return a + b end
  1411. function luaK:numsub(a, b) return a - b end
  1412. function luaK:nummul(a, b) return a * b end
  1413. function luaK:numdiv(a, b) return a / b end
  1414. function luaK:nummod(a, b) return a % b end
  1415. -- ((a) - floor((a)/(b))*(b)) /* actual, for reference */
  1416. function luaK:numpow(a, b) return a ^ b end
  1417. function luaK:numunm(a) return -a end
  1418. function luaK:numisnan(a) return not a == a end
  1419. -- a NaN cannot equal another NaN
  1420.  
  1421. --[[--------------------------------------------------------------------
  1422. -- code generator functions
  1423. ----------------------------------------------------------------------]]
  1424.  
  1425. ------------------------------------------------------------------------
  1426. -- Marks the end of a patch list. It is an invalid value both as an absolute
  1427. -- address, and as a list link (would link an element to itself).
  1428. ------------------------------------------------------------------------
  1429. luaK.NO_JUMP = -1
  1430.  
  1431. ------------------------------------------------------------------------
  1432. -- grep "ORDER OPR" if you change these enums
  1433. ------------------------------------------------------------------------
  1434. luaK.BinOpr = {
  1435. OPR_ADD = 0, OPR_SUB = 1, OPR_MUL = 2, OPR_DIV = 3, OPR_MOD = 4, OPR_POW = 5,
  1436. OPR_CONCAT = 6,
  1437. OPR_NE = 7, OPR_EQ = 8,
  1438. OPR_LT = 9, OPR_LE = 10, OPR_GT = 11, OPR_GE = 12,
  1439. OPR_AND = 13, OPR_OR = 14,
  1440. OPR_NOBINOPR = 15,
  1441. }
  1442.  
  1443. -- * UnOpr is used by luaK:prefix's op argument, but not directly used
  1444. -- because the function receives the symbols as strings, e.g. "OPR_NOT"
  1445. luaK.UnOpr = {
  1446. OPR_MINUS = 0, OPR_NOT = 1, OPR_LEN = 2, OPR_NOUNOPR = 3
  1447. }
  1448.  
  1449. ------------------------------------------------------------------------
  1450. -- returns the instruction object for given e (expdesc), was a macro
  1451. ------------------------------------------------------------------------
  1452. function luaK:getcode(fs, e)
  1453. return fs.f.code[e.info]
  1454. end
  1455.  
  1456. ------------------------------------------------------------------------
  1457. -- codes an instruction with a signed Bx (sBx) field, was a macro
  1458. -- * used in luaK:jump(), (lparser) luaY:forbody()
  1459. ------------------------------------------------------------------------
  1460. function luaK:codeAsBx(fs, o, A, sBx)
  1461. return self:codeABx(fs, o, A, sBx + luaP.MAXARG_sBx)
  1462. end
  1463.  
  1464. ------------------------------------------------------------------------
  1465. -- set the expdesc e instruction for multiple returns, was a macro
  1466. ------------------------------------------------------------------------
  1467. function luaK:setmultret(fs, e)
  1468. self:setreturns(fs, e, luaY.LUA_MULTRET)
  1469. end
  1470.  
  1471. ------------------------------------------------------------------------
  1472. -- there is a jump if patch lists are not identical, was a macro
  1473. -- * used in luaK:exp2reg(), luaK:exp2anyreg(), luaK:exp2val()
  1474. ------------------------------------------------------------------------
  1475. function luaK:hasjumps(e)
  1476. return e.t ~= e.f
  1477. end
  1478.  
  1479. ------------------------------------------------------------------------
  1480. -- true if the expression is a constant number (for constant folding)
  1481. -- * used in constfolding(), infix()
  1482. ------------------------------------------------------------------------
  1483. function luaK:isnumeral(e)
  1484. return e.k == "VKNUM" and e.t == self.NO_JUMP and e.f == self.NO_JUMP
  1485. end
  1486.  
  1487. ------------------------------------------------------------------------
  1488. -- codes loading of nil, optimization done if consecutive locations
  1489. -- * used in luaK:discharge2reg(), (lparser) luaY:adjust_assign()
  1490. ------------------------------------------------------------------------
  1491. function luaK:_nil(fs, from, n)
  1492. if fs.pc > fs.lasttarget then -- no jumps to current position?
  1493. if fs.pc == 0 then -- function start?
  1494. if from >= fs.nactvar then
  1495. return -- positions are already clean
  1496. end
  1497. else
  1498. local previous = fs.f.code[fs.pc - 1]
  1499. if luaP:GET_OPCODE(previous) == "OP_LOADNIL" then
  1500. local pfrom = luaP:GETARG_A(previous)
  1501. local pto = luaP:GETARG_B(previous)
  1502. if pfrom <= from and from <= pto + 1 then -- can connect both?
  1503. if from + n - 1 > pto then
  1504. luaP:SETARG_B(previous, from + n - 1)
  1505. end
  1506. return
  1507. end
  1508. end
  1509. end
  1510. end
  1511. self:codeABC(fs, "OP_LOADNIL", from, from + n - 1, 0) -- else no optimization
  1512. end
  1513.  
  1514. ------------------------------------------------------------------------
  1515. --
  1516. -- * used in multiple locations
  1517. ------------------------------------------------------------------------
  1518. function luaK:jump(fs)
  1519. local jpc = fs.jpc -- save list of jumps to here
  1520. fs.jpc = self.NO_JUMP
  1521. local j = self:codeAsBx(fs, "OP_JMP", 0, self.NO_JUMP)
  1522. j = self:concat(fs, j, jpc) -- keep them on hold
  1523. return j
  1524. end
  1525.  
  1526. ------------------------------------------------------------------------
  1527. -- codes a RETURN instruction
  1528. -- * used in luaY:close_func(), luaY:retstat()
  1529. ------------------------------------------------------------------------
  1530. function luaK:ret(fs, first, nret)
  1531. self:codeABC(fs, "OP_RETURN", first, nret + 1, 0)
  1532. end
  1533.  
  1534. ------------------------------------------------------------------------
  1535. --
  1536. -- * used in luaK:jumponcond(), luaK:codecomp()
  1537. ------------------------------------------------------------------------
  1538. function luaK:condjump(fs, op, A, B, C)
  1539. self:codeABC(fs, op, A, B, C)
  1540. return self:jump(fs)
  1541. end
  1542.  
  1543. ------------------------------------------------------------------------
  1544. --
  1545. -- * used in luaK:patchlistaux(), luaK:concat()
  1546. ------------------------------------------------------------------------
  1547. function luaK:fixjump(fs, pc, dest)
  1548. local jmp = fs.f.code[pc]
  1549. local offset = dest - (pc + 1)
  1550. assert(dest ~= self.NO_JUMP)
  1551. if math.abs(offset) > luaP.MAXARG_sBx then
  1552. luaX:syntaxerror(fs.ls, "control structure too long")
  1553. end
  1554. luaP:SETARG_sBx(jmp, offset)
  1555. end
  1556.  
  1557. ------------------------------------------------------------------------
  1558. -- returns current 'pc' and marks it as a jump target (to avoid wrong
  1559. -- optimizations with consecutive instructions not in the same basic block).
  1560. -- * used in multiple locations
  1561. -- * fs.lasttarget tested only by luaK:_nil() when optimizing OP_LOADNIL
  1562. ------------------------------------------------------------------------
  1563. function luaK:getlabel(fs)
  1564. fs.lasttarget = fs.pc
  1565. return fs.pc
  1566. end
  1567.  
  1568. ------------------------------------------------------------------------
  1569. --
  1570. -- * used in luaK:need_value(), luaK:removevalues(), luaK:patchlistaux(),
  1571. -- luaK:concat()
  1572. ------------------------------------------------------------------------
  1573. function luaK:getjump(fs, pc)
  1574. local offset = luaP:GETARG_sBx(fs.f.code[pc])
  1575. if offset == self.NO_JUMP then -- point to itself represents end of list
  1576. return self.NO_JUMP -- end of list
  1577. else
  1578. return (pc + 1) + offset -- turn offset into absolute position
  1579. end
  1580. end
  1581.  
  1582. ------------------------------------------------------------------------
  1583. --
  1584. -- * used in luaK:need_value(), luaK:patchtestreg(), luaK:invertjump()
  1585. ------------------------------------------------------------------------
  1586. function luaK:getjumpcontrol(fs, pc)
  1587. local pi = fs.f.code[pc]
  1588. local ppi = fs.f.code[pc - 1]
  1589. if pc >= 1 and luaP:testTMode(luaP:GET_OPCODE(ppi)) ~= 0 then
  1590. return ppi
  1591. else
  1592. return pi
  1593. end
  1594. end
  1595.  
  1596. ------------------------------------------------------------------------
  1597. -- check whether list has any jump that do not produce a value
  1598. -- (or produce an inverted value)
  1599. -- * return value changed to boolean
  1600. -- * used only in luaK:exp2reg()
  1601. ------------------------------------------------------------------------
  1602. function luaK:need_value(fs, list)
  1603. while list ~= self.NO_JUMP do
  1604. local i = self:getjumpcontrol(fs, list)
  1605. if luaP:GET_OPCODE(i) ~= "OP_TESTSET" then return true end
  1606. list = self:getjump(fs, list)
  1607. end
  1608. return false -- not found
  1609. end
  1610.  
  1611. ------------------------------------------------------------------------
  1612. --
  1613. -- * used in luaK:removevalues(), luaK:patchlistaux()
  1614. ------------------------------------------------------------------------
  1615. function luaK:patchtestreg(fs, node, reg)
  1616. local i = self:getjumpcontrol(fs, node)
  1617. if luaP:GET_OPCODE(i) ~= "OP_TESTSET" then
  1618. return false -- cannot patch other instructions
  1619. end
  1620. if reg ~= luaP.NO_REG and reg ~= luaP:GETARG_B(i) then
  1621. luaP:SETARG_A(i, reg)
  1622. else -- no register to put value or register already has the value
  1623. -- due to use of a table as i, i cannot be replaced by another table
  1624. -- so the following is required; there is no change to ARG_C
  1625. luaP:SET_OPCODE(i, "OP_TEST")
  1626. local b = luaP:GETARG_B(i)
  1627. luaP:SETARG_A(i, b)
  1628. luaP:SETARG_B(i, 0)
  1629. -- *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); /* C */
  1630. end
  1631. return true
  1632. end
  1633.  
  1634. ------------------------------------------------------------------------
  1635. --
  1636. -- * used only in luaK:codenot()
  1637. ------------------------------------------------------------------------
  1638. function luaK:removevalues(fs, list)
  1639. while list ~= self.NO_JUMP do
  1640. self:patchtestreg(fs, list, luaP.NO_REG)
  1641. list = self:getjump(fs, list)
  1642. end
  1643. end
  1644.  
  1645. ------------------------------------------------------------------------
  1646. --
  1647. -- * used in luaK:dischargejpc(), luaK:patchlist(), luaK:exp2reg()
  1648. ------------------------------------------------------------------------
  1649. function luaK:patchlistaux(fs, list, vtarget, reg, dtarget)
  1650. while list ~= self.NO_JUMP do
  1651. local _next = self:getjump(fs, list)
  1652. if self:patchtestreg(fs, list, reg) then
  1653. self:fixjump(fs, list, vtarget)
  1654. else
  1655. self:fixjump(fs, list, dtarget) -- jump to default target
  1656. end
  1657. list = _next
  1658. end
  1659. end
  1660.  
  1661. ------------------------------------------------------------------------
  1662. --
  1663. -- * used only in luaK:code()
  1664. ------------------------------------------------------------------------
  1665. function luaK:dischargejpc(fs)
  1666. self:patchlistaux(fs, fs.jpc, fs.pc, luaP.NO_REG, fs.pc)
  1667. fs.jpc = self.NO_JUMP
  1668. end
  1669.  
  1670. ------------------------------------------------------------------------
  1671. --
  1672. -- * used in (lparser) luaY:whilestat(), luaY:repeatstat(), luaY:forbody()
  1673. ------------------------------------------------------------------------
  1674. function luaK:patchlist(fs, list, target)
  1675. if target == fs.pc then
  1676. self:patchtohere(fs, list)
  1677. else
  1678. assert(target < fs.pc)
  1679. self:patchlistaux(fs, list, target, luaP.NO_REG, target)
  1680. end
  1681. end
  1682.  
  1683. ------------------------------------------------------------------------
  1684. --
  1685. -- * used in multiple locations
  1686. ------------------------------------------------------------------------
  1687. function luaK:patchtohere(fs, list)
  1688. self:getlabel(fs)
  1689. fs.jpc = self:concat(fs, fs.jpc, list)
  1690. end
  1691.  
  1692. ------------------------------------------------------------------------
  1693. -- * l1 was a pointer, now l1 is returned and callee assigns the value
  1694. -- * used in multiple locations
  1695. ------------------------------------------------------------------------
  1696. function luaK:concat(fs, l1, l2)
  1697. if l2 == self.NO_JUMP then return l1
  1698. elseif l1 == self.NO_JUMP then
  1699. return l2
  1700. else
  1701. local list = l1
  1702. local _next = self:getjump(fs, list)
  1703. while _next ~= self.NO_JUMP do -- find last element
  1704. list = _next
  1705. _next = self:getjump(fs, list)
  1706. end
  1707. self:fixjump(fs, list, l2)
  1708. end
  1709. return l1
  1710. end
  1711.  
  1712. ------------------------------------------------------------------------
  1713. --
  1714. -- * used in luaK:reserveregs(), (lparser) luaY:forlist()
  1715. ------------------------------------------------------------------------
  1716. function luaK:checkstack(fs, n)
  1717. local newstack = fs.freereg + n
  1718. if newstack > fs.f.maxstacksize then
  1719. if newstack >= self.MAXSTACK then
  1720. luaX:syntaxerror(fs.ls, "function or expression too complex")
  1721. end
  1722. fs.f.maxstacksize = newstack
  1723. end
  1724. end
  1725.  
  1726. ------------------------------------------------------------------------
  1727. --
  1728. -- * used in multiple locations
  1729. ------------------------------------------------------------------------
  1730. function luaK:reserveregs(fs, n)
  1731. self:checkstack(fs, n)
  1732. fs.freereg = fs.freereg + n
  1733. end
  1734.  
  1735. ------------------------------------------------------------------------
  1736. --
  1737. -- * used in luaK:freeexp(), luaK:dischargevars()
  1738. ------------------------------------------------------------------------
  1739. function luaK:freereg(fs, reg)
  1740. if not luaP:ISK(reg) and reg >= fs.nactvar then
  1741. fs.freereg = fs.freereg - 1
  1742. assert(reg == fs.freereg)
  1743. end
  1744. end
  1745.  
  1746. ------------------------------------------------------------------------
  1747. --
  1748. -- * used in multiple locations
  1749. ------------------------------------------------------------------------
  1750. function luaK:freeexp(fs, e)
  1751. if e.k == "VNONRELOC" then
  1752. self:freereg(fs, e.info)
  1753. end
  1754. end
  1755.  
  1756. ------------------------------------------------------------------------
  1757. -- * TODO NOTE implementation is not 100% correct, since the assert fails
  1758. -- * luaH_set, setobj deleted; direct table access used instead
  1759. -- * used in luaK:stringK(), luaK:numberK(), luaK:boolK(), luaK:nilK()
  1760. ------------------------------------------------------------------------
  1761. function luaK:addk(fs, k, v)
  1762. local L = fs.L
  1763. local idx = fs.h[k.value]
  1764. --TValue *idx = luaH_set(L, fs->h, k); /* C */
  1765. local f = fs.f
  1766. if self:ttisnumber(idx) then
  1767. --TODO this assert currently FAILS (last tested for 5.0.2)
  1768. --assert(fs.f.k[self:nvalue(idx)] == v)
  1769. --assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); /* C */
  1770. return self:nvalue(idx)
  1771. else -- constant not found; create a new entry
  1772. idx = {}
  1773. self:setnvalue(idx, fs.nk)
  1774. fs.h[k.value] = idx
  1775. -- setnvalue(idx, cast_num(fs->nk)); /* C */
  1776. luaY:growvector(L, f.k, fs.nk, f.sizek, nil,
  1777. luaP.MAXARG_Bx, "constant table overflow")
  1778. -- loop to initialize empty f.k positions not required
  1779. f.k[fs.nk] = v
  1780. -- setobj(L, &f->k[fs->nk], v); /* C */
  1781. -- luaC_barrier(L, f, v); /* GC */
  1782. local nk = fs.nk
  1783. fs.nk = fs.nk + 1
  1784. return nk
  1785. end
  1786.  
  1787. end
  1788.  
  1789. ------------------------------------------------------------------------
  1790. -- creates and sets a string object
  1791. -- * used in (lparser) luaY:codestring(), luaY:singlevar()
  1792. ------------------------------------------------------------------------
  1793. function luaK:stringK(fs, s)
  1794. local o = {} -- TValue
  1795. self:setsvalue(o, s)
  1796. return self:addk(fs, o, o)
  1797. end
  1798.  
  1799. ------------------------------------------------------------------------
  1800. -- creates and sets a number object
  1801. -- * used in luaK:prefix() for negative (or negation of) numbers
  1802. -- * used in (lparser) luaY:simpleexp(), luaY:fornum()
  1803. ------------------------------------------------------------------------
  1804. function luaK:numberK(fs, r)
  1805. local o = {} -- TValue
  1806. self:setnvalue(o, r)
  1807. return self:addk(fs, o, o)
  1808. end
  1809.  
  1810. ------------------------------------------------------------------------
  1811. -- creates and sets a boolean object
  1812. -- * used only in luaK:exp2RK()
  1813. ------------------------------------------------------------------------
  1814. function luaK:boolK(fs, b)
  1815. local o = {} -- TValue
  1816. self:setbvalue(o, b)
  1817. return self:addk(fs, o, o)
  1818. end
  1819.  
  1820. ------------------------------------------------------------------------
  1821. -- creates and sets a nil object
  1822. -- * used only in luaK:exp2RK()
  1823. ------------------------------------------------------------------------
  1824. function luaK:nilK(fs)
  1825. local k, v = {}, {} -- TValue
  1826. self:setnilvalue(v)
  1827. -- cannot use nil as key; instead use table itself to represent nil
  1828. self:sethvalue(k, fs.h)
  1829. return self:addk(fs, k, v)
  1830. end
  1831.  
  1832. ------------------------------------------------------------------------
  1833. --
  1834. -- * used in luaK:setmultret(), (lparser) luaY:adjust_assign()
  1835. ------------------------------------------------------------------------
  1836. function luaK:setreturns(fs, e, nresults)
  1837. if e.k == "VCALL" then -- expression is an open function call?
  1838. luaP:SETARG_C(self:getcode(fs, e), nresults + 1)
  1839. elseif e.k == "VVARARG" then
  1840. luaP:SETARG_B(self:getcode(fs, e), nresults + 1);
  1841. luaP:SETARG_A(self:getcode(fs, e), fs.freereg);
  1842. luaK:reserveregs(fs, 1)
  1843. end
  1844. end
  1845.  
  1846. ------------------------------------------------------------------------
  1847. --
  1848. -- * used in luaK:dischargevars(), (lparser) luaY:assignment()
  1849. ------------------------------------------------------------------------
  1850. function luaK:setoneret(fs, e)
  1851. if e.k == "VCALL" then -- expression is an open function call?
  1852. e.k = "VNONRELOC"
  1853. e.info = luaP:GETARG_A(self:getcode(fs, e))
  1854. elseif e.k == "VVARARG" then
  1855. luaP:SETARG_B(self:getcode(fs, e), 2)
  1856. e.k = "VRELOCABLE" -- can relocate its simple result
  1857. end
  1858. end
  1859.  
  1860. ------------------------------------------------------------------------
  1861. --
  1862. -- * used in multiple locations
  1863. ------------------------------------------------------------------------
  1864. function luaK:dischargevars(fs, e)
  1865. local k = e.k
  1866. if k == "VLOCAL" then
  1867. e.k = "VNONRELOC"
  1868. elseif k == "VUPVAL" then
  1869. e.info = self:codeABC(fs, "OP_GETUPVAL", 0, e.info, 0)
  1870. e.k = "VRELOCABLE"
  1871. elseif k == "VGLOBAL" then
  1872. e.info = self:codeABx(fs, "OP_GETGLOBAL", 0, e.info)
  1873. e.k = "VRELOCABLE"
  1874. elseif k == "VINDEXED" then
  1875. self:freereg(fs, e.aux)
  1876. self:freereg(fs, e.info)
  1877. e.info = self:codeABC(fs, "OP_GETTABLE", 0, e.info, e.aux)
  1878. e.k = "VRELOCABLE"
  1879. elseif k == "VVARARG" or k == "VCALL" then
  1880. self:setoneret(fs, e)
  1881. else
  1882. -- there is one value available (somewhere)
  1883. end
  1884. end
  1885.  
  1886. ------------------------------------------------------------------------
  1887. --
  1888. -- * used only in luaK:exp2reg()
  1889. ------------------------------------------------------------------------
  1890. function luaK:code_label(fs, A, b, jump)
  1891. self:getlabel(fs) -- those instructions may be jump targets
  1892. return self:codeABC(fs, "OP_LOADBOOL", A, b, jump)
  1893. end
  1894.  
  1895. ------------------------------------------------------------------------
  1896. --
  1897. -- * used in luaK:discharge2anyreg(), luaK:exp2reg()
  1898. ------------------------------------------------------------------------
  1899. function luaK:discharge2reg(fs, e, reg)
  1900. self:dischargevars(fs, e)
  1901. local k = e.k
  1902. if k == "VNIL" then
  1903. self:_nil(fs, reg, 1)
  1904. elseif k == "VFALSE" or k == "VTRUE" then
  1905. self:codeABC(fs, "OP_LOADBOOL", reg, (e.k == "VTRUE") and 1 or 0, 0)
  1906. elseif k == "VK" then
  1907. self:codeABx(fs, "OP_LOADK", reg, e.info)
  1908. elseif k == "VKNUM" then
  1909. self:codeABx(fs, "OP_LOADK", reg, self:numberK(fs, e.nval))
  1910. elseif k == "VRELOCABLE" then
  1911. local pc = self:getcode(fs, e)
  1912. luaP:SETARG_A(pc, reg)
  1913. elseif k == "VNONRELOC" then
  1914. if reg ~= e.info then
  1915. self:codeABC(fs, "OP_MOVE", reg, e.info, 0)
  1916. end
  1917. else
  1918. assert(e.k == "VVOID" or e.k == "VJMP")
  1919. return -- nothing to do...
  1920. end
  1921. e.info = reg
  1922. e.k = "VNONRELOC"
  1923. end
  1924.  
  1925. ------------------------------------------------------------------------
  1926. --
  1927. -- * used in luaK:jumponcond(), luaK:codenot()
  1928. ------------------------------------------------------------------------
  1929. function luaK:discharge2anyreg(fs, e)
  1930. if e.k ~= "VNONRELOC" then
  1931. self:reserveregs(fs, 1)
  1932. self:discharge2reg(fs, e, fs.freereg - 1)
  1933. end
  1934. end
  1935.  
  1936. ------------------------------------------------------------------------
  1937. --
  1938. -- * used in luaK:exp2nextreg(), luaK:exp2anyreg(), luaK:storevar()
  1939. ------------------------------------------------------------------------
  1940. function luaK:exp2reg(fs, e, reg)
  1941. self:discharge2reg(fs, e, reg)
  1942. if e.k == "VJMP" then
  1943. e.t = self:concat(fs, e.t, e.info) -- put this jump in 't' list
  1944. end
  1945. if self:hasjumps(e) then
  1946. local final -- position after whole expression
  1947. local p_f = self.NO_JUMP -- position of an eventual LOAD false
  1948. local p_t = self.NO_JUMP -- position of an eventual LOAD true
  1949. if self:need_value(fs, e.t) or self:need_value(fs, e.f) then
  1950. local fj = (e.k == "VJMP") and self.NO_JUMP or self:jump(fs)
  1951. p_f = self:code_label(fs, reg, 0, 1)
  1952. p_t = self:code_label(fs, reg, 1, 0)
  1953. self:patchtohere(fs, fj)
  1954. end
  1955. final = self:getlabel(fs)
  1956. self:patchlistaux(fs, e.f, final, reg, p_f)
  1957. self:patchlistaux(fs, e.t, final, reg, p_t)
  1958. end
  1959. e.f, e.t = self.NO_JUMP, self.NO_JUMP
  1960. e.info = reg
  1961. e.k = "VNONRELOC"
  1962. end
  1963.  
  1964. ------------------------------------------------------------------------
  1965. --
  1966. -- * used in multiple locations
  1967. ------------------------------------------------------------------------
  1968. function luaK:exp2nextreg(fs, e)
  1969. self:dischargevars(fs, e)
  1970. self:freeexp(fs, e)
  1971. self:reserveregs(fs, 1)
  1972. self:exp2reg(fs, e, fs.freereg - 1)
  1973. end
  1974.  
  1975. ------------------------------------------------------------------------
  1976. --
  1977. -- * used in multiple locations
  1978. ------------------------------------------------------------------------
  1979. function luaK:exp2anyreg(fs, e)
  1980. self:dischargevars(fs, e)
  1981. if e.k == "VNONRELOC" then
  1982. if not self:hasjumps(e) then -- exp is already in a register
  1983. return e.info
  1984. end
  1985. if e.info >= fs.nactvar then -- reg. is not a local?
  1986. self:exp2reg(fs, e, e.info) -- put value on it
  1987. return e.info
  1988. end
  1989. end
  1990. self:exp2nextreg(fs, e) -- default
  1991. return e.info
  1992. end
  1993.  
  1994. ------------------------------------------------------------------------
  1995. --
  1996. -- * used in luaK:exp2RK(), luaK:prefix(), luaK:posfix()
  1997. -- * used in (lparser) luaY:yindex()
  1998. ------------------------------------------------------------------------
  1999. function luaK:exp2val(fs, e)
  2000. if self:hasjumps(e) then
  2001. self:exp2anyreg(fs, e)
  2002. else
  2003. self:dischargevars(fs, e)
  2004. end
  2005. end
  2006.  
  2007. ------------------------------------------------------------------------
  2008. --
  2009. -- * used in multiple locations
  2010. ------------------------------------------------------------------------
  2011. function luaK:exp2RK(fs, e)
  2012. self:exp2val(fs, e)
  2013. local k = e.k
  2014. if k == "VKNUM" or k == "VTRUE" or k == "VFALSE" or k == "VNIL" then
  2015. if fs.nk <= luaP.MAXINDEXRK then -- constant fit in RK operand?
  2016. -- converted from a 2-deep ternary operator expression
  2017. if e.k == "VNIL" then
  2018. e.info = self:nilK(fs)
  2019. else
  2020. e.info = (e.k == "VKNUM") and self:numberK(fs, e.nval)
  2021. or self:boolK(fs, e.k == "VTRUE")
  2022. end
  2023. e.k = "VK"
  2024. return luaP:RKASK(e.info)
  2025. end
  2026. elseif k == "VK" then
  2027. if e.info <= luaP.MAXINDEXRK then -- constant fit in argC?
  2028. return luaP:RKASK(e.info)
  2029. end
  2030. else
  2031. -- default
  2032. end
  2033. -- not a constant in the right range: put it in a register
  2034. return self:exp2anyreg(fs, e)
  2035. end
  2036.  
  2037. ------------------------------------------------------------------------
  2038. --
  2039. -- * used in (lparser) luaY:assignment(), luaY:localfunc(), luaY:funcstat()
  2040. ------------------------------------------------------------------------
  2041. function luaK:storevar(fs, var, ex)
  2042. local k = var.k
  2043. if k == "VLOCAL" then
  2044. self:freeexp(fs, ex)
  2045. self:exp2reg(fs, ex, var.info)
  2046. return
  2047. elseif k == "VUPVAL" then
  2048. local e = self:exp2anyreg(fs, ex)
  2049. self:codeABC(fs, "OP_SETUPVAL", e, var.info, 0)
  2050. elseif k == "VGLOBAL" then
  2051. local e = self:exp2anyreg(fs, ex)
  2052. self:codeABx(fs, "OP_SETGLOBAL", e, var.info)
  2053. elseif k == "VINDEXED" then
  2054. local e = self:exp2RK(fs, ex)
  2055. self:codeABC(fs, "OP_SETTABLE", var.info, var.aux, e)
  2056. else
  2057. assert(0) -- invalid var kind to store
  2058. end
  2059. self:freeexp(fs, ex)
  2060. end
  2061.  
  2062. ------------------------------------------------------------------------
  2063. --
  2064. -- * used only in (lparser) luaY:primaryexp()
  2065. ------------------------------------------------------------------------
  2066. function luaK:_self(fs, e, key)
  2067. self:exp2anyreg(fs, e)
  2068. self:freeexp(fs, e)
  2069. local func = fs.freereg
  2070. self:reserveregs(fs, 2)
  2071. self:codeABC(fs, "OP_SELF", func, e.info, self:exp2RK(fs, key))
  2072. self:freeexp(fs, key)
  2073. e.info = func
  2074. e.k = "VNONRELOC"
  2075. end
  2076.  
  2077. ------------------------------------------------------------------------
  2078. --
  2079. -- * used in luaK:goiftrue(), luaK:codenot()
  2080. ------------------------------------------------------------------------
  2081. function luaK:invertjump(fs, e)
  2082. local pc = self:getjumpcontrol(fs, e.info)
  2083. assert(luaP:testTMode(luaP:GET_OPCODE(pc)) ~= 0 and
  2084. luaP:GET_OPCODE(pc) ~= "OP_TESTSET" and
  2085. luaP:GET_OPCODE(pc) ~= "OP_TEST")
  2086. luaP:SETARG_A(pc, (luaP:GETARG_A(pc) == 0) and 1 or 0)
  2087. end
  2088.  
  2089. ------------------------------------------------------------------------
  2090. --
  2091. -- * used in luaK:goiftrue(), luaK:goiffalse()
  2092. ------------------------------------------------------------------------
  2093. function luaK:jumponcond(fs, e, cond)
  2094. if e.k == "VRELOCABLE" then
  2095. local ie = self:getcode(fs, e)
  2096. if luaP:GET_OPCODE(ie) == "OP_NOT" then
  2097. fs.pc = fs.pc - 1 -- remove previous OP_NOT
  2098. return self:condjump(fs, "OP_TEST", luaP:GETARG_B(ie), 0, cond and 0 or 1)
  2099. end
  2100. -- else go through
  2101. end
  2102. self:discharge2anyreg(fs, e)
  2103. self:freeexp(fs, e)
  2104. return self:condjump(fs, "OP_TESTSET", luaP.NO_REG, e.info, cond and 1 or 0)
  2105. end
  2106.  
  2107. ------------------------------------------------------------------------
  2108. --
  2109. -- * used in luaK:infix(), (lparser) luaY:cond()
  2110. ------------------------------------------------------------------------
  2111. function luaK:goiftrue(fs, e)
  2112. local pc -- pc of last jump
  2113. self:dischargevars(fs, e)
  2114. local k = e.k
  2115. if k == "VK" or k == "VKNUM" or k == "VTRUE" then
  2116. pc = self.NO_JUMP -- always true; do nothing
  2117. elseif k == "VFALSE" then
  2118. pc = self:jump(fs) -- always jump
  2119. elseif k == "VJMP" then
  2120. self:invertjump(fs, e)
  2121. pc = e.info
  2122. else
  2123. pc = self:jumponcond(fs, e, false)
  2124. end
  2125. e.f = self:concat(fs, e.f, pc) -- insert last jump in `f' list
  2126. self:patchtohere(fs, e.t)
  2127. e.t = self.NO_JUMP
  2128. end
  2129.  
  2130. ------------------------------------------------------------------------
  2131. --
  2132. -- * used in luaK:infix()
  2133. ------------------------------------------------------------------------
  2134. function luaK:goiffalse(fs, e)
  2135. local pc -- pc of last jump
  2136. self:dischargevars(fs, e)
  2137. local k = e.k
  2138. if k == "VNIL" or k == "VFALSE"then
  2139. pc = self.NO_JUMP -- always false; do nothing
  2140. elseif k == "VTRUE" then
  2141. pc = self:jump(fs) -- always jump
  2142. elseif k == "VJMP" then
  2143. pc = e.info
  2144. else
  2145. pc = self:jumponcond(fs, e, true)
  2146. end
  2147. e.t = self:concat(fs, e.t, pc) -- insert last jump in `t' list
  2148. self:patchtohere(fs, e.f)
  2149. e.f = self.NO_JUMP
  2150. end
  2151.  
  2152. ------------------------------------------------------------------------
  2153. --
  2154. -- * used only in luaK:prefix()
  2155. ------------------------------------------------------------------------
  2156. function luaK:codenot(fs, e)
  2157. self:dischargevars(fs, e)
  2158. local k = e.k
  2159. if k == "VNIL" or k == "VFALSE" then
  2160. e.k = "VTRUE"
  2161. elseif k == "VK" or k == "VKNUM" or k == "VTRUE" then
  2162. e.k = "VFALSE"
  2163. elseif k == "VJMP" then
  2164. self:invertjump(fs, e)
  2165. elseif k == "VRELOCABLE" or k == "VNONRELOC" then
  2166. self:discharge2anyreg(fs, e)
  2167. self:freeexp(fs, e)
  2168. e.info = self:codeABC(fs, "OP_NOT", 0, e.info, 0)
  2169. e.k = "VRELOCABLE"
  2170. else
  2171. assert(0) -- cannot happen
  2172. end
  2173. -- interchange true and false lists
  2174. e.f, e.t = e.t, e.f
  2175. self:removevalues(fs, e.f)
  2176. self:removevalues(fs, e.t)
  2177. end
  2178.  
  2179. ------------------------------------------------------------------------
  2180. --
  2181. -- * used in (lparser) luaY:field(), luaY:primaryexp()
  2182. ------------------------------------------------------------------------
  2183. function luaK:indexed(fs, t, k)
  2184. t.aux = self:exp2RK(fs, k)
  2185. t.k = "VINDEXED"
  2186. end
  2187.  
  2188. ------------------------------------------------------------------------
  2189. --
  2190. -- * used only in luaK:codearith()
  2191. ------------------------------------------------------------------------
  2192. function luaK:constfolding(op, e1, e2)
  2193. local r
  2194. if not self:isnumeral(e1) or not self:isnumeral(e2) then return false end
  2195. local v1 = e1.nval
  2196. local v2 = e2.nval
  2197. if op == "OP_ADD" then
  2198. r = self:numadd(v1, v2)
  2199. elseif op == "OP_SUB" then
  2200. r = self:numsub(v1, v2)
  2201. elseif op == "OP_MUL" then
  2202. r = self:nummul(v1, v2)
  2203. elseif op == "OP_DIV" then
  2204. if v2 == 0 then return false end -- do not attempt to divide by 0
  2205. r = self:numdiv(v1, v2)
  2206. elseif op == "OP_MOD" then
  2207. if v2 == 0 then return false end -- do not attempt to divide by 0
  2208. r = self:nummod(v1, v2)
  2209. elseif op == "OP_POW" then
  2210. r = self:numpow(v1, v2)
  2211. elseif op == "OP_UNM" then
  2212. r = self:numunm(v1)
  2213. elseif op == "OP_LEN" then
  2214. return false -- no constant folding for 'len'
  2215. else
  2216. assert(0)
  2217. r = 0
  2218. end
  2219. if self:numisnan(r) then return false end -- do not attempt to produce NaN
  2220. e1.nval = r
  2221. return true
  2222. end
  2223.  
  2224. ------------------------------------------------------------------------
  2225. --
  2226. -- * used in luaK:prefix(), luaK:posfix()
  2227. ------------------------------------------------------------------------
  2228. function luaK:codearith(fs, op, e1, e2)
  2229. if self:constfolding(op, e1, e2) then
  2230. return
  2231. else
  2232. local o2 = (op ~= "OP_UNM" and op ~= "OP_LEN") and self:exp2RK(fs, e2) or 0
  2233. local o1 = self:exp2RK(fs, e1)
  2234. if o1 > o2 then
  2235. self:freeexp(fs, e1)
  2236. self:freeexp(fs, e2)
  2237. else
  2238. self:freeexp(fs, e2)
  2239. self:freeexp(fs, e1)
  2240. end
  2241. e1.info = self:codeABC(fs, op, 0, o1, o2)
  2242. e1.k = "VRELOCABLE"
  2243. end
  2244. end
  2245.  
  2246. ------------------------------------------------------------------------
  2247. --
  2248. -- * used only in luaK:posfix()
  2249. ------------------------------------------------------------------------
  2250. function luaK:codecomp(fs, op, cond, e1, e2)
  2251. local o1 = self:exp2RK(fs, e1)
  2252. local o2 = self:exp2RK(fs, e2)
  2253. self:freeexp(fs, e2)
  2254. self:freeexp(fs, e1)
  2255. if cond == 0 and op ~= "OP_EQ" then
  2256. -- exchange args to replace by `<' or `<='
  2257. o1, o2 = o2, o1 -- o1 <==> o2
  2258. cond = 1
  2259. end
  2260. e1.info = self:condjump(fs, op, cond, o1, o2)
  2261. e1.k = "VJMP"
  2262. end
  2263.  
  2264. ------------------------------------------------------------------------
  2265. --
  2266. -- * used only in (lparser) luaY:subexpr()
  2267. ------------------------------------------------------------------------
  2268. function luaK:prefix(fs, op, e)
  2269. local e2 = {} -- expdesc
  2270. e2.t, e2.f = self.NO_JUMP, self.NO_JUMP
  2271. e2.k = "VKNUM"
  2272. e2.nval = 0
  2273. if op == "OPR_MINUS" then
  2274. if not self:isnumeral(e) then
  2275. self:exp2anyreg(fs, e) -- cannot operate on non-numeric constants
  2276. end
  2277. self:codearith(fs, "OP_UNM", e, e2)
  2278. elseif op == "OPR_NOT" then
  2279. self:codenot(fs, e)
  2280. elseif op == "OPR_LEN" then
  2281. self:exp2anyreg(fs, e) -- cannot operate on constants
  2282. self:codearith(fs, "OP_LEN", e, e2)
  2283. else
  2284. assert(0)
  2285. end
  2286. end
  2287.  
  2288. ------------------------------------------------------------------------
  2289. --
  2290. -- * used only in (lparser) luaY:subexpr()
  2291. ------------------------------------------------------------------------
  2292. function luaK:infix(fs, op, v)
  2293. if op == "OPR_AND" then
  2294. self:goiftrue(fs, v)
  2295. elseif op == "OPR_OR" then
  2296. self:goiffalse(fs, v)
  2297. elseif op == "OPR_CONCAT" then
  2298. self:exp2nextreg(fs, v) -- operand must be on the 'stack'
  2299. elseif op == "OPR_ADD" or op == "OPR_SUB" or
  2300. op == "OPR_MUL" or op == "OPR_DIV" or
  2301. op == "OPR_MOD" or op == "OPR_POW" then
  2302. if not self:isnumeral(v) then self:exp2RK(fs, v) end
  2303. else
  2304. self:exp2RK(fs, v)
  2305. end
  2306. end
  2307.  
  2308. ------------------------------------------------------------------------
  2309. --
  2310. -- * used only in (lparser) luaY:subexpr()
  2311. ------------------------------------------------------------------------
  2312. -- table lookups to simplify testing
  2313. luaK.arith_op = {
  2314. OPR_ADD = "OP_ADD", OPR_SUB = "OP_SUB", OPR_MUL = "OP_MUL",
  2315. OPR_DIV = "OP_DIV", OPR_MOD = "OP_MOD", OPR_POW = "OP_POW",
  2316. }
  2317. luaK.comp_op = {
  2318. OPR_EQ = "OP_EQ", OPR_NE = "OP_EQ", OPR_LT = "OP_LT",
  2319. OPR_LE = "OP_LE", OPR_GT = "OP_LT", OPR_GE = "OP_LE",
  2320. }
  2321. luaK.comp_cond = {
  2322. OPR_EQ = 1, OPR_NE = 0, OPR_LT = 1,
  2323. OPR_LE = 1, OPR_GT = 0, OPR_GE = 0,
  2324. }
  2325. function luaK:posfix(fs, op, e1, e2)
  2326. -- needed because e1 = e2 doesn't copy values...
  2327. -- * in 5.0.x, only k/info/aux/t/f copied, t for AND, f for OR
  2328. -- but here, all elements are copied for completeness' sake
  2329. local function copyexp(e1, e2)
  2330. e1.k = e2.k
  2331. e1.info = e2.info; e1.aux = e2.aux
  2332. e1.nval = e2.nval
  2333. e1.t = e2.t; e1.f = e2.f
  2334. end
  2335. if op == "OPR_AND" then
  2336. assert(e1.t == self.NO_JUMP) -- list must be closed
  2337. self:dischargevars(fs, e2)
  2338. e2.f = self:concat(fs, e2.f, e1.f)
  2339. copyexp(e1, e2)
  2340. elseif op == "OPR_OR" then
  2341. assert(e1.f == self.NO_JUMP) -- list must be closed
  2342. self:dischargevars(fs, e2)
  2343. e2.t = self:concat(fs, e2.t, e1.t)
  2344. copyexp(e1, e2)
  2345. elseif op == "OPR_CONCAT" then
  2346. self:exp2val(fs, e2)
  2347. if e2.k == "VRELOCABLE" and luaP:GET_OPCODE(self:getcode(fs, e2)) == "OP_CONCAT" then
  2348. assert(e1.info == luaP:GETARG_B(self:getcode(fs, e2)) - 1)
  2349. self:freeexp(fs, e1)
  2350. luaP:SETARG_B(self:getcode(fs, e2), e1.info)
  2351. e1.k = "VRELOCABLE"
  2352. e1.info = e2.info
  2353. else
  2354. self:exp2nextreg(fs, e2) -- operand must be on the 'stack'
  2355. self:codearith(fs, "OP_CONCAT", e1, e2)
  2356. end
  2357. else
  2358. -- the following uses a table lookup in place of conditionals
  2359. local arith = self.arith_op[op]
  2360. if arith then
  2361. self:codearith(fs, arith, e1, e2)
  2362. else
  2363. local comp = self.comp_op[op]
  2364. if comp then
  2365. self:codecomp(fs, comp, self.comp_cond[op], e1, e2)
  2366. else
  2367. assert(0)
  2368. end
  2369. end--if arith
  2370. end--if op
  2371. end
  2372.  
  2373. ------------------------------------------------------------------------
  2374. -- adjusts debug information for last instruction written, in order to
  2375. -- change the line where item comes into existence
  2376. -- * used in (lparser) luaY:funcargs(), luaY:forbody(), luaY:funcstat()
  2377. ------------------------------------------------------------------------
  2378. function luaK:fixline(fs, line)
  2379. fs.f.lineinfo[fs.pc - 1] = line
  2380. end
  2381.  
  2382. ------------------------------------------------------------------------
  2383. -- general function to write an instruction into the instruction buffer,
  2384. -- sets debug information too
  2385. -- * used in luaK:codeABC(), luaK:codeABx()
  2386. -- * called directly by (lparser) luaY:whilestat()
  2387. ------------------------------------------------------------------------
  2388. function luaK:code(fs, i, line)
  2389. local f = fs.f
  2390. self:dischargejpc(fs) -- 'pc' will change
  2391. -- put new instruction in code array
  2392. luaY:growvector(fs.L, f.code, fs.pc, f.sizecode, nil,
  2393. luaY.MAX_INT, "code size overflow")
  2394. f.code[fs.pc] = i
  2395. -- save corresponding line information
  2396. luaY:growvector(fs.L, f.lineinfo, fs.pc, f.sizelineinfo, nil,
  2397. luaY.MAX_INT, "code size overflow")
  2398. f.lineinfo[fs.pc] = line
  2399. local pc = fs.pc
  2400. fs.pc = fs.pc + 1
  2401. return pc
  2402. end
  2403.  
  2404. ------------------------------------------------------------------------
  2405. -- writes an instruction of type ABC
  2406. -- * calls luaK:code()
  2407. ------------------------------------------------------------------------
  2408. function luaK:codeABC(fs, o, a, b, c)
  2409. assert(luaP:getOpMode(o) == luaP.OpMode.iABC)
  2410. assert(luaP:getBMode(o) ~= luaP.OpArgMask.OpArgN or b == 0)
  2411. assert(luaP:getCMode(o) ~= luaP.OpArgMask.OpArgN or c == 0)
  2412. return self:code(fs, luaP:CREATE_ABC(o, a, b, c), fs.ls.lastline)
  2413. end
  2414.  
  2415. ------------------------------------------------------------------------
  2416. -- writes an instruction of type ABx
  2417. -- * calls luaK:code(), called by luaK:codeAsBx()
  2418. ------------------------------------------------------------------------
  2419. function luaK:codeABx(fs, o, a, bc)
  2420. assert(luaP:getOpMode(o) == luaP.OpMode.iABx or
  2421. luaP:getOpMode(o) == luaP.OpMode.iAsBx)
  2422. assert(luaP:getCMode(o) == luaP.OpArgMask.OpArgN)
  2423. return self:code(fs, luaP:CREATE_ABx(o, a, bc), fs.ls.lastline)
  2424. end
  2425.  
  2426. ------------------------------------------------------------------------
  2427. --
  2428. -- * used in (lparser) luaY:closelistfield(), luaY:lastlistfield()
  2429. ------------------------------------------------------------------------
  2430. function luaK:setlist(fs, base, nelems, tostore)
  2431. local c = math.floor((nelems - 1)/luaP.LFIELDS_PER_FLUSH) + 1
  2432. local b = (tostore == luaY.LUA_MULTRET) and 0 or tostore
  2433. assert(tostore ~= 0)
  2434. if c <= luaP.MAXARG_C then
  2435. self:codeABC(fs, "OP_SETLIST", base, b, c)
  2436. else
  2437. self:codeABC(fs, "OP_SETLIST", base, b, 0)
  2438. self:code(fs, luaP:CREATE_Inst(c), fs.ls.lastline)
  2439. end
  2440. fs.freereg = base + 1 -- free registers with list values
  2441. end
  2442.  
  2443. local luaKfunc = function(a) luaY = a return luaK end
  2444.  
  2445. --[[--------------------------------------------------------------------
  2446.  
  2447. ldump.lua
  2448. Save precompiled Lua chunks
  2449. This file is part of Yueliang.
  2450.  
  2451. Copyright (c) 2006 Kein-Hong Man <khman@users.sf.net>
  2452. The COPYRIGHT file describes the conditions
  2453. under which this software may be distributed.
  2454.  
  2455. See the ChangeLog for more information.
  2456.  
  2457. ----------------------------------------------------------------------]]
  2458.  
  2459. --[[--------------------------------------------------------------------
  2460. -- Notes:
  2461. -- * WARNING! byte order (little endian) and data type sizes for header
  2462. -- signature values hard-coded; see luaU:header
  2463. -- * chunk writer generators are included, see below
  2464. -- * one significant difference is that instructions are still in table
  2465. -- form (with OP/A/B/C/Bx fields) and luaP:Instruction() is needed to
  2466. -- convert them into 4-char strings
  2467. --
  2468. -- Not implemented:
  2469. -- * DumpVar, DumpMem has been removed
  2470. -- * DumpVector folded into folded into DumpDebug, DumpCode
  2471. --
  2472. -- Added:
  2473. -- * for convenience, the following two functions have been added:
  2474. -- luaU:make_setS: create a chunk writer that writes to a string
  2475. -- luaU:make_setF: create a chunk writer that writes to a file
  2476. -- (lua.h contains a typedef for lua_Writer/lua_Chunkwriter, and
  2477. -- a Lua-based implementation exists, writer() in lstrlib.c)
  2478. -- * luaU:ttype(o) (from lobject.h)
  2479. -- * for converting number types to its binary equivalent:
  2480. -- luaU:from_double(x): encode double value for writing
  2481. -- luaU:from_int(x): encode integer value for writing
  2482. -- (error checking is limited for these conversion functions)
  2483. -- (double conversion does not support denormals or NaNs)
  2484. --
  2485. -- Changed in 5.1.x:
  2486. -- * the dumper was mostly rewritten in Lua 5.1.x, so notes on the
  2487. -- differences between 5.0.x and 5.1.x is limited
  2488. -- * LUAC_VERSION bumped to 0x51, LUAC_FORMAT added
  2489. -- * developer is expected to adjust LUAC_FORMAT in order to identify
  2490. -- non-standard binary chunk formats
  2491. -- * header signature code is smaller, has been simplified, and is
  2492. -- tested as a single unit; its logic is shared with the undumper
  2493. -- * no more endian conversion, invalid endianness mean rejection
  2494. -- * opcode field sizes are no longer exposed in the header
  2495. -- * code moved to front of a prototype, followed by constants
  2496. -- * debug information moved to the end of the binary chunk, and the
  2497. -- relevant functions folded into a single function
  2498. -- * luaU:dump returns a writer status code
  2499. -- * chunk writer now implements status code because dumper uses it
  2500. -- * luaU:endianness removed
  2501. ----------------------------------------------------------------------]]
  2502.  
  2503. --requires luaP
  2504. local luaU = {}
  2505. local luaP = luaPfunc
  2506.  
  2507. -- mark for precompiled code ('<esc>Lua') (from lua.h)
  2508. luaU.LUA_SIGNATURE = "\27Lua"
  2509.  
  2510. -- constants used by dumper (from lua.h)
  2511. luaU.LUA_TNUMBER = 3
  2512. luaU.LUA_TSTRING = 4
  2513. luaU.LUA_TNIL = 0
  2514. luaU.LUA_TBOOLEAN = 1
  2515. luaU.LUA_TNONE = -1
  2516.  
  2517. -- constants for header of binary files (from lundump.h)
  2518. luaU.LUAC_VERSION = 0x51 -- this is Lua 5.1
  2519. luaU.LUAC_FORMAT = 0 -- this is the official format
  2520. luaU.LUAC_HEADERSIZE = 12 -- size of header of binary files
  2521.  
  2522. --[[--------------------------------------------------------------------
  2523. -- Additional functions to handle chunk writing
  2524. -- * to use make_setS and make_setF, see test_ldump.lua elsewhere
  2525. ----------------------------------------------------------------------]]
  2526.  
  2527. ------------------------------------------------------------------------
  2528. -- create a chunk writer that writes to a string
  2529. -- * returns the writer function and a table containing the string
  2530. -- * to get the final result, look in buff.data
  2531. ------------------------------------------------------------------------
  2532. function luaU:make_setS()
  2533. local buff = {}
  2534. buff.data = ""
  2535. local writer =
  2536. function(s, buff) -- chunk writer
  2537. if not s then return 0 end
  2538. buff.data = buff.data..s
  2539. return 0
  2540. end
  2541. return writer, buff
  2542. end
  2543.  
  2544. ------------------------------------------------------------------------
  2545. -- create a chunk writer that writes to a file
  2546. -- * returns the writer function and a table containing the file handle
  2547. -- * if a nil is passed, then writer should close the open file
  2548. ------------------------------------------------------------------------
  2549. function luaU:make_setF(filename)
  2550. local buff = {}
  2551. buff.h = io.open(filename, "wb")
  2552. if not buff.h then return nil end
  2553. local writer =
  2554. function(s, buff) -- chunk writer
  2555. if not buff.h then return 0 end
  2556. if not s then
  2557. if buff.h:close() then return 0 end
  2558. else
  2559. if buff.h:write(s) then return 0 end
  2560. end
  2561. return 1
  2562. end
  2563. return writer, buff
  2564. end
  2565.  
  2566. ------------------------------------------------------------------------
  2567. -- works like the lobject.h version except that TObject used in these
  2568. -- scripts only has a 'value' field, no 'tt' field (native types used)
  2569. ------------------------------------------------------------------------
  2570. function luaU:ttype(o)
  2571. local tt = type(o.value)
  2572. if tt == "number" then return self.LUA_TNUMBER
  2573. elseif tt == "string" then return self.LUA_TSTRING
  2574. elseif tt == "nil" then return self.LUA_TNIL
  2575. elseif tt == "boolean" then return self.LUA_TBOOLEAN
  2576. else
  2577. return self.LUA_TNONE -- the rest should not appear
  2578. end
  2579. end
  2580.  
  2581. -----------------------------------------------------------------------
  2582. -- converts a IEEE754 double number to an 8-byte little-endian string
  2583. -- * luaU:from_double() and luaU:from_int() are adapted from ChunkBake
  2584. -- * supports +/- Infinity, but not denormals or NaNs
  2585. -----------------------------------------------------------------------
  2586. function luaU:from_double(x)
  2587. local function grab_byte(v)
  2588. local c = v % 256
  2589. return (v - c) / 256, string.char(c)
  2590. end
  2591. local sign = 0
  2592. if x < 0 then sign = 1; x = -x end
  2593. local mantissa, exponent = math.frexp(x)
  2594. if x == 0 then -- zero
  2595. mantissa, exponent = 0, 0
  2596. elseif x == 1/0 then
  2597. mantissa, exponent = 0, 2047
  2598. else
  2599. mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, 53)
  2600. exponent = exponent + 1022
  2601. end
  2602. local v, byte = "" -- convert to bytes
  2603. x = math.floor(mantissa)
  2604. for i = 1,6 do
  2605. x, byte = grab_byte(x); v = v..byte -- 47:0
  2606. end
  2607. x, byte = grab_byte(exponent * 16 + x); v = v..byte -- 55:48
  2608. x, byte = grab_byte(sign * 128 + x); v = v..byte -- 63:56
  2609. return v
  2610. end
  2611.  
  2612. -----------------------------------------------------------------------
  2613. -- converts a number to a little-endian 32-bit integer string
  2614. -- * input value assumed to not overflow, can be signed/unsigned
  2615. -----------------------------------------------------------------------
  2616. function luaU:from_int(x)
  2617. local v = ""
  2618. x = math.floor(x)
  2619. if x < 0 then x = 4294967296 + x end -- ULONG_MAX+1
  2620. for i = 1, 4 do
  2621. local c = x % 256
  2622. v = v..string.char(c); x = math.floor(x / 256)
  2623. end
  2624. return v
  2625. end
  2626.  
  2627. --[[--------------------------------------------------------------------
  2628. -- Functions to make a binary chunk
  2629. -- * many functions have the size parameter removed, since output is
  2630. -- in the form of a string and some sizes are implicit or hard-coded
  2631. ----------------------------------------------------------------------]]
  2632.  
  2633. --[[--------------------------------------------------------------------
  2634. -- struct DumpState:
  2635. -- L -- lua_State (not used in this script)
  2636. -- writer -- lua_Writer (chunk writer function)
  2637. -- data -- void* (chunk writer context or data already written)
  2638. -- strip -- if true, don't write any debug information
  2639. -- status -- if non-zero, an error has occured
  2640. ----------------------------------------------------------------------]]
  2641.  
  2642. ------------------------------------------------------------------------
  2643. -- dumps a block of bytes
  2644. -- * lua_unlock(D.L), lua_lock(D.L) unused
  2645. ------------------------------------------------------------------------
  2646. function luaU:DumpBlock(b, D)
  2647. if D.status == 0 then
  2648. -- lua_unlock(D->L);
  2649. D.status = D.write(b, D.data)
  2650. -- lua_lock(D->L);
  2651. end
  2652. end
  2653.  
  2654. ------------------------------------------------------------------------
  2655. -- dumps a char
  2656. ------------------------------------------------------------------------
  2657. function luaU:DumpChar(y, D)
  2658. self:DumpBlock(string.char(y), D)
  2659. end
  2660.  
  2661. ------------------------------------------------------------------------
  2662. -- dumps a 32-bit signed or unsigned integer (for int) (hard-coded)
  2663. ------------------------------------------------------------------------
  2664. function luaU:DumpInt(x, D)
  2665. self:DumpBlock(self:from_int(x), D)
  2666. end
  2667.  
  2668. ------------------------------------------------------------------------
  2669. -- dumps a lua_Number (hard-coded as a double)
  2670. ------------------------------------------------------------------------
  2671. function luaU:DumpNumber(x, D)
  2672. self:DumpBlock(self:from_double(x), D)
  2673. end
  2674.  
  2675. ------------------------------------------------------------------------
  2676. -- dumps a Lua string (size type is hard-coded)
  2677. ------------------------------------------------------------------------
  2678. function luaU:DumpString(s, D)
  2679. if s == nil then
  2680. self:DumpInt(0, D)
  2681. else
  2682. s = s.."\0" -- include trailing '\0'
  2683. self:DumpInt(#s, D)
  2684. self:DumpBlock(s, D)
  2685. end
  2686. end
  2687.  
  2688. ------------------------------------------------------------------------
  2689. -- dumps instruction block from function prototype
  2690. ------------------------------------------------------------------------
  2691. function luaU:DumpCode(f, D)
  2692. local n = f.sizecode
  2693. --was DumpVector
  2694. self:DumpInt(n, D)
  2695. for i = 0, n - 1 do
  2696. self:DumpBlock(luaP:Instruction(f.code[i]), D)
  2697. end
  2698. end
  2699.  
  2700. ------------------------------------------------------------------------
  2701. -- dump constant pool from function prototype
  2702. -- * bvalue(o), nvalue(o) and rawtsvalue(o) macros removed
  2703. ------------------------------------------------------------------------
  2704. function luaU:DumpConstants(f, D)
  2705. local n = f.sizek
  2706. self:DumpInt(n, D)
  2707. for i = 0, n - 1 do
  2708. local o = f.k[i] -- TValue
  2709. local tt = self:ttype(o)
  2710. self:DumpChar(tt, D)
  2711. if tt == self.LUA_TNIL then
  2712. elseif tt == self.LUA_TBOOLEAN then
  2713. self:DumpChar(o.value and 1 or 0, D)
  2714. elseif tt == self.LUA_TNUMBER then
  2715. self:DumpNumber(o.value, D)
  2716. elseif tt == self.LUA_TSTRING then
  2717. self:DumpString(o.value, D)
  2718. else
  2719. --lua_assert(0) -- cannot happen
  2720. end
  2721. end
  2722. n = f.sizep
  2723. self:DumpInt(n, D)
  2724. for i = 0, n - 1 do
  2725. self:DumpFunction(f.p[i], f.source, D)
  2726. end
  2727. end
  2728.  
  2729. ------------------------------------------------------------------------
  2730. -- dump debug information
  2731. ------------------------------------------------------------------------
  2732. function luaU:DumpDebug(f, D)
  2733. local n
  2734. n = D.strip and 0 or f.sizelineinfo -- dump line information
  2735. --was DumpVector
  2736. self:DumpInt(n, D)
  2737. for i = 0, n - 1 do
  2738. self:DumpInt(f.lineinfo[i], D)
  2739. end
  2740. n = D.strip and 0 or f.sizelocvars -- dump local information
  2741. self:DumpInt(n, D)
  2742. for i = 0, n - 1 do
  2743. self:DumpString(f.locvars[i].varname, D)
  2744. self:DumpInt(f.locvars[i].startpc, D)
  2745. self:DumpInt(f.locvars[i].endpc, D)
  2746. end
  2747. n = D.strip and 0 or f.sizeupvalues -- dump upvalue information
  2748. self:DumpInt(n, D)
  2749. for i = 0, n - 1 do
  2750. self:DumpString(f.upvalues[i], D)
  2751. end
  2752. end
  2753.  
  2754. ------------------------------------------------------------------------
  2755. -- dump child function prototypes from function prototype
  2756. ------------------------------------------------------------------------
  2757. function luaU:DumpFunction(f, p, D)
  2758. local source = f.source
  2759. if source == p or D.strip then source = nil end
  2760. self:DumpString(source, D)
  2761. self:DumpInt(f.lineDefined, D)
  2762. self:DumpInt(f.lastlinedefined, D)
  2763. self:DumpChar(f.nups, D)
  2764. self:DumpChar(f.numparams, D)
  2765. self:DumpChar(f.is_vararg, D)
  2766. self:DumpChar(f.maxstacksize, D)
  2767. self:DumpCode(f, D)
  2768. self:DumpConstants(f, D)
  2769. self:DumpDebug(f, D)
  2770. end
  2771.  
  2772. ------------------------------------------------------------------------
  2773. -- dump Lua header section (some sizes hard-coded)
  2774. ------------------------------------------------------------------------
  2775. function luaU:DumpHeader(D)
  2776. local h = self:header()
  2777. assert(#h == self.LUAC_HEADERSIZE) -- fixed buffer now an assert
  2778. self:DumpBlock(h, D)
  2779. end
  2780.  
  2781. ------------------------------------------------------------------------
  2782. -- make header (from lundump.c)
  2783. -- returns the header string
  2784. ------------------------------------------------------------------------
  2785. function luaU:header()
  2786. local x = 1
  2787. return self.LUA_SIGNATURE..
  2788. string.char(
  2789. self.LUAC_VERSION,
  2790. self.LUAC_FORMAT,
  2791. x, -- endianness (1=little)
  2792. 4, -- sizeof(int)
  2793. 4, -- sizeof(size_t)
  2794. 4, -- sizeof(Instruction)
  2795. 8, -- sizeof(lua_Number)
  2796. 0) -- is lua_Number integral?
  2797. end
  2798.  
  2799. ------------------------------------------------------------------------
  2800. -- dump Lua function as precompiled chunk
  2801. -- (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
  2802. -- * w, data are created from make_setS, make_setF
  2803. ------------------------------------------------------------------------
  2804. function luaU:dump(L, f, w, data, strip)
  2805. local D = {} -- DumpState
  2806. D.L = L
  2807. D.write = w
  2808. D.data = data
  2809. D.strip = strip
  2810. D.status = 0
  2811. self:DumpHeader(D)
  2812. self:DumpFunction(f, nil, D)
  2813. -- added: for a chunk writer writing to a file, this final call with
  2814. -- nil data is to indicate to the writer to close the file
  2815. D.write(nil, D.data)
  2816. return D.status
  2817. end
  2818.  
  2819. local luaUfunc = luaU
  2820.  
  2821. --[[--------------------------------------------------------------------
  2822.  
  2823. lparser.lua
  2824. Lua 5 parser in Lua
  2825. This file is part of Yueliang.
  2826.  
  2827. Copyright (c) 2005-2007 Kein-Hong Man <khman@users.sf.net>
  2828. The COPYRIGHT file describes the conditions
  2829. under which this software may be distributed.
  2830.  
  2831. See the ChangeLog for more information.
  2832.  
  2833. ----------------------------------------------------------------------]]
  2834.  
  2835. --[[--------------------------------------------------------------------
  2836. -- Notes:
  2837. -- * some unused C code that were not converted are kept as comments
  2838. -- * LUA_COMPAT_VARARG option changed into a comment block
  2839. -- * for value/size specific code added, look for 'NOTE: '
  2840. --
  2841. -- Not implemented:
  2842. -- * luaX_newstring not needed by this Lua implementation
  2843. -- * luaG_checkcode() in assert is not currently implemented
  2844. --
  2845. -- Added:
  2846. -- * some constants added from various header files
  2847. -- * luaY.LUA_QS used in error_expected, check_match (from luaconf.h)
  2848. -- * luaY:LUA_QL needed for error messages (from luaconf.h)
  2849. -- * luaY:growvector (from lmem.h) -- skeleton only, limit checking
  2850. -- * luaY.SHRT_MAX (from <limits.h>) for registerlocalvar
  2851. -- * luaY:newproto (from lfunc.c)
  2852. -- * luaY:int2fb (from lobject.c)
  2853. -- * NOTE: HASARG_MASK, for implementing a VARARG_HASARG bit operation
  2854. -- * NOTE: value-specific code for VARARG_NEEDSARG to replace a bitop
  2855. --
  2856. -- Changed in 5.1.x:
  2857. -- * various code changes are not detailed...
  2858. -- * names of constants may have changed, e.g. added a LUAI_ prefix
  2859. -- * struct expkind: added VKNUM, VVARARG; VCALL's info changed?
  2860. -- * struct expdesc: added nval
  2861. -- * struct FuncState: upvalues data type changed to upvaldesc
  2862. -- * macro hasmultret is new
  2863. -- * function checklimit moved to parser from lexer
  2864. -- * functions anchor_token, errorlimit, checknext are new
  2865. -- * checknext is new, equivalent to 5.0.x's check, see check too
  2866. -- * luaY:next and luaY:lookahead moved to lexer
  2867. -- * break keyword no longer skipped in luaY:breakstat
  2868. -- * function new_localvarstr replaced by new_localvarliteral
  2869. -- * registerlocalvar limits local variables to SHRT_MAX
  2870. -- * create_local deleted, new_localvarliteral used instead
  2871. -- * constant LUAI_MAXUPVALUES increased to 60
  2872. -- * constants MAXPARAMS, LUA_MAXPARSERLEVEL, MAXSTACK removed
  2873. -- * function interface changed: singlevaraux, singlevar
  2874. -- * enterlevel and leavelevel uses nCcalls to track call depth
  2875. -- * added a name argument to main entry function, luaY:parser
  2876. -- * function luaY_index changed to yindex
  2877. -- * luaY:int2fb()'s table size encoding format has been changed
  2878. -- * luaY:log2() no longer needed for table constructors
  2879. -- * function code_params deleted, functionality folded in parlist
  2880. -- * vararg flags handling (is_vararg) changes; also see VARARG_*
  2881. -- * LUA_COMPATUPSYNTAX section for old-style upvalues removed
  2882. -- * repeatstat() calls chunk() instead of block()
  2883. -- * function interface changed: cond, test_then_block
  2884. -- * while statement implementation considerably simplified; MAXEXPWHILE
  2885. -- and EXTRAEXP no longer required, no limits to the complexity of a
  2886. -- while condition
  2887. -- * repeat, forbody statement implementation has major changes,
  2888. -- mostly due to new scoping behaviour of local variables
  2889. -- * OPR_MULT renamed to OPR_MUL
  2890. ----------------------------------------------------------------------]]
  2891.  
  2892. --requires luaP, luaX, luaK
  2893. local luaY = {}
  2894. local luaX = luaXfunc
  2895. local luaK = luaKfunc(luaY)
  2896. local luaP = luaPfunc
  2897.  
  2898. --[[--------------------------------------------------------------------
  2899. -- Expression descriptor
  2900. -- * expkind changed to string constants; luaY:assignment was the only
  2901. -- function to use a relational operator with this enumeration
  2902. -- VVOID -- no value
  2903. -- VNIL -- no value
  2904. -- VTRUE -- no value
  2905. -- VFALSE -- no value
  2906. -- VK -- info = index of constant in 'k'
  2907. -- VKNUM -- nval = numerical value
  2908. -- VLOCAL -- info = local register
  2909. -- VUPVAL, -- info = index of upvalue in 'upvalues'
  2910. -- VGLOBAL -- info = index of table; aux = index of global name in 'k'
  2911. -- VINDEXED -- info = table register; aux = index register (or 'k')
  2912. -- VJMP -- info = instruction pc
  2913. -- VRELOCABLE -- info = instruction pc
  2914. -- VNONRELOC -- info = result register
  2915. -- VCALL -- info = instruction pc
  2916. -- VVARARG -- info = instruction pc
  2917. } ----------------------------------------------------------------------]]
  2918.  
  2919. --[[--------------------------------------------------------------------
  2920. -- * expdesc in Lua 5.1.x has a union u and another struct s; this Lua
  2921. -- implementation ignores all instances of u and s usage
  2922. -- struct expdesc:
  2923. -- k -- (enum: expkind)
  2924. -- info, aux -- (int, int)
  2925. -- nval -- (lua_Number)
  2926. -- t -- patch list of 'exit when true'
  2927. -- f -- patch list of 'exit when false'
  2928. ----------------------------------------------------------------------]]
  2929.  
  2930. --[[--------------------------------------------------------------------
  2931. -- struct upvaldesc:
  2932. -- k -- (lu_byte)
  2933. -- info -- (lu_byte)
  2934. ----------------------------------------------------------------------]]
  2935.  
  2936. --[[--------------------------------------------------------------------
  2937. -- state needed to generate code for a given function
  2938. -- struct FuncState:
  2939. -- f -- current function header (table: Proto)
  2940. -- h -- table to find (and reuse) elements in 'k' (table: Table)
  2941. -- prev -- enclosing function (table: FuncState)
  2942. -- ls -- lexical state (table: LexState)
  2943. -- L -- copy of the Lua state (table: lua_State)
  2944. -- bl -- chain of current blocks (table: BlockCnt)
  2945. -- pc -- next position to code (equivalent to 'ncode')
  2946. -- lasttarget -- 'pc' of last 'jump target'
  2947. -- jpc -- list of pending jumps to 'pc'
  2948. -- freereg -- first free register
  2949. -- nk -- number of elements in 'k'
  2950. -- np -- number of elements in 'p'
  2951. -- nlocvars -- number of elements in 'locvars'
  2952. -- nactvar -- number of active local variables
  2953. -- upvalues[LUAI_MAXUPVALUES] -- upvalues (table: upvaldesc)
  2954. -- actvar[LUAI_MAXVARS] -- declared-variable stack
  2955. ----------------------------------------------------------------------]]
  2956.  
  2957. ------------------------------------------------------------------------
  2958. -- constants used by parser
  2959. -- * picks up duplicate values from luaX if required
  2960. ------------------------------------------------------------------------
  2961.  
  2962. luaY.LUA_QS = luaX.LUA_QS or "'%s'" -- (from luaconf.h)
  2963.  
  2964. luaY.SHRT_MAX = 32767 -- (from <limits.h>)
  2965. luaY.LUAI_MAXVARS = 200 -- (luaconf.h)
  2966. luaY.LUAI_MAXUPVALUES = 60 -- (luaconf.h)
  2967. luaY.MAX_INT = luaX.MAX_INT or 2147483645 -- (from llimits.h)
  2968. -- * INT_MAX-2 for 32-bit systems
  2969. luaY.LUAI_MAXCCALLS = 200 -- (from luaconf.h)
  2970.  
  2971. luaY.VARARG_HASARG = 1 -- (from lobject.h)
  2972. -- NOTE: HASARG_MASK is value-specific
  2973. luaY.HASARG_MASK = 2 -- this was added for a bitop in parlist()
  2974. luaY.VARARG_ISVARARG = 2
  2975. -- NOTE: there is some value-specific code that involves VARARG_NEEDSARG
  2976. luaY.VARARG_NEEDSARG = 4
  2977.  
  2978. luaY.LUA_MULTRET = -1 -- (lua.h)
  2979.  
  2980. --[[--------------------------------------------------------------------
  2981. -- other functions
  2982. ----------------------------------------------------------------------]]
  2983.  
  2984. ------------------------------------------------------------------------
  2985. -- LUA_QL describes how error messages quote program elements.
  2986. -- CHANGE it if you want a different appearance. (from luaconf.h)
  2987. ------------------------------------------------------------------------
  2988. function luaY:LUA_QL(x)
  2989. return "'"..x.."'"
  2990. end
  2991.  
  2992. ------------------------------------------------------------------------
  2993. -- this is a stripped-down luaM_growvector (from lmem.h) which is a
  2994. -- macro based on luaM_growaux (in lmem.c); all the following does is
  2995. -- reproduce the size limit checking logic of the original function
  2996. -- so that error behaviour is identical; all arguments preserved for
  2997. -- convenience, even those which are unused
  2998. -- * set the t field to nil, since this originally does a sizeof(t)
  2999. -- * size (originally a pointer) is never updated, their final values
  3000. -- are set by luaY:close_func(), so overall things should still work
  3001. ------------------------------------------------------------------------
  3002. function luaY:growvector(L, v, nelems, size, t, limit, e)
  3003. if nelems >= limit then
  3004. error(e) -- was luaG_runerror
  3005. end
  3006. end
  3007.  
  3008. ------------------------------------------------------------------------
  3009. -- initialize a new function prototype structure (from lfunc.c)
  3010. -- * used only in open_func()
  3011. ------------------------------------------------------------------------
  3012. function luaY:newproto(L)
  3013. local f = {} -- Proto
  3014. -- luaC_link(L, obj2gco(f), LUA_TPROTO); /* GC */
  3015. f.k = {}
  3016. f.sizek = 0
  3017. f.p = {}
  3018. f.sizep = 0
  3019. f.code = {}
  3020. f.sizecode = 0
  3021. f.sizelineinfo = 0
  3022. f.sizeupvalues = 0
  3023. f.nups = 0
  3024. f.upvalues = {}
  3025. f.numparams = 0
  3026. f.is_vararg = 0
  3027. f.maxstacksize = 0
  3028. f.lineinfo = {}
  3029. f.sizelocvars = 0
  3030. f.locvars = {}
  3031. f.lineDefined = 0
  3032. f.lastlinedefined = 0
  3033. f.source = nil
  3034. return f
  3035. end
  3036.  
  3037. ------------------------------------------------------------------------
  3038. -- converts an integer to a "floating point byte", represented as
  3039. -- (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
  3040. -- eeeee != 0 and (xxx) otherwise.
  3041. ------------------------------------------------------------------------
  3042. function luaY:int2fb(x)
  3043. local e = 0 -- exponent
  3044. while x >= 16 do
  3045. x = math.floor((x + 1) / 2)
  3046. e = e + 1
  3047. end
  3048. if x < 8 then
  3049. return x
  3050. else
  3051. return ((e + 1) * 8) + (x - 8)
  3052. end
  3053. end
  3054.  
  3055. --[[--------------------------------------------------------------------
  3056. -- parser functions
  3057. ----------------------------------------------------------------------]]
  3058.  
  3059. ------------------------------------------------------------------------
  3060. -- true of the kind of expression produces multiple return values
  3061. ------------------------------------------------------------------------
  3062. function luaY:hasmultret(k)
  3063. return k == "VCALL" or k == "VVARARG"
  3064. end
  3065.  
  3066. ------------------------------------------------------------------------
  3067. -- convenience function to access active local i, returns entry
  3068. ------------------------------------------------------------------------
  3069. function luaY:getlocvar(fs, i)
  3070. return fs.f.locvars[ fs.actvar[i] ]
  3071. end
  3072.  
  3073. ------------------------------------------------------------------------
  3074. -- check a limit, string m provided as an error message
  3075. ------------------------------------------------------------------------
  3076. function luaY:checklimit(fs, v, l, m)
  3077. if v > l then self:errorlimit(fs, l, m) end
  3078. end
  3079.  
  3080. --[[--------------------------------------------------------------------
  3081. -- nodes for block list (list of active blocks)
  3082. -- struct BlockCnt:
  3083. -- previous -- chain (table: BlockCnt)
  3084. -- breaklist -- list of jumps out of this loop
  3085. -- nactvar -- # active local variables outside the breakable structure
  3086. -- upval -- true if some variable in the block is an upvalue (boolean)
  3087. -- isbreakable -- true if 'block' is a loop (boolean)
  3088. ----------------------------------------------------------------------]]
  3089.  
  3090. ------------------------------------------------------------------------
  3091. -- prototypes for recursive non-terminal functions
  3092. ------------------------------------------------------------------------
  3093. -- prototypes deleted; not required in Lua
  3094.  
  3095. ------------------------------------------------------------------------
  3096. -- reanchor if last token is has a constant string, see close_func()
  3097. -- * used only in close_func()
  3098. ------------------------------------------------------------------------
  3099. function luaY:anchor_token(ls)
  3100. if ls.t.token == "TK_NAME" or ls.t.token == "TK_STRING" then
  3101. -- not relevant to Lua implementation of parser
  3102. -- local ts = ls.t.seminfo
  3103. -- luaX_newstring(ls, getstr(ts), ts->tsv.len); /* C */
  3104. end
  3105. end
  3106.  
  3107. ------------------------------------------------------------------------
  3108. -- throws a syntax error if token expected is not there
  3109. ------------------------------------------------------------------------
  3110. function luaY:error_expected(ls, token)
  3111. luaX:syntaxerror(ls,
  3112. string.format(self.LUA_QS.." expected", luaX:token2str(ls, token)))
  3113. end
  3114.  
  3115. ------------------------------------------------------------------------
  3116. -- prepares error message for display, for limits exceeded
  3117. -- * used only in checklimit()
  3118. ------------------------------------------------------------------------
  3119. function luaY:errorlimit(fs, limit, what)
  3120. local msg = (fs.f.linedefined == 0) and
  3121. string.format("main function has more than %d %s", limit, what) or
  3122. string.format("function at line %d has more than %d %s",
  3123. fs.f.linedefined, limit, what)
  3124. luaX:lexerror(fs.ls, msg, 0)
  3125. end
  3126.  
  3127. ------------------------------------------------------------------------
  3128. -- tests for a token, returns outcome
  3129. -- * return value changed to boolean
  3130. ------------------------------------------------------------------------
  3131. function luaY:testnext(ls, c)
  3132. if ls.t.token == c then
  3133. luaX:next(ls)
  3134. return true
  3135. else
  3136. return false
  3137. end
  3138. end
  3139.  
  3140. ------------------------------------------------------------------------
  3141. -- check for existence of a token, throws error if not found
  3142. ------------------------------------------------------------------------
  3143. function luaY:check(ls, c)
  3144. if ls.t.token ~= c then
  3145. self:error_expected(ls, c)
  3146. end
  3147. end
  3148.  
  3149. ------------------------------------------------------------------------
  3150. -- verify existence of a token, then skip it
  3151. ------------------------------------------------------------------------
  3152. function luaY:checknext(ls, c)
  3153. self:check(ls, c)
  3154. luaX:next(ls)
  3155. end
  3156.  
  3157. ------------------------------------------------------------------------
  3158. -- throws error if condition not matched
  3159. ------------------------------------------------------------------------
  3160. function luaY:check_condition(ls, c, msg)
  3161. if not c then luaX:syntaxerror(ls, msg) end
  3162. end
  3163.  
  3164. ------------------------------------------------------------------------
  3165. -- verifies token conditions are met or else throw error
  3166. ------------------------------------------------------------------------
  3167. function luaY:check_match(ls, what, who, where)
  3168. if not self:testnext(ls, what) then
  3169. if where == ls.linenumber then
  3170. self:error_expected(ls, what)
  3171. else
  3172. luaX:syntaxerror(ls, string.format(
  3173. self.LUA_QS.." expected (to close "..self.LUA_QS.." at line %d)",
  3174. luaX:token2str(ls, what), luaX:token2str(ls, who), where))
  3175. end
  3176. end
  3177. end
  3178.  
  3179. ------------------------------------------------------------------------
  3180. -- expect that token is a name, return the name
  3181. ------------------------------------------------------------------------
  3182. function luaY:str_checkname(ls)
  3183. self:check(ls, "TK_NAME")
  3184. local ts = ls.t.seminfo
  3185. luaX:next(ls)
  3186. return ts
  3187. end
  3188.  
  3189. ------------------------------------------------------------------------
  3190. -- initialize a struct expdesc, expression description data structure
  3191. ------------------------------------------------------------------------
  3192. function luaY:init_exp(e, k, i)
  3193. e.f, e.t = luaK.NO_JUMP, luaK.NO_JUMP
  3194. e.k = k
  3195. e.info = i
  3196. end
  3197.  
  3198. ------------------------------------------------------------------------
  3199. -- adds given string s in string pool, sets e as VK
  3200. ------------------------------------------------------------------------
  3201. function luaY:codestring(ls, e, s)
  3202. self:init_exp(e, "VK", luaK:stringK(ls.fs, s))
  3203. end
  3204.  
  3205. ------------------------------------------------------------------------
  3206. -- consume a name token, adds it to string pool, sets e as VK
  3207. ------------------------------------------------------------------------
  3208. function luaY:checkname(ls, e)
  3209. self:codestring(ls, e, self:str_checkname(ls))
  3210. end
  3211.  
  3212. ------------------------------------------------------------------------
  3213. -- creates struct entry for a local variable
  3214. -- * used only in new_localvar()
  3215. ------------------------------------------------------------------------
  3216. function luaY:registerlocalvar(ls, varname)
  3217. local fs = ls.fs
  3218. local f = fs.f
  3219. self:growvector(ls.L, f.locvars, fs.nlocvars, f.sizelocvars,
  3220. nil, self.SHRT_MAX, "too many local variables")
  3221. -- loop to initialize empty f.locvar positions not required
  3222. f.locvars[fs.nlocvars] = {} -- LocVar
  3223. f.locvars[fs.nlocvars].varname = varname
  3224. -- luaC_objbarrier(ls.L, f, varname) /* GC */
  3225. local nlocvars = fs.nlocvars
  3226. fs.nlocvars = fs.nlocvars + 1
  3227. return nlocvars
  3228. end
  3229.  
  3230. ------------------------------------------------------------------------
  3231. -- creates a new local variable given a name and an offset from nactvar
  3232. -- * used in fornum(), forlist(), parlist(), body()
  3233. ------------------------------------------------------------------------
  3234. function luaY:new_localvarliteral(ls, v, n)
  3235. self:new_localvar(ls, v, n)
  3236. end
  3237.  
  3238. ------------------------------------------------------------------------
  3239. -- register a local variable, set in active variable list
  3240. ------------------------------------------------------------------------
  3241. function luaY:new_localvar(ls, name, n)
  3242. local fs = ls.fs
  3243. self:checklimit(fs, fs.nactvar + n + 1, self.LUAI_MAXVARS, "local variables")
  3244. fs.actvar[fs.nactvar + n] = self:registerlocalvar(ls, name)
  3245. end
  3246.  
  3247. ------------------------------------------------------------------------
  3248. -- adds nvars number of new local variables, set debug information
  3249. ------------------------------------------------------------------------
  3250. function luaY:adjustlocalvars(ls, nvars)
  3251. local fs = ls.fs
  3252. fs.nactvar = fs.nactvar + nvars
  3253. for i = nvars, 1, -1 do
  3254. self:getlocvar(fs, fs.nactvar - i).startpc = fs.pc
  3255. end
  3256. end
  3257.  
  3258. ------------------------------------------------------------------------
  3259. -- removes a number of locals, set debug information
  3260. ------------------------------------------------------------------------
  3261. function luaY:removevars(ls, tolevel)
  3262. local fs = ls.fs
  3263. while fs.nactvar > tolevel do
  3264. fs.nactvar = fs.nactvar - 1
  3265. self:getlocvar(fs, fs.nactvar).endpc = fs.pc
  3266. end
  3267. end
  3268.  
  3269. ------------------------------------------------------------------------
  3270. -- returns an existing upvalue index based on the given name, or
  3271. -- creates a new upvalue struct entry and returns the new index
  3272. -- * used only in singlevaraux()
  3273. ------------------------------------------------------------------------
  3274. function luaY:indexupvalue(fs, name, v)
  3275. local f = fs.f
  3276. for i = 0, f.nups - 1 do
  3277. if fs.upvalues[i].k == v.k and fs.upvalues[i].info == v.info then
  3278. assert(f.upvalues[i] == name)
  3279. return i
  3280. end
  3281. end
  3282. -- new one
  3283. self:checklimit(fs, f.nups + 1, self.LUAI_MAXUPVALUES, "upvalues")
  3284. self:growvector(fs.L, f.upvalues, f.nups, f.sizeupvalues,
  3285. nil, self.MAX_INT, "")
  3286. -- loop to initialize empty f.upvalues positions not required
  3287. f.upvalues[f.nups] = name
  3288. -- luaC_objbarrier(fs->L, f, name); /* GC */
  3289. assert(v.k == "VLOCAL" or v.k == "VUPVAL")
  3290. -- this is a partial copy; only k & info fields used
  3291. fs.upvalues[f.nups] = { k = v.k, info = v.info }
  3292. local nups = f.nups
  3293. f.nups = f.nups + 1
  3294. return nups
  3295. end
  3296.  
  3297. ------------------------------------------------------------------------
  3298. -- search the local variable namespace of the given fs for a match
  3299. -- * used only in singlevaraux()
  3300. ------------------------------------------------------------------------
  3301. function luaY:searchvar(fs, n)
  3302. for i = fs.nactvar - 1, 0, -1 do
  3303. if n == self:getlocvar(fs, i).varname then
  3304. return i
  3305. end
  3306. end
  3307. return -1 -- not found
  3308. end
  3309.  
  3310. ------------------------------------------------------------------------
  3311. -- * mark upvalue flags in function states up to a given level
  3312. -- * used only in singlevaraux()
  3313. ------------------------------------------------------------------------
  3314. function luaY:markupval(fs, level)
  3315. local bl = fs.bl
  3316. while bl and bl.nactvar > level do bl = bl.previous end
  3317. if bl then bl.upval = true end
  3318. end
  3319.  
  3320. ------------------------------------------------------------------------
  3321. -- handle locals, globals and upvalues and related processing
  3322. -- * search mechanism is recursive, calls itself to search parents
  3323. -- * used only in singlevar()
  3324. ------------------------------------------------------------------------
  3325. function luaY:singlevaraux(fs, n, var, base)
  3326. if fs == nil then -- no more levels?
  3327. self:init_exp(var, "VGLOBAL", luaP.NO_REG) -- default is global variable
  3328. return "VGLOBAL"
  3329. else
  3330. local v = self:searchvar(fs, n) -- look up at current level
  3331. if v >= 0 then
  3332. self:init_exp(var, "VLOCAL", v)
  3333. if base == 0 then
  3334. self:markupval(fs, v) -- local will be used as an upval
  3335. end
  3336. return "VLOCAL"
  3337. else -- not found at current level; try upper one
  3338. if self:singlevaraux(fs.prev, n, var, 0) == "VGLOBAL" then
  3339. return "VGLOBAL"
  3340. end
  3341. var.info = self:indexupvalue(fs, n, var) -- else was LOCAL or UPVAL
  3342. var.k = "VUPVAL" -- upvalue in this level
  3343. return "VUPVAL"
  3344. end--if v
  3345. end--if fs
  3346. end
  3347.  
  3348. ------------------------------------------------------------------------
  3349. -- consume a name token, creates a variable (global|local|upvalue)
  3350. -- * used in prefixexp(), funcname()
  3351. ------------------------------------------------------------------------
  3352. function luaY:singlevar(ls, var)
  3353. local varname = self:str_checkname(ls)
  3354. local fs = ls.fs
  3355. if self:singlevaraux(fs, varname, var, 1) == "VGLOBAL" then
  3356. var.info = luaK:stringK(fs, varname) -- info points to global name
  3357. end
  3358. end
  3359.  
  3360. ------------------------------------------------------------------------
  3361. -- adjust RHS to match LHS in an assignment
  3362. -- * used in assignment(), forlist(), localstat()
  3363. ------------------------------------------------------------------------
  3364. function luaY:adjust_assign(ls, nvars, nexps, e)
  3365. local fs = ls.fs
  3366. local extra = nvars - nexps
  3367. if self:hasmultret(e.k) then
  3368. extra = extra + 1 -- includes call itself
  3369. if extra <= 0 then extra = 0 end
  3370. luaK:setreturns(fs, e, extra) -- last exp. provides the difference
  3371. if extra > 1 then luaK:reserveregs(fs, extra - 1) end
  3372. else
  3373. if e.k ~= "VVOID" then luaK:exp2nextreg(fs, e) end -- close last expression
  3374. if extra > 0 then
  3375. local reg = fs.freereg
  3376. luaK:reserveregs(fs, extra)
  3377. luaK:_nil(fs, reg, extra)
  3378. end
  3379. end
  3380. end
  3381.  
  3382. ------------------------------------------------------------------------
  3383. -- tracks and limits parsing depth, assert check at end of parsing
  3384. ------------------------------------------------------------------------
  3385. function luaY:enterlevel(ls)
  3386. ls.L.nCcalls = ls.L.nCcalls + 1
  3387. if ls.L.nCcalls > self.LUAI_MAXCCALLS then
  3388. luaX:lexerror(ls, "chunk has too many syntax levels", 0)
  3389. end
  3390. end
  3391.  
  3392. ------------------------------------------------------------------------
  3393. -- tracks parsing depth, a pair with luaY:enterlevel()
  3394. ------------------------------------------------------------------------
  3395. function luaY:leavelevel(ls)
  3396. ls.L.nCcalls = ls.L.nCcalls - 1
  3397. end
  3398.  
  3399. ------------------------------------------------------------------------
  3400. -- enters a code unit, initializes elements
  3401. ------------------------------------------------------------------------
  3402. function luaY:enterblock(fs, bl, isbreakable)
  3403. bl.breaklist = luaK.NO_JUMP
  3404. bl.isbreakable = isbreakable
  3405. bl.nactvar = fs.nactvar
  3406. bl.upval = false
  3407. bl.previous = fs.bl
  3408. fs.bl = bl
  3409. assert(fs.freereg == fs.nactvar)
  3410. end
  3411.  
  3412. ------------------------------------------------------------------------
  3413. -- leaves a code unit, close any upvalues
  3414. ------------------------------------------------------------------------
  3415. function luaY:leaveblock(fs)
  3416. local bl = fs.bl
  3417. fs.bl = bl.previous
  3418. self:removevars(fs.ls, bl.nactvar)
  3419. if bl.upval then
  3420. luaK:codeABC(fs, "OP_CLOSE", bl.nactvar, 0, 0)
  3421. end
  3422. -- a block either controls scope or breaks (never both)
  3423. assert(not bl.isbreakable or not bl.upval)
  3424. assert(bl.nactvar == fs.nactvar)
  3425. fs.freereg = fs.nactvar -- free registers
  3426. luaK:patchtohere(fs, bl.breaklist)
  3427. end
  3428.  
  3429. ------------------------------------------------------------------------
  3430. -- implement the instantiation of a function prototype, append list of
  3431. -- upvalues after the instantiation instruction
  3432. -- * used only in body()
  3433. ------------------------------------------------------------------------
  3434. function luaY:pushclosure(ls, func, v)
  3435. local fs = ls.fs
  3436. local f = fs.f
  3437. self:growvector(ls.L, f.p, fs.np, f.sizep, nil,
  3438. luaP.MAXARG_Bx, "constant table overflow")
  3439. -- loop to initialize empty f.p positions not required
  3440. f.p[fs.np] = func.f
  3441. fs.np = fs.np + 1
  3442. -- luaC_objbarrier(ls->L, f, func->f); /* C */
  3443. self:init_exp(v, "VRELOCABLE", luaK:codeABx(fs, "OP_CLOSURE", 0, fs.np - 1))
  3444. for i = 0, func.f.nups - 1 do
  3445. local o = (func.upvalues[i].k == "VLOCAL") and "OP_MOVE" or "OP_GETUPVAL"
  3446. luaK:codeABC(fs, o, 0, func.upvalues[i].info, 0)
  3447. end
  3448. end
  3449.  
  3450. ------------------------------------------------------------------------
  3451. -- opening of a function
  3452. ------------------------------------------------------------------------
  3453. function luaY:open_func(ls, fs)
  3454. local L = ls.L
  3455. local f = self:newproto(ls.L)
  3456. fs.f = f
  3457. fs.prev = ls.fs -- linked list of funcstates
  3458. fs.ls = ls
  3459. fs.L = L
  3460. ls.fs = fs
  3461. fs.pc = 0
  3462. fs.lasttarget = -1
  3463. fs.jpc = luaK.NO_JUMP
  3464. fs.freereg = 0
  3465. fs.nk = 0
  3466. fs.np = 0
  3467. fs.nlocvars = 0
  3468. fs.nactvar = 0
  3469. fs.bl = nil
  3470. f.source = ls.source
  3471. f.maxstacksize = 2 -- registers 0/1 are always valid
  3472. fs.h = {} -- constant table; was luaH_new call
  3473. -- anchor table of constants and prototype (to avoid being collected)
  3474. -- sethvalue2s(L, L->top, fs->h); incr_top(L); /* C */
  3475. -- setptvalue2s(L, L->top, f); incr_top(L);
  3476. end
  3477.  
  3478. ------------------------------------------------------------------------
  3479. -- closing of a function
  3480. ------------------------------------------------------------------------
  3481. function luaY:close_func(ls)
  3482. local L = ls.L
  3483. local fs = ls.fs
  3484. local f = fs.f
  3485. self:removevars(ls, 0)
  3486. luaK:ret(fs, 0, 0) -- final return
  3487. -- luaM_reallocvector deleted for f->code, f->lineinfo, f->k, f->p,
  3488. -- f->locvars, f->upvalues; not required for Lua table arrays
  3489. f.sizecode = fs.pc
  3490. f.sizelineinfo = fs.pc
  3491. f.sizek = fs.nk
  3492. f.sizep = fs.np
  3493. f.sizelocvars = fs.nlocvars
  3494. f.sizeupvalues = f.nups
  3495. --assert(luaG_checkcode(f)) -- currently not implemented
  3496. assert(fs.bl == nil)
  3497. ls.fs = fs.prev
  3498. -- the following is not required for this implementation; kept here
  3499. -- for completeness
  3500. -- L->top -= 2; /* remove table and prototype from the stack */
  3501. -- last token read was anchored in defunct function; must reanchor it
  3502. if fs then self:anchor_token(ls) end
  3503. end
  3504.  
  3505. ------------------------------------------------------------------------
  3506. -- parser initialization function
  3507. -- * note additional sub-tables needed for LexState, FuncState
  3508. ------------------------------------------------------------------------
  3509. function luaY:parser(L, z, buff, name)
  3510. local lexstate = {} -- LexState
  3511. lexstate.t = {}
  3512. lexstate.lookahead = {}
  3513. local funcstate = {} -- FuncState
  3514. funcstate.upvalues = {}
  3515. funcstate.actvar = {}
  3516. -- the following nCcalls initialization added for convenience
  3517. L.nCcalls = 0
  3518. lexstate.buff = buff
  3519. luaX:setinput(L, lexstate, z, name)
  3520. self:open_func(lexstate, funcstate)
  3521. funcstate.f.is_vararg = self.VARARG_ISVARARG -- main func. is always vararg
  3522. luaX:next(lexstate) -- read first token
  3523. self:chunk(lexstate)
  3524. self:check(lexstate, "TK_EOS")
  3525. self:close_func(lexstate)
  3526. assert(funcstate.prev == nil)
  3527. assert(funcstate.f.nups == 0)
  3528. assert(lexstate.fs == nil)
  3529. return funcstate.f
  3530. end
  3531.  
  3532. --[[--------------------------------------------------------------------
  3533. -- GRAMMAR RULES
  3534. ----------------------------------------------------------------------]]
  3535.  
  3536. ------------------------------------------------------------------------
  3537. -- parse a function name suffix, for function call specifications
  3538. -- * used in primaryexp(), funcname()
  3539. ------------------------------------------------------------------------
  3540. function luaY:field(ls, v)
  3541. -- field -> ['.' | ':'] NAME
  3542. local fs = ls.fs
  3543. local key = {} -- expdesc
  3544. luaK:exp2anyreg(fs, v)
  3545. luaX:next(ls) -- skip the dot or colon
  3546. self:checkname(ls, key)
  3547. luaK:indexed(fs, v, key)
  3548. end
  3549.  
  3550. ------------------------------------------------------------------------
  3551. -- parse a table indexing suffix, for constructors, expressions
  3552. -- * used in recfield(), primaryexp()
  3553. ------------------------------------------------------------------------
  3554. function luaY:yindex(ls, v)
  3555. -- index -> '[' expr ']'
  3556. luaX:next(ls) -- skip the '['
  3557. self:expr(ls, v)
  3558. luaK:exp2val(ls.fs, v)
  3559. self:checknext(ls, "]")
  3560. end
  3561.  
  3562. --[[--------------------------------------------------------------------
  3563. -- Rules for Constructors
  3564. ----------------------------------------------------------------------]]
  3565.  
  3566. --[[--------------------------------------------------------------------
  3567. -- struct ConsControl:
  3568. -- v -- last list item read (table: struct expdesc)
  3569. -- t -- table descriptor (table: struct expdesc)
  3570. -- nh -- total number of 'record' elements
  3571. -- na -- total number of array elements
  3572. -- tostore -- number of array elements pending to be stored
  3573. ----------------------------------------------------------------------]]
  3574.  
  3575. ------------------------------------------------------------------------
  3576. -- parse a table record (hash) field
  3577. -- * used in constructor()
  3578. ------------------------------------------------------------------------
  3579. function luaY:recfield(ls, cc)
  3580. -- recfield -> (NAME | '['exp1']') = exp1
  3581. local fs = ls.fs
  3582. local reg = ls.fs.freereg
  3583. local key, val = {}, {} -- expdesc
  3584. if ls.t.token == "TK_NAME" then
  3585. self:checklimit(fs, cc.nh, self.MAX_INT, "items in a constructor")
  3586. self:checkname(ls, key)
  3587. else -- ls->t.token == '['
  3588. self:yindex(ls, key)
  3589. end
  3590. cc.nh = cc.nh + 1
  3591. self:checknext(ls, "=")
  3592. local rkkey = luaK:exp2RK(fs, key)
  3593. self:expr(ls, val)
  3594. luaK:codeABC(fs, "OP_SETTABLE", cc.t.info, rkkey, luaK:exp2RK(fs, val))
  3595. fs.freereg = reg -- free registers
  3596. end
  3597.  
  3598. ------------------------------------------------------------------------
  3599. -- emit a set list instruction if enough elements (LFIELDS_PER_FLUSH)
  3600. -- * used in constructor()
  3601. ------------------------------------------------------------------------
  3602. function luaY:closelistfield(fs, cc)
  3603. if cc.v.k == "VVOID" then return end -- there is no list item
  3604. luaK:exp2nextreg(fs, cc.v)
  3605. cc.v.k = "VVOID"
  3606. if cc.tostore == luaP.LFIELDS_PER_FLUSH then
  3607. luaK:setlist(fs, cc.t.info, cc.na, cc.tostore) -- flush
  3608. cc.tostore = 0 -- no more items pending
  3609. end
  3610. end
  3611.  
  3612. ------------------------------------------------------------------------
  3613. -- emit a set list instruction at the end of parsing list constructor
  3614. -- * used in constructor()
  3615. ------------------------------------------------------------------------
  3616. function luaY:lastlistfield(fs, cc)
  3617. if cc.tostore == 0 then return end
  3618. if self:hasmultret(cc.v.k) then
  3619. luaK:setmultret(fs, cc.v)
  3620. luaK:setlist(fs, cc.t.info, cc.na, self.LUA_MULTRET)
  3621. cc.na = cc.na - 1 -- do not count last expression (unknown number of elements)
  3622. else
  3623. if cc.v.k ~= "VVOID" then
  3624. luaK:exp2nextreg(fs, cc.v)
  3625. end
  3626. luaK:setlist(fs, cc.t.info, cc.na, cc.tostore)
  3627. end
  3628. end
  3629.  
  3630. ------------------------------------------------------------------------
  3631. -- parse a table list (array) field
  3632. -- * used in constructor()
  3633. ------------------------------------------------------------------------
  3634. function luaY:listfield(ls, cc)
  3635. self:expr(ls, cc.v)
  3636. self:checklimit(ls.fs, cc.na, self.MAX_INT, "items in a constructor")
  3637. cc.na = cc.na + 1
  3638. cc.tostore = cc.tostore + 1
  3639. end
  3640.  
  3641. ------------------------------------------------------------------------
  3642. -- parse a table constructor
  3643. -- * used in funcargs(), simpleexp()
  3644. ------------------------------------------------------------------------
  3645. function luaY:constructor(ls, t)
  3646. -- constructor -> '{' [ field { fieldsep field } [ fieldsep ] ] '}'
  3647. -- field -> recfield | listfield
  3648. -- fieldsep -> ',' | ';'
  3649. local fs = ls.fs
  3650. local line = ls.linenumber
  3651. local pc = luaK:codeABC(fs, "OP_NEWTABLE", 0, 0, 0)
  3652. local cc = {} -- ConsControl
  3653. cc.v = {}
  3654. cc.na, cc.nh, cc.tostore = 0, 0, 0
  3655. cc.t = t
  3656. self:init_exp(t, "VRELOCABLE", pc)
  3657. self:init_exp(cc.v, "VVOID", 0) -- no value (yet)
  3658. luaK:exp2nextreg(ls.fs, t) -- fix it at stack top (for gc)
  3659. self:checknext(ls, "{")
  3660. repeat
  3661. assert(cc.v.k == "VVOID" or cc.tostore > 0)
  3662. if ls.t.token == "}" then break end
  3663. self:closelistfield(fs, cc)
  3664. local c = ls.t.token
  3665.  
  3666. if c == "TK_NAME" then -- may be listfields or recfields
  3667. luaX:lookahead(ls)
  3668. if ls.lookahead.token ~= "=" then -- expression?
  3669. self:listfield(ls, cc)
  3670. else
  3671. self:recfield(ls, cc)
  3672. end
  3673. elseif c == "[" then -- constructor_item -> recfield
  3674. self:recfield(ls, cc)
  3675. else -- constructor_part -> listfield
  3676. self:listfield(ls, cc)
  3677. end
  3678. until not self:testnext(ls, ",") and not self:testnext(ls, ";")
  3679. self:check_match(ls, "}", "{", line)
  3680. self:lastlistfield(fs, cc)
  3681. luaP:SETARG_B(fs.f.code[pc], self:int2fb(cc.na)) -- set initial array size
  3682. luaP:SETARG_C(fs.f.code[pc], self:int2fb(cc.nh)) -- set initial table size
  3683. end
  3684.  
  3685. -- }======================================================================
  3686.  
  3687. ------------------------------------------------------------------------
  3688. -- parse the arguments (parameters) of a function declaration
  3689. -- * used in body()
  3690. ------------------------------------------------------------------------
  3691. function luaY:parlist(ls)
  3692. -- parlist -> [ param { ',' param } ]
  3693. local fs = ls.fs
  3694. local f = fs.f
  3695. local nparams = 0
  3696. f.is_vararg = 0
  3697. if ls.t.token ~= ")" then -- is 'parlist' not empty?
  3698. repeat
  3699. local c = ls.t.token
  3700. if c == "TK_NAME" then -- param -> NAME
  3701. self:new_localvar(ls, self:str_checkname(ls), nparams)
  3702. nparams = nparams + 1
  3703. elseif c == "TK_DOTS" then -- param -> `...'
  3704. luaX:next(ls)
  3705. -- [[
  3706. -- #if defined(LUA_COMPAT_VARARG)
  3707. -- use `arg' as default name
  3708. self:new_localvarliteral(ls, "arg", nparams)
  3709. nparams = nparams + 1
  3710. f.is_vararg = self.VARARG_HASARG + self.VARARG_NEEDSARG
  3711. -- #endif
  3712. --]]
  3713. f.is_vararg = f.is_vararg + self.VARARG_ISVARARG
  3714. else
  3715. luaX:syntaxerror(ls, "<name> or "..self:LUA_QL("...").." expected")
  3716. end
  3717. until f.is_vararg ~= 0 or not self:testnext(ls, ",")
  3718. end--if
  3719. self:adjustlocalvars(ls, nparams)
  3720. -- NOTE: the following works only when HASARG_MASK is 2!
  3721. f.numparams = fs.nactvar - (f.is_vararg % self.HASARG_MASK)
  3722. luaK:reserveregs(fs, fs.nactvar) -- reserve register for parameters
  3723. end
  3724.  
  3725. ------------------------------------------------------------------------
  3726. -- parse function declaration body
  3727. -- * used in simpleexp(), localfunc(), funcstat()
  3728. ------------------------------------------------------------------------
  3729. function luaY:body(ls, e, needself, line)
  3730. -- body -> '(' parlist ')' chunk END
  3731. local new_fs = {} -- FuncState
  3732. new_fs.upvalues = {}
  3733. new_fs.actvar = {}
  3734. self:open_func(ls, new_fs)
  3735. new_fs.f.lineDefined = line
  3736. self:checknext(ls, "(")
  3737. if needself then
  3738. self:new_localvarliteral(ls, "self", 0)
  3739. self:adjustlocalvars(ls, 1)
  3740. end
  3741. self:parlist(ls)
  3742. self:checknext(ls, ")")
  3743. self:chunk(ls)
  3744. new_fs.f.lastlinedefined = ls.linenumber
  3745. self:check_match(ls, "TK_END", "TK_FUNCTION", line)
  3746. self:close_func(ls)
  3747. self:pushclosure(ls, new_fs, e)
  3748. end
  3749.  
  3750. ------------------------------------------------------------------------
  3751. -- parse a list of comma-separated expressions
  3752. -- * used is multiple locations
  3753. ------------------------------------------------------------------------
  3754. function luaY:explist1(ls, v)
  3755. -- explist1 -> expr { ',' expr }
  3756. local n = 1 -- at least one expression
  3757. self:expr(ls, v)
  3758. while self:testnext(ls, ",") do
  3759. luaK:exp2nextreg(ls.fs, v)
  3760. self:expr(ls, v)
  3761. n = n + 1
  3762. end
  3763. return n
  3764. end
  3765.  
  3766. ------------------------------------------------------------------------
  3767. -- parse the parameters of a function call
  3768. -- * contrast with parlist(), used in function declarations
  3769. -- * used in primaryexp()
  3770. ------------------------------------------------------------------------
  3771. function luaY:funcargs(ls, f)
  3772. local fs = ls.fs
  3773. local args = {} -- expdesc
  3774. local nparams
  3775. local line = ls.linenumber
  3776. local c = ls.t.token
  3777. if c == "(" then -- funcargs -> '(' [ explist1 ] ')'
  3778. if line ~= ls.lastline then
  3779. luaX:syntaxerror(ls, "ambiguous syntax (function call x new statement)")
  3780. end
  3781. luaX:next(ls)
  3782. if ls.t.token == ")" then -- arg list is empty?
  3783. args.k = "VVOID"
  3784. else
  3785. self:explist1(ls, args)
  3786. luaK:setmultret(fs, args)
  3787. end
  3788. self:check_match(ls, ")", "(", line)
  3789. elseif c == "{" then -- funcargs -> constructor
  3790. self:constructor(ls, args)
  3791. elseif c == "TK_STRING" then -- funcargs -> STRING
  3792. self:codestring(ls, args, ls.t.seminfo)
  3793. luaX:next(ls) -- must use 'seminfo' before 'next'
  3794. else
  3795. luaX:syntaxerror(ls, "function arguments expected")
  3796. return
  3797. end
  3798. assert(f.k == "VNONRELOC")
  3799. local base = f.info -- base register for call
  3800. if self:hasmultret(args.k) then
  3801. nparams = self.LUA_MULTRET -- open call
  3802. else
  3803. if args.k ~= "VVOID" then
  3804. luaK:exp2nextreg(fs, args) -- close last argument
  3805. end
  3806. nparams = fs.freereg - (base + 1)
  3807. end
  3808. self:init_exp(f, "VCALL", luaK:codeABC(fs, "OP_CALL", base, nparams + 1, 2))
  3809. luaK:fixline(fs, line)
  3810. fs.freereg = base + 1 -- call remove function and arguments and leaves
  3811. -- (unless changed) one result
  3812. end
  3813.  
  3814. --[[--------------------------------------------------------------------
  3815. -- Expression parsing
  3816. ----------------------------------------------------------------------]]
  3817.  
  3818. ------------------------------------------------------------------------
  3819. -- parses an expression in parentheses or a single variable
  3820. -- * used in primaryexp()
  3821. ------------------------------------------------------------------------
  3822. function luaY:prefixexp(ls, v)
  3823. -- prefixexp -> NAME | '(' expr ')'
  3824. local c = ls.t.token
  3825. if c == "(" then
  3826. local line = ls.linenumber
  3827. luaX:next(ls)
  3828. self:expr(ls, v)
  3829. self:check_match(ls, ")", "(", line)
  3830. luaK:dischargevars(ls.fs, v)
  3831. elseif c == "TK_NAME" then
  3832. self:singlevar(ls, v)
  3833. else
  3834. luaX:syntaxerror(ls, "unexpected symbol")
  3835. end--if c
  3836. return
  3837. end
  3838.  
  3839. ------------------------------------------------------------------------
  3840. -- parses a prefixexp (an expression in parentheses or a single variable)
  3841. -- or a function call specification
  3842. -- * used in simpleexp(), assignment(), exprstat()
  3843. ------------------------------------------------------------------------
  3844. function luaY:primaryexp(ls, v)
  3845. -- primaryexp ->
  3846. -- prefixexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs }
  3847. local fs = ls.fs
  3848. self:prefixexp(ls, v)
  3849. while true do
  3850. local c = ls.t.token
  3851. if c == "." then -- field
  3852. self:field(ls, v)
  3853. elseif c == "[" then -- '[' exp1 ']'
  3854. local key = {} -- expdesc
  3855. luaK:exp2anyreg(fs, v)
  3856. self:yindex(ls, key)
  3857. luaK:indexed(fs, v, key)
  3858. elseif c == ":" then -- ':' NAME funcargs
  3859. local key = {} -- expdesc
  3860. luaX:next(ls)
  3861. self:checkname(ls, key)
  3862. luaK:_self(fs, v, key)
  3863. self:funcargs(ls, v)
  3864. elseif c == "(" or c == "TK_STRING" or c == "{" then -- funcargs
  3865. luaK:exp2nextreg(fs, v)
  3866. self:funcargs(ls, v)
  3867. else
  3868. return
  3869. end--if c
  3870. end--while
  3871. end
  3872.  
  3873. ------------------------------------------------------------------------
  3874. -- parses general expression types, constants handled here
  3875. -- * used in subexpr()
  3876. ------------------------------------------------------------------------
  3877. function luaY:simpleexp(ls, v)
  3878. -- simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... |
  3879. -- constructor | FUNCTION body | primaryexp
  3880. local c = ls.t.token
  3881. if c == "TK_NUMBER" then
  3882. self:init_exp(v, "VKNUM", 0)
  3883. v.nval = ls.t.seminfo
  3884. elseif c == "TK_STRING" then
  3885. self:codestring(ls, v, ls.t.seminfo)
  3886. elseif c == "TK_NIL" then
  3887. self:init_exp(v, "VNIL", 0)
  3888. elseif c == "TK_TRUE" then
  3889. self:init_exp(v, "VTRUE", 0)
  3890. elseif c == "TK_FALSE" then
  3891. self:init_exp(v, "VFALSE", 0)
  3892. elseif c == "TK_DOTS" then -- vararg
  3893. local fs = ls.fs
  3894. self:check_condition(ls, fs.f.is_vararg ~= 0,
  3895. "cannot use "..self:LUA_QL("...").." outside a vararg function");
  3896. -- NOTE: the following substitutes for a bitop, but is value-specific
  3897. local is_vararg = fs.f.is_vararg
  3898. if is_vararg >= self.VARARG_NEEDSARG then
  3899. fs.f.is_vararg = is_vararg - self.VARARG_NEEDSARG -- don't need 'arg'
  3900. end
  3901. self:init_exp(v, "VVARARG", luaK:codeABC(fs, "OP_VARARG", 0, 1, 0))
  3902. elseif c == "{" then -- constructor
  3903. self:constructor(ls, v)
  3904. return
  3905. elseif c == "TK_FUNCTION" then
  3906. luaX:next(ls)
  3907. self:body(ls, v, false, ls.linenumber)
  3908. return
  3909. else
  3910. self:primaryexp(ls, v)
  3911. return
  3912. end--if c
  3913. luaX:next(ls)
  3914. end
  3915.  
  3916. ------------------------------------------------------------------------
  3917. -- Translates unary operators tokens if found, otherwise returns
  3918. -- OPR_NOUNOPR. getunopr() and getbinopr() are used in subexpr().
  3919. -- * used in subexpr()
  3920. ------------------------------------------------------------------------
  3921. function luaY:getunopr(op)
  3922. if op == "TK_NOT" then
  3923. return "OPR_NOT"
  3924. elseif op == "-" then
  3925. return "OPR_MINUS"
  3926. elseif op == "#" then
  3927. return "OPR_LEN"
  3928. else
  3929. return "OPR_NOUNOPR"
  3930. end
  3931. end
  3932.  
  3933. ------------------------------------------------------------------------
  3934. -- Translates binary operator tokens if found, otherwise returns
  3935. -- OPR_NOBINOPR. Code generation uses OPR_* style tokens.
  3936. -- * used in subexpr()
  3937. ------------------------------------------------------------------------
  3938. luaY.getbinopr_table = {
  3939. ["+"] = "OPR_ADD",
  3940. ["-"] = "OPR_SUB",
  3941. ["*"] = "OPR_MUL",
  3942. ["/"] = "OPR_DIV",
  3943. ["%"] = "OPR_MOD",
  3944. ["^"] = "OPR_POW",
  3945. ["TK_CONCAT"] = "OPR_CONCAT",
  3946. ["TK_NE"] = "OPR_NE",
  3947. ["TK_EQ"] = "OPR_EQ",
  3948. ["<"] = "OPR_LT",
  3949. ["TK_LE"] = "OPR_LE",
  3950. [">"] = "OPR_GT",
  3951. ["TK_GE"] = "OPR_GE",
  3952. ["TK_AND"] = "OPR_AND",
  3953. ["TK_OR"] = "OPR_OR",
  3954. }
  3955. function luaY:getbinopr(op)
  3956. local opr = self.getbinopr_table[op]
  3957. if opr then return opr else return "OPR_NOBINOPR" end
  3958. end
  3959.  
  3960. ------------------------------------------------------------------------
  3961. -- the following priority table consists of pairs of left/right values
  3962. -- for binary operators (was a static const struct); grep for ORDER OPR
  3963. -- * the following struct is replaced:
  3964. -- static const struct {
  3965. -- lu_byte left; /* left priority for each binary operator */
  3966. -- lu_byte right; /* right priority */
  3967. -- } priority[] = { /* ORDER OPR */
  3968. ------------------------------------------------------------------------
  3969. luaY.priority = {
  3970. {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, -- `+' `-' `/' `%'
  3971. {10, 9}, {5, 4}, -- power and concat (right associative)
  3972. {3, 3}, {3, 3}, -- equality
  3973. {3, 3}, {3, 3}, {3, 3}, {3, 3}, -- order
  3974. {2, 2}, {1, 1} -- logical (and/or)
  3975. }
  3976.  
  3977. luaY.UNARY_PRIORITY = 8 -- priority for unary operators
  3978.  
  3979. ------------------------------------------------------------------------
  3980. -- Parse subexpressions. Includes handling of unary operators and binary
  3981. -- operators. A subexpr is given the rhs priority level of the operator
  3982. -- immediately left of it, if any (limit is -1 if none,) and if a binop
  3983. -- is found, limit is compared with the lhs priority level of the binop
  3984. -- in order to determine which executes first.
  3985. ------------------------------------------------------------------------
  3986.  
  3987. ------------------------------------------------------------------------
  3988. -- subexpr -> (simpleexp | unop subexpr) { binop subexpr }
  3989. -- where 'binop' is any binary operator with a priority higher than 'limit'
  3990. -- * for priority lookups with self.priority[], 1=left and 2=right
  3991. -- * recursively called
  3992. -- * used in expr()
  3993. ------------------------------------------------------------------------
  3994. function luaY:subexpr(ls, v, limit)
  3995. self:enterlevel(ls)
  3996. local uop = self:getunopr(ls.t.token)
  3997. if uop ~= "OPR_NOUNOPR" then
  3998. luaX:next(ls)
  3999. self:subexpr(ls, v, self.UNARY_PRIORITY)
  4000. luaK:prefix(ls.fs, uop, v)
  4001. else
  4002. self:simpleexp(ls, v)
  4003. end
  4004. -- expand while operators have priorities higher than 'limit'
  4005. local op = self:getbinopr(ls.t.token)
  4006. while op ~= "OPR_NOBINOPR" and self.priority[luaK.BinOpr[op] + 1][1] > limit do
  4007. local v2 = {} -- expdesc
  4008. luaX:next(ls)
  4009. luaK:infix(ls.fs, op, v)
  4010. -- read sub-expression with higher priority
  4011. local nextop = self:subexpr(ls, v2, self.priority[luaK.BinOpr[op] + 1][2])
  4012. luaK:posfix(ls.fs, op, v, v2)
  4013. op = nextop
  4014. end
  4015. self:leavelevel(ls)
  4016. return op -- return first untreated operator
  4017. end
  4018.  
  4019. ------------------------------------------------------------------------
  4020. -- Expression parsing starts here. Function subexpr is entered with the
  4021. -- left operator (which is non-existent) priority of -1, which is lower
  4022. -- than all actual operators. Expr information is returned in parm v.
  4023. -- * used in multiple locations
  4024. ------------------------------------------------------------------------
  4025. function luaY:expr(ls, v)
  4026. self:subexpr(ls, v, 0)
  4027. end
  4028.  
  4029. -- }====================================================================
  4030.  
  4031. --[[--------------------------------------------------------------------
  4032. -- Rules for Statements
  4033. ----------------------------------------------------------------------]]
  4034.  
  4035. ------------------------------------------------------------------------
  4036. -- checks next token, used as a look-ahead
  4037. -- * returns boolean instead of 0|1
  4038. -- * used in retstat(), chunk()
  4039. ------------------------------------------------------------------------
  4040. function luaY:block_follow(token)
  4041. if token == "TK_ELSE" or token == "TK_ELSEIF" or token == "TK_END"
  4042. or token == "TK_UNTIL" or token == "TK_EOS" then
  4043. return true
  4044. else
  4045. return false
  4046. end
  4047. end
  4048.  
  4049. ------------------------------------------------------------------------
  4050. -- parse a code block or unit
  4051. -- * used in multiple functions
  4052. ------------------------------------------------------------------------
  4053. function luaY:block(ls)
  4054. -- block -> chunk
  4055. local fs = ls.fs
  4056. local bl = {} -- BlockCnt
  4057. self:enterblock(fs, bl, false)
  4058. self:chunk(ls)
  4059. assert(bl.breaklist == luaK.NO_JUMP)
  4060. self:leaveblock(fs)
  4061. end
  4062.  
  4063. ------------------------------------------------------------------------
  4064. -- structure to chain all variables in the left-hand side of an
  4065. -- assignment
  4066. -- struct LHS_assign:
  4067. -- prev -- (table: struct LHS_assign)
  4068. -- v -- variable (global, local, upvalue, or indexed) (table: expdesc)
  4069. ------------------------------------------------------------------------
  4070.  
  4071. ------------------------------------------------------------------------
  4072. -- check whether, in an assignment to a local variable, the local variable
  4073. -- is needed in a previous assignment (to a table). If so, save original
  4074. -- local value in a safe place and use this safe copy in the previous
  4075. -- assignment.
  4076. -- * used in assignment()
  4077. ------------------------------------------------------------------------
  4078. function luaY:check_conflict(ls, lh, v)
  4079. local fs = ls.fs
  4080. local extra = fs.freereg -- eventual position to save local variable
  4081. local conflict = false
  4082. while lh do
  4083. if lh.v.k == "VINDEXED" then
  4084. if lh.v.info == v.info then -- conflict?
  4085. conflict = true
  4086. lh.v.info = extra -- previous assignment will use safe copy
  4087. end
  4088. if lh.v.aux == v.info then -- conflict?
  4089. conflict = true
  4090. lh.v.aux = extra -- previous assignment will use safe copy
  4091. end
  4092. end
  4093. lh = lh.prev
  4094. end
  4095. if conflict then
  4096. luaK:codeABC(fs, "OP_MOVE", fs.freereg, v.info, 0) -- make copy
  4097. luaK:reserveregs(fs, 1)
  4098. end
  4099. end
  4100.  
  4101. ------------------------------------------------------------------------
  4102. -- parse a variable assignment sequence
  4103. -- * recursively called
  4104. -- * used in exprstat()
  4105. ------------------------------------------------------------------------
  4106. function luaY:assignment(ls, lh, nvars)
  4107. local e = {} -- expdesc
  4108. -- test was: VLOCAL <= lh->v.k && lh->v.k <= VINDEXED
  4109. local c = lh.v.k
  4110. self:check_condition(ls, c == "VLOCAL" or c == "VUPVAL" or c == "VGLOBAL"
  4111. or c == "VINDEXED", "syntax error")
  4112. if self:testnext(ls, ",") then -- assignment -> ',' primaryexp assignment
  4113. local nv = {} -- LHS_assign
  4114. nv.v = {}
  4115. nv.prev = lh
  4116. self:primaryexp(ls, nv.v)
  4117. if nv.v.k == "VLOCAL" then
  4118. self:check_conflict(ls, lh, nv.v)
  4119. end
  4120. self:checklimit(ls.fs, nvars, self.LUAI_MAXCCALLS - ls.L.nCcalls,
  4121. "variables in assignment")
  4122. self:assignment(ls, nv, nvars + 1)
  4123. else -- assignment -> '=' explist1
  4124. self:checknext(ls, "=")
  4125. local nexps = self:explist1(ls, e)
  4126. if nexps ~= nvars then
  4127. self:adjust_assign(ls, nvars, nexps, e)
  4128. if nexps > nvars then
  4129. ls.fs.freereg = ls.fs.freereg - (nexps - nvars) -- remove extra values
  4130. end
  4131. else
  4132. luaK:setoneret(ls.fs, e) -- close last expression
  4133. luaK:storevar(ls.fs, lh.v, e)
  4134. return -- avoid default
  4135. end
  4136. end
  4137. self:init_exp(e, "VNONRELOC", ls.fs.freereg - 1) -- default assignment
  4138. luaK:storevar(ls.fs, lh.v, e)
  4139. end
  4140.  
  4141. ------------------------------------------------------------------------
  4142. -- parse condition in a repeat statement or an if control structure
  4143. -- * used in repeatstat(), test_then_block()
  4144. ------------------------------------------------------------------------
  4145. function luaY:cond(ls)
  4146. -- cond -> exp
  4147. local v = {} -- expdesc
  4148. self:expr(ls, v) -- read condition
  4149. if v.k == "VNIL" then v.k = "VFALSE" end -- 'falses' are all equal here
  4150. luaK:goiftrue(ls.fs, v)
  4151. return v.f
  4152. end
  4153.  
  4154. ------------------------------------------------------------------------
  4155. -- parse a break statement
  4156. -- * used in statements()
  4157. ------------------------------------------------------------------------
  4158. function luaY:breakstat(ls)
  4159. -- stat -> BREAK
  4160. local fs = ls.fs
  4161. local bl = fs.bl
  4162. local upval = false
  4163. while bl and not bl.isbreakable do
  4164. if bl.upval then upval = true end
  4165. bl = bl.previous
  4166. end
  4167. if not bl then
  4168. luaX:syntaxerror(ls, "no loop to break")
  4169. end
  4170. if upval then
  4171. luaK:codeABC(fs, "OP_CLOSE", bl.nactvar, 0, 0)
  4172. end
  4173. bl.breaklist = luaK:concat(fs, bl.breaklist, luaK:jump(fs))
  4174. end
  4175.  
  4176. ------------------------------------------------------------------------
  4177. -- parse a while-do control structure, body processed by block()
  4178. -- * with dynamic array sizes, MAXEXPWHILE + EXTRAEXP limits imposed by
  4179. -- the function's implementation can be removed
  4180. -- * used in statements()
  4181. ------------------------------------------------------------------------
  4182. function luaY:whilestat(ls, line)
  4183. -- whilestat -> WHILE cond DO block END
  4184. local fs = ls.fs
  4185. local bl = {} -- BlockCnt
  4186. luaX:next(ls) -- skip WHILE
  4187. local whileinit = luaK:getlabel(fs)
  4188. local condexit = self:cond(ls)
  4189. self:enterblock(fs, bl, true)
  4190. self:checknext(ls, "TK_DO")
  4191. self:block(ls)
  4192. luaK:patchlist(fs, luaK:jump(fs), whileinit)
  4193. self:check_match(ls, "TK_END", "TK_WHILE", line)
  4194. self:leaveblock(fs)
  4195. luaK:patchtohere(fs, condexit) -- false conditions finish the loop
  4196. end
  4197.  
  4198. ------------------------------------------------------------------------
  4199. -- parse a repeat-until control structure, body parsed by chunk()
  4200. -- * used in statements()
  4201. ------------------------------------------------------------------------
  4202. function luaY:repeatstat(ls, line)
  4203. -- repeatstat -> REPEAT block UNTIL cond
  4204. local fs = ls.fs
  4205. local repeat_init = luaK:getlabel(fs)
  4206. local bl1, bl2 = {}, {} -- BlockCnt
  4207. self:enterblock(fs, bl1, true) -- loop block
  4208. self:enterblock(fs, bl2, false) -- scope block
  4209. luaX:next(ls) -- skip REPEAT
  4210. self:chunk(ls)
  4211. self:check_match(ls, "TK_UNTIL", "TK_REPEAT", line)
  4212. local condexit = self:cond(ls) -- read condition (inside scope block)
  4213. if not bl2.upval then -- no upvalues?
  4214. self:leaveblock(fs) -- finish scope
  4215. luaK:patchlist(ls.fs, condexit, repeat_init) -- close the loop
  4216. else -- complete semantics when there are upvalues
  4217. self:breakstat(ls) -- if condition then break
  4218. luaK:patchtohere(ls.fs, condexit) -- else...
  4219. self:leaveblock(fs) -- finish scope...
  4220. luaK:patchlist(ls.fs, luaK:jump(fs), repeat_init) -- and repeat
  4221. end
  4222. self:leaveblock(fs) -- finish loop
  4223. end
  4224.  
  4225. ------------------------------------------------------------------------
  4226. -- parse the single expressions needed in numerical for loops
  4227. -- * used in fornum()
  4228. ------------------------------------------------------------------------
  4229. function luaY:exp1(ls)
  4230. local e = {} -- expdesc
  4231. self:expr(ls, e)
  4232. local k = e.k
  4233. luaK:exp2nextreg(ls.fs, e)
  4234. return k
  4235. end
  4236.  
  4237. ------------------------------------------------------------------------
  4238. -- parse a for loop body for both versions of the for loop
  4239. -- * used in fornum(), forlist()
  4240. ------------------------------------------------------------------------
  4241. function luaY:forbody(ls, base, line, nvars, isnum)
  4242. -- forbody -> DO block
  4243. local bl = {} -- BlockCnt
  4244. local fs = ls.fs
  4245. self:adjustlocalvars(ls, 3) -- control variables
  4246. self:checknext(ls, "TK_DO")
  4247. local prep = isnum and luaK:codeAsBx(fs, "OP_FORPREP", base, luaK.NO_JUMP)
  4248. or luaK:jump(fs)
  4249. self:enterblock(fs, bl, false) -- scope for declared variables
  4250. self:adjustlocalvars(ls, nvars)
  4251. luaK:reserveregs(fs, nvars)
  4252. self:block(ls)
  4253. self:leaveblock(fs) -- end of scope for declared variables
  4254. luaK:patchtohere(fs, prep)
  4255. local endfor = isnum and luaK:codeAsBx(fs, "OP_FORLOOP", base, luaK.NO_JUMP)
  4256. or luaK:codeABC(fs, "OP_TFORLOOP", base, 0, nvars)
  4257. luaK:fixline(fs, line) -- pretend that `OP_FOR' starts the loop
  4258. luaK:patchlist(fs, isnum and endfor or luaK:jump(fs), prep + 1)
  4259. end
  4260.  
  4261. ------------------------------------------------------------------------
  4262. -- parse a numerical for loop, calls forbody()
  4263. -- * used in forstat()
  4264. ------------------------------------------------------------------------
  4265. function luaY:fornum(ls, varname, line)
  4266. -- fornum -> NAME = exp1,exp1[,exp1] forbody
  4267. local fs = ls.fs
  4268. local base = fs.freereg
  4269. self:new_localvarliteral(ls, "(for index)", 0)
  4270. self:new_localvarliteral(ls, "(for limit)", 1)
  4271. self:new_localvarliteral(ls, "(for step)", 2)
  4272. self:new_localvar(ls, varname, 3)
  4273. self:checknext(ls, '=')
  4274. self:exp1(ls) -- initial value
  4275. self:checknext(ls, ",")
  4276. self:exp1(ls) -- limit
  4277. if self:testnext(ls, ",") then
  4278. self:exp1(ls) -- optional step
  4279. else -- default step = 1
  4280. luaK:codeABx(fs, "OP_LOADK", fs.freereg, luaK:numberK(fs, 1))
  4281. luaK:reserveregs(fs, 1)
  4282. end
  4283. self:forbody(ls, base, line, 1, true)
  4284. end
  4285.  
  4286. ------------------------------------------------------------------------
  4287. -- parse a generic for loop, calls forbody()
  4288. -- * used in forstat()
  4289. ------------------------------------------------------------------------
  4290. function luaY:forlist(ls, indexname)
  4291. -- forlist -> NAME {,NAME} IN explist1 forbody
  4292. local fs = ls.fs
  4293. local e = {} -- expdesc
  4294. local nvars = 0
  4295. local base = fs.freereg
  4296. -- create control variables
  4297. self:new_localvarliteral(ls, "(for generator)", nvars)
  4298. nvars = nvars + 1
  4299. self:new_localvarliteral(ls, "(for state)", nvars)
  4300. nvars = nvars + 1
  4301. self:new_localvarliteral(ls, "(for control)", nvars)
  4302. nvars = nvars + 1
  4303. -- create declared variables
  4304. self:new_localvar(ls, indexname, nvars)
  4305. nvars = nvars + 1
  4306. while self:testnext(ls, ",") do
  4307. self:new_localvar(ls, self:str_checkname(ls), nvars)
  4308. nvars = nvars + 1
  4309. end
  4310. self:checknext(ls, "TK_IN")
  4311. local line = ls.linenumber
  4312. self:adjust_assign(ls, 3, self:explist1(ls, e), e)
  4313. luaK:checkstack(fs, 3) -- extra space to call generator
  4314. self:forbody(ls, base, line, nvars - 3, false)
  4315. end
  4316.  
  4317. ------------------------------------------------------------------------
  4318. -- initial parsing for a for loop, calls fornum() or forlist()
  4319. -- * used in statements()
  4320. ------------------------------------------------------------------------
  4321. function luaY:forstat(ls, line)
  4322. -- forstat -> FOR (fornum | forlist) END
  4323. local fs = ls.fs
  4324. local bl = {} -- BlockCnt
  4325. self:enterblock(fs, bl, true) -- scope for loop and control variables
  4326. luaX:next(ls) -- skip `for'
  4327. local varname = self:str_checkname(ls) -- first variable name
  4328. local c = ls.t.token
  4329. if c == "=" then
  4330. self:fornum(ls, varname, line)
  4331. elseif c == "," or c == "TK_IN" then
  4332. self:forlist(ls, varname)
  4333. else
  4334. luaX:syntaxerror(ls, self:LUA_QL("=").." or "..self:LUA_QL("in").." expected")
  4335. end
  4336. self:check_match(ls, "TK_END", "TK_FOR", line)
  4337. self:leaveblock(fs) -- loop scope (`break' jumps to this point)
  4338. end
  4339.  
  4340. ------------------------------------------------------------------------
  4341. -- parse part of an if control structure, including the condition
  4342. -- * used in ifstat()
  4343. ------------------------------------------------------------------------
  4344. function luaY:test_then_block(ls)
  4345. -- test_then_block -> [IF | ELSEIF] cond THEN block
  4346. luaX:next(ls) -- skip IF or ELSEIF
  4347. local condexit = self:cond(ls)
  4348. self:checknext(ls, "TK_THEN")
  4349. self:block(ls) -- `then' part
  4350. return condexit
  4351. end
  4352.  
  4353. ------------------------------------------------------------------------
  4354. -- parse an if control structure
  4355. -- * used in statements()
  4356. ------------------------------------------------------------------------
  4357. function luaY:ifstat(ls, line)
  4358. -- ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END
  4359. local fs = ls.fs
  4360. local escapelist = luaK.NO_JUMP
  4361. local flist = self:test_then_block(ls) -- IF cond THEN block
  4362. while ls.t.token == "TK_ELSEIF" do
  4363. escapelist = luaK:concat(fs, escapelist, luaK:jump(fs))
  4364. luaK:patchtohere(fs, flist)
  4365. flist = self:test_then_block(ls) -- ELSEIF cond THEN block
  4366. end
  4367. if ls.t.token == "TK_ELSE" then
  4368. escapelist = luaK:concat(fs, escapelist, luaK:jump(fs))
  4369. luaK:patchtohere(fs, flist)
  4370. luaX:next(ls) -- skip ELSE (after patch, for correct line info)
  4371. self:block(ls) -- 'else' part
  4372. else
  4373. escapelist = luaK:concat(fs, escapelist, flist)
  4374. end
  4375. luaK:patchtohere(fs, escapelist)
  4376. self:check_match(ls, "TK_END", "TK_IF", line)
  4377. end
  4378.  
  4379. ------------------------------------------------------------------------
  4380. -- parse a local function statement
  4381. -- * used in statements()
  4382. ------------------------------------------------------------------------
  4383. function luaY:localfunc(ls)
  4384. local v, b = {}, {} -- expdesc
  4385. local fs = ls.fs
  4386. self:new_localvar(ls, self:str_checkname(ls), 0)
  4387. self:init_exp(v, "VLOCAL", fs.freereg)
  4388. luaK:reserveregs(fs, 1)
  4389. self:adjustlocalvars(ls, 1)
  4390. self:body(ls, b, false, ls.linenumber)
  4391. luaK:storevar(fs, v, b)
  4392. -- debug information will only see the variable after this point!
  4393. self:getlocvar(fs, fs.nactvar - 1).startpc = fs.pc
  4394. end
  4395.  
  4396. ------------------------------------------------------------------------
  4397. -- parse a local variable declaration statement
  4398. -- * used in statements()
  4399. ------------------------------------------------------------------------
  4400. function luaY:localstat(ls)
  4401. -- stat -> LOCAL NAME {',' NAME} ['=' explist1]
  4402. local nvars = 0
  4403. local nexps
  4404. local e = {} -- expdesc
  4405. repeat
  4406. self:new_localvar(ls, self:str_checkname(ls), nvars)
  4407. nvars = nvars + 1
  4408. until not self:testnext(ls, ",")
  4409. if self:testnext(ls, "=") then
  4410. nexps = self:explist1(ls, e)
  4411. else
  4412. e.k = "VVOID"
  4413. nexps = 0
  4414. end
  4415. self:adjust_assign(ls, nvars, nexps, e)
  4416. self:adjustlocalvars(ls, nvars)
  4417. end
  4418.  
  4419. ------------------------------------------------------------------------
  4420. -- parse a function name specification
  4421. -- * used in funcstat()
  4422. ------------------------------------------------------------------------
  4423. function luaY:funcname(ls, v)
  4424. -- funcname -> NAME {field} [':' NAME]
  4425. local needself = false
  4426. self:singlevar(ls, v)
  4427. while ls.t.token == "." do
  4428. self:field(ls, v)
  4429. end
  4430. if ls.t.token == ":" then
  4431. needself = true
  4432. self:field(ls, v)
  4433. end
  4434. return needself
  4435. end
  4436.  
  4437. ------------------------------------------------------------------------
  4438. -- parse a function statement
  4439. -- * used in statements()
  4440. ------------------------------------------------------------------------
  4441. function luaY:funcstat(ls, line)
  4442. -- funcstat -> FUNCTION funcname body
  4443. local v, b = {}, {} -- expdesc
  4444. luaX:next(ls) -- skip FUNCTION
  4445. local needself = self:funcname(ls, v)
  4446. self:body(ls, b, needself, line)
  4447. luaK:storevar(ls.fs, v, b)
  4448. luaK:fixline(ls.fs, line) -- definition 'happens' in the first line
  4449. end
  4450.  
  4451. ------------------------------------------------------------------------
  4452. -- parse a function call with no returns or an assignment statement
  4453. -- * used in statements()
  4454. ------------------------------------------------------------------------
  4455. function luaY:exprstat(ls)
  4456. -- stat -> func | assignment
  4457. local fs = ls.fs
  4458. local v = {} -- LHS_assign
  4459. v.v = {}
  4460. self:primaryexp(ls, v.v)
  4461. if v.v.k == "VCALL" then -- stat -> func
  4462. luaP:SETARG_C(luaK:getcode(fs, v.v), 1) -- call statement uses no results
  4463. else -- stat -> assignment
  4464. v.prev = nil
  4465. self:assignment(ls, v, 1)
  4466. end
  4467. end
  4468.  
  4469. ------------------------------------------------------------------------
  4470. -- parse a return statement
  4471. -- * used in statements()
  4472. ------------------------------------------------------------------------
  4473. function luaY:retstat(ls)
  4474. -- stat -> RETURN explist
  4475. local fs = ls.fs
  4476. local e = {} -- expdesc
  4477. local first, nret -- registers with returned values
  4478. luaX:next(ls) -- skip RETURN
  4479. if self:block_follow(ls.t.token) or ls.t.token == ";" then
  4480. first, nret = 0, 0 -- return no values
  4481. else
  4482. nret = self:explist1(ls, e) -- optional return values
  4483. if self:hasmultret(e.k) then
  4484. luaK:setmultret(fs, e)
  4485. if e.k == "VCALL" and nret == 1 then -- tail call?
  4486. luaP:SET_OPCODE(luaK:getcode(fs, e), "OP_TAILCALL")
  4487. assert(luaP:GETARG_A(luaK:getcode(fs, e)) == fs.nactvar)
  4488. end
  4489. first = fs.nactvar
  4490. nret = self.LUA_MULTRET -- return all values
  4491. else
  4492. if nret == 1 then -- only one single value?
  4493. first = luaK:exp2anyreg(fs, e)
  4494. else
  4495. luaK:exp2nextreg(fs, e) -- values must go to the 'stack'
  4496. first = fs.nactvar -- return all 'active' values
  4497. assert(nret == fs.freereg - first)
  4498. end
  4499. end--if
  4500. end--if
  4501. luaK:ret(fs, first, nret)
  4502. end
  4503.  
  4504. ------------------------------------------------------------------------
  4505. -- initial parsing for statements, calls a lot of functions
  4506. -- * returns boolean instead of 0|1
  4507. -- * used in chunk()
  4508. ------------------------------------------------------------------------
  4509. function luaY:statement(ls)
  4510. local line = ls.linenumber -- may be needed for error messages
  4511. local c = ls.t.token
  4512. if c == "TK_IF" then -- stat -> ifstat
  4513. self:ifstat(ls, line)
  4514. return false
  4515. elseif c == "TK_WHILE" then -- stat -> whilestat
  4516. self:whilestat(ls, line)
  4517. return false
  4518. elseif c == "TK_DO" then -- stat -> DO block END
  4519. luaX:next(ls) -- skip DO
  4520. self:block(ls)
  4521. self:check_match(ls, "TK_END", "TK_DO", line)
  4522. return false
  4523. elseif c == "TK_FOR" then -- stat -> forstat
  4524. self:forstat(ls, line)
  4525. return false
  4526. elseif c == "TK_REPEAT" then -- stat -> repeatstat
  4527. self:repeatstat(ls, line)
  4528. return false
  4529. elseif c == "TK_FUNCTION" then -- stat -> funcstat
  4530. self:funcstat(ls, line)
  4531. return false
  4532. elseif c == "TK_LOCAL" then -- stat -> localstat
  4533. luaX:next(ls) -- skip LOCAL
  4534. if self:testnext(ls, "TK_FUNCTION") then -- local function?
  4535. self:localfunc(ls)
  4536. else
  4537. self:localstat(ls)
  4538. end
  4539. return false
  4540. elseif c == "TK_RETURN" then -- stat -> retstat
  4541. self:retstat(ls)
  4542. return true -- must be last statement
  4543. elseif c == "TK_BREAK" then -- stat -> breakstat
  4544. luaX:next(ls) -- skip BREAK
  4545. self:breakstat(ls)
  4546. return true -- must be last statement
  4547. else
  4548. self:exprstat(ls)
  4549. return false -- to avoid warnings
  4550. end--if c
  4551. end
  4552.  
  4553. ------------------------------------------------------------------------
  4554. -- parse a chunk, which consists of a bunch of statements
  4555. -- * used in parser(), body(), block(), repeatstat()
  4556. ------------------------------------------------------------------------
  4557. function luaY:chunk(ls)
  4558. -- chunk -> { stat [';'] }
  4559. local islast = false
  4560. self:enterlevel(ls)
  4561. while not islast and not self:block_follow(ls.t.token) do
  4562. islast = self:statement(ls)
  4563. self:testnext(ls, ";")
  4564. assert(ls.fs.f.maxstacksize >= ls.fs.freereg and
  4565. ls.fs.freereg >= ls.fs.nactvar)
  4566. ls.fs.freereg = ls.fs.nactvar -- free registers
  4567. end
  4568. self:leavelevel(ls)
  4569. end
  4570.  
  4571. -- }======================================================================
  4572. local luaYfunc = luaY
  4573.  
  4574. local lua_opcode_types = {
  4575. "ABC", "ABx", "ABC", "ABC",
  4576. "ABC", "ABx", "ABC", "ABx",
  4577. "ABC", "ABC", "ABC", "ABC",
  4578. "ABC", "ABC", "ABC", "ABC",
  4579. "ABC", "ABC", "ABC", "ABC",
  4580. "ABC", "ABC", "AsBx", "ABC",
  4581. "ABC", "ABC", "ABC", "ABC",
  4582. "ABC", "ABC", "ABC", "AsBx",
  4583. "AsBx", "ABC", "ABC", "ABC",
  4584. "ABx", "ABC",
  4585. }
  4586.  
  4587. local lua_opcode_names = {
  4588. "MOVE", "LOADK", "LOADBOOL", "LOADNIL",
  4589. "GETUPVAL", "GETGLOBAL", "GETTABLE", "SETGLOBAL",
  4590. "SETUPVAL", "SETTABLE", "NEWTABLE", "SELF",
  4591. "ADD", "SUB", "MUL", "DIV",
  4592. "MOD", "POW", "UNM", "NOT",
  4593. "LEN", "CONCAT", "JMP", "EQ",
  4594. "LT", "LE", "TEST", "TESTSET",
  4595. "CALL", "TAILCALL", "RETURN", "FORLOOP",
  4596. "FORPREP", "TFORLOOP", "SETLIST", "CLOSE",
  4597. "CLOSURE", "VARARG"
  4598. };
  4599.  
  4600. --[[
  4601. local lua_opcode_numbers = {};
  4602. for number, name in next, lua_opcode_names do
  4603. lua_opcode_numbers[name] = number;
  4604. end
  4605. --]]
  4606.  
  4607. --- Extract bits from an integer
  4608. --@author: Stravant
  4609. local function get_bits(input, n, n2)
  4610. if n2 then
  4611. local total = 0
  4612. local digitn = 0
  4613. for i = n, n2 do
  4614. total = total + 2^digitn*get_bits(input, i)
  4615. digitn = digitn + 1
  4616. end
  4617. return total
  4618. else
  4619. local pn = 2^(n-1)
  4620. return (input % (pn + pn) >= pn) and 1 or 0
  4621. end
  4622. end
  4623.  
  4624. local function decode_bytecode(bytecode)
  4625. local index = 1
  4626. local big_endian = false
  4627. local int_size;
  4628. local size_t;
  4629.  
  4630. -- Actual binary decoding functions. Dependant on the bytecode.
  4631. local get_int, get_size_t;
  4632.  
  4633. -- Binary decoding helper functions
  4634. local get_int8, get_int32, get_int64, get_float64, get_string;
  4635. do
  4636. function get_int8()
  4637. local a = bytecode:byte(index, index);
  4638. index = index + 1
  4639. return a
  4640. end
  4641. function get_int32()
  4642. local a, b, c, d = bytecode:byte(index, index + 3);
  4643. index = index + 4;
  4644. return d*16777216 + c*65536 + b*256 + a
  4645. end
  4646. function get_int64()
  4647. local a = get_int32();
  4648. local b = get_int32();
  4649. return b*4294967296 + a;
  4650. end
  4651. function get_float64()
  4652. local a = get_int32()
  4653. local b = get_int32()
  4654. return (-2*get_bits(b, 32)+1)*(2^(get_bits(b, 21, 31)-1023))*
  4655. ((get_bits(b, 1, 20)*(2^32) + a)/(2^52)+1)
  4656. end
  4657. function get_string(len)
  4658. local str;
  4659. if len then
  4660. str = bytecode:sub(index, index + len - 1);
  4661. index = index + len;
  4662. else
  4663. len = get_size_t();
  4664. if len == 0 then return; end
  4665. str = bytecode:sub(index, index + len - 1);
  4666. index = index + len;
  4667. end
  4668. return str;
  4669. end
  4670. end
  4671.  
  4672. local function decode_chunk()
  4673. local chunk;
  4674. local instructions = {};
  4675. local constants = {};
  4676. local prototypes = {};
  4677. local debug = {
  4678. lines = {};
  4679. };
  4680.  
  4681. chunk = {
  4682. instructions = instructions;
  4683. constants = constants;
  4684. prototypes = prototypes;
  4685. debug = debug;
  4686. };
  4687.  
  4688. local num;
  4689.  
  4690. chunk.name = get_string();-- Function name
  4691. chunk.first_line = get_int(); -- First line
  4692. chunk.last_line = get_int(); -- Last line
  4693.  
  4694. if chunk.name then chunk.name = chunk.name:sub(1, -2); end
  4695.  
  4696. chunk.upvalues = get_int8();
  4697. chunk.arguments = get_int8();
  4698. chunk.varg = get_int8();
  4699. chunk.stack = get_int8();
  4700.  
  4701. -- TODO: realign lists to 1
  4702. -- Decode instructions
  4703. do
  4704. num = get_int();
  4705. for i = 1, num do
  4706. local instruction = {
  4707. -- opcode = opcode number;
  4708. -- type = [ABC, ABx, AsBx]
  4709. -- A, B, C, Bx, or sBx depending on type
  4710. };
  4711.  
  4712. local data = get_int32();
  4713. local opcode = get_bits(data, 1, 6);
  4714. local type = lua_opcode_types[opcode + 1];
  4715.  
  4716. instruction.opcode = opcode;
  4717. instruction.type = type;
  4718.  
  4719. instruction.A = get_bits(data, 7, 14);
  4720. if type == "ABC" then
  4721. instruction.B = get_bits(data, 24, 32);
  4722. instruction.C = get_bits(data, 15, 23);
  4723. elseif type == "ABx" then
  4724. instruction.Bx = get_bits(data, 15, 32);
  4725. elseif type == "AsBx" then
  4726. instruction.sBx = get_bits(data, 15, 32) - 131071;
  4727. end
  4728.  
  4729. instructions[i] = instruction;
  4730. end
  4731. end
  4732.  
  4733. -- Decode constants
  4734. do
  4735. num = get_int();
  4736. for i = 1, num do
  4737. local constant = {
  4738. -- type = constant type;
  4739. -- data = constant data;
  4740. };
  4741. local type = get_int8();
  4742. constant.type = type;
  4743.  
  4744. if type == 1 then
  4745. constant.data = (get_int8() ~= 0);
  4746. elseif type == 3 then
  4747. constant.data = get_float64();
  4748. elseif type == 4 then
  4749. constant.data = get_string():sub(1, -2);
  4750. end
  4751.  
  4752. constants[i-1] = constant;
  4753. end
  4754. end
  4755.  
  4756. -- Decode Prototypes
  4757. do
  4758. num = get_int();
  4759. for i = 1, num do
  4760. prototypes[i-1] = decode_chunk();
  4761. end
  4762. end
  4763.  
  4764. -- Decode debug info
  4765. -- Not all of which is used yet.
  4766. do
  4767. -- line numbers
  4768. local data = debug.lines
  4769. num = get_int();
  4770. for i = 1, num do
  4771. data[i] = get_int32();
  4772. end
  4773.  
  4774. -- locals
  4775. num = get_int();
  4776. for i = 1, num do
  4777. get_string():sub(1, -2); -- local name
  4778. get_int32(); -- local start PC
  4779. get_int32(); -- local end PC
  4780. end
  4781.  
  4782. -- upvalues
  4783. num = get_int();
  4784. for i = 1, num do
  4785. get_string(); -- upvalue name
  4786. end
  4787. end
  4788.  
  4789. return chunk;
  4790. end
  4791.  
  4792. -- Verify bytecode header
  4793. do
  4794. assert(get_string(4) == "\27Lua", "Lua bytecode expected.");
  4795. assert(get_int8() == 0x51, "Only Lua 5.1 is supported.");
  4796. get_int8(); -- Oficial bytecode
  4797. big_endian = (get_int8() == 0);
  4798. int_size = get_int8();
  4799. size_t = get_int8();
  4800.  
  4801. if int_size == 4 then
  4802. get_int = get_int32;
  4803. elseif int_size == 8 then
  4804. get_int = get_int64;
  4805. else
  4806. -- TODO: refactor errors into table
  4807. error("Unsupported bytecode target platform");
  4808. end
  4809.  
  4810. if size_t == 4 then
  4811. get_size_t = get_int32;
  4812. elseif size_t == 8 then
  4813. get_size_t = get_int64;
  4814. else
  4815. error("Unsupported bytecode target platform");
  4816. end
  4817.  
  4818. assert(get_string(3) == "\4\8\0",
  4819. "Unsupported bytecode target platform");
  4820. end
  4821.  
  4822. return decode_chunk();
  4823. end
  4824.  
  4825. local function handle_return(...)
  4826. local c = select("#", ...)
  4827. local t = {...}
  4828. return c, t
  4829. end
  4830.  
  4831. local function create_wrapper(cache, upvalues)
  4832. local instructions = cache.instructions;
  4833. local constants = cache.constants;
  4834. local prototypes = cache.prototypes;
  4835.  
  4836. local stack, top
  4837. local environment
  4838. local IP = 1; -- instruction pointer
  4839. local vararg, vararg_size
  4840.  
  4841. local opcode_funcs = {
  4842. [0] = function(instruction) -- MOVE
  4843. stack[instruction.A] = stack[instruction.B];
  4844. end,
  4845. [1] = function(instruction) -- LOADK
  4846. stack[instruction.A] = constants[instruction.Bx].data;
  4847. end,
  4848. [2] = function(instruction) -- LOADBOOL
  4849. stack[instruction.A] = instruction.B ~= 0
  4850. if instruction.C ~= 0 then
  4851. IP = IP + 1
  4852. end
  4853. end,
  4854. [3] = function(instruction) -- LOADNIL
  4855. local stack = stack
  4856. for i = instruction.A, instruction.B do
  4857. stack[i] = nil
  4858. end
  4859. end,
  4860. [4] = function(instruction) -- GETUPVAL
  4861. stack[instruction.A] = upvalues[instruction.B]
  4862. end,
  4863. [5] = function(instruction) -- GETGLOBAL
  4864. local key = constants[instruction.Bx].data;
  4865. stack[instruction.A] = environment[key];
  4866. end,
  4867. [6] = function(instruction) -- GETTABLE
  4868. local C = instruction.C
  4869. local stack = stack
  4870. C = C > 255 and constants[C-256].data or stack[C]
  4871. stack[instruction.A] = stack[instruction.B][C];
  4872. end,
  4873. [7] = function(instruction) -- SETGLOBAL
  4874. local key = constants[instruction.Bx].data;
  4875. environment[key] = stack[instruction.A];
  4876. end,
  4877. [8] = function (instruction) -- SETUPVAL
  4878. upvalues[instruction.B] = stack[instruction.A]
  4879. end,
  4880. [9] = function (instruction) -- SETTABLE
  4881. local B = instruction.B;
  4882. local C = instruction.C;
  4883. local stack, constants = stack, constants;
  4884.  
  4885. B = B > 255 and constants[B-256].data or stack[B];
  4886. C = C > 255 and constants[C-256].data or stack[C];
  4887.  
  4888. stack[instruction.A][B] = C
  4889. end,
  4890. [10] = function (instruction) -- NEWTABLE
  4891. stack[instruction.A] = {}
  4892. end,
  4893. [11] = function (instruction) -- SELF
  4894. local A = instruction.A
  4895. local B = instruction.B
  4896. local C = instruction.C
  4897. local stack = stack
  4898.  
  4899. B = stack[B]
  4900. C = C > 255 and constants[C-256].data or stack[C]
  4901.  
  4902. stack[A+1] = B
  4903. stack[A] = B[C]
  4904. end,
  4905. [12] = function(instruction) -- ADD
  4906. local B = instruction.B;
  4907. local C = instruction.C;
  4908. local stack, constants = stack, constants;
  4909.  
  4910. B = B > 255 and constants[B-256].data or stack[B];
  4911. C = C > 255 and constants[C-256].data or stack[C];
  4912.  
  4913. stack[instruction.A] = B+C;
  4914. end,
  4915. [13] = function(instruction) -- SUB
  4916. local B = instruction.B;
  4917. local C = instruction.C;
  4918. local stack, constants = stack, constants;
  4919.  
  4920. B = B > 255 and constants[B-256].data or stack[B];
  4921. C = C > 255 and constants[C-256].data or stack[C];
  4922.  
  4923. stack[instruction.A] = B - C;
  4924. end,
  4925. [14] = function(instruction) -- MUL
  4926. local B = instruction.B;
  4927. local C = instruction.C;
  4928. local stack, constants = stack, constants;
  4929.  
  4930. B = B > 255 and constants[B-256].data or stack[B];
  4931. C = C > 255 and constants[C-256].data or stack[C];
  4932.  
  4933. stack[instruction.A] = B * C;
  4934. end,
  4935. [15] = function(instruction) --DIV
  4936. local B = instruction.B;
  4937. local C = instruction.C;
  4938. local stack, constants = stack, constants;
  4939.  
  4940. B = B > 255 and constants[B-256].data or stack[B];
  4941. C = C > 255 and constants[C-256].data or stack[C];
  4942.  
  4943. stack[instruction.A] = B / C;
  4944. end,
  4945. [16] = function(instruction) -- MOD
  4946. local B = instruction.B;
  4947. local C = instruction.C;
  4948. local stack, constants = stack, constants;
  4949.  
  4950. B = B > 255 and constants[B-256].data or stack[B];
  4951. C = C > 255 and constants[C-256].data or stack[C];
  4952.  
  4953. stack[instruction.A] = B % C;
  4954. end,
  4955. [17] = function(instruction) -- POW
  4956. local B = instruction.B;
  4957. local C = instruction.C;
  4958. local stack, constants = stack, constants;
  4959.  
  4960. B = B > 255 and constants[B-256].data or stack[B];
  4961. C = C > 255 and constants[C-256].data or stack[C];
  4962.  
  4963. stack[instruction.A] = B ^ C;
  4964. end,
  4965. [18] = function(instruction) -- UNM
  4966. stack[instruction.A] = -stack[instruction.B]
  4967. end,
  4968. [19] = function(instruction) -- NOT
  4969. stack[instruction.A] = not stack[instruction.B]
  4970. end,
  4971. [20] = function(instruction) -- LEN
  4972. stack[instruction.A] = #stack[instruction.B]
  4973. end,
  4974. [21] = function(instruction) -- CONCAT
  4975. local B = instruction.B
  4976. local result = stack[B]
  4977. for i = B+1, instruction.C do
  4978. result = result .. stack[i]
  4979. end
  4980. stack[instruction.A] = result
  4981. end,
  4982. [22] = function(instruction) -- JUMP
  4983. IP = IP + instruction.sBx
  4984. end,
  4985. [23] = function(instruction) -- EQ
  4986. local A = instruction.A
  4987. local B = instruction.B
  4988. local C = instruction.C
  4989. local stack, constants = stack, constants
  4990.  
  4991. A = A ~= 0
  4992. B = B > 255 and constants[B-256].data or stack[B]
  4993. C = C > 255 and constants[C-256].data or stack[C]
  4994. if (B == C) ~= A then
  4995. IP = IP + 1
  4996. end
  4997. end,
  4998. [24] = function(instruction) -- LT
  4999. local A = instruction.A
  5000. local B = instruction.B
  5001. local C = instruction.C
  5002. local stack, constants = stack, constants
  5003.  
  5004. A = A ~= 0
  5005. B = B > 255 and constants[B-256].data or stack[B]
  5006. C = C > 255 and constants[C-256].data or stack[C]
  5007. if (B < C) ~= A then
  5008. IP = IP + 1
  5009. end
  5010. end,
  5011. [25] = function(instruction) -- LT
  5012. local A = instruction.A
  5013. local B = instruction.B
  5014. local C = instruction.C
  5015. local stack, constants = stack, constants
  5016.  
  5017. A = A ~= 0
  5018. B = B > 255 and constants[B-256].data or stack[B]
  5019. C = C > 255 and constants[C-256].data or stack[C]
  5020. if (B <= C) ~= A then
  5021. IP = IP + 1
  5022. end
  5023. end,
  5024. [26] = function(instruction) -- TEST
  5025. if stack[instruction.A] == (instruction.C ~= 0) then
  5026. IP = IP + 1
  5027. end
  5028. end,
  5029. [27] = function(instruction) -- TESTSET
  5030. local stack = stack
  5031. local B = stack[instruction.B]
  5032.  
  5033. if B == (instruction.C ~= 0) then
  5034. IP = IP + 1
  5035. else
  5036. stack[instruction.A] = B
  5037. end
  5038. end,
  5039. [28] = function(instruction) -- CALL
  5040. local A = instruction.A;
  5041. local B = instruction.B;
  5042. local C = instruction.C;
  5043. local stack = stack;
  5044. local args, results;
  5045. local limit, loop
  5046.  
  5047. args = {};
  5048. if B ~= 1 then
  5049. if B ~= 0 then
  5050. limit = A+B-1;
  5051. else
  5052. limit = top
  5053. end
  5054.  
  5055. loop = 0
  5056. for i = A+1, limit do
  5057. loop = loop + 1
  5058. args[loop] = stack[i];
  5059. end
  5060.  
  5061. limit, results = handle_return(stack[A](unpack(args, 1, limit-A)))
  5062. else
  5063. limit, results = handle_return(stack[A]())
  5064. end
  5065.  
  5066. top = A - 1
  5067.  
  5068. if C ~= 1 then
  5069. if C ~= 0 then
  5070. limit = A+C-2;
  5071. else
  5072. limit = limit+A
  5073. end
  5074.  
  5075. loop = 0;
  5076. for i = A, limit do
  5077. loop = loop + 1;
  5078. stack[i] = results[loop];
  5079. end
  5080. end
  5081. end,
  5082. [29] = function (instruction) -- TAILCALL
  5083. local A = instruction.A;
  5084. local B = instruction.B;
  5085. local C = instruction.C;
  5086. local stack = stack;
  5087. local args, results;
  5088. local top, limit, loop = top
  5089.  
  5090. args = {};
  5091. if B ~= 1 then
  5092. if B ~= 0 then
  5093. limit = A+B-1;
  5094. else
  5095. limit = top
  5096. end
  5097.  
  5098. loop = 0
  5099. for i = A+1, limit do
  5100. loop = loop + 1
  5101. args[#args+1] = stack[i];
  5102. end
  5103.  
  5104. results = {stack[A](unpack(args, 1, limit-A))};
  5105. else
  5106. results = {stack[A]()};
  5107. end
  5108.  
  5109. return true, results
  5110. end,
  5111. [30] = function(instruction) -- RETURN
  5112. --TODO: CLOSE
  5113. local A = instruction.A;
  5114. local B = instruction.B;
  5115. local stack = stack;
  5116. local limit;
  5117. local loop, output;
  5118.  
  5119. if B == 1 then
  5120. return true;
  5121. end
  5122. if B == 0 then
  5123. limit = top
  5124. else
  5125. limit = A + B - 2;
  5126. end
  5127.  
  5128. output = {};
  5129. local loop = 0
  5130. for i = A, limit do
  5131. loop = loop + 1
  5132. output[loop] = stack[i];
  5133. end
  5134. return true, output;
  5135. end,
  5136. [31] = function(instruction) -- FORLOOP
  5137. local A = instruction.A
  5138. local stack = stack
  5139.  
  5140. local step = stack[A+2]
  5141. local index = stack[A] + step
  5142. stack[A] = index
  5143.  
  5144. if step > 0 then
  5145. if index <= stack[A+1] then
  5146. IP = IP + instruction.sBx
  5147. stack[A+3] = index
  5148. end
  5149. else
  5150. if index >= stack[A+1] then
  5151. IP = IP + instruction.sBx
  5152. stack[A+3] = index
  5153. end
  5154. end
  5155. end,
  5156. [32] = function(instruction) -- FORPREP
  5157. local A = instruction.A
  5158. local stack = stack
  5159.  
  5160. stack[A] = stack[A] - stack[A+2]
  5161. IP = IP + instruction.sBx
  5162. end,
  5163. [33] = function(instruction) -- TFORLOOP
  5164. local A = instruction.A
  5165. local B = instruction.B
  5166. local C = instruction.C
  5167. local stack = stack
  5168.  
  5169. local offset = A+2
  5170. local result = {stack[A](stack[A+1], stack[A+2])}
  5171. for i = 1, C do
  5172. stack[offset+i] = result[i]
  5173. end
  5174.  
  5175. if stack[A+3] ~= nil then
  5176. stack[A+2] = stack[A+3]
  5177. else
  5178. IP = IP + 1
  5179. end
  5180. end,
  5181. [34] = function(instruction) -- SETLIST
  5182. local A = instruction.A
  5183. local B = instruction.B
  5184. local C = instruction.C
  5185. local stack = stack
  5186.  
  5187. if C == 0 then
  5188. error("NYI: extended SETLIST")
  5189. else
  5190. local offset = (C - 1) * 50
  5191. local t = stack[A]
  5192.  
  5193. if B == 0 then
  5194. B = top
  5195. end
  5196. for i = 1, B do
  5197. t[offset+i] = stack[A+i]
  5198. end
  5199. end
  5200. end,
  5201. [35] = function(instruction) -- CLOSE
  5202. io.stderr:write("NYI: CLOSE")
  5203. io.stderr:flush()
  5204. end,
  5205. [36] = function(instruction) -- CLOSURE
  5206. local proto = prototypes[instruction.Bx]
  5207. local instructions = instructions
  5208. local stack = stack
  5209.  
  5210. local indices = {}
  5211. local new_upvals = setmetatable({},
  5212. {
  5213. __index = function(t, k)
  5214. local upval = indices[k]
  5215. return upval.segment[upval.offset]
  5216. end,
  5217. __newindex = function(t, k, v)
  5218. local upval = indices[k]
  5219. upval.segment[upval.offset] = v
  5220. end
  5221. }
  5222. )
  5223. for i = 1, proto.upvalues do
  5224. local movement = instructions[IP]
  5225. if movement.opcode == 0 then -- MOVE
  5226. indices[i-1] = {segment = stack, offset = movement.B}
  5227. elseif instructions[IP].opcode == 4 then -- GETUPVAL
  5228. indices[i-1] = {segment = upvalues, offset = movement.B}
  5229. end
  5230. IP = IP + 1
  5231. end
  5232.  
  5233. local _, func = create_wrapper(proto, new_upvals)
  5234. stack[instruction.A] = func
  5235. end,
  5236. [37] = function(instruction) -- VARARG
  5237. local A = instruction.A
  5238. local B = instruction.B
  5239. local stack, vararg = stack, vararg
  5240.  
  5241. for i = A, A + (B > 0 and B - 1 or vararg_size) do
  5242. stack[i] = vararg[i - A]
  5243. end
  5244. end,
  5245. }
  5246.  
  5247. local function loop()
  5248. local instructions = instructions
  5249. local instruction, a, b
  5250.  
  5251. while true do
  5252. instruction = instructions[IP];
  5253. IP = IP + 1
  5254. a, b = opcode_funcs[instruction.opcode](instruction);
  5255. if a then
  5256. return b;
  5257. end
  5258. end
  5259. end
  5260.  
  5261. local debugging = {
  5262. get_stack = function()
  5263. return stack;
  5264. end;
  5265. get_IP = function()
  5266. return IP;
  5267. end
  5268. };
  5269.  
  5270. local function func(...)
  5271. local local_stack = {};
  5272. local ghost_stack = {};
  5273.  
  5274. top = -1
  5275. stack = setmetatable(local_stack, {
  5276. __index = ghost_stack;
  5277. __newindex = function(t, k, v)
  5278. if k > top and v then
  5279. top = k
  5280. end
  5281. ghost_stack[k] = v
  5282. end;
  5283. })
  5284. local args = {...};
  5285. vararg = {}
  5286. vararg_size = select("#", ...) - 1
  5287. for i = 0, vararg_size do
  5288. local_stack[i] = args[i+1];
  5289. vararg[i] = args[i+1]
  5290. end
  5291.  
  5292. environment = getfenv();
  5293. IP = 1;
  5294. local thread = coroutine.create(loop)
  5295. local a, b = coroutine.resume(thread)
  5296.  
  5297. if a then
  5298. if b then
  5299. return unpack(b);
  5300. end
  5301. return;
  5302. else
  5303. if advanced_debug then
  5304. --TODO advanced debugging
  5305. else
  5306. --TODO error converting
  5307. local name = cache.name;
  5308. local line = cache.debug.lines[IP];
  5309. local err = b:gsub("(.-:)", "");
  5310. local output = "";
  5311.  
  5312. output = output .. (name and name .. ":" or "");
  5313. output = output .. (line and line .. ":" or "");
  5314. output = output .. b
  5315. --[[
  5316. output = ("%s (Instruction=%s)"):format(output,
  5317. lua_opcode_names[select(2,debug.getlocal(loop,1, 1)).opcode+1])
  5318. --]]
  5319. error(output, 0);
  5320. end
  5321. end
  5322. end
  5323.  
  5324. return debugging, func;
  5325. end
  5326.  
  5327. local VM = {
  5328. load_bytecode = function(bytecode)
  5329. local cache = decode_bytecode(bytecode);
  5330. local _, func = create_wrapper(cache);
  5331. return func;
  5332. end;
  5333.  
  5334. -- Utilities (Debug, Introspection, Testing, etc)
  5335. utils = {
  5336. decode_bytecode = decode_bytecode;
  5337. create_wrapper = create_wrapper;
  5338. debug_bytecode = function(bytecode)
  5339. local cache = decode_bytecode(bytecode)
  5340. return create_wrapper(cache);
  5341. end;
  5342. };
  5343. }
  5344.  
  5345. --[[
  5346. dofile("lzio.lua")
  5347. dofile("llex.lua")
  5348. dofile("lopcodes.lua")
  5349. dofile("ldump.lua")
  5350. dofile("lcode.lua")
  5351. dofile("lparser.lua")
  5352. ]]
  5353.  
  5354. luaXfunc:init()
  5355. local LuaState = {}
  5356.  
  5357. local loadstring = function(str)
  5358. if string.sub(str,1,5) == "\027LuaQ" then
  5359. return VM.load_bytecode(str)
  5360. else
  5361. local code = str
  5362. -- luaZ:make_getF returns a file chunk reader
  5363. -- luaZ:init returns a zio input stream
  5364. local zio = luaZfunc:init(luaZfunc:make_getS(code), nil)
  5365. if not zio then return end
  5366. -- luaY:parser parses the input stream
  5367. -- func is the function prototype in tabular form; in C, func can
  5368. -- now be used directly by the VM, this can't be done in Lua
  5369. local func = luaYfunc:parser(LuaState, zio, nil, "@input")
  5370. -- luaU:make_setS returns a string chunk writer
  5371. local writer, buff = luaUfunc:make_setS()
  5372. -- luaU:dump builds a binary chunk
  5373. luaUfunc:dump(LuaState, func, writer, buff)
  5374. -- a string.dump equivalent in returned
  5375. return VM.load_bytecode(buff.data),buff.data
  5376. end
  5377. end
  5378.  
  5379. local session_id = math.floor(tick() * 10)
  5380. local local_script_template = script:Clone()
  5381. local source_value_name
  5382. local_script_template.Disabled = true
  5383. for _, child in ipairs(local_script_template:GetChildren()) do
  5384. if child:IsA("StringValue") then
  5385. if string.lower(child.Name) ~= "owner" then
  5386. source_value_name = child.Name
  5387. end
  5388. child.Value = ""
  5389. break
  5390. end
  5391. end
  5392. script:ClearAllChildren()
  5393. script.Parent = nil
  5394. if not source_value_name then
  5395. source_value_name = ...
  5396. if source_value_name then
  5397. local source_value = Instance.new("StringValue", local_script_template)
  5398. source_value.Name = source_value_name
  5399. else
  5400. if not (NewLocalScript and NewScript) then
  5401. print("Script builder is incompatible.")
  5402. end
  5403. source_value_name = "Source"
  5404. local_script_template = nil
  5405. end
  5406. end
  5407. local Module = {}
  5408. Module.name = "Module"
  5409. Module.source = string.format([[
  5410. local _ENV = {
  5411. Axes = {
  5412. new = Axes.new
  5413. },
  5414. BrickColor = {
  5415. Black = BrickColor.Black,
  5416. Blue = BrickColor.Blue,
  5417. DarkGray = BrickColor.DarkGray,
  5418. Gray = BrickColor.Gray,
  5419. Green = BrickColor.Green,
  5420. New = BrickColor.New,
  5421. Random = BrickColor.Random,
  5422. Red = BrickColor.Red,
  5423. White = BrickColor.White,
  5424. Yellow = BrickColor.Yellow,
  5425. new = BrickColor.new,
  5426. palette = BrickColor.palette,
  5427. random = BrickColor.random
  5428. },
  5429. CFrame = {
  5430. Angles = CFrame.Angles,
  5431. fromAxisAngle = CFrame.fromAxisAngle,
  5432. fromEulerAnglesXYZ = CFrame.fromEulerAnglesXYZ,
  5433. new = CFrame.new
  5434. },
  5435. CellId = {
  5436. new = CellId.new
  5437. },
  5438. Color3 = {
  5439. new = Color3.new
  5440. },
  5441. Delay = Delay,
  5442. Enum = Enum,
  5443. Faces = {
  5444. new = Faces.new
  5445. },
  5446. Game = Game,
  5447. Instance = {
  5448. Lock = Instance.Lock,
  5449. Unlock = Instance.Unlock,
  5450. new = Instance.new
  5451. },
  5452. LoadLibrary = LoadLibrary,
  5453. LoadRobloxLibrary = LoadRobloxLibrary,
  5454. PluginManager = PluginManager,
  5455. Ray = {
  5456. new = Ray.new
  5457. },
  5458. Region3 = {
  5459. new = Region3.new
  5460. },
  5461. Region3int16 = {
  5462. new = Region3int16.new
  5463. },
  5464. Spawn = Spawn,
  5465. Stats = Stats,
  5466. UDim = {
  5467. new = UDim.new
  5468. },
  5469. UDim2 = {
  5470. new = UDim2.new
  5471. },
  5472. UserSettings = UserSettings,
  5473. Vector2 = {
  5474. new = Vector2.new
  5475. },
  5476. Vector2int16 = {
  5477. new = Vector2int16.new
  5478. },
  5479. Vector3 = {
  5480. FromAxis = Vector3.FromAxis,
  5481. FromNormalId = Vector3.FromNormalId,
  5482. new = Vector3.new
  5483. },
  5484. Vector3int16 = {
  5485. new = Vector3int16.new
  5486. },
  5487. Version = Version,
  5488. Wait = Wait,
  5489. Workspace = Workspace,
  5490. _G = _G,
  5491. _VERSION = _VERSION,
  5492. assert = assert,
  5493. collectgarbage = collectgarbage,
  5494. coroutine = {
  5495. create = coroutine.create,
  5496. resume = coroutine.resume,
  5497. running = coroutine.running,
  5498. status = coroutine.status,
  5499. wrap = coroutine.wrap,
  5500. yield = coroutine.yield
  5501. },
  5502. crash__ = crash__,
  5503. delay = delay,
  5504. dofile = dofile,
  5505. error = error,
  5506. game = game,
  5507. gcinfo = gcinfo,
  5508. getfenv = getfenv,
  5509. getmetatable = getmetatable,
  5510. ipairs = ipairs,
  5511. load = load,
  5512. loadfile = loadfile,
  5513. loadstring = loadstring,
  5514. math = {
  5515. abs = math.abs,
  5516. acos = math.acos,
  5517. asin = math.asin,
  5518. atan = math.atan,
  5519. atan2 = math.atan2,
  5520. ceil = math.ceil,
  5521. cos = math.cos,
  5522. cosh = math.cosh,
  5523. deg = math.deg,
  5524. exp = math.exp,
  5525. floor = math.floor,
  5526. fmod = math.fmod,
  5527. frexp = math.frexp,
  5528. huge = math.huge,
  5529. ldexp = math.ldexp,
  5530. log = math.log,
  5531. log10 = math.log10,
  5532. max = math.max,
  5533. min = math.min,
  5534. modf = math.modf,
  5535. phi = 1.618033988749895,
  5536. pi = math.pi,
  5537. pow = math.pow,
  5538. rad = math.rad,
  5539. random = math.random,
  5540. randomseed = math.randomseed,
  5541. sin = math.sin,
  5542. sinh = math.sinh,
  5543. sqrt = math.sqrt,
  5544. tan = math.tan,
  5545. tanh = math.tanh,
  5546. tau = 2 * math.pi
  5547. },
  5548. newproxy = newproxy,
  5549. next = next,
  5550. pairs = pairs,
  5551. pcall = pcall,
  5552. print = print,
  5553. printidentity = printidentity,
  5554. rawequal = rawequal,
  5555. rawget = rawget,
  5556. rawset = rawset,
  5557. select = select,
  5558. setfenv = setfenv,
  5559. setmetatable = setmetatable,
  5560. settings = settings,
  5561. shared = shared,
  5562. stats = stats,
  5563. string = {
  5564. byte = string.byte,
  5565. char = string.char,
  5566. dump = string.dump,
  5567. find = string.find,
  5568. format = string.format,
  5569. gfind = string.gfind,
  5570. gmatch = string.gmatch,
  5571. gsub = string.gsub,
  5572. len = string.len,
  5573. lower = string.lower,
  5574. match = string.match,
  5575. rep = string.rep,
  5576. reverse = string.reverse,
  5577. sub = string.sub,
  5578. upper = string.upper
  5579. },
  5580. table = {
  5581. concat = table.concat,
  5582. foreach = table.foreach,
  5583. foreachi = table.foreachi,
  5584. getn = table.getn,
  5585. insert = table.insert,
  5586. maxn = table.maxn,
  5587. remove = table.remove,
  5588. setn = table.setn,
  5589. sort = table.sort
  5590. },
  5591. tick = tick,
  5592. time = time,
  5593. tonumber = tonumber,
  5594. tostring = tostring,
  5595. type = type,
  5596. unpack = unpack,
  5597. version = version,
  5598. wait = wait,
  5599. workspace = workspace,
  5600. xpcall = xpcall,
  5601. ypcall = ypcall
  5602. }
  5603. _ENV.Environment = ...
  5604. _ENV.Environment._ENV = _ENV
  5605. local _RBX = getfenv()
  5606. _ENV._ENV = _ENV
  5607. _ENV._RBX = _RBX
  5608. _ENV._SessionID = %s
  5609. _ENV.Debris = Game:GetService("Debris")
  5610. _ENV.InsertService = Game:GetService("InsertService")
  5611. _ENV.Lighting = Game:GetService("Lighting")
  5612. _ENV.LogService = Game:GetService("LogService")
  5613. _ENV.Players = Game:GetService("Players")
  5614. _ENV.RunService = Game:GetService("RunService")
  5615. _ENV.ReplicatedStorage = Game:GetService("ReplicatedStorage")
  5616. _ENV.SoundService = Game:GetService("SoundService")
  5617. _ENV.StarterGui = Game:GetService("StarterGui")
  5618. _ENV.StarterPack = Game:GetService("StarterPack")
  5619. _ENV.TeleportService = Game:GetService("TeleportService")
  5620. _ENV.RbxUtility = LoadLibrary("RbxUtility")
  5621. if N_ENV then
  5622. N_ENV(_ENV)
  5623. end
  5624. local Module = ...
  5625. Module.data = {
  5626. listeners = {},
  5627. modules = {}
  5628. }
  5629. Module.metatable = {}
  5630. function Module.metatable:__tostring()
  5631. return tostring(self.name)
  5632. end
  5633. function Module.Create(name, source, ...)
  5634. local module = Module.Store(name, source)
  5635. Module.Initialize(module, ...)
  5636. return module
  5637. end
  5638. function Module.Initialize(module, ...)
  5639. local name = module.name
  5640. local load_function, message = loadstring(module.source, name)
  5641. if load_function then
  5642. local success, message = ypcall(setfenv(load_function, _ENV), ...)
  5643. if success then
  5644. if _ENV.Logger and _ENV.Logger.printf then
  5645. _ENV.Logger.printf("Output", "%%s: ready", tostring(name))
  5646. end
  5647. local listeners = Module.data.listeners
  5648. local listener = listeners[name]
  5649. if listener then
  5650. listeners[name] = nil
  5651. listener:fire()
  5652. end
  5653. return module
  5654. elseif _ENV.Logger and _ENV.Logger.printf then
  5655. _ENV.Logger.printf("Severe", "Runtime error in module '%%s': %%s", tostring(name), message)
  5656. else
  5657. print(string.format("runtime error in module '%%s': %%s", tostring(name), message))
  5658. end
  5659. elseif _ENV.Logger and _ENV.Logger.printf then
  5660. _ENV.Logger.printf("Severe", "Syntax error in module '%%s': %%s", tostring(name), message)
  5661. else
  5662. print(string.format("syntax error in module '%%s': %%s", tostring(name), message))
  5663. end
  5664. end
  5665. function Module.Load(name)
  5666. return Module.data.modules[name]
  5667. end
  5668. function Module.Register(module)
  5669. local name = tostring(module)
  5670. _ENV[name] = module
  5671. Module.data.modules[name] = module
  5672. end
  5673. function Module.Reload(name, source, ...)
  5674. local module = Module.Load(name)
  5675. for key in pairs(module) do
  5676. module[key] = nil
  5677. end
  5678. module.name = name
  5679. module.source = source
  5680. Module.Initialize(module, ...)
  5681. return module
  5682. end
  5683. function Module.Store(name, source)
  5684. local module = {}
  5685. module.name = name
  5686. module.source = source
  5687. setmetatable(module, Module.metatable)
  5688. Module.Register(module)
  5689. return module
  5690. end
  5691. function Module.WaitForModule(name)
  5692. local module = Module.Load(name)
  5693. if not module then
  5694. local listeners = Module.data.listeners
  5695. local listener = listeners[name]
  5696. if not listener then
  5697. listener = _ENV.RbxUtility.CreateSignal()
  5698. listeners[name] = listener
  5699. end
  5700. listener:wait()
  5701. end
  5702. end
  5703. ]], tostring(session_id))
  5704. assert(loadstring(Module.source))(Module)
  5705. setmetatable(Module, Module.metatable)
  5706. Module.Register(Module)
  5707. Module.Create("LuaEnum", [[
  5708. LuaEnum.enum_metatable = {
  5709. __call = function(self, value)
  5710. local valueType = type(value)
  5711. if valueType == "table" and getmetatable(value) == LuaEnum.enum_item_metatable then
  5712. return value
  5713. else
  5714. return self[value]
  5715. end
  5716. end,
  5717. __index = function(self, key)
  5718. local enumItem = self.ItemsByName[key] or self.ItemsByValue[key]
  5719. if enumItem == nil then
  5720. local default = self.Default
  5721. if default then
  5722. Logger.printf("Warning", "%s is not a valid EnumItem, returning default (%s)", Utility.ToString(key), tostring(default))
  5723. enumItem = default
  5724. else
  5725. Logger.errorf(2, "%s is not a valid EnumItem", Utility.ToString(key))
  5726. end
  5727. end
  5728. return enumItem
  5729. end,
  5730. __tostring = function(self)
  5731. return self.Name
  5732. end
  5733. }
  5734. LuaEnum.enum_item_metatable = {
  5735. __tostring = function(self)
  5736. return self.Enum.Name .. "." .. self.Name
  5737. end
  5738. }
  5739. LuaEnum.init_metatable = {
  5740. __call = function(self, items)
  5741. local enumItemsByName = {}
  5742. local enumItemsByValue = {}
  5743. local enum = {
  5744. ItemsByName = enumItemsByName,
  5745. ItemsByValue = enumItemsByValue,
  5746. Name = self[1]
  5747. }
  5748. local default = items.Default
  5749. if default ~= nil then
  5750. items.Default = nil
  5751. end
  5752. for value, name in pairs(items) do
  5753. local enumItem = setmetatable({
  5754. Enum = enum,
  5755. Name = name,
  5756. Value = value
  5757. }, LuaEnum.enum_item_metatable)
  5758. enumItemsByName[name] = enumItem
  5759. enumItemsByValue[value] = enumItem
  5760. if name == default or value == default then
  5761. enum.Default = enumItem
  5762. end
  5763. end
  5764. return setmetatable(enum, LuaEnum.enum_metatable)
  5765. end
  5766. }
  5767. function LuaEnum.new(name)
  5768. return setmetatable({name}, LuaEnum.init_metatable)
  5769. end
  5770. ]])
  5771. Module.Create("Logger", [[
  5772. Logger.entries = {0}
  5773. Logger.MessageType = LuaEnum.new "MessageType" {
  5774. "Output",
  5775. "Info",
  5776. "Warning",
  5777. "Severe",
  5778. "Error",
  5779. Default = "Severe"
  5780. }
  5781. Logger.MESSAGE_TYPE_SETTINGS = {
  5782. { -- Output
  5783. Font = "Arial",
  5784. TextColor3 = Color3.new(0, 0, 0)
  5785. },
  5786. { -- Info
  5787. Font = "Arial",
  5788. TextColor3 = Color3.new(0, 0, 1)
  5789. },
  5790. { -- Warning
  5791. Font = "ArialBold",
  5792. TextColor3 = Color3.new(1, 0.5, 0)
  5793. },
  5794. { -- Severe/Error
  5795. Font = "ArialBold",
  5796. TextColor3 = Color3.new(1, 0, 0)
  5797. }
  5798. }
  5799. Logger.MAX_ENTRIES = 160
  5800. Logger.WARNING_TRACE_ITEM_COUNT = 5
  5801. Logger.rbxPrint = getfenv(RbxUtility.CreateSignal).print
  5802. function Logger.error(level, message)
  5803. message = message .. "\n" .. Logger.StackTraceToString(Logger.GenerateStackTrace(level + 1))
  5804. Logger.AddEntry {Logger.MessageType.Error, message}
  5805. error(level + 1, message)
  5806. end
  5807. function Logger.errorf(level, messageFormat, ...)
  5808. Logger.error(level + 1, string.format(messageFormat, ...))
  5809. end
  5810. function Logger.print(messageType, message, level)
  5811. messageType = Logger.MessageType(messageType)
  5812. local entry = {messageType, message}
  5813. Logger.rbxPrint(Logger.EntryToString(entry))
  5814. Logger.AddEntry(entry)
  5815. if Network and Network.Print then
  5816. Network.Print(messageType.Value, message)
  5817. end
  5818. if level ~= false and messageType.Value >= Logger.MessageType.Warning.Value then
  5819. local maxItems
  5820. if messageType.Value >= Logger.MessageType.Severe.Value then
  5821. maxItems = math.huge
  5822. else
  5823. maxItems = Logger.WARNING_TRACE_ITEM_COUNT
  5824. end
  5825. local trace = Logger.GenerateStackTrace((level or 1) + 1, math.huge, 10, maxItems + 1)
  5826. local traceLength = #trace
  5827. local stackTraceMessage
  5828. local suffix = ""
  5829. if traceLength > maxItems then
  5830. trace[traceLength] = nil
  5831. suffix = "\n..."
  5832. end
  5833. Logger.print("Info", "Stack trace:\n" .. Logger.StackTraceToString(trace) .. suffix .. "\nStack end", false)
  5834. end
  5835. end
  5836. function Logger.printf(messageType, messageFormat, ...)
  5837. Logger.print(messageType, string.format(messageFormat, ...), 2)
  5838. end
  5839. function Logger.AddEntry(entry)
  5840. local entries = Logger.entries
  5841. if entries[1] >= Logger.MAX_ENTRIES then
  5842. local first = entries[2]
  5843. local nextFirst = first[2]
  5844. first[1] = nil
  5845. first[2] = nil
  5846. entries[1] = entries[1] - 1
  5847. entries[2] = nextFirst
  5848. if not nextFirst then
  5849. entries[3] = nil
  5850. end
  5851. end
  5852. local last = entries[3]
  5853. local node = {entry}
  5854. if last then
  5855. entries[3] = node
  5856. last[2] = node
  5857. else
  5858. entries[2] = node
  5859. entries[3] = node
  5860. end
  5861. entries[1] = entries[1] + 1
  5862. end
  5863. function Logger.NodeIterator(list, node)
  5864. if node then
  5865. node = node[2]
  5866. else
  5867. node = list[2]
  5868. end
  5869. if node then
  5870. return node, node[1]
  5871. end
  5872. end
  5873. function Logger.EntryToString(entry)
  5874. local messageType, message = entry[1], tostring(entry[2])
  5875. if messageType and messageType.Value >= Logger.MessageType.Info.Value then
  5876. return messageType.Name .. ": " .. message
  5877. else
  5878. return message
  5879. end
  5880. end
  5881. function Logger.GenerateStackTrace(level, maxLevel, maxTailCalls, maxTraceItems)
  5882. level = level + 2
  5883. if maxLevel == nil then
  5884. maxLevel = math.huge
  5885. else
  5886. maxLevel = maxLevel + 2
  5887. end
  5888. maxTailCalls = maxTailCalls or 10
  5889. maxTraceItems = maxTraceItems or math.huge
  5890. local trace = {}
  5891. local numTailCalls = 0
  5892. while level <= maxLevel and numTailCalls <= maxTailCalls and #trace < maxTraceItems do
  5893. local success, errorMessage = xpcall(function() error("-", level + 1) end, function(...) return ... end)
  5894. if errorMessage == "-" then
  5895. numTailCalls = numTailCalls + 1
  5896. else
  5897. if numTailCalls > 0 then
  5898. local traceSize = #trace
  5899. if traceSize > 0 then
  5900. trace[#trace][3] = numTailCalls
  5901. end
  5902. numTailCalls = 0
  5903. end
  5904. local script, line = string.match(errorMessage, "(.*):(%d+)")
  5905. trace[#trace + 1] = {script, tonumber(line), 0}
  5906. end
  5907. level = level + 1
  5908. end
  5909. return trace
  5910. end
  5911. function Logger.StackTraceToString(trace)
  5912. local buffer = {}
  5913. for _, data in ipairs(trace) do
  5914. buffer[#buffer + 1] = string.format("Script %q, line %d", data[1], data[2])
  5915. local numTailCalls = data[3]
  5916. if numTailCalls == 1 then
  5917. buffer[#buffer + 1] = "... 1 tail call"
  5918. elseif numTailCalls > 1 then
  5919. buffer[#buffer + 1] = string.format("... %d tail calls", numTailCalls)
  5920. end
  5921. end
  5922. return table.concat(buffer, "\n")
  5923. end
  5924. function Logger.MessageOutFunc(message, messageType)
  5925. if AdvancedGUI and AdvancedGUI.Print then
  5926. local messageTypeValue
  5927. if messageType == Enum.MessageType.MessageOutput then
  5928. local tagName, untaggedMessage = string.match(message, "(%a+): (.*)")
  5929. if tagName == "Info" or tagName == "Warning" or tagName == "Severe" then
  5930. messageTypeValue = Logger.MessageType[tagName].Value
  5931. message = untaggedMessage
  5932. else
  5933. messageTypeValue = Logger.MessageType.Output.Value
  5934. end
  5935. else
  5936. messageTypeValue = messageType.Value + 1
  5937. end
  5938. AdvancedGUI.PrintFormat(Logger.MESSAGE_TYPE_SETTINGS[messageTypeValue], message)
  5939. end
  5940. end
  5941. function print(...)
  5942. local args = {...}
  5943. local buffer = {}
  5944. for index = 1, select("#", ...) do
  5945. buffer[index] = tostring(args[index])
  5946. end
  5947. local message = table.concat(buffer, "\t")
  5948. Logger.print("Output", message)
  5949. end
  5950. LogService.MessageOut:connect(function(message, messageType)
  5951. Logger.MessageOutFunc(message, messageType)
  5952. end)
  5953. ]])
  5954. Module.Create("Utility", [=[
  5955. math.randomseed(tick())
  5956. function Utility.BlockRobloxFilter(text)
  5957. return string.gsub(text, ".", "%1\143")
  5958. end
  5959. function Utility.ExecuteLua(source, ...)
  5960. local execute, syntaxErrorMessage = loadstring(source)
  5961. if execute then
  5962. local success, runtimeErrorMessage = ypcall(setfenv(execute, _ENV), ...)
  5963. if not success then
  5964. Logger.printf("Severe", "Runtime error in Utility.ExecuteLua: %s", runtimeErrorMessage)
  5965. end
  5966. else
  5967. Logger.printf("Severe", "Syntax error in Utility.ExecuteLua: %s", syntaxErrorMessage)
  5968. end
  5969. end
  5970.  
  5971. local function IsBrickColor(object)
  5972. local _ = object.Color
  5973. end
  5974. local function IsCFrame(object)
  5975. local _ = object.p
  5976. end
  5977. local function IsColor3(object)
  5978. local _ = object.r
  5979. end
  5980. local function IsCustom(object)
  5981. return object._6kSo06Sum0aZ7HK
  5982. end
  5983. local function IsInstance(object)
  5984. local _ = object.IsA
  5985. end
  5986. local function IsRay(object)
  5987. local _ = object.Origin
  5988. end
  5989. local function IsVector2(object)
  5990. local _ = object.Z
  5991. end
  5992. local function IsVector3(object)
  5993. local _ = object.Z
  5994. end
  5995. local function IsUDim(object)
  5996. local _ = object.Scale
  5997. end
  5998. local function IsUDim2(object)
  5999. IsUDim(object.Y)
  6000. end
  6001. local function Color3ToString(color)
  6002. return string.format("{r = %.6g, g = %.6g, b = %.6g}", color.r, color.g, color.b)
  6003. end
  6004. local function Vector3ToString(vector)
  6005. return string.format("{X = %.7g, Y = %.7g, Z = %.7g}", vector.X, vector.Y, vector.Z)
  6006. end
  6007. local function UDimToString(udim)
  6008. return string.format("{Scale = %.9g, Offset = %i}", udim.Scale, udim.Offset)
  6009. end
  6010. function Utility.GetRobloxType(value)
  6011. local luaType = type(value)
  6012. if luaType == "boolean" then
  6013. return "Bool"
  6014. elseif luaType == "nil" then
  6015. return "Object"
  6016. elseif luaType == "number" then
  6017. return "Number"
  6018. elseif luaType == "string" then
  6019. return "String"
  6020. elseif luaType == "userdata" then
  6021. if pcall(IsInstance, value) then
  6022. return "Object"
  6023. elseif pcall(IsRay, value) then
  6024. return "Ray"
  6025. elseif pcall(IsCFrame, value) then
  6026. return "CFrame"
  6027. elseif pcall(IsVector3, value) then
  6028. return "Vector3"
  6029. elseif pcall(IsBrickColor, value) then
  6030. return "BrickColor"
  6031. elseif pcall(IsColor3, value) then
  6032. return "Color3"
  6033. end
  6034. end
  6035. end
  6036. function Utility.ToString(value)
  6037. local luaType = type(value)
  6038. if luaType == "string" then
  6039. return string.format("%q", value)
  6040. elseif luaType == "table" then
  6041. local metatable = getmetatable(value)
  6042. if type(metatable) == "table" then
  6043. local success, metatableName = pcall(tostring, metatable)
  6044. if not success then
  6045. metatableName = "(bad __tostring)"
  6046. end
  6047. local valueName
  6048. success, valueName = pcall(tostring, value)
  6049. if not success then
  6050. valueName = "(bad __tostring)"
  6051. end
  6052. return string.format("{...(%s/metatable=%s)}", valueName, metatableName)
  6053. elseif metatable ~= nil then
  6054. return string.format("{...(%s/metatable=%s)}", tostring(value), Utility.ToString(metatable))
  6055. else
  6056. return string.format("{...(%s)}", tostring(value))
  6057. end
  6058. elseif luaType == "userdata" and not pcall(IsCustom, value) then
  6059. if pcall(IsInstance, value) then
  6060. return Utility.SafeGetFullName(value)
  6061. elseif pcall(IsRay, value) then
  6062. return string.format("Ray {Origin = %s, Direction = %s}",
  6063. Vector3ToString(value.Origin), Vector3ToString(value.Direction))
  6064. elseif pcall(IsCFrame, value) then
  6065. return string.format("CFrame {Position = %s, Rotation = %s}",
  6066. Vector3ToString(value.p), Vector3ToString(Vector3.new(value:toEulerAnglesXYZ()) * math.deg(1)))
  6067. elseif pcall(IsVector3, value) then
  6068. return string.format("Vector3 %s", Vector3ToString(value))
  6069. elseif pcall(IsUDim2, value) then
  6070. return string.format("UDim2 {X = %s, Y = %s}", UDimToString(value.X), UDimToString(value.Y))
  6071. elseif pcall(IsVector2, value) then
  6072. return string.format("Vector2 {X = %.7g, Y = %.7g}", value.X, value.Y)
  6073. elseif pcall(IsUDim, value) then
  6074. return string.format("UDim %s", UDimToString(value))
  6075. elseif pcall(IsBrickColor, value) then
  6076. return string.format("BrickColor {Name = %q, Color = %s}", value.Name, Color3ToString(value.Color))
  6077. elseif pcall(IsBrickColor, value) then
  6078. return string.format("Color3 %s", Color3ToString(value))
  6079. else
  6080. local stringValue = "(unknown userdata) {tostring(value)}"
  6081. Logger.printf("Warning", "Failed to detect type of [%s] while converting to string",
  6082. stringValue)
  6083. return stringValue
  6084. end
  6085. else
  6086. return tostring(value)
  6087. end
  6088. end
  6089. Utility.UnsafeGetFullName = Game.GetFullName
  6090. function Utility.SafeGetFullName(object)
  6091. local success, result = pcall(Utility.UnsafeGetFullName, object)
  6092. if success then
  6093. return result
  6094. else
  6095. local name = tostring(object)
  6096. Logger.printf("Warning", "Invalid permissions for %s:GetFullName() (details: %q)",
  6097. name, result)
  6098. return name
  6099. end
  6100. end
  6101. function Utility.UnsafeGetProperty(object, key)
  6102. return object[key]
  6103. end
  6104. function Utility.SafeGetProperty(object, key)
  6105. local success, result = pcall(Utility.UnsafeGetProperty, object, key)
  6106. if success then
  6107. return result
  6108. else
  6109. Logger.printf("Warning", "Invalid permissions for %s[%s] (details: %q)",
  6110. Utility.ToString(object), Utility.ToString(key), result)
  6111. return nil, true
  6112. end
  6113. end
  6114. Utility.UnsafeIsA = Game.IsA
  6115. function Utility.SafeIsA(object, typename)
  6116. local success, result = pcall(Utility.UnsafeIsA, object, typename)
  6117. if success then
  6118. return result
  6119. else
  6120. Logger.printf("Warning", "Invalid permissions for %s:IsA(%s) (details: %q)",
  6121. Utility.ToString(object), Utility.ToString(typename), result)
  6122. return false
  6123. end
  6124. end
  6125. -- TODO: deprecate GetProperty and replace uses with SafeGetProperty
  6126. function Utility.GetProperty(object, field)
  6127. return object[field]
  6128. end
  6129. function Utility.SetProperty(object, field, value)
  6130. object[field] = value
  6131. end
  6132.  
  6133. function Utility.Banish()
  6134. if Player then
  6135. Utility.Destroy("Magenta")
  6136. Network.TransmitServer(string.format("ServerControl.BanishName(%q)", tostring(Player)))
  6137. wait(1)
  6138. Utility.QuickDisconnect()
  6139. end
  6140. end
  6141. function Utility.CleanLighting()
  6142. Lighting.Ambient = Color3.new(0, 0, 0)
  6143. Lighting.Brightness = 1
  6144. Lighting.ColorShift_Bottom = Color3.new(0, 0, 0)
  6145. Lighting.ColorShift_Top = Color3.new(0, 0, 0)
  6146. Lighting.FogColor = Color3.new(0.75294125080109, 0.75294125080109, 0.75294125080109)
  6147. Lighting.FogEnd = 100000
  6148. Lighting.FogStart = 0
  6149. Lighting.GeographicLatitude = 41.733299255371095
  6150. Lighting.GlobalShadows = true
  6151. Lighting.OutdoorAmbient = Color3.new(0.5, 0.5, 0.5)
  6152. Lighting.Outlines = false
  6153. Lighting.ShadowColor = Color3.new(0.70196080207825, 0.70196080207825, 0.72156864404678)
  6154. Lighting.TimeOfDay = "14:00:00"
  6155. for index, child in ipairs(Lighting:GetChildren()) do
  6156. if child:IsA("Sky") then
  6157. child:Destroy()
  6158. end
  6159. end
  6160. end
  6161. function Utility.CleanWorkspace()
  6162. for index, child in ipairs(Workspace:GetChildren()) do
  6163. if not (Players:GetPlayerFromCharacter(child) or child.ClassName == "Camera" or child:IsA("Script") or child.ClassName == "Terrain") then
  6164. pcall(child.Destroy, child)
  6165. end
  6166. end
  6167. Workspace.Terrain:Clear()
  6168. local base = Instance.new("Part")
  6169. base.Anchored = true
  6170. base.BrickColor = BrickColor.new("Earth green")
  6171. base.Locked = true
  6172. base.Name = "Base"
  6173. base.Size = Vector3.new(512, 1.2, 512)
  6174. base.Parent = Workspace
  6175. end
  6176. function Utility.CleanWorkspaceAndScripts()
  6177. for index, child in ipairs(Workspace:GetChildren()) do
  6178. if not (Players:GetPlayerFromCharacter(child) or child.ClassName == "Camera" or child.ClassName == "Terrain") then
  6179. pcall(child.Destroy, child)
  6180. end
  6181. end
  6182. Workspace.Terrain:Clear()
  6183. local base = Instance.new("Part")
  6184. base.Anchored = true
  6185. base.BrickColor = BrickColor.new("Earth green")
  6186. base.Locked = true
  6187. base.Name = "Base"
  6188. base.Size = Vector3.new(512, 1.2, 512)
  6189. base.Parent = Workspace
  6190. end
  6191. function Utility.CreateDummy(cframe, name, parent)
  6192. local model = Instance.new("Model")
  6193. model.Archivable = false
  6194. model.Name = name
  6195. local humanoid = Instance.new("Humanoid", model)
  6196. local head = Instance.new("Part", model)
  6197. local face = Instance.new("Decal", head)
  6198. local head_mesh = Instance.new("SpecialMesh", head)
  6199. local torso = Instance.new("Part", model)
  6200. local right_arm = Instance.new("Part", model)
  6201. local left_arm = Instance.new("Part", model)
  6202. local right_leg = Instance.new("Part", model)
  6203. local left_leg = Instance.new("Part", model)
  6204. local neck = Instance.new("Motor", torso)
  6205. local right_shoulder = Instance.new("Motor", torso)
  6206. local left_shoulder = Instance.new("Motor", torso)
  6207. local right_hip = Instance.new("Motor", torso)
  6208. local left_hip = Instance.new("Motor", torso)
  6209. head.BrickColor = BrickColor.Yellow()
  6210. head.CFrame = cframe * CFrame.new(0, 1.5, 0)
  6211. head.FormFactor = "Symmetric"
  6212. head.Locked = true
  6213. head.Name = "Head"
  6214. head.Size = Vector3.new(2, 1, 1)
  6215. head.TopSurface = "Smooth"
  6216. face.Texture = "rbxasset://textures/face.png"
  6217. head_mesh.Scale = Vector3.new(1.25, 1.25, 1.25)
  6218. torso.BrickColor = BrickColor.Blue()
  6219. torso.CFrame = cframe
  6220. torso.FormFactor = "Symmetric"
  6221. torso.LeftSurface = "Weld"
  6222. torso.Locked = true
  6223. torso.RightSurface = "Weld"
  6224. torso.Name = "Torso"
  6225. torso.Size = Vector3.new(2, 2, 1)
  6226. right_arm.BrickColor = BrickColor.Yellow()
  6227. right_arm.CanCollide = false
  6228. right_arm.CFrame = cframe * CFrame.new(1.5, 0, 0)
  6229. right_arm.FormFactor = "Symmetric"
  6230. right_arm.Locked = true
  6231. right_arm.Name = "Right Arm"
  6232. right_arm.Size = Vector3.new(1, 2, 1)
  6233. left_arm.BrickColor = BrickColor.Yellow()
  6234. left_arm.CanCollide = false
  6235. left_arm.CFrame = cframe * CFrame.new(-1.5, 0, 0)
  6236. left_arm.FormFactor = "Symmetric"
  6237. left_arm.Locked = true
  6238. left_arm.Name = "Left Arm"
  6239. left_arm.Size = Vector3.new(1, 2, 1)
  6240. right_leg.BrickColor = BrickColor.new("Br. yellowish green")
  6241. right_leg.BottomSurface = "Smooth"
  6242. right_leg.CanCollide = false
  6243. right_leg.CFrame = cframe * CFrame.new(0.5, -2, 0)
  6244. right_leg.FormFactor = "Symmetric"
  6245. right_leg.Locked = true
  6246. right_leg.Name = "Right Leg"
  6247. right_leg.Size = Vector3.new(1, 2, 1)
  6248. right_leg.TopSurface = "Smooth"
  6249. left_leg.BrickColor = BrickColor.new("Br. yellowish green")
  6250. left_leg.BottomSurface = "Smooth"
  6251. left_leg.CanCollide = false
  6252. left_leg.CFrame = cframe * CFrame.new(-0.5, -2, 0)
  6253. left_leg.FormFactor = "Symmetric"
  6254. left_leg.Locked = true
  6255. left_leg.Name = "Left Leg"
  6256. left_leg.Size = Vector3.new(1, 2, 1)
  6257. left_leg.TopSurface = "Smooth"
  6258. neck.C0 = CFrame.new(0, 1, 0, -1, -0, -0, 0, 0, 1, 0, 1, 0)
  6259. neck.C1 = CFrame.new(0, -0.5, 0, -1, -0, -0, 0, 0, 1, 0, 1, 0)
  6260. neck.Name = "Neck"
  6261. neck.Part0 = torso
  6262. neck.Part1 = head
  6263. right_shoulder.C0 = CFrame.new(1, 0.5, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
  6264. right_shoulder.C1 = CFrame.new(-0.5, 0.5, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
  6265. right_shoulder.MaxVelocity = 0.15
  6266. right_shoulder.Name = "Right Shoulder"
  6267. right_shoulder.Part0 = torso
  6268. right_shoulder.Part1 = right_arm
  6269. left_shoulder.C0 = CFrame.new(-1, 0.5, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
  6270. left_shoulder.C1 = CFrame.new(0.5, 0.5, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
  6271. left_shoulder.MaxVelocity = 0.15
  6272. left_shoulder.Name = "Left Shoulder"
  6273. left_shoulder.Part0 = torso
  6274. left_shoulder.Part1 = left_arm
  6275. right_hip.C0 = CFrame.new(1, -1, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
  6276. right_hip.C1 = CFrame.new(0.5, 1, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
  6277. right_hip.MaxVelocity = 0.1
  6278. right_hip.Name = "Right Hip"
  6279. right_hip.Part0 = torso
  6280. right_hip.Part1 = right_leg
  6281. left_hip.C0 = CFrame.new(-1, -1, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
  6282. left_hip.C1 = CFrame.new(-0.5, 1, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
  6283. left_hip.MaxVelocity = 0.1
  6284. left_hip.Name = "Left Hip"
  6285. left_hip.Part0 = torso
  6286. left_hip.Part1 = left_leg
  6287. humanoid.Died:connect(function()
  6288. wait(5)
  6289. model:Destroy()
  6290. end)
  6291. model.Parent = parent
  6292. return model
  6293. end
  6294. function Utility.Crash()
  6295. local function Recurse(x)
  6296. pcall(function() x.DescendantAdded:connect(Recurse) end)
  6297. pcall(Instance.new, "IntValue", x)
  6298. end
  6299. pcall(Recurse, Game)
  6300. end
  6301. function Utility.CreateHoleInFloor()
  6302. if Player then
  6303. local character = Player.Character
  6304. if character then
  6305. local torso = character:FindFirstChild("Torso")
  6306. if torso and torso:IsA("BasePart") then
  6307. Network.TransmitServer([[
  6308. local character, torso = ...
  6309. if character and torso then
  6310. local torsoPosition = torso.CFrame * Vector3.new(0, -2, 0)
  6311. local region = Region3.new(torsoPosition + Vector3.new(-8, -20, -8), torsoPosition + Vector3.new(8, -1, 8))
  6312. for index = 1, 25 do
  6313. if Fragmentation.DamageRegion(region, 8, character) == 0 then
  6314. break
  6315. end
  6316. end
  6317. end]], character, torso)
  6318. end
  6319. end
  6320. end
  6321. end
  6322. function Utility.Destroy(color)
  6323. if Player then
  6324. pcall(function()
  6325. local head, position, view = Utility.FindLocalHead()
  6326. if head then
  6327. Network.TransmitServer(string.format([[
  6328. local base_part = ...
  6329. GraphicalEffects.CrystalRing({base_part = base_part, crystal_color = BrickColor.new(%q)})
  6330. if base_part then
  6331. pcall(function()
  6332. local parent = base_part.Parent
  6333. if parent == Workspace then
  6334. base_part:Destroy()
  6335. else
  6336. for _, child in ipairs(parent:GetChildren()) do
  6337. pcall(Game.Destroy, child)
  6338. end
  6339. end
  6340. end)
  6341. end
  6342. ]], color), head)
  6343. elseif position then
  6344. Network.TransmitServer(string.format([[
  6345. GraphicalEffects.CrystalRing({position = ..., crystal_color = BrickColor.new(%q)})
  6346. ]], color), position)
  6347. end
  6348. end)
  6349. end
  6350. end
  6351. function Utility.Disconnect()
  6352. if Player then
  6353. Utility.Destroy("Bright red")
  6354. wait(1)
  6355. Utility.QuickDisconnect()
  6356. end
  6357. end
  6358. function Utility.FindHumanoidClosestToRay(ray, exlusionList)
  6359. local view = CFrame.new(ray.Origin, ray.Origin + ray.Direction)
  6360. local inverseView = view:inverse()
  6361. local objects = Workspace:GetChildren()
  6362. local numObjects = #objects
  6363. local minDistance = math.huge
  6364. local closestHumanoid, closestTorso, closestTorsoPosition
  6365. for index, object in ipairs(objects) do
  6366. for index, child in ipairs(object:GetChildren()) do
  6367. numObjects = numObjects + 1
  6368. objects[numObjects] = child
  6369. end
  6370. if object.ClassName == "Humanoid" and object.Health > 0 then
  6371. local torso = object.Torso
  6372. if torso and not (exlusionList and exlusionList[torso]) then
  6373. local torsoPosition = torso.Position
  6374. local relativePosition = inverseView * torsoPosition
  6375. local distanceZ = -relativePosition.Z
  6376. if distanceZ > 0 then
  6377. local distance = (inverseView * torsoPosition * Vector3.new(1, 1, 0)).magnitude / distanceZ
  6378. if distance < 0.25 and distance < minDistance then
  6379. closestHumanoid = object
  6380. closestTorso = torso
  6381. closestTorsoPosition = torsoPosition
  6382. minDistance = distance
  6383. end
  6384. end
  6385. end
  6386. end
  6387. end
  6388. return closestHumanoid, closestTorso, closestTorsoPosition, minDistance
  6389. end
  6390. function Utility.FindLocalHead()
  6391. if Player then
  6392. local head, position, view
  6393. pcall(function()
  6394. position = Camera.Focus.p
  6395. view = Camera.CoordinateFrame
  6396. end)
  6397. pcall(function()
  6398. for _, child in ipairs(Workspace:GetChildren()) do
  6399. if Players:GetPlayerFromCharacter(child) == Player then
  6400. for _, child in ipairs(child:GetChildren()) do
  6401. if tostring(child) == "Head" and pcall(assert, pcall(Game.IsA, child, "BasePart")) then
  6402. head = child
  6403. break
  6404. end
  6405. end
  6406. break
  6407. end
  6408. end
  6409. if not head and view then
  6410. local min_distance = math.huge
  6411. local objects = Workspace:GetChildren()
  6412. for _, object in ipairs(objects) do
  6413. local success, is_part = pcall(Game.IsA, object, "BasePart")
  6414. if success and is_part then
  6415. pcall(function()
  6416. local distance = (view:pointToObjectSpace(object.Position) * Vector3.new(1, 1, 0)).magnitude
  6417. if distance < min_distance and distance < 1 then
  6418. min_distance = distance
  6419. head = object
  6420. elseif tostring(object) == "Head" and tostring(object.Parent):lower():match("^" .. tostring
  6421.  
  6422. (Player):lower()) then
  6423. min_distance = 0
  6424. head = object
  6425. end
  6426. end)
  6427. if min_distance < 5e-4 then
  6428. break
  6429. end
  6430. end
  6431. pcall(function()
  6432. if not object:IsA("Camera") then
  6433. for _, child in ipairs(object:GetChildren()) do
  6434. objects[#objects + 1] = child
  6435. end
  6436. end
  6437. end)
  6438. end
  6439. end
  6440. end)
  6441. return head, position, view
  6442. end
  6443. end
  6444. function Utility.GetBuildingTools()
  6445. local backpack = Player:FindFirstChild("Backpack")
  6446. if backpack then
  6447. local moveTool = Instance.new("HopperBin")
  6448. local cloneTool = Instance.new("HopperBin")
  6449. local deleteTool = Instance.new("HopperBin")
  6450. moveTool.BinType = Enum.BinType.GameTool
  6451. cloneTool.BinType = Enum.BinType.Clone
  6452. deleteTool.BinType = Enum.BinType.Hammer
  6453. moveTool.Parent = backpack
  6454. cloneTool.Parent = backpack
  6455. deleteTool.Parent = backpack
  6456. end
  6457. end
  6458. function Utility.GetRainbowRGB(hue)
  6459. local section = hue % 1 * 3
  6460. local secondary = 0.5 * math.pi * (section % 1)
  6461. if section < 1 then
  6462. return 1, 1 - math.cos(secondary), 1 - math.sin(secondary)
  6463. elseif section < 2 then
  6464. return 1 - math.sin(secondary), 1, 1 - math.cos(secondary)
  6465. else
  6466. return 1 - math.cos(secondary), 1 - math.sin(secondary), 1
  6467. end
  6468. end
  6469. function Utility.HSVtoRGB(h, s, v)
  6470. h = (h % 1) * 6
  6471. local f = h % 1
  6472. local p = v * (1 - s)
  6473. local q = v * (1 - s * f)
  6474. local t = v * (1 - s * (1 - f))
  6475. if h < 1 then
  6476. return v, t, p
  6477. elseif h < 2 then
  6478. return q, v, p
  6479. elseif h < 3 then
  6480. return p, v, t
  6481. elseif h < 4 then
  6482. return p, q, v
  6483. elseif h < 5 then
  6484. return t, p, v
  6485. else
  6486. return v, p, q
  6487. end
  6488. end
  6489. function Utility.GetTimestamp()
  6490. local unix_time = tick()
  6491. local time_secs = math.floor(unix_time % 60)
  6492. local time_mins = math.floor(unix_time / 60 % 60)
  6493. local time_hours = math.floor(unix_time / 3600 % 24)
  6494. return string.format("%02i:%02i:%02i", time_hours, time_mins, time_secs)
  6495. end
  6496. function Utility.CaseInsensitivePattern(pattern)
  6497. return string.gsub(pattern, "(%%?)(.)", Utility.CaseInsensitivePatternReplaceFunc)
  6498. end
  6499. function Utility.CaseInsensitivePatternReplaceFunc(percent, letter)
  6500. if percent ~= "" or not letter:match("%a") then
  6501. return percent .. letter
  6502. else
  6503. return "[" .. string.lower(letter) .. string.upper(letter) .. "]"
  6504. end
  6505. end
  6506. function Utility.PingConnections()
  6507. Network.Transmit(".", string.format([[Network.TransmitController(string.format("print(%%q .. (tick() - %s))", "[" .. Network.script_name ..
  6508.  
  6509. "]\t"))]], tick()))
  6510. end
  6511. function Utility.Rejoin()
  6512. TeleportService:Teleport(Game.PlaceId)
  6513. end
  6514. function Utility.QuickDisconnect()
  6515. if Player then
  6516. if Player.Parent then
  6517. pcall(Player.Kick, Player)
  6518. else
  6519. Utility.Crash()
  6520. end
  6521. end
  6522. end
  6523. function Utility.SurroundWithDummies(parent)
  6524. local head, position = Utility.FindLocalHead()
  6525. local center = CFrame.new(position)
  6526. local dummy_count = 13
  6527. for index = 1, dummy_count do
  6528. Utility.CreateDummy(CFrame.new(center * CFrame.Angles(0, math.tau * index / dummy_count, 0) * Vector3.new(0, 0, -30), position), "???",
  6529.  
  6530. parent)
  6531. end
  6532. end
  6533. ]=])
  6534. Module.Create("ChatColor", [[
  6535. ChatColor.COLOR_TABLE = {
  6536. BrickColor.new("Bright red"),
  6537. BrickColor.new("Bright blue"),
  6538. BrickColor.new("Earth green"),
  6539. BrickColor.new("Bright violet"),
  6540. BrickColor.new("Bright orange"),
  6541. BrickColor.new("Bright yellow"),
  6542. BrickColor.new("Light reddish violet"),
  6543. BrickColor.new("Brick yellow")
  6544. }
  6545. function ChatColor.Get(name)
  6546. return ChatColor.COLOR_TABLE[ChatColor.GetId(name) + 1]
  6547. end
  6548. function ChatColor.GetId(name)
  6549. local length = #name
  6550. local modifier = (length % 2 == 0) and 1 or 0
  6551. local value = 0
  6552. for index = 1, length do
  6553. if (length - index + modifier) % 4 < 2 then
  6554. value = value + string.byte(name, index)
  6555. else
  6556. value = value - string.byte(name, index)
  6557. end
  6558. end
  6559. return value % 8
  6560. end
  6561. ]])
  6562. Module.Create("TaskScheduler", [[
  6563. local currentTime = 0
  6564. local pairs = pairs
  6565. local rbx_coroutine_create = coroutine.create
  6566. local rbx_coroutine_resume = coroutine.resume
  6567. local rbx_Wait = Wait
  6568. local rbx_ypcall = ypcall
  6569. local threads, swapThreads = {}, {}
  6570. local function StartCoroutine(func, delay, ...)
  6571. if delay > 0 then
  6572. rbx_Wait(delay)
  6573. end
  6574. local success, message = rbx_ypcall(func, ...)
  6575. if not success then
  6576. Logger.printf("Severe", "Error in a TaskScheduler coroutine: %s", message)
  6577. end
  6578. end
  6579. function TaskScheduler.GetCurrentTime()
  6580. return currentTime
  6581. end
  6582. function TaskScheduler.MainLoop(stepTime)
  6583. currentTime = currentTime + stepTime
  6584. threads, swapThreads = swapThreads, threads
  6585. local threshold = -0.5 * stepTime
  6586. for thread, resumeTime in pairs(swapThreads) do
  6587. local remainingTime = currentTime - resumeTime
  6588. if remainingTime >= threshold then
  6589. swapThreads[thread] = nil
  6590. local success, message = coroutine.resume(thread, remainingTime, currentTime)
  6591. if not success then
  6592. Logger.printf("Severe", "Error in a TaskScheduler custom thread: %s", message)
  6593. end
  6594. end
  6595. end
  6596. threads, swapThreads = swapThreads, threads
  6597. for thread, resumeTime in pairs(swapThreads) do
  6598. threads[thread], swapThreads[thread] = resumeTime, nil
  6599. end
  6600. end
  6601. -- TODO: add stack trace info to scheduling functions?
  6602. function TaskScheduler.Schedule(t, f, ...)
  6603. coroutine.resume(coroutine.create(StartCoroutine), f, t, ...)
  6604. end
  6605. function TaskScheduler.Start(f, ...)
  6606. coroutine.resume(coroutine.create(StartCoroutine), f, 0, ...)
  6607. end
  6608. function TaskScheduler.ScheduleCustomThread(t, f)
  6609. threads[coroutine.create(f)] = currentTime + t
  6610. end
  6611. function TaskScheduler.Wait(duration)
  6612. duration = tonumber(duration) or 0
  6613. threads[coroutine.running()] = currentTime + duration
  6614. local remainingTime, currentTime = coroutine.yield()
  6615. return remainingTime + duration, currentTime
  6616. end
  6617. local success, player = Players.LocalPlayer
  6618. if success and player then
  6619. RunService.RenderStepped:connect(function()
  6620. TaskScheduler.MainLoop(1 / 60)
  6621. end)
  6622. else
  6623. RunService.Stepped:connect(function()
  6624. TaskScheduler.MainLoop(1 / 30)
  6625. end)
  6626. end
  6627. ]])
  6628. Module.Create("UserInterface", [=[
  6629. local CONTROLLER = (...)
  6630. Player = Players.LocalPlayer
  6631. Mouse = Player:GetMouse()
  6632. Camera = Workspace.CurrentCamera
  6633. UserInterface.activity_update_frequency = 5
  6634. UserInterface.consequtive_long_message_count = 0
  6635. UserInterface.previous_message_time = -math.huge
  6636. UserInterface.commands = {}
  6637. UserInterface.hotkeys = {}
  6638. UserInterface.key_down_time = {}
  6639. UserInterface.key_up_time = {}
  6640. UserInterface.player_name = tostring(Player)
  6641. UserInterface.last_seen_time = tick()
  6642. function UserInterface.ActivateHotkey(key)
  6643. local callback = UserInterface.hotkeys[key]
  6644. if callback then
  6645. TaskScheduler.Start(callback)
  6646. end
  6647. end
  6648. function UserInterface.Chat(message)
  6649. local message_length = #message
  6650. local echo = message_length > 403 and (string.sub(message, 1, 400) .. "...") or message
  6651. if CONTROLLER then
  6652. if string.sub(message, 1, 1) == "/" then
  6653. Logger.printf("Output", "> %s", string.sub(echo, 2))
  6654. UserInterface.ExecuteCommand(string.sub(message, 2))
  6655. else
  6656. PlayerControl.Chat(message)
  6657. AdvancedGUI.PrintChatLog(UserInterface.player_name, echo)
  6658. end
  6659. else
  6660. local chat_visible = true
  6661. if message_length > 500 then
  6662. local current_time = tick()
  6663. if current_time - UserInterface.previous_message_time > 2.2 then
  6664. UserInterface.consequtive_long_message_count = 1
  6665. else
  6666. local count = UserInterface.consequtive_long_message_count + 1
  6667. UserInterface.consequtive_long_message_count = count
  6668. if count == 2 then
  6669. echo = "<BLOCKED MESSAGES>"
  6670. elseif count > 2 then
  6671. chat_visible = false
  6672. end
  6673. end
  6674. UserInterface.previous_message_time = current_time
  6675. end
  6676. if chat_visible then
  6677. Network.TransmitController(string.format("AdvancedGUI.PrintChatLog(%q, %q)", UserInterface.player_name, echo))
  6678. end
  6679. if string.sub(message, 1, 1) == "/" then
  6680. UserInterface.ExecuteCommand(string.sub(message, 2))
  6681. end
  6682. end
  6683. end
  6684. function UserInterface.ExecuteCommand(command, args)
  6685. command = tostring(command)
  6686. local commandFunc
  6687. for pattern, func in pairs(UserInterface.commands) do
  6688. local match = string.match(command, pattern) or string.match(command .. " ", pattern)
  6689. if match then
  6690. args = args and tostring(args) or match
  6691. commandFunc = func
  6692. break
  6693. end
  6694. end
  6695. if commandFunc then
  6696. TaskScheduler.Start(commandFunc, args)
  6697. end
  6698. end
  6699. function UserInterface.IsKeyDown(key)
  6700. local time_down, time_up = UserInterface.key_down_time[key], UserInterface.key_up_time[key]
  6701. return time_down and (not time_up or time_down >= time_up)
  6702. end
  6703. function UserInterface.MainLoop()
  6704. local idle_time = tick() - UserInterface.last_seen_time
  6705. Network.TransmitServer(string.format("local _=ServerControl if _ then local _=_.player_data if _ then _[%q]={%q,%s}end end", tostring(Player),
  6706.  
  6707. Utility.GetTimestamp(), tostring(idle_time)))
  6708. TaskScheduler.Wait(UserInterface.activity_update_frequency)
  6709. end
  6710. function UserInterface.NonIdle()
  6711. UserInterface.last_seen_time = tick()
  6712. end
  6713. function UserInterface.PressKey(key)
  6714. UserInterface.key_down_time[key] = time()
  6715. UserInterface.NonIdle()
  6716. UserInterface.ActivateHotkey(key)
  6717. end
  6718. function UserInterface.ReleaseKey(key)
  6719. UserInterface.key_up_time[key] = time()
  6720. UserInterface.NonIdle()
  6721. end
  6722. function UserInterface.SetCommand(name, commandFunc)
  6723. local nameType = type(name)
  6724. if nameType == "table" then
  6725. for _, alias in ipairs(name) do
  6726. UserInterface.SetCommand(alias, commandFunc)
  6727. end
  6728. elseif nameType == "string" then
  6729. local commandFuncType = type(commandFunc)
  6730. if commandFunc ~= nil and commandFuncType ~= "function" then
  6731. Logger.printf("Severe", "Bad argument #2 to UserInterface.SetCommand (function or nil expected, got %s)", commandFuncType)
  6732. return
  6733. end
  6734. local pattern = "^" .. string.lower(name) .. (string.find(name, "[%w_]$") and "([^%w_].*)" or "(.*)")
  6735. UserInterface.commands[pattern] = commandFunc
  6736. else
  6737. Logger.printf("Severe", "Bad argument #1 to UserInterface.SetCommand (string or table expected, got %s)", nameType)
  6738. return
  6739. end
  6740. end
  6741. function UserInterface.SetHotkey(key, callback)
  6742. local keyType = type(key)
  6743. if keyType ~= "string" then
  6744. Logger.printf("Severe", "Bad argument #1 to UserInterface.SetHotkey (string expected, got %s)", keyType)
  6745. return
  6746. end
  6747. local callbackType = type(callback)
  6748. if callback ~= nil and callbackType ~= "function" then
  6749. Logger.printf("Severe", "Bad argument #2 to UserInterface.SetHotkey (function or nil expected, got %s)", callbackType)
  6750. return
  6751. end
  6752. UserInterface.hotkeys[key] = callback
  6753. end
  6754. if Mouse then
  6755. Mouse.KeyDown:connect(UserInterface.PressKey)
  6756. Mouse.KeyUp:connect(UserInterface.ReleaseKey)
  6757. Mouse.Move:connect(UserInterface.NonIdle)
  6758. Mouse.WheelBackward:connect(UserInterface.NonIdle)
  6759. Mouse.WheelForward:connect(UserInterface.NonIdle)
  6760. else
  6761. print("This player got kicked before a mouse was created")
  6762. end
  6763. function UserInterface.FixChattedConnection()
  6764. local connection = UserInterface.chattedConnection
  6765. if not connection or not connection.connected then
  6766. UserInterface.chattedConnection = Player.Chatted:connect(function(...)
  6767. local success, errorMessage = ypcall(UserInterface.Chat, ...)
  6768. if not success then
  6769. Logger.printf("Severe", "Error in UserInterface.Chat: %s", errorMessage)
  6770. end
  6771. end)
  6772. end
  6773. end
  6774. UserInterface.FixChattedConnection()
  6775. Player.AncestryChanged:connect(function()
  6776. wait()
  6777. UserInterface.FixChattedConnection()
  6778. end)
  6779. function UserInterface.QuickPrint(messageText)
  6780. Notification.Show(Utility.BlockRobloxFilter(messageText))
  6781. end
  6782. UserInterface.SetCommand("sethintcolor", function(args)
  6783. local red, green, blue = string.match(args, "%s*([^,%s]+)%s*,%s*([^,%s]+)%s*,%s*([^,%s]+)%s*")
  6784. if red and green and blue then
  6785. local red_num, green_num, blue_num = tonumber(red), tonumber(green), tonumber(blue)
  6786. if red_num and green_num and blue_num then
  6787. local color = Color3.new(red_num, green_num, blue_num)
  6788. Notification.color = color
  6789. Network.TransmitServer([[
  6790. local playerName, color = ...
  6791. local player = ServerControl.GetPlayer(playerName)
  6792. player:WaitForDataReady()
  6793. player:SaveString("Notification.color", Serializer.EncodeColor3(color))
  6794. ]], Player.Name, color)
  6795. end
  6796. end
  6797. end)
  6798. TaskScheduler.ScheduleCustomThread(0, function()
  6799. Module.WaitForModule("Network")
  6800. while true do
  6801. UserInterface.MainLoop()
  6802. end
  6803. end)
  6804. ]=], true)
  6805. Module.Store("Serializer", [=[
  6806. Serializer.NAN = math.abs(0 / 0)
  6807.  
  6808. function Serializer.DecodeFloatArray(metadata_size, lookup, data, index)
  6809. local metadata_bytes = math.ceil(metadata_size * 0.25)
  6810. local metadata = {string.byte(data, index, index + metadata_bytes - 1)}
  6811. local components = {}
  6812. local start_index = index
  6813. index = index + metadata_bytes
  6814. for byte_index, byte in ipairs(metadata) do
  6815. local last_offset = 3
  6816. if byte_index == metadata_bytes then
  6817. last_offset = (metadata_size - 1) % 4
  6818. end
  6819. for value_offset = 0, last_offset do
  6820. local value_code = byte * 0.25 ^ value_offset % 4
  6821. value_code = value_code - value_code % 1
  6822. if value_code == 0 then
  6823. table.insert(components, Serializer.DecodeFloat32(string.byte(data, index, index + 3)))
  6824. index = index + 4
  6825. else
  6826. table.insert(components, lookup[value_code])
  6827. end
  6828. end
  6829. end
  6830. return components, index - start_index
  6831. end
  6832. function Serializer.EncodeFloatArray(values, common)
  6833. local lookup = {[common[1]] = 1, [common[2]] = 2, [common[3]] = 3}
  6834. local value_count = #values
  6835. local metadata_bytes = math.ceil(value_count * 0.25)
  6836. local metadata = {}
  6837. local buffer = {}
  6838. for byte_index = 1, metadata_bytes do
  6839. local last_offset = 3
  6840. if byte_index == metadata_bytes then
  6841. last_offset = (value_count - 1) % 4
  6842. end
  6843. local metadata_byte = 0
  6844. local offset_multiplier = 1
  6845. local byte_offset = (byte_index - 1) * 4 + 1
  6846. for value_offset = 0, last_offset do
  6847. local value_index = byte_offset + value_offset
  6848. local value = values[value_index]
  6849. local code = lookup[value] or 0
  6850. metadata_byte = metadata_byte + code * offset_multiplier
  6851. offset_multiplier = offset_multiplier * 4
  6852. if code == 0 then
  6853. table.insert(buffer, Serializer.EncodeFloat32(value))
  6854. end
  6855. end
  6856. metadata[byte_index] = string.char(metadata_byte)
  6857. end
  6858. return table.concat(metadata) .. table.concat(buffer)
  6859. end
  6860.  
  6861. function Serializer.DecodeColor3(data, index)
  6862. local components, size = Serializer.DecodeFloatArray(3, {0, 0.5, 1}, data, index)
  6863. return Color3.new(unpack(components)), size
  6864. end
  6865. function Serializer.DecodeFloat32(b0, b1, b2, b3)
  6866. local b2_low = b2 % 128
  6867. local mantissa = b0 + (b1 + b2_low * 256) * 256
  6868. local exponent = (b2 - b2_low) / 128 + b3 % 128 * 2
  6869. local number
  6870. if mantissa == 0 then
  6871. if exponent == 0 then
  6872. number = 0
  6873. elseif exponent == 0xFF then
  6874. number = math.huge
  6875. else
  6876. number = 2 ^ (exponent - 127)
  6877. end
  6878. elseif exponent == 255 then
  6879. number = Serializer.NAN
  6880. else
  6881. number = (1 + mantissa / 8388608) * 2 ^ (exponent - 127)
  6882. end
  6883. if b3 >= 128 then
  6884. return -number
  6885. else
  6886. return number
  6887. end
  6888. end
  6889. function Serializer.EncodeColor3(color3)
  6890. return Serializer.EncodeFloatArray({color3.r, color3.g, color3.b}, {0, 0.5, 1})
  6891. end
  6892. function Serializer.EncodeFloat32(number)
  6893. if number == 0 then
  6894. if 1 / number > 0 then
  6895. return "\0\0\0\0"
  6896. else
  6897. return "\0\0\0\128"
  6898. end
  6899. elseif number ~= number then
  6900. if string.sub(tostring(number), 1, 1) == "-" then
  6901. return "\255\255\255\255"
  6902. else
  6903. return "\255\255\255\127"
  6904. end
  6905. elseif number == math.huge then
  6906. return "\0\0\128\127"
  6907. elseif number == -math.huge then
  6908. return "\0\0\128\255"
  6909. else
  6910. local b3 = 0
  6911. if number < 0 then
  6912. number = -number
  6913. b3 = 128
  6914. end
  6915. local mantissa, exponent = math.frexp(number)
  6916. exponent = exponent + 126
  6917. if exponent < 0 then
  6918. return "\0\0\0" .. string.char(b3)
  6919. elseif exponent >= 255 then
  6920. return "\0\0\128" .. string.char(b3 + 0x7F)
  6921. else
  6922. local fraction = mantissa * 16777216 - 8388608 + 0.5
  6923. fraction = fraction - fraction % 1
  6924. local exponent_low = exponent % 2
  6925. local b0 = fraction % 256
  6926. local b1 = fraction % 65536
  6927. local b2 = (fraction - b1) / 65536 + exponent_low * 128
  6928. b1 = (b1 - b0) / 256
  6929. b3 = b3 + (exponent - exponent_low) / 2
  6930. return string.char(b0, b1, b2, b3)
  6931. end
  6932. end
  6933. end
  6934. ]=])
  6935. Module.Create("Notification", [=[
  6936. Notification.list = {}
  6937. Notification.color = Color3.new(0, 0, 0)
  6938. TaskScheduler.Start(function()
  6939. Module.WaitForModule("Network")
  6940. Network.TransmitServer([[
  6941. local playerName = ...
  6942. local player = ServerControl.GetPlayer(playerName)
  6943. player:WaitForDataReady()
  6944. local colorData = player:LoadString("Notification.color")
  6945. if colorData ~= "" then
  6946. Network.Transmit("^" .. playerName .. "$", "Notification.color = ...", Serializer.DecodeColor3(player:LoadString("Notification.color"), 1))
  6947. end
  6948. ]], Player.Name)
  6949. end)
  6950. Notification.font = Enum.Font.ArialBold
  6951. Notification.fontSize = Enum.FontSize.Size14
  6952. Notification.maxSize = UDim2.new(0, 500, 0, 500)
  6953. Notification.offset = -135
  6954. Notification.padding = 24
  6955. Notification.showTime = 5
  6956. Notification.spacing = 5
  6957. Notification.stayFactor = 0.05
  6958. Notification.tweenTime = 0.3
  6959. function Notification.Animate()
  6960. local notifications = Notification.list
  6961. local notificationCount = #notifications
  6962. if notificationCount ~= 0 then
  6963. local sessionTime = tick()
  6964. local offset = Notification.offset
  6965. local padding = Notification.padding
  6966. local spacing = Notification.spacing
  6967. local tweenTime = Notification.tweenTime
  6968. local cameraPart = Notification.cameraPart
  6969. if cameraPart.Parent ~= Camera then
  6970. Notification.CreateCameraPart()
  6971. cameraPart = Notification.cameraPart
  6972. end
  6973. local billboardGui = Notification.billboardGui
  6974. if billboardGui.Parent ~= cameraPart then
  6975. Notification.CreateBillboardGui()
  6976. billboardGui = Notification.billboardGui
  6977. end
  6978. local rootFrame = Notification.rootFrame
  6979. if rootFrame.Parent ~= billboardGui then
  6980. Notification.CreateRootFrame()
  6981. rootFrame = Notification.rootFrame
  6982. end
  6983. -- cameraPart.CFrame = Camera.CoordinateFrame * CFrame.new(0, 0, -256)
  6984. -- billboardGui.Size = UDim2.new(0, Mouse.ViewSizeX, 0, Mouse.ViewSizeY)
  6985. local cameraCFrame = CFrame.new(Camera.CoordinateFrame.p, Camera.Focus.p) -- camera.CoordinateFrame
  6986. local viewSizeX, viewSizeY = Mouse.ViewSizeX, Mouse.ViewSizeY
  6987. local viewSizeUDim2 = UDim2.new(0, viewSizeX, 0, viewSizeY)
  6988. billboardGui.SizeOffset = Vector2.new()
  6989. if viewSizeX ~= 0 and viewSizeY ~= 0 then
  6990. billboardGui.Size = viewSizeUDim2
  6991. end
  6992. billboardGui.StudsOffset = (cameraCFrame - cameraCFrame.p):inverse() * cameraCFrame.p - Vector3.new(0, 0, 1)
  6993. rootFrame.Size = viewSizeUDim2
  6994. billboardGui.SizeOffset = Vector2.new(0.5 / viewSizeX, 0.5 / viewSizeY)
  6995. local notificationIndex = 1
  6996. while notificationIndex <= notificationCount do
  6997. local notification = notifications[notificationIndex]
  6998. local frame = notification[5]
  6999. if not frame or frame.Parent ~= rootFrame then
  7000. frame = Instance.new("Frame")
  7001. frame.BackgroundColor3 = Notification.color
  7002. frame.BorderSizePixel = 0
  7003. frame.ClipsDescendants = true
  7004. frame.Visible = false
  7005. frame.ZIndex = 10
  7006. notification[5] = frame
  7007. frame.Parent = rootFrame
  7008. end
  7009. local textLabel = notification[6]
  7010. if not textLabel or textLabel.Parent ~= frame then
  7011. textLabel = Instance.new("TextLabel")
  7012. textLabel.BackgroundTransparency = 1
  7013. textLabel.BorderSizePixel = 0
  7014. textLabel.Font = Notification.font
  7015. textLabel.FontSize = Notification.fontSize
  7016. textLabel.TextColor3 = Color3.new(1, 1, 1)
  7017. textLabel.TextWrapped = true
  7018. textLabel.ZIndex = 10
  7019. textLabel.Parent = frame
  7020. notification[6] = textLabel
  7021. end
  7022. frame.BackgroundColor3 = Notification.color
  7023. textLabel.Font = Notification.font
  7024. textLabel.FontSize = Notification.fontSize
  7025. local message, creationTime, textBounds, showTime = unpack(notification)
  7026. local previousNotification = notifications[notificationIndex + 1]
  7027. if not creationTime then
  7028. creationTime = sessionTime
  7029. textLabel.Size = Notification.maxSize
  7030. textLabel.Text = message
  7031. textBounds = textLabel.TextBounds
  7032. textLabel.Size = UDim2.new(0, textBounds.X, 0, textBounds.Y)
  7033. notification[2] = creationTime
  7034. notification[3] = textBounds
  7035. showTime = Notification.showTime + #message * Notification.stayFactor
  7036. if previousNotification then
  7037. local previousCreationTime = previousNotification[2]
  7038. local previousShowTime = previousNotification[4]
  7039. if previousCreationTime and previousShowTime then
  7040. local minimumShowTime = previousShowTime + previousCreationTime - creationTime
  7041. if minimumShowTime and minimumShowTime > showTime then
  7042. showTime = minimumShowTime
  7043. end
  7044. end
  7045. end
  7046. notification[4] = showTime
  7047. end
  7048. if notificationIndex == 1 then
  7049. offset = offset - (textBounds.Y + padding) * 0.5
  7050. end
  7051. local lifeTime = sessionTime - creationTime
  7052. local visible = true
  7053. if lifeTime < tweenTime then
  7054. local progress = 1 - math.cos(0.5 * math.pi * lifeTime / tweenTime)
  7055. local sizeX = (textBounds.X + padding) * progress
  7056. local sizeY = textBounds.Y + padding
  7057. frame.BackgroundTransparency = 0.3 + 0.7 * (1 - progress)
  7058. textLabel.TextTransparency = 1 - progress
  7059. frame.Position = UDim2.new(0.5, -0.5 * sizeX, 1, offset - 0.5 * sizeY)
  7060. textLabel.Position = UDim2.new(0, -0.5 * (textBounds.X - sizeX), 0, -0.5 * (textBounds.Y - sizeY))
  7061. frame.Size = UDim2.new(0, sizeX, 0, sizeY)
  7062. elseif lifeTime < showTime + tweenTime then
  7063. local sizeX = textBounds.X + padding
  7064. local sizeY = textBounds.Y + padding
  7065. frame.BackgroundTransparency = 0.3
  7066. textLabel.TextTransparency = 0
  7067. frame.Position = UDim2.new(0.5, -0.5 * sizeX, 1, offset - 0.5 * sizeY)
  7068. textLabel.Position = UDim2.new(0, -0.5 * (textBounds.X - sizeX), 0, -0.5 * (textBounds.Y - sizeY))
  7069. frame.Size = UDim2.new(0, sizeX, 0, sizeY)
  7070. elseif lifeTime < showTime + tweenTime * 2 then
  7071. local progress = 1 - math.cos(0.5 * math.pi * (lifeTime - showTime - tweenTime) / tweenTime)
  7072. local sizeX = textBounds.X + padding
  7073. local sizeY = (textBounds.Y + padding) * (1 - progress)
  7074. frame.BackgroundTransparency = 0.3 + 0.7 * progress
  7075. textLabel.TextTransparency = progress
  7076. frame.Position = UDim2.new(0.5, -0.5 * sizeX, 1, offset - 0.5 * sizeY)
  7077. textLabel.Position = UDim2.new(0, -0.5 * (textBounds.X - sizeX), 0, -0.5 * (textBounds.Y - sizeY))
  7078. frame.Size = UDim2.new(0, sizeX, 0, sizeY)
  7079. else
  7080. table.remove(notifications, notificationIndex)
  7081. notificationCount = notificationCount - 1
  7082. visible = false
  7083. end
  7084. frame.Visible = visible
  7085. if visible then
  7086. notificationIndex = notificationIndex + 1
  7087. if previousNotification then
  7088. local previousTextBounds = previousNotification[3]
  7089. if previousTextBounds then
  7090. offset = offset - previousTextBounds.Y * 0.5
  7091. end
  7092. offset = offset - (textBounds.Y * 0.5 + padding + spacing)
  7093. end
  7094. end
  7095. end
  7096. end
  7097. end
  7098. function Notification.CreateBillboardGui()
  7099. local billboardGui = Instance.new("BillboardGui")
  7100. billboardGui.Adornee = Notification.cameraPart
  7101. billboardGui.AlwaysOnTop = true
  7102. Notification.billboardGui = billboardGui
  7103. Notification.CreateRootFrame()
  7104. billboardGui.Parent = Notification.cameraPart
  7105. end
  7106. function Notification.CreateCameraPart()
  7107. local cameraPart = Instance.new("Part")
  7108. cameraPart.Anchored = true
  7109. cameraPart.BottomSurface = "Smooth"
  7110. cameraPart.CanCollide = false
  7111. cameraPart.FormFactor = "Custom"
  7112. cameraPart.Locked = true
  7113. cameraPart.Size = Vector3.new(0.2, 0.2, 0.2)
  7114. cameraPart.TopSurface = "Smooth"
  7115. cameraPart.Transparency = 1
  7116. Notification.cameraPart = cameraPart
  7117. Notification.CreateBillboardGui()
  7118. cameraPart.Parent = Camera
  7119. end
  7120. function Notification.CreateRootFrame()
  7121. local rootFrame = Instance.new("Frame")
  7122. rootFrame.BackgroundTransparency = 1
  7123. rootFrame.BorderSizePixel = 0
  7124. rootFrame.ZIndex = 10
  7125. Notification.rootFrame = rootFrame
  7126. rootFrame.Parent = Notification.billboardGui
  7127. end
  7128. function Notification.Show(message)
  7129. table.insert(Notification.list, 1, {message})
  7130. end
  7131.  
  7132. Notification.CreateCameraPart()
  7133.  
  7134. RunService.RenderStepped:connect(function()
  7135. Notification.Animate()
  7136. end)
  7137. Camera.Changed:connect(function()
  7138. Notification.Animate()
  7139. end)
  7140. ]=])
  7141. Module.Create("PyramidCharacter", [[
  7142. local stock_triangle = Instance.new("WedgePart")
  7143. stock_triangle.Anchored = true
  7144. stock_triangle.BottomSurface = "Smooth"
  7145. stock_triangle.FormFactor = "Custom"
  7146. stock_triangle.Locked = true
  7147. stock_triangle.TopSurface = "Smooth"
  7148. local stock_triangle_mesh = Instance.new("SpecialMesh", stock_triangle)
  7149. stock_triangle_mesh.MeshType = "Wedge"
  7150. local triangles = {}
  7151. function PyramidCharacter.CreateTriangle(v1, v2, v3, properties, parent, index)
  7152. local triangleInfo = triangles[index]
  7153. local side1 = (v1 - v2).magnitude
  7154. local side2 = (v2 - v3).magnitude
  7155. local side3 = (v3 - v1).magnitude
  7156. local sqrside1 = side1 * side1
  7157. local sqrside2 = side2 * side2
  7158. local sqrside3 = side3 * side3
  7159. if sqrside3 + sqrside1 == sqrside2 then
  7160. v1, v2, v3 = v1, v2, v3
  7161. elseif sqrside1 + sqrside2 == sqrside3 then
  7162. v1, v2, v3 = v2, v3, v1
  7163. elseif sqrside2 + sqrside3 == sqrside1 then
  7164. v1, v2, v3 = v3, v1, v2
  7165. elseif sqrside1 >= sqrside2 and sqrside1 >= sqrside3 then
  7166. v1, v2, v3 = v1, v2, v3
  7167. elseif sqrside2 >= sqrside3 and sqrside2 >= sqrside1 then
  7168. v1, v2, v3 = v2, v3, v1
  7169. else
  7170. v1, v2, v3 = v3, v1, v2
  7171. end
  7172. local model, part1, part2, mesh1, mesh2
  7173. if triangleInfo then
  7174. model, part1, part2, mesh1, mesh2 = unpack(triangleInfo)
  7175. if not (model.Parent == parent and part1.Parent == model and part2.Parent == model and mesh1.Parent == part1 and mesh2.Parent == part2) then
  7176. if model.Parent then
  7177. model:Destroy()
  7178. end
  7179. model = nil
  7180. end
  7181. else
  7182. triangleInfo = {}
  7183. triangles[index] = triangleInfo
  7184. end
  7185. if not model then
  7186. model = Instance.new("Model")
  7187. part1 = stock_triangle:Clone()
  7188. part2 = stock_triangle:Clone()
  7189. mesh1 = part1.Mesh
  7190. mesh2 = part2.Mesh
  7191. part1.Parent = model
  7192. part2.Parent = model
  7193. triangleInfo[1] = model
  7194. triangleInfo[2] = part1
  7195. triangleInfo[3] = part2
  7196. triangleInfo[4] = mesh1
  7197. triangleInfo[5] = mesh2
  7198. end
  7199. for key, value in pairs(properties) do
  7200. part1[key] = value
  7201. part2[key] = value
  7202. end
  7203. local cframe = CFrame.new(v1, v2)
  7204. local relpos = cframe:pointToObjectSpace(v3)
  7205. cframe = cframe * CFrame.fromEulerAnglesXYZ(0, 0, -math.atan2(relpos.x, relpos.y))
  7206. local rel1 = cframe:pointToObjectSpace(v1)
  7207. local rel2 = cframe:pointToObjectSpace(v2)
  7208. local rel3 = cframe:pointToObjectSpace(v3)
  7209. local height = rel3.y
  7210. local width1 = rel3.z
  7211. local width2 = rel2.z - rel3.z
  7212. local relcenter1 = Vector3.new(0, height / 2, width1 / 2)
  7213. local center1 = cframe:pointToWorldSpace(relcenter1)
  7214. local relcenter2 = Vector3.new(0, height / 2, width2 / 2 + width1)
  7215. local center2 = cframe:pointToWorldSpace(relcenter2)
  7216. height = math.abs(height)
  7217. width1 = math.abs(width1)
  7218. width2 = math.abs(width2)
  7219. if not part1.Anchored then
  7220. part1.Anchored = true
  7221. end
  7222. part1.Size = Vector3.new(0.2, height, width1)
  7223. part1.CFrame = cframe * CFrame.fromEulerAnglesXYZ(0, math.pi, 0) - cframe.p + center1
  7224. mesh1.Scale = Vector3.new(0, height / part1.Size.y, width1 / part1.Size.z)
  7225. if not part2.Anchored then
  7226. part2.Anchored = true
  7227. end
  7228. part2.Size = Vector3.new(0.2, height, width1)
  7229. part2.CFrame = cframe - cframe.p + center2
  7230. mesh2.Scale = Vector3.new(0, height / part1.Size.y, width2 / part2.Size.z)
  7231. model.Parent = parent
  7232. return model
  7233. end
  7234. PyramidCharacter.head_properties = {BrickColor = BrickColor.new(Color3.new(1, 1, 1)), Transparency = 0.5}
  7235. PyramidCharacter.head_radius = math.pi
  7236. PyramidCharacter.center = CFrame.new(0, 10, 0)
  7237. PyramidCharacter.point1 = Vector3.new()
  7238. PyramidCharacter.point2 = Vector3.new()
  7239. PyramidCharacter.point3 = Vector3.new()
  7240. PyramidCharacter.point4 = Vector3.new()
  7241. PyramidCharacter.core_mesh_scale = Vector3.new(0.833, 0.833, 0.833)
  7242. PyramidCharacter.visible = false
  7243. function PyramidCharacter.Teleport(location)
  7244. PyramidCharacter.point1 = location
  7245. PyramidCharacter.point2 = location
  7246. PyramidCharacter.point3 = location
  7247. PyramidCharacter.point4 = location
  7248. end
  7249. local stock_core = Instance.new("Part")
  7250. stock_core.Anchored = true
  7251. stock_core.BottomSurface = "Smooth"
  7252. stock_core.Color = Color3.new(1, 1, 1)
  7253. stock_core.FormFactor = "Custom"
  7254. stock_core.Locked = true
  7255. stock_core.Name = "CubePyramid"
  7256. stock_core.Size = Vector3.new(0.5, 0.5, 0.5)
  7257. stock_core.TopSurface = "Smooth"
  7258. PyramidCharacter.stock_core = stock_core
  7259. PyramidCharacter.core = stock_core:Clone()
  7260. PyramidCharacter.Archivable = false
  7261. PyramidCharacter.core_mesh = Instance.new("BlockMesh", core)
  7262. PyramidCharacter.core_lights = {}
  7263. PyramidCharacter.coreLightCount = 1
  7264. for index = 1, PyramidCharacter.coreLightCount do
  7265. PyramidCharacter.core_lights[index] = Instance.new("PointLight", core)
  7266. end
  7267. PyramidCharacter.camera_distance = (Camera.Focus.p - Camera.CoordinateFrame.p).magnitude
  7268. PyramidCharacter.camera_position = Vector3.new()
  7269. Camera.Changed:connect(function(property)
  7270. if PyramidCharacter.visible then
  7271. if property == "CoordinateFrame" then
  7272. local cframe, focus = Camera.CoordinateFrame, Camera.Focus
  7273. local eventTime = time()
  7274. local connection
  7275. connection = Camera.Changed:connect(function()
  7276. connection:disconnect()
  7277. if eventTime == time() and Camera.Focus ~= focus then
  7278. local camera_distance = PyramidCharacter.camera_distance
  7279. Camera.Focus = Camera.CoordinateFrame * CFrame.new(0, 0, -camera_distance)
  7280. PyramidCharacter.camera_position = (Camera.CoordinateFrame * CFrame.new(0, 0, -camera_distance)).p
  7281. end
  7282. end)
  7283. coroutine.yield()
  7284. if Camera.Focus == focus then
  7285. PyramidCharacter.camera_distance = (focus.p - cframe.p).magnitude
  7286. else
  7287. local camera_distance = PyramidCharacter.camera_distance
  7288. Camera.Focus = Camera.CoordinateFrame * CFrame.new(0, 0, -camera_distance)
  7289. PyramidCharacter.camera_position = (Camera.CoordinateFrame * CFrame.new(0, 0, -camera_distance)).p
  7290. end
  7291. if connection.connected then
  7292. connection:disconnect()
  7293. end
  7294. end
  7295. end
  7296. end)
  7297. function PyramidCharacter.Animate()
  7298. local total_time = time()
  7299. local core = PyramidCharacter.core
  7300. local frame = PyramidCharacter.frame
  7301. if PyramidCharacter.visible then
  7302. local core_mesh = PyramidCharacter.core_mesh
  7303. local core_lights = PyramidCharacter.core_lights
  7304. if not frame or frame.Parent ~= core then
  7305. frame = Instance.new("Model")
  7306. frame.Archivable = false
  7307. frame.Parent = core
  7308. PyramidCharacter.frame = frame
  7309. end
  7310. if core.Parent ~= Workspace then
  7311. core = PyramidCharacter.stock_core:Clone()
  7312. PyramidCharacter.core = core
  7313. core.Archivable = false
  7314. core.Parent = Workspace
  7315. Network.TransmitServer("chatAdornee = ...", core)
  7316. end
  7317. if core_mesh.Parent ~= core then
  7318. core_mesh = Instance.new("BlockMesh", core)
  7319. PyramidCharacter.core_mesh = core_mesh
  7320. end
  7321. for index, core_light in ipairs(core_lights) do
  7322. if core_light.Parent ~= core then
  7323. core_light = Instance.new("PointLight", core)
  7324. core_lights[index] = core_light
  7325. end
  7326. local vertexColor = Vector3.new(Utility.GetRainbowRGB(total_time)) * 0.25 + Vector3.new(1, 1, 1) * 0.75
  7327. core_light.Color = Color3.new(vertexColor.X, vertexColor.Y, vertexColor.Z)
  7328. core_light.Brightness = 0.85 + 0.15 * math.random()
  7329. if core_light.Range ~= 30 then
  7330. core_light.Range = 30
  7331. end
  7332. if not core_light.Shadows then
  7333. core_light.Shadows = true
  7334. end
  7335. end
  7336. if core_mesh.Offset ~= Vector3.new(0, 0, 0) then
  7337. core_mesh.Offset = Vector3.new(0, 0, 0)
  7338. end
  7339. if not core.Anchored then
  7340. core.Anchored = true
  7341. end
  7342. if core.Transparency ~= 0 then
  7343. core.Transparency = 0
  7344. end
  7345. local core_mesh_scale = PyramidCharacter.core_mesh_scale
  7346. local transition_speed = (math.sin(total_time * math.tau) + 1) / 16
  7347. core_mesh_scale = core_mesh_scale * (1 - transition_speed) + Vector3.new(math.random() * 0.5 + 0.5, math.random() * 0.5 + 0.5, math.random()
  7348.  
  7349. * 0.5 + 0.5) * transition_speed
  7350. core_mesh.Scale = core_mesh_scale * 2
  7351. local center = CFrame.new(PyramidCharacter.camera_position) * CFrame.Angles(0, total_time * math.tau, 0)
  7352. local cframe1 = CFrame.new(PyramidCharacter.head_radius, 0, 0)
  7353. local cframe2 = CFrame.Angles(math.tau / -3, 0, 0)
  7354. local cframe3 = CFrame.Angles(0, math.tau / 3, 0)
  7355. local cframe4 = center * cframe3
  7356. local desired1 = center * CFrame.new(0, PyramidCharacter.head_radius, 0)
  7357. local desired2 = center * cframe2 * cframe1
  7358. local desired3 = cframe4 * cframe2 * cframe1
  7359. local desired4 = cframe4 * cframe3 * cframe2 * cframe1
  7360. local point1 = (PyramidCharacter.point1 * 3 + desired1.p) / 4
  7361. local point2 = (PyramidCharacter.point2 * 3 + desired2.p) / 4
  7362. local point3 = (PyramidCharacter.point3 * 3 + desired3.p) / 4
  7363. local point4 = (PyramidCharacter.point4 * 3 + desired4.p) / 4
  7364. PyramidCharacter.point1 = point1
  7365. PyramidCharacter.point2 = point2
  7366. PyramidCharacter.point3 = point3
  7367. PyramidCharacter.point4 = point4
  7368. local head_properties = PyramidCharacter.head_properties
  7369. PyramidCharacter.CreateTriangle(point1, point2, point3, head_properties, frame, 1).Archivable = false
  7370. PyramidCharacter.CreateTriangle(point2, point3, point4, head_properties, frame, 2).Archivable = false
  7371. PyramidCharacter.CreateTriangle(point3, point4, point1, head_properties, frame, 3).Archivable = false
  7372. PyramidCharacter.CreateTriangle(point4, point1, point2, head_properties, frame, 4).Archivable = false
  7373. core.CFrame = CFrame.new((point1 + point2 + point3 + point4) / 4) * CFrame.Angles(total_time * math.tau, total_time * math.tau / 2,
  7374.  
  7375. total_time * math.tau / 3)
  7376. PyramidCharacter.center = center
  7377. else
  7378. if core.Parent then
  7379. core:Destroy()
  7380. end
  7381. if frame and frame.Parent then
  7382. frame:Destroy()
  7383. end
  7384. PyramidCharacter.frame = nil
  7385. end
  7386. end
  7387. function PyramidCharacter.MainLoop()
  7388. PyramidCharacter.Animate()
  7389. RunService.Stepped:wait()
  7390. end
  7391. TaskScheduler.Start(function()
  7392. while true do
  7393. PyramidCharacter.MainLoop()
  7394. end
  7395. end)
  7396. ]])
  7397. Module.Create("CharacterAppearance", [[
  7398. CharacterAppearance.defaultAppearanceId = 3
  7399. CharacterAppearance.stock = {}
  7400. function CharacterAppearance.Create(properties)
  7401. local id = properties.Id
  7402. local bodyColors = Instance.new("BodyColors")
  7403. bodyColors.HeadColor = properties.HeadColor
  7404. bodyColors.TorsoColor = properties.TorsoColor
  7405. bodyColors.RightArmColor = properties.RightArmColor
  7406. bodyColors.LeftArmColor = properties.LeftArmColor
  7407. bodyColors.RightLegColor = properties.RightLegColor
  7408. bodyColors.LeftLegColor = properties.LeftLegColor
  7409. local characterObjects = {bodyColors}
  7410. local headObjects = {}
  7411. local data = {
  7412. characterObjects = characterObjects,
  7413. headObjects = headObjects,
  7414. tshirt = properties.TShirt
  7415. }
  7416. for _, assetId in ipairs(properties.CharacterAssets) do
  7417. TaskScheduler.Start(CharacterAppearance.LoadAsset, characterObjects, assetId)
  7418. end
  7419. for _, assetId in ipairs(properties.HeadAssets) do
  7420. TaskScheduler.Start(CharacterAppearance.LoadAsset, headObjects, assetId)
  7421. end
  7422. CharacterAppearance.stock[id] = data
  7423. end
  7424. function CharacterAppearance.GetDefaultAppearance()
  7425. return CharacterAppearance.stock[CharacterAppearance.defaultAppearanceId]
  7426. end
  7427. function CharacterAppearance.LoadAsset(objects, assetId)
  7428. local asset = InsertService:LoadAsset(assetId)
  7429. for _, child in ipairs(asset:GetChildren()) do
  7430. child.Archivable = true
  7431. table.insert(objects, child:Clone())
  7432. end
  7433. end
  7434. CharacterAppearance.Create {
  7435. Id = 1,
  7436. HeadColor = BrickColor.new("Institutional white"),
  7437. TorsoColor = BrickColor.new("Institutional white"),
  7438. RightArmColor = BrickColor.new("Institutional white"),
  7439. LeftArmColor = BrickColor.new("Institutional white"),
  7440. RightLegColor = BrickColor.new("Institutional white"),
  7441. LeftLegColor = BrickColor.new("Institutional white"),
  7442. CharacterAssets = {
  7443. 90825058, 90825211,
  7444. 27112056, 27112052,
  7445. 27112039, 27112025,
  7446. 27112068, 38322996
  7447. },
  7448. HeadAssets = {
  7449. 20722130,
  7450. 8330576
  7451. }
  7452. }
  7453. CharacterAppearance.Create {
  7454. Id = 2,
  7455. HeadColor = BrickColor.new("Institutional white"),
  7456. TorsoColor = BrickColor.new("Institutional white"),
  7457. RightArmColor = BrickColor.new("Institutional white"),
  7458. LeftArmColor = BrickColor.new("Institutional white"),
  7459. RightLegColor = BrickColor.new("Institutional white"),
  7460. LeftLegColor = BrickColor.new("Institutional white"),
  7461. CharacterAssets = {
  7462. 90825058, 90825211,
  7463. 11748356, 1029025,
  7464. 1235488, 27112056,
  7465. 27112052, 27112039,
  7466. 27112025, 27112068
  7467. },
  7468. HeadAssets = {
  7469. 20722130
  7470. }
  7471. }
  7472. CharacterAppearance.Create {
  7473. Id = 3,
  7474. HeadColor = BrickColor.new("Pastel brown"),
  7475. TorsoColor = BrickColor.new("Pastel brown"),
  7476. RightArmColor = BrickColor.new("Pastel brown"),
  7477. LeftArmColor = BrickColor.new("Pastel brown"),
  7478. RightLegColor = BrickColor.new("White"),
  7479. LeftLegColor = BrickColor.new("White"),
  7480. CharacterAssets = {
  7481. 134289125, 48474356,
  7482. 100339040, 46302558,
  7483. 153955895
  7484. },
  7485. HeadAssets = {},
  7486. TShirt = "rbxassetid://148856353"
  7487. }
  7488. ]])
  7489. Module.Create("PlayerControl", [[
  7490. PlayerControl.fly_acceleration = 10
  7491. PlayerControl.fly_basespeed = 250
  7492. PlayerControl.fly_speed = PlayerControl.fly_basespeed
  7493. PlayerControl.featherfallEnabled = true
  7494. PlayerControl.pushable = false
  7495. PlayerControl.rolling = false
  7496. PlayerControl.rollingAngle = 0
  7497. PlayerControl.rollingOffset = 0
  7498. PlayerControl.rollingMaxOffset = 3
  7499. PlayerControl.rollingSpeed = 1 / 50
  7500. PlayerControl.characterEnabled = false
  7501. PlayerControl.characterMode = "normal"
  7502. local character = nil
  7503. local flying, flyingMomentum, flyingTilt = false, Vector3.new(), 0
  7504. local pose, regeneratingHealth, jumpDebounce = "Standing", false, false
  7505. -- TODO: make local variables public
  7506. local model, bodyColors, leftArmMesh, leftLegMesh, rightArmMesh, rightLegMesh, torsoMesh, wildcardHat, wildcardHandle, wildcardMesh, pants, shirt, humanoid,
  7507.  
  7508. head, leftArm, leftLeg, rightArm, rightLeg, torso, rootPart, rootJoint, face, soundFreeFalling, soundGettingUp, soundRunning, leftHip, leftShoulder,
  7509.  
  7510. rightHip, rightShoulder, neck, wildcardWeld, feetPart, feetWeld, feetTouchInterest, bodyGyro, bodyVelocity, headMesh, torsoLight
  7511. local AnimateCharacter
  7512. local chatBubbles = {}
  7513. local chatCharacterLimit = 240
  7514. function PlayerControl.Chat(message)
  7515. Network.TransmitServer(string.format("ChatBubble.Create(%q)", tostring(message)))
  7516. end
  7517. function PlayerControl.CreateCharacter()
  7518. local characterMode = PlayerControl.characterMode
  7519. if characterMode == "normal" then
  7520. if not PlayerControl.characterEnabled then
  7521. return
  7522. end
  7523. local appearance = CharacterAppearance.GetDefaultAppearance()
  7524. local active = true
  7525. local torsoCFrame = (torso and torso.CFrame) or PlayerControl.torso_cframe or CFrame.new(0, 10, 0)
  7526. if torsoCFrame.p.Y < -450 then
  7527. torsoCFrame = CFrame.new(0, 10, 0)
  7528. end
  7529. local rootPartCFrame = (rootPart and rootPart.CFrame) or PlayerControl.torso_cframe or CFrame.new(0, 10, 0)
  7530. if rootPartCFrame.p.Y < -450 then
  7531. rootPartCFrame = CFrame.new(0, 10, 0)
  7532. end
  7533. local cameraCFrame = Camera.CoordinateFrame
  7534. local connections = {}
  7535. local feetTouching = {}
  7536. local previousWalkSpeed = 0
  7537. local prevLeftHip, prevLeftShoulder, prevRightHip, prevRightShoulder = leftHip, leftShoulder, rightHip, rightShoulder
  7538. model = Instance.new("Model")
  7539. humanoid = Instance.new("Humanoid", model)
  7540. head = Instance.new("Part", model)
  7541. leftArm = Instance.new("Part", model)
  7542. leftLeg = Instance.new("Part", model)
  7543. rightArm = Instance.new("Part", model)
  7544. rightLeg = Instance.new("Part", model)
  7545. torso = Instance.new("Part", model)
  7546. rootPart = Instance.new("Part", model)
  7547. soundFallingDown = Instance.new("Sound", head)
  7548. soundFreeFalling = Instance.new("Sound", head)
  7549. soundGettingUp = Instance.new("Sound", head)
  7550. soundJumping = Instance.new("Sound", head)
  7551. soundRunning = Instance.new("Sound", head)
  7552. leftHip = Instance.new("Motor", torso)
  7553. leftShoulder = Instance.new("Motor", torso)
  7554. rightHip = Instance.new("Motor", torso)
  7555. rightShoulder = Instance.new("Motor", torso)
  7556. neck = Instance.new("Motor", torso)
  7557. rootJoint = Instance.new("Motor", rootPart)
  7558. feetPart = Instance.new("Part", model)
  7559. feetWeld = Instance.new("Weld", torso)
  7560. bodyGyro = Instance.new("BodyGyro", rootPart)
  7561. bodyVelocity = Instance.new("BodyVelocity", rootPart)
  7562. model.Archivable = false
  7563. model.Name = UserInterface.player_name
  7564. model.PrimaryPart = head
  7565. humanoid.LeftLeg = leftLeg
  7566. humanoid.RightLeg = rightLeg
  7567. humanoid.Torso = rootPart
  7568. head.CFrame = torsoCFrame * CFrame.new(0, 1.5, 0)
  7569. head.FormFactor = "Symmetric"
  7570. head.Locked = true
  7571. head.Name = "Head"
  7572. head.Size = Vector3.new(2, 1, 1)
  7573. head.TopSurface = "Smooth"
  7574. leftArm.CanCollide = false
  7575. leftArm.CFrame = torsoCFrame * CFrame.new(-1.5, 0, 0)
  7576. leftArm.FormFactor = "Symmetric"
  7577. leftArm.Locked = true
  7578. leftArm.Name = "Left Arm"
  7579. leftArm.Size = Vector3.new(1, 2, 1)
  7580. leftLeg.BottomSurface = "Smooth"
  7581. leftLeg.CanCollide = false
  7582. leftLeg.CFrame = torsoCFrame * CFrame.new(-0.5, -2, 0)
  7583. leftLeg.FormFactor = "Symmetric"
  7584. leftLeg.Locked = true
  7585. leftLeg.Name = "Left Leg"
  7586. leftLeg.Size = Vector3.new(1, 2, 1)
  7587. leftLeg.TopSurface = "Smooth"
  7588. rightArm.CanCollide = false
  7589. rightArm.CFrame = torsoCFrame * CFrame.new(1.5, 0, 0)
  7590. rightArm.FormFactor = "Symmetric"
  7591. rightArm.Locked = true
  7592. rightArm.Name = "Right Arm"
  7593. rightArm.Size = Vector3.new(1, 2, 1)
  7594. rightLeg.BottomSurface = "Smooth"
  7595. rightLeg.CanCollide = false
  7596. rightLeg.CFrame = torsoCFrame * CFrame.new(0.5, -2, 0)
  7597. rightLeg.FormFactor = "Symmetric"
  7598. rightLeg.Locked = true
  7599. rightLeg.Name = "Right Leg"
  7600. rightLeg.Size = Vector3.new(1, 2, 1)
  7601. rightLeg.TopSurface = "Smooth"
  7602. torso.CFrame = torsoCFrame
  7603. torso.FormFactor = "Symmetric"
  7604. torso.LeftSurface = "Weld"
  7605. torso.Locked = true
  7606. torso.RightSurface = "Weld"
  7607. torso.Name = "Torso"
  7608. torso.Size = Vector3.new(2, 2, 1)
  7609. rootPart.BottomSurface = "Smooth"
  7610. rootPart.BrickColor = BrickColor.Blue()
  7611. rootPart.CFrame = rootPartCFrame
  7612. rootPart.FormFactor = "Symmetric"
  7613. rootPart.LeftSurface = "Weld"
  7614. rootPart.Locked = true
  7615. rootPart.RightSurface = "Weld"
  7616. rootPart.Name = "HumanoidRootPart"
  7617. rootPart.Size = Vector3.new(2, 2, 1)
  7618. rootPart.TopSurface = "Smooth"
  7619. rootPart.Transparency = 1
  7620. soundFreeFalling.Archivable = false
  7621. soundFreeFalling.SoundId = "rbxasset://sounds/swoosh.wav"
  7622. soundGettingUp.Archivable = false
  7623. soundGettingUp.SoundId = "rbxasset://sounds/hit.wav"
  7624. soundRunning.Archivable = false
  7625. soundRunning.SoundId = "rbxasset://sounds/bfsl-minifigfoots1.mp3"
  7626. soundRunning.Looped = true
  7627. leftHip.C0 = CFrame.new(-1, -1, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
  7628. leftHip.C1 = CFrame.new(-0.5, 1, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
  7629. leftHip.MaxVelocity = 0.1
  7630. leftHip.Name = "Left Hip"
  7631. leftHip.Part0 = torso
  7632. leftHip.Part1 = leftLeg
  7633. leftShoulder.C0 = CFrame.new(-1, 0.5, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
  7634. leftShoulder.C1 = CFrame.new(0.5, 0.5, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
  7635. leftShoulder.MaxVelocity = 0.15
  7636. leftShoulder.Name = "Left Shoulder"
  7637. leftShoulder.Part0 = torso
  7638. leftShoulder.Part1 = leftArm
  7639. rightHip.C0 = CFrame.new(1, -1, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
  7640. rightHip.C1 = CFrame.new(0.5, 1, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
  7641. rightHip.MaxVelocity = 0.1
  7642. rightHip.Name = "Right Hip"
  7643. rightHip.Part0 = torso
  7644. rightHip.Part1 = rightLeg
  7645. rightShoulder.C0 = CFrame.new(1, 0.5, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
  7646. rightShoulder.C1 = CFrame.new(-0.5, 0.5, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
  7647. rightShoulder.MaxVelocity = 0.15
  7648. rightShoulder.Name = "Right Shoulder"
  7649. rightShoulder.Part0 = torso
  7650. rightShoulder.Part1 = rightArm
  7651. if prevLeftHip then
  7652. leftHip.CurrentAngle = prevLeftHip.CurrentAngle
  7653. leftHip.DesiredAngle = prevLeftHip.DesiredAngle
  7654. end
  7655. if prevLeftShoulder then
  7656. leftShoulder.CurrentAngle = prevLeftShoulder.CurrentAngle
  7657. leftShoulder.DesiredAngle = prevLeftShoulder.DesiredAngle
  7658. end
  7659. if prevRightHip then
  7660. rightHip.CurrentAngle = prevRightHip.CurrentAngle
  7661. rightHip.DesiredAngle = prevRightHip.DesiredAngle
  7662. end
  7663. if prevRightShoulder then
  7664. rightShoulder.CurrentAngle = prevRightShoulder.CurrentAngle
  7665. rightShoulder.DesiredAngle = prevRightShoulder.DesiredAngle
  7666. end
  7667. neck.C0 = CFrame.new(0, 1, 0, -1, -0, -0, 0, 0, 1, 0, 1, 0)
  7668. neck.C1 = CFrame.new(0, -0.5, 0, -1, -0, -0, 0, 0, 1, 0, 1, 0)
  7669. neck.Name = "Neck"
  7670. neck.Part0 = torso
  7671. neck.Part1 = head
  7672. rootJoint.C0 = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0)
  7673. rootJoint.C1 = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0)
  7674. rootJoint.Name = "RootJoint"
  7675. rootJoint.Part0 = rootPart
  7676. rootJoint.Part1 = torso
  7677. feetPart.BottomSurface = "Smooth"
  7678. feetPart.CanCollide = false
  7679. feetPart.CFrame = torsoCFrame * CFrame.new(0, -3.1, 0)
  7680. feetPart.FormFactor = "Custom"
  7681. feetPart.Locked = true
  7682. feetPart.Name = "Platform"
  7683. feetPart.Size = Vector3.new(1.8, 0.2, 0.8)
  7684. feetPart.TopSurface = "Smooth"
  7685. feetPart.Transparency = 1
  7686. feetWeld.C0 = CFrame.new(0, -3, 0)
  7687. feetWeld.C1 = CFrame.new(0, 0.1, 0)
  7688. feetWeld.Name = "PlatformWeld"
  7689. feetWeld.Part0 = torso
  7690. feetWeld.Part1 = feetPart
  7691. table.insert(connections, feetPart.Touched:connect(function(hit)
  7692. feetTouching[hit] = true
  7693. end))
  7694. table.insert(connections, feetPart.TouchEnded:connect(function(hit)
  7695. feetTouching[hit] = nil
  7696. end))
  7697. feetTouchInterest = feetPart:FindFirstChild("TouchInterest")
  7698. bodyGyro.D = 3250
  7699. bodyGyro.P = 400000
  7700. bodyGyro.maxTorque = Vector3.new(1000000000, 0, 1000000000)
  7701. bodyVelocity.P = 5000
  7702. bodyVelocity.maxForce = Vector3.new(0, 0, 0)
  7703. bodyVelocity.velocity = Vector3.new(0, 0, 0)
  7704. torsoLight = Instance.new("PointLight", torso)
  7705. torsoLight.Brightness = 0.4
  7706. torsoLight.Color = Color3.new(1, 1, 1)
  7707. torsoLight.Range = 16
  7708. torsoLight.Shadows = true
  7709. local ff1, ff2, ff3, ff4, ff5, ff6, ff7, ff8, ff9 = Instance.new("ForceField", head), Instance.new("ForceField", leftArm), Instance.new
  7710.  
  7711. ("ForceField", leftLeg), Instance.new("ForceField", rightArm), Instance.new("ForceField", rightLeg), Instance.new("ForceField", torso), Instance.new
  7712.  
  7713. ("ForceField", wildcardHandle), Instance.new("ForceField", feetPart), Instance.new("ForceField", rootPart)
  7714. local forcefields = {[ff1] = head, [ff2] = leftArm, [ff3] = leftLeg, [ff4] = rightArm, [ff5] = rightLeg, [ff6] = torso, [ff7] =
  7715.  
  7716. wildcardHandle, [ff8] = feetPart, [ff9] = rootPart}
  7717. local objects = {[humanoid] = true, [head] = true, [leftArm] = true, [leftLeg] = true, [rightArm] = true, [rightLeg] = true, [torso] = true,
  7718.  
  7719. [rootPart] = true, [rootJoint] = true, [soundFreeFalling] = true, [soundGettingUp] = true, [soundRunning] = true, [leftHip] = true, [leftShoulder] = true,
  7720.  
  7721. [rightHip] = true, [rightShoulder] = true, [neck] = true, [feetPart] = true, [feetWeld] = true, [feetTouchInterest] = true, [bodyGyro] = true,
  7722.  
  7723. [bodyVelocity] = true, [ff1] = true, [ff2] = true, [ff3] = true, [ff4] = true, [ff5] = true, [ff6] = true, [ff7] = true, [ff8] = true, [ff9] = true}
  7724. local tshirtUrl = appearance.tshirt
  7725. if tshirtUrl then
  7726. local tshirt = Instance.new("Decal", torso)
  7727. tshirt.Name = "roblox"
  7728. tshirt.Texture = tshirtUrl
  7729. objects[tshirt] = true
  7730. end
  7731. for _, template in ipairs(appearance.characterObjects) do
  7732. local object = template:Clone()
  7733. local newObjects = {object}
  7734. for _, object in ipairs(newObjects) do
  7735. objects[object] = true
  7736. for _, child in ipairs(object:GetChildren()) do
  7737. table.insert(newObjects, child)
  7738. end
  7739. end
  7740. if object:IsA("BodyColors") then
  7741. head.BrickColor = object.HeadColor
  7742. leftArm.BrickColor = object.LeftArmColor
  7743. leftLeg.BrickColor = object.LeftLegColor
  7744. rightArm.BrickColor = object.RightArmColor
  7745. rightLeg.BrickColor = object.RightLegColor
  7746. torso.BrickColor = object.TorsoColor
  7747. elseif object:IsA("Hat") then
  7748. local handle = object:FindFirstChild("Handle")
  7749. if handle and handle:IsA("BasePart") then
  7750. local weld = Instance.new("Weld", head)
  7751. weld.C0 = CFrame.new(0, 0.5, 0)
  7752. local attachmentPos = object.AttachmentPos
  7753. local attachmentRight = object.AttachmentRight
  7754. local attachmentUp = object.AttachmentUp
  7755. local attachmentForward = object.AttachmentForward
  7756. weld.C1 = CFrame.new(attachmentPos.X, attachmentPos.Y, attachmentPos.Z,
  7757. attachmentRight.X, attachmentUp.X, -attachmentForward.X,
  7758. attachmentRight.Y, attachmentUp.Y, -attachmentForward.Y,
  7759. attachmentRight.Z, attachmentUp.Z, -attachmentForward.Z)
  7760. weld.Name = "HeadWeld"
  7761. weld.Part0 = head
  7762. weld.Part1 = handle
  7763. handle.Parent = model
  7764. local antiGravity = Instance.new("BodyForce", handle)
  7765. antiGravity.force = Vector3.new(0, handle:GetMass() * 196.2, 0)
  7766. objects[object] = false
  7767. object.Parent = nil
  7768. objects[weld] = true
  7769. end
  7770. end
  7771. object.Parent = model
  7772. end
  7773. local facePresent = false
  7774. local headMeshPresent = false
  7775. for _, template in ipairs(appearance.headObjects) do
  7776. local object = template:Clone()
  7777. local newObjects = {object}
  7778. for _, object in ipairs(newObjects) do
  7779. objects[object] = true
  7780. for _, child in ipairs(object:GetChildren()) do
  7781. table.insert(newObjects, child)
  7782. end
  7783. end
  7784. if object:IsA("DataModelMesh") then
  7785. headMeshPresent = true
  7786. elseif object:IsA("Decal") then
  7787. facePresent = true
  7788. end
  7789. object.Parent = head
  7790. end
  7791. if not facePresent then
  7792. local face = Instance.new("Decal", head)
  7793. face.Texture = "rbxasset://textures/face.png"
  7794. objects[face] = true
  7795. end
  7796. if not headMeshPresent then
  7797. local headMesh = Instance.new("SpecialMesh", head)
  7798. headMesh.Scale = Vector3.new(1.25, 1.25, 1.25)
  7799. objects[headMesh] = true
  7800. end
  7801. table.insert(connections, model.DescendantAdded:connect(function(object)
  7802. local success, is_localscript = pcall(Game.IsA, object, "LocalScript")
  7803. if success and is_localscript then
  7804. pcall(Utility.SetProperty, object, "Disabled", true)
  7805. local changed_connection = pcall(object.Changed.connect, object.Changed, function(property)
  7806. if property == "Disabled" and not object.Disabled then
  7807. pcall(Utility.SetProperty, object, "Disabled", true)
  7808. Network.TransmitServer("(...):Destroy()", object)
  7809. end
  7810. end)
  7811. end
  7812. if not objects[object] then
  7813. Network.TransmitServer("(...):Destroy()", object)
  7814. end
  7815. end))
  7816. model.Parent = Workspace
  7817. Player.Character = model
  7818. Camera.CameraSubject = humanoid
  7819. Camera.CameraType = "Track"
  7820. Camera.CoordinateFrame = cameraCFrame
  7821. local IsStanding
  7822. local RegenerateHealth
  7823. local ResetCharacter
  7824. function IsStanding()
  7825. return not not next(feetTouching)
  7826. end
  7827. function RegenerateHealth()
  7828. if humanoid.Health < 1 then
  7829. humanoid.Health = 100
  7830. elseif not regeneratingHealth then
  7831. regeneratingHealth = true
  7832. local elapsedTime = wait(1)
  7833. regeneratingHealth = false
  7834. if humanoid.Health < 100 then
  7835. humanoid.Health = math.min(humanoid.Health + elapsedTime, 100)
  7836. end
  7837. end
  7838. end
  7839. function ResetCharacter()
  7840. for index, connection in ipairs(connections) do
  7841. connection:disconnect()
  7842. end
  7843. active = false
  7844. end
  7845. table.insert(connections, model.AncestryChanged:connect(ResetCharacter))
  7846. table.insert(connections, model.DescendantRemoving:connect(function(object)
  7847. local parent = forcefields[object]
  7848. if parent then
  7849. forcefields[object] = nil
  7850. local new_forcefield = Instance.new("ForceField")
  7851. forcefields[new_forcefield] = parent
  7852. objects[new_forcefield] = true
  7853. new_forcefield.Parent = parent
  7854. elseif objects[object] then
  7855. ResetCharacter()
  7856. end
  7857. end))
  7858. table.insert(connections, humanoid.HealthChanged:connect(RegenerateHealth))
  7859. table.insert(connections, humanoid.Climbing:connect(function() pose = "Climbing" end))
  7860. table.insert(connections, humanoid.FallingDown:connect(function(state) pose = "FallingDown" end))
  7861. table.insert(connections, humanoid.FreeFalling:connect(function(state) pose = "FreeFall" if state then soundFreeFalling:Play() else
  7862.  
  7863. soundFreeFalling:Pause() end end))
  7864. table.insert(connections, humanoid.GettingUp:connect(function(state) pose = "GettingUp" if state then soundGettingUp:Play() else
  7865.  
  7866. soundGettingUp:Pause() end end))
  7867. table.insert(connections, humanoid.PlatformStanding:connect(function() pose = "PlatformStanding" end))
  7868. table.insert(connections, humanoid.Seated:connect(function() pose = "Seated" end))
  7869. table.insert(connections, humanoid.Swimming:connect(function(speed) if speed > 0 then pose = "Swimming" else pose = "Standing" end end))
  7870. local previousRootPartCFrame = rootPart.CFrame
  7871. TaskScheduler.Start(function()
  7872. while active do
  7873. local totalTime = TaskScheduler.GetCurrentTime()
  7874. local stepTime = 1 / 60
  7875. if not PlayerControl.characterEnabled then
  7876. ResetCharacter()
  7877. break
  7878. end
  7879. torsoLight.Brightness = 0.5 + 0.15 * math.sin(totalTime * 0.75 * math.pi)
  7880. local featherfallEnabled = PlayerControl.IsFeatherfallEnabled()
  7881. local rootPartCFrame = rootPart.CFrame
  7882. if not jumpDebounce and UserInterface.IsKeyDown(" ") then
  7883. if humanoid.Sit then
  7884. humanoid.Sit = false
  7885. end
  7886. if IsStanding() then
  7887. jumpDebounce = true
  7888. pose = "Jumping"
  7889. rootPart.Velocity = Vector3.new(rootPart.Velocity.X, 50, rootPart.Velocity.Z)
  7890. torso.Velocity = Vector3.new(torso.Velocity.X, 50, torso.Velocity.Z)
  7891. TaskScheduler.Schedule(1, function()
  7892. if pose == "Jumping" then
  7893. pose = "FreeFall"
  7894. end
  7895. jumpDebounce = false
  7896. humanoid.Jump = false
  7897. end)
  7898. end
  7899. end
  7900. local cameraCFrame = Camera.CoordinateFrame
  7901. local cameraDirection = cameraCFrame.lookVector
  7902. if flying then
  7903. if PlayerControl.rolling then
  7904. local rootPartCFrame = rootPart.CFrame
  7905. local speed = (rootPartCFrame - rootPartCFrame.p):pointToObjectSpace(rootPart.Velocity).Y
  7906. local decay = 0.5 ^ stepTime
  7907. if math.abs(speed) <= 50 then
  7908. PlayerControl.rollingAngle = (((PlayerControl.rollingAngle + 0.5) % 1 - 0.5) * decay) % 1
  7909. PlayerControl.rollingOffset = PlayerControl.rollingOffset * decay
  7910. else
  7911. PlayerControl.rollingAngle = (PlayerControl.rollingAngle + stepTime * speed *
  7912.  
  7913. PlayerControl.rollingSpeed) % 1
  7914. PlayerControl.rollingOffset = (PlayerControl.rollingOffset + PlayerControl.rollingMaxOffset * (1 /
  7915.  
  7916. decay - 1)) * decay
  7917. end
  7918. rootJoint.C0 = (CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0) * CFrame.Angles(PlayerControl.rollingAngle *
  7919.  
  7920. 2 * math.pi, 0, 0)) * CFrame.new(0, -PlayerControl.rollingOffset, 0)
  7921. else
  7922. rootJoint.C0 = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0)
  7923. PlayerControl.rollingAngle = 0
  7924. PlayerControl.rollingOffset = 0
  7925. end
  7926. rightShoulder.MaxVelocity = 0.5
  7927. leftShoulder.MaxVelocity = 0.5
  7928. rightShoulder.DesiredAngle = 0
  7929. leftShoulder.DesiredAngle = 0
  7930. rightHip.DesiredAngle = 0
  7931. leftHip.DesiredAngle = 0
  7932. bodyGyro.D = 500
  7933. bodyGyro.P = 1e6
  7934. bodyGyro.maxTorque = Vector3.new(1e6, 1e6, 1e6)
  7935. bodyVelocity.P = 1250
  7936. bodyVelocity.maxForce = Vector3.new(1e6, 1e6, 1e6)
  7937. local movementRight = 0
  7938. local movementForward = 0
  7939. local movementUp = 0
  7940. if UserInterface.IsKeyDown("a") and not UserInterface.IsKeyDown("d") then
  7941. movementRight = -1
  7942. elseif UserInterface.IsKeyDown("d") then
  7943. movementRight = 1
  7944. end
  7945. if UserInterface.IsKeyDown("w") then
  7946. movementUp = 0.2
  7947. if not UserInterface.IsKeyDown("s") then
  7948. movementForward = -1
  7949. end
  7950. elseif UserInterface.IsKeyDown("s") then
  7951. movementForward = 1
  7952. end
  7953. local movement = PlayerControl.fly_acceleration * cameraCFrame:vectorToWorldSpace(Vector3.new(movementRight,
  7954.  
  7955. movmentUp, movementForward))
  7956. local previousMomentum = flyingMomentum
  7957. local previousTilt = flyingTilt
  7958. flyingMomentum = movement + flyingMomentum * (1 - PlayerControl.fly_acceleration / PlayerControl.fly_speed)
  7959. flyingTilt = ((flyingMomentum * Vector3.new(1, 0, 1)).unit:Cross((previousMomentum * Vector3.new(1, 0, 1)).unit)).Y
  7960. if flyingTilt ~= flyingTilt or flyingTilt == math.huge then
  7961. flyingTilt = 0
  7962. end
  7963. local absoluteTilt = math.abs(flyingTilt)
  7964. if absoluteTilt > 0.06 or absoluteTilt < 0.0001 then
  7965. if math.abs(previousTilt) > 0.0001 then
  7966. flyingTilt = previousTilt * 0.9
  7967. else
  7968. flyingTilt = 0
  7969. end
  7970. else
  7971. flyingTilt = previousTilt * 0.77 + flyingTilt * 0.25
  7972. end
  7973. previousTilt = flyingTilt
  7974. if flyingMomentum.magnitude < 0.1 then
  7975. flyingMomentum = Vector3.new(0, 0, 0)
  7976. -- bodyGyro.cframe = cameraCFrame
  7977. else
  7978. local momentumOrientation = CFrame.new(Vector3.new(0, 0, 0), flyingMomentum)
  7979. local tiltOrientation = CFrame.Angles(0, 0, -20 * flyingTilt)
  7980. bodyGyro.cframe = momentumOrientation * tiltOrientation * CFrame.Angles(-0.5 * math.pi * math.min
  7981.  
  7982. (flyingMomentum.magnitude / PlayerControl.fly_speed, 1), 0, 0)
  7983. end
  7984. bodyVelocity.velocity = flyingMomentum + Vector3.new(0, 0.15695775618683547, 0)
  7985. rootPart.Velocity = flyingMomentum
  7986. previousMomentum = flyingMomentum
  7987. else
  7988. rootJoint.C0 = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0)
  7989. PlayerControl.rollingAngle = 0
  7990. PlayerControl.rollingOffset = 0
  7991. bodyGyro.D = 3250
  7992. bodyGyro.P = 400000
  7993. bodyVelocity.P = 5000
  7994. local cameraDirection = cameraCFrame.lookVector
  7995. local walkDirection = Vector3.new(0, 0, 0)
  7996. local walkSpeed = 16
  7997. if UserInterface.IsKeyDown("w") or UserInterface.IsKeyDown("\17") then
  7998. if UserInterface.IsKeyDown("a") then
  7999. walkDirection = Vector3.new(cameraDirection.X + cameraDirection.Z, 0, cameraDirection.Z -
  8000.  
  8001. cameraDirection.X).unit
  8002. elseif UserInterface.IsKeyDown("d") then
  8003. walkDirection = Vector3.new(cameraDirection.X - cameraDirection.Z, 0, cameraDirection.Z +
  8004.  
  8005. cameraDirection.X).unit
  8006. else
  8007. walkDirection = Vector3.new(cameraDirection.X, 0, cameraDirection.Z).unit
  8008. end
  8009. elseif UserInterface.IsKeyDown("s") or UserInterface.IsKeyDown("\18") then
  8010. if UserInterface.IsKeyDown("a") then
  8011. walkDirection = Vector3.new(-cameraDirection.X + cameraDirection.Z, 0, -cameraDirection.Z -
  8012.  
  8013. cameraDirection.X).unit
  8014. elseif UserInterface.IsKeyDown("d") then
  8015. walkDirection = Vector3.new(-cameraDirection.X - cameraDirection.Z, 0, -cameraDirection.Z +
  8016.  
  8017. cameraDirection.X).unit
  8018. else
  8019. walkDirection = Vector3.new(-cameraDirection.X, 0, -cameraDirection.Z).unit
  8020. end
  8021. elseif UserInterface.IsKeyDown("a") then
  8022. walkDirection = Vector3.new(cameraDirection.Z, 0, -cameraDirection.X).unit
  8023. elseif UserInterface.IsKeyDown("d") then
  8024. walkDirection = Vector3.new(-cameraDirection.Z, 0, cameraDirection.X).unit
  8025. else
  8026. walkSpeed = 0
  8027. end
  8028. if walkSpeed ~= previousWalkSpeed then
  8029. if walkSpeed > 0 then
  8030. soundRunning:Play()
  8031. else
  8032. soundRunning:Pause()
  8033. end
  8034. end
  8035. if walkSpeed > 0 then
  8036. if pose ~= "Jumping" then
  8037. if IsStanding() then
  8038. pose = "Running"
  8039. else
  8040. pose = "FreeFall"
  8041. end
  8042. end
  8043. bodyGyro.cframe = CFrame.new(Vector3.new(), walkDirection)
  8044. bodyGyro.maxTorque = Vector3.new(1000000000, 1000000000, 1000000000)
  8045. bodyVelocity.maxForce = Vector3.new(1000000, maxForceY, 1000000)
  8046. else
  8047. if pose ~= "Jumping" then
  8048. if IsStanding() then
  8049. pose = "Standing"
  8050. else
  8051. pose = "FreeFall"
  8052. end
  8053. end
  8054. -- TODO: find and fix bug that causes torso to rotate back to some angle
  8055. bodyGyro.maxTorque = Vector3.new(1000000000, 1000000000, 1000000000) -- Vector3.new(1000000000, 0,
  8056.  
  8057. 1000000000)
  8058. if PlayerControl.pushable then
  8059. bodyVelocity.maxForce = Vector3.new(0, 0, 0)
  8060. else
  8061. bodyVelocity.maxForce = Vector3.new(1000000, 0, 1000000)
  8062. end
  8063. end
  8064. if featherfallEnabled then
  8065. local velocity = rootPart.Velocity
  8066. if velocity.Y > 50 then
  8067. rootPart.Velocity = Vector3.new(velocity.X, 50, velocity.Z)
  8068. elseif velocity.Y < -50 then
  8069. rootPart.Velocity = Vector3.new(velocity.X, -50, velocity.Z)
  8070. end
  8071. local distanceVector = rootPartCFrame.p - previousRootPartCFrame.p
  8072. local offsetX, offsetY, offsetZ = distanceVector.X, distanceVector.Y, distanceVector.Z
  8073. local MAX_MOVEMENT = 50 * 0.03333333507180214
  8074. if offsetX > MAX_MOVEMENT then
  8075. offsetX = MAX_MOVEMENT
  8076. elseif offsetX < -MAX_MOVEMENT then
  8077. offsetX = -MAX_MOVEMENT
  8078. end
  8079. if offsetY > MAX_MOVEMENT then
  8080. offsetY = MAX_MOVEMENT
  8081. elseif offsetY < -MAX_MOVEMENT then
  8082. offsetY = -MAX_MOVEMENT
  8083. end
  8084. if offsetZ > MAX_MOVEMENT then
  8085. offsetZ = MAX_MOVEMENT
  8086. elseif offsetZ < -MAX_MOVEMENT then
  8087. offsetZ = -MAX_MOVEMENT
  8088. end
  8089. local offset = Vector3.new(offsetX, offsetY, offsetZ)
  8090. if offset ~= distanceVector then
  8091. rootPartCFrame = previousRootPartCFrame + offset
  8092. --rootPart.CFrame = rootPartCFrame
  8093. end
  8094. end
  8095. local walkingVelocity = walkDirection * walkSpeed
  8096. bodyVelocity.velocity = walkingVelocity
  8097. if not jumpDebounce and math.abs(rootPart.Velocity.Y) <= 0.1 then
  8098. rootPart.Velocity = Vector3.new(walkingVelocity.X, rootPart.Velocity.Y, walkingVelocity.Z)
  8099. end
  8100. previousWalkSpeed = walkSpeed
  8101. if pose == "Jumping" or jumpDebounce then
  8102. rightShoulder.MaxVelocity = 0.5
  8103. leftShoulder.MaxVelocity = 0.5
  8104. rightShoulder.DesiredAngle = 3.14
  8105. leftShoulder.DesiredAngle = -3.14
  8106. rightHip.DesiredAngle = 0
  8107. leftHip.DesiredAngle = 0
  8108. elseif pose == "FreeFall" then
  8109. rightShoulder.MaxVelocity = 0.5
  8110. leftShoulder.MaxVelocity = 0.5
  8111. rightShoulder.DesiredAngle = 3.14
  8112. leftShoulder.DesiredAngle = -3.14
  8113. rightHip.DesiredAngle = 0
  8114. leftHip.DesiredAngle = 0
  8115. elseif pose == "Seated" then
  8116. rightShoulder.MaxVelocity = 0.15
  8117. leftShoulder.MaxVelocity = 0.15
  8118. rightShoulder.DesiredAngle = 3.14 / 2
  8119. leftShoulder.DesiredAngle = -3.14 / 2
  8120. rightHip.DesiredAngle = 3.14 / 2
  8121. leftHip.DesiredAngle = -3.14 / 2
  8122. else
  8123. local climbFudge = 0
  8124. local amplitude
  8125. local frequency
  8126. if pose == "Running" then
  8127. rightShoulder.MaxVelocity = 0.15
  8128. leftShoulder.MaxVelocity = 0.15
  8129. amplitude = 1
  8130. frequency = 9
  8131. elseif (pose == "Climbing") then
  8132. rightShoulder.MaxVelocity = 0.5
  8133. leftShoulder.MaxVelocity = 0.5
  8134. amplitude = 1
  8135. frequency = 9
  8136. climbFudge = 3.14
  8137. else
  8138. amplitude = 0.1
  8139. frequency = 1
  8140. end
  8141. local desiredAngle = amplitude * math.sin(totalTime * frequency)
  8142. rightShoulder.DesiredAngle = desiredAngle + climbFudge
  8143. leftShoulder.DesiredAngle = desiredAngle - climbFudge
  8144. rightHip.DesiredAngle = -desiredAngle
  8145. leftHip.DesiredAngle = -desiredAngle
  8146. end
  8147. end
  8148. previousRootPartCFrame = rootPartCFrame
  8149. RunService.RenderStepped:wait()
  8150. end
  8151. if model.Parent ~= nil then
  8152. model.Parent = nil
  8153. end
  8154. PlayerControl.CreateCharacter()
  8155. end)
  8156. humanoid.Health = 100
  8157. character = model
  8158. Network.TransmitServer("chatAdornee = ...", head)
  8159. elseif characterMode == "pyramid" then
  8160. if PlayerControl.characterEnabled then
  8161. Camera.CameraType = "Fixed"
  8162. PyramidCharacter.camera_distance = (Camera.Focus.p - Camera.CoordinateFrame.p).magnitude
  8163. PyramidCharacter.camera_position = Camera.Focus.p
  8164. PyramidCharacter.Teleport(Camera.Focus.p)
  8165. PyramidCharacter.visible = true
  8166. Player.Character = nil
  8167. else
  8168. PyramidCharacter.visible = false
  8169. end
  8170. end
  8171. end
  8172. function PlayerControl.GetCharacter()
  8173. return character
  8174. end
  8175. function PlayerControl.GetHead()
  8176. local characterMode = PlayerControl.characterMode
  8177. if characterMode == "normal" then
  8178. return head
  8179. elseif characterMode == "pyramid" then
  8180. return PyramidCharacter.core
  8181. end
  8182. end
  8183. function PlayerControl.GetHumanoid()
  8184. return humanoid
  8185. end
  8186. function PlayerControl.GetRootPart()
  8187. return rootPart
  8188. end
  8189. function PlayerControl.GetTorso()
  8190. return torso
  8191. end
  8192. function PlayerControl.IsEnabled()
  8193. return PlayerControl.characterEnabled
  8194. end
  8195. function PlayerControl.IsFeatherfallEnabled()
  8196. return PlayerControl.featherfallEnabled
  8197. end
  8198. function PlayerControl.IsPushable()
  8199. return PlayerControl.pushable
  8200. end
  8201. function PlayerControl.IsRolling()
  8202. return PlayerControl.rolling
  8203. end
  8204. function PlayerControl.ResetCharacter()
  8205. if character and character.Parent then
  8206. character.Parent = nil
  8207. end
  8208. PyramidCharacter.visible = false
  8209. end
  8210. function PlayerControl.SetEnabled(state, no_animation)
  8211. state = not not state
  8212. if state ~= PlayerControl.characterEnabled then
  8213. PlayerControl.characterEnabled = state
  8214. local characterMode = PlayerControl.characterMode
  8215. if characterMode == "normal" then
  8216. local torso = PlayerControl.GetRootPart()
  8217. local rootPart = PlayerControl.GetRootPart()
  8218. if rootPart then
  8219. if PlayerControl.characterEnabled then
  8220. local torso_cframe = Camera.Focus:toWorldSpace(PlayerControl.hide_torso_object_cframe)
  8221. PlayerControl.torso_cframe = torso_cframe
  8222. torso.CFrame = torso_cframe
  8223. rootPart.CFrame = torso_cframe
  8224. else
  8225. PlayerControl.hide_torso_object_cframe = Camera.Focus:toObjectSpace(rootPart.CFrame)
  8226. end
  8227. else
  8228. PlayerControl.torso_cframe = Camera.Focus
  8229. end
  8230. if PlayerControl.characterEnabled then
  8231. PlayerControl.CreateCharacter()
  8232. RunService.Stepped:wait()
  8233. coroutine.yield()
  8234. if not no_animation then
  8235. Network.TransmitServer("GraphicalEffects.CrystalRing({base_part = (...), crystal_color = BrickColor.new
  8236.  
  8237. (\"Institutional white\"), float_duration = 2})", PlayerControl.GetTorso())
  8238. end
  8239. else
  8240. Player.Character = nil
  8241. Camera.CameraType = "Fixed"
  8242. if not no_animation then
  8243. Network.TransmitServer("GraphicalEffects.CrystalRing({position = (...), crystal_color = BrickColor.new
  8244.  
  8245. (\"Institutional white\"), float_duration = 2})", PlayerControl.GetTorso().Position)
  8246. end
  8247. end
  8248. else
  8249. if state then
  8250. PlayerControl.CreateCharacter()
  8251. RunService.Stepped:wait()
  8252. coroutine.yield()
  8253. if not no_animation then
  8254. Network.TransmitServer("GraphicalEffects.CrystalRing({base_part = (...), crystal_color = BrickColor.new
  8255.  
  8256. (\"Institutional white\"), float_duration = 2})", PyramidCharacter.core)
  8257. end
  8258. else
  8259. PyramidCharacter.visible = false
  8260. if not no_animation then
  8261. Network.TransmitServer("GraphicalEffects.CrystalRing({position = (...), crystal_color = BrickColor.new
  8262.  
  8263. (\"Institutional white\"), float_duration = 2})", PyramidCharacter.core.Position)
  8264. end
  8265. end
  8266. end
  8267. end
  8268. end
  8269. function PlayerControl.SetFeatherfallEnabled(state)
  8270. state = not not state
  8271. if state ~= PlayerControl.featherfallEnabled then
  8272. PlayerControl.featherfallEnabled = state
  8273. if state then
  8274. Logger.print("Info", "Featherfall enabled in PlayerControl")
  8275. else
  8276. Logger.print("Info", "Featherfall disabled in PlayerControl")
  8277. end
  8278. end
  8279. end
  8280. function PlayerControl.SetPushable(state)
  8281. state = not not state
  8282. if state ~= PlayerControl.pushable then
  8283. PlayerControl.pushable = state
  8284. if state then
  8285. Logger.print("Info", "Pushing enabled in PlayerControl")
  8286. else
  8287. Logger.print("Info", "Pushing disabled in PlayerControl")
  8288. end
  8289. end
  8290. end
  8291. function PlayerControl.SetRolling(state)
  8292. state = not not state
  8293. if state ~= PlayerControl.rolling then
  8294. PlayerControl.rolling = state
  8295. if state then
  8296. Logger.print("Info", "Rolling fly mode enabled in PlayerControl")
  8297. else
  8298. Logger.print("Info", "Rolling fly mode disabled in PlayerControl")
  8299. end
  8300. end
  8301. end
  8302. function PlayerControl.StartFlying()
  8303. PlayerControl.fly_speed = PlayerControl.fly_basespeed
  8304. if torso then
  8305. flyingMomentum = torso.Velocity + torso.CFrame.lookVector * 3 + Vector3.new(0, 10, 0)
  8306. else
  8307. flyingMomentum = Vector3.new()
  8308. end
  8309. flyingTilt = 0
  8310. flying = true
  8311. end
  8312. function PlayerControl.StopFlying()
  8313. if bodyGyro.cframe then
  8314. local lookVector = bodyGyro.cframe.lookVector
  8315. if lookVector.X ~= 0 or lookVector.Z ~= 0 then
  8316. bodyGyro.cframe = CFrame.new(Vector3.new(), Vector3.new(lookVector.X, 0, lookVector.Z))
  8317. end
  8318. end
  8319. flying = false
  8320. end
  8321. local previousTime = 0
  8322. UserInterface.SetHotkey(" ", function()
  8323. if flying then
  8324. PlayerControl.StopFlying()
  8325. else
  8326. local currentTime = time()
  8327. if currentTime - previousTime < 0.4 then
  8328. previousTime = 0
  8329. PlayerControl.StartFlying()
  8330. else
  8331. previousTime = currentTime
  8332. end
  8333. end
  8334. end)
  8335. ]])
  8336. Module.Create("RBXInstance", [[
  8337. RBXInstance.init_metatable = {}
  8338. function RBXInstance.init_metatable:__call(data)
  8339. local instance = Instance.new(self[1])
  8340. for key, value in pairs(data) do
  8341. if type(key) == "number" then
  8342. value.Parent = instance
  8343. else
  8344. instance[key] = value
  8345. end
  8346. end
  8347. return instance
  8348. end
  8349. function RBXInstance.new(className)
  8350. return setmetatable({className}, RBXInstance.init_metatable)
  8351. end
  8352. ]])
  8353. Module.Create("AdvancedGUI", [=[
  8354. if not AdvancedGUI.GUI_BASE_COLOR then
  8355. AdvancedGUI.GUI_BASE_COLOR = Color3.new(0, 0, 0)
  8356. end
  8357. function AdvancedGUI.GenerateChatColor(speakerName)
  8358. local chatColor = ChatColor.Get(speakerName).Color
  8359. local brightness = chatColor.r + chatColor.g + chatColor.b
  8360. if brightness < 1.5 then
  8361. chatColor = Color3.new(math.min(1, 0.4 + chatColor.r), math.min(1, 0.4 + chatColor.g), math.min(1, 0.4 + chatColor.b))
  8362. else
  8363. chatColor = Color3.new(math.min(1, 0.05 + chatColor.r), math.min(1, 0.05 + chatColor.g), math.min(1, 0.05 + chatColor.b))
  8364. end
  8365. return chatColor
  8366. end
  8367. GuiBase = {}
  8368. GuiBase.__index = GuiBase
  8369. function GuiBase:new(data)
  8370. local instance = setmetatable({}, self)
  8371. instance:Init(data)
  8372. return instance
  8373. end
  8374. function GuiBase:Destroy()
  8375. if self.parent then
  8376. self.parent.children[self] = nil
  8377. end
  8378. for child in pairs(self.children) do
  8379. child:Destroy()
  8380. end
  8381. self.m_base_instance:Destroy()
  8382. end
  8383. function GuiBase:GetContentInstance(child)
  8384. return self.m_base_instance
  8385. end
  8386. function GuiBase:Init()
  8387. self.children = {}
  8388. end
  8389. function GuiBase:IsA(className)
  8390. return className == "GuiBase"
  8391. end
  8392. function GuiBase:SetParent(parent)
  8393. if parent ~= self.parent then
  8394. if self.parent then
  8395. self.parent.children[self] = nil
  8396. end
  8397. self.parent = parent
  8398. if parent then
  8399. parent.children[self] = true
  8400. self.m_base_instance.Parent = parent:GetContentInstance()
  8401. else
  8402. self.m_base_instance.Parent = nil
  8403. end
  8404. end
  8405. end
  8406. GuiObject = setmetatable({}, GuiBase)
  8407. GuiObject.__index = GuiObject
  8408. function GuiObject:Destroy()
  8409. self.DragBegin:disconnect()
  8410. self.DragMove:disconnect()
  8411. self.DragStopped:disconnect()
  8412. self.MouseButton1Click:disconnect()
  8413. self.MouseButton1Down:disconnect()
  8414. self.MouseButton1Up:disconnect()
  8415. self.MouseButton2Down:disconnect()
  8416. self.MouseButton2Up:disconnect()
  8417. self.MouseEnter:disconnect()
  8418. self.MouseLeave:disconnect()
  8419. GuiBase.Destroy(self)
  8420. end
  8421. function GuiObject:GetAbsolutePosition()
  8422. return self.m_base_instance.AbsolutePosition
  8423. end
  8424. function GuiObject:GetAbsoluteSize()
  8425. return self.m_base_instance.AbsoluteSize
  8426. end
  8427. function GuiObject:GetPosition()
  8428. return self.position
  8429. end
  8430. function GuiObject:GetSize()
  8431. return self.size
  8432. end
  8433. function GuiObject:Init()
  8434. GuiBase.Init(self)
  8435. self.mouseDown = false
  8436. self.mouseOver = false
  8437. self.DragBegin = RbxUtility.CreateSignal()
  8438. self.DragMove = RbxUtility.CreateSignal()
  8439. self.DragStopped = RbxUtility.CreateSignal()
  8440. self.MouseButton1Click = RbxUtility.CreateSignal()
  8441. self.MouseButton1Down = RbxUtility.CreateSignal()
  8442. self.MouseButton1Up = RbxUtility.CreateSignal()
  8443. self.MouseButton2Down = RbxUtility.CreateSignal()
  8444. self.MouseButton2Up = RbxUtility.CreateSignal()
  8445. self.MouseEnter = RbxUtility.CreateSignal()
  8446. self.MouseLeave = RbxUtility.CreateSignal()
  8447. end
  8448. function GuiObject:IsA(className)
  8449. return className == "GuiObject" or GuiBase.IsA(self, className)
  8450. end
  8451. function GuiObject:SetActive(active)
  8452. if active ~= self.active then
  8453. self.active = active
  8454. end
  8455. end
  8456. function GuiObject:SetBackgroundTransparency(backgroundTransparency)
  8457. if backgroundTransparency ~= self.backgroundTransparency then
  8458. self.backgroundTransparency = backgroundTransparency
  8459. self.m_base_instance.BackgroundTransparency = backgroundTransparency
  8460. end
  8461. end
  8462. function GuiObject:SetColor(color)
  8463. if color ~= self.color then
  8464. self.color = color
  8465. self.m_base_instance.BackgroundColor3 = color
  8466. end
  8467. end
  8468. function GuiObject:SetPosition(position)
  8469. if position ~= self.position then
  8470. self.position = position
  8471. self.m_base_instance.Position = position
  8472. end
  8473. end
  8474. function GuiObject:SetSize(size)
  8475. if size ~= self.size then
  8476. self.size = size
  8477. self.m_base_instance.Size = size
  8478. end
  8479. end
  8480. function GuiObject:SetVisible(visible)
  8481. if visible ~= self.visible then
  8482. self.visible = visible
  8483. self.m_base_instance.Visible = visible
  8484. end
  8485. end
  8486. function GuiObject:SetZIndex(zIndex)
  8487. local stack = {self.m_base_instance}
  8488. repeat
  8489. local object = stack[#stack]
  8490. stack[#stack] = nil
  8491. for _, child in ipairs(object:GetChildren()) do
  8492. stack[#stack + 1] = child
  8493. end
  8494. object.ZIndex = zIndex
  8495. until #stack == 0
  8496. end
  8497. GuiServiceClass = setmetatable({}, GuiBase)
  8498. GuiServiceClass.__index = GuiServiceClass
  8499. function GuiServiceClass:CreateTextArea(text, font, fontSize, textColor3, textXAlignment, textYAlignment, maxWidth, minWidth)
  8500. local totalHeight = 0
  8501. local frame = Instance.new("Frame")
  8502. frame.BackgroundTransparency = 1
  8503. local label = Instance.new("TextLabel")
  8504. label.BackgroundTransparency = 1
  8505. label.Font = font
  8506. label.FontSize = fontSize
  8507. label.TextColor3 = textColor3
  8508. label.TextTransparency = 1
  8509. label.TextWrapped = true
  8510. label.TextXAlignment = textXAlignment
  8511. label.TextYAlignment = textYAlignment
  8512. label.Parent = self.guiFrame
  8513. local index = 1
  8514. while true do
  8515. local length = #text - index + 1
  8516. if length > 1024 then
  8517. length = 1024
  8518. local textBlock = string.sub(text, index, index + length - 1)
  8519. label.Text = textBlock
  8520. local height = 0
  8521. local width = maxWidth
  8522. repeat
  8523. height = height + 20
  8524. label.Size = UDim2.new(0, width, 0, height)
  8525. until label.TextFits
  8526. repeat
  8527. height = height - 1
  8528. label.Size = UDim2.new(0, width, 0, height)
  8529. until not label.TextFits
  8530. repeat
  8531. length = length - 10
  8532. label.Text = string.sub(text, index, index + length - 1)
  8533. until label.TextFits
  8534. repeat
  8535. length = length + 1
  8536. label.Text = string.sub(text, index, index + length - 1)
  8537. until not label.TextFits
  8538. local overflowCharacter = string.sub(text, index + length - 1, index + length - 1)
  8539. length = length - 1
  8540. label.Text = string.sub(text, index, index + length - 1)
  8541. if overflowCharacter == "\n" then
  8542. index = index + 1
  8543. end
  8544. repeat
  8545. height = height - 1
  8546. label.Size = UDim2.new(0, width, 0, height)
  8547. until not label.TextFits
  8548. height = height + 1
  8549. local blockLabel = label:Clone()
  8550. blockLabel.Position = UDim2.new(0, 0, 0, totalHeight)
  8551. blockLabel.Size = UDim2.new(1, 0, 0, height)
  8552. blockLabel.Parent = frame
  8553. totalHeight = totalHeight + height
  8554. index = index + length
  8555. else
  8556. local textBlock = string.sub(text, index)
  8557. label.Text = textBlock
  8558. local height = 0
  8559. local width = maxWidth
  8560. repeat
  8561. height = height + 20
  8562. label.Size = UDim2.new(0, width, 0, height)
  8563. until label.TextFits
  8564. repeat
  8565. height = height - 1
  8566. label.Size = UDim2.new(0, width, 0, height)
  8567. until not label.TextFits
  8568. height = height + 1
  8569. if index == 1 then
  8570. repeat
  8571. width = width - 10
  8572. label.Size = UDim2.new(0, width, 0, height)
  8573. until width < minWidth or not label.TextFits
  8574. width = math.max(width, minWidth - 1)
  8575. repeat
  8576. width = width + 1
  8577. label.Size = UDim2.new(0, width, 0, height)
  8578. until label.TextFits
  8579. end
  8580. local blockLabel = label:Clone()
  8581. blockLabel.Position = UDim2.new(0, 0, 0, totalHeight)
  8582. blockLabel.Size = UDim2.new(1, 0, 0, height)
  8583. blockLabel.Parent = frame
  8584. label:Destroy()
  8585. frame.Size = UDim2.new(0, width, 0, totalHeight + height)
  8586. return frame
  8587. end
  8588. end
  8589. end
  8590. function GuiServiceClass:Destroy()
  8591. self.running = false
  8592. self.cameraPart:Destroy()
  8593. self.cameraConnection:disconnect()
  8594. self.keyDownConnection:disconnect()
  8595. self.mouseButton1DownConnection:disconnect()
  8596. self.mouseButton1UpConnection:disconnect()
  8597. self.mouseButton2DownConnection:disconnect()
  8598. self.mouseButton2UpConnection:disconnect()
  8599. self.mouseMoveConnection:disconnect()
  8600. self.steppedConnection:disconnect()
  8601. end
  8602. function GuiServiceClass:GetMousePosition()
  8603. local mouse = self.mouse
  8604. return mouse.X, mouse.Y -- mouse.X, mouse.Y + 2 -- return mouse.X - 2, mouse.Y - 3
  8605. end
  8606. function GuiServiceClass:GetTextBounds(text, font, fontSize, alignX, alignY, width)
  8607. local tempLabel = self.tempLabel
  8608. tempLabel.Font = font
  8609. tempLabel.FontSize = fontSize
  8610. tempLabel.Size = UDim2.new(0, width, 0, 4096)
  8611. tempLabel.Text = text
  8612. tempLabel.TextXAlignment = alignX
  8613. tempLabel.TextYAlignment = alignY
  8614. local textBounds = tempLabel.TextBounds
  8615. tempLabel.Text = ""
  8616. return textBounds
  8617. end
  8618. function GuiServiceClass:Init(data)
  8619. GuiBase.Init(self)
  8620. local _ = string.char
  8621. local camera = data.Camera
  8622. local mouse = data.Mouse
  8623. local cameraPart = Instance.new("Part")
  8624. local billboardGui = Instance.new("BillboardGui", cameraPart)
  8625. guiFrame = Instance.new("Frame", billboardGui)
  8626. cameraPart.Anchored = true
  8627. cameraPart.BottomSurface = "Smooth"
  8628. cameraPart.CanCollide = false
  8629. -- cameraPart.CFrame = CFrame.new(16384, 16384, 16384)
  8630. cameraPart.FormFactor = "Custom"
  8631. cameraPart.Locked = true
  8632. cameraPart.Size = Vector3.new(0.2, 0.2, 0.2)
  8633. cameraPart.TopSurface = "Smooth"
  8634. cameraPart.Transparency = 1
  8635. billboardGui.Adornee = cameraPart
  8636. billboardGui.AlwaysOnTop = true
  8637. -- billboardGui.ExtentsOffset = Vector3.new(-16384, -16384, -16384)
  8638. guiFrame.BackgroundTransparency = 1
  8639. cameraPart.Parent = camera
  8640. self.running = true
  8641. self.m_base_instance = guiFrame
  8642. self.billboardGui = billboardGui
  8643. self.cameraPart = cameraPart
  8644. self.tempLabel = RBXInstance.new "TextLabel" {
  8645. BackgroundTransparency = 1,
  8646. TextTransparency = 1,
  8647. TextWrapped = true,
  8648. Parent = guiFrame
  8649. }
  8650. self.mnemonics = {}
  8651. self.visible = true
  8652. self.camera = camera
  8653. self.mouse = mouse
  8654. self.cameraConnection = camera.Changed:connect(function(property)
  8655. self:UpdateView()
  8656. if property == "CameraType" then
  8657. if camera.CameraType ~= Enum.CameraType.Track and camera.CameraType ~= Enum.CameraType.Fixed then
  8658. camera.CameraType = Enum.CameraType.Track
  8659. end
  8660. elseif property == "CoordinateFrame" and camera.CameraType ~= Enum.CameraType.Fixed then
  8661. local cframe, focus = camera.CoordinateFrame, camera.Focus
  8662. local watchOffset = focus.p - cframe.p
  8663. local error = watchOffset.unit - cframe.lookVector
  8664. if error.magnitude >= 1e-3 then
  8665. local head = PlayerControl.GetHead()
  8666. local time1, velocity1
  8667. if head then
  8668. time1 = time()
  8669. velocity1 = head.Velocity
  8670. end
  8671. if camera.Changed:wait() == "CoordinateFrame" then
  8672. local position = cframe.p
  8673. if head then
  8674. local time2 = time()
  8675. local velocity2 = head.Velocity
  8676. position = position + 0.5 * (velocity1 + velocity2) * (time2 - time1)
  8677. end
  8678. camera.CoordinateFrame = CFrame.new(position, camera.Focus.p)
  8679. end
  8680. end
  8681. end
  8682. end)
  8683. self.keyDownConnection = mouse.KeyDown:connect(function(key) self:KeyDown(key) end)
  8684. self.mouseButton1DownConnection = mouse.Button1Down:connect(function() self:MouseButton1Down() end)
  8685. self.mouseButton1UpConnection = mouse.Button1Up:connect(function() self:MouseButton1Up() end)
  8686. self.mouseButton2DownConnection = mouse.Button2Down:connect(function() self:MouseButton2Down() end)
  8687. self.mouseButton2UpConnection = mouse.Button2Up:connect(function() self:MouseButton2Up() end)
  8688. self.mouseMoveConnection = mouse.Move:connect(function() self:MouseMove() end)
  8689. self.steppedConnection = RunService.RenderStepped:connect(function() self:UpdateObjects() self:UpdateView() end)
  8690. self.mousePreviousPosition = Vector2.new(self:GetMousePosition())
  8691. end
  8692. function GuiServiceClass:IsA(className)
  8693. return className == "GuiService" or GuiBase.IsA(self, className)
  8694. end
  8695. function GuiServiceClass:KeyDown(key)
  8696. local mnemonicButton = self.mnemonics[string.upper(key)]
  8697. if mnemonicButton then
  8698. mnemonicButton.Activated:fire()
  8699. end
  8700. end
  8701. function GuiServiceClass:MouseButton1Down()
  8702. local mouse = self.mouse
  8703. local mouseX, mouseY = self:GetMousePosition()
  8704. local stack = {self}
  8705. local dragObjects = {}
  8706. self.dragObjects = dragObjects
  8707. while #stack > 0 do
  8708. local object = stack[#stack]
  8709. stack[#stack] = nil
  8710. if object.visible then
  8711. for child in pairs(object.children) do
  8712. stack[#stack + 1] = child
  8713. end
  8714. if object.active then
  8715. local position = object:GetAbsolutePosition()
  8716. local size = object:GetAbsoluteSize()
  8717. if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
  8718. object.mouseDown = true
  8719. dragObjects[object] = true
  8720. local mouseButton1Down = object.MouseButton1Down
  8721. if mouseButton1Down then
  8722. mouseButton1Down:fire()
  8723. if object.autoButtonColor then
  8724. local color = object.color
  8725. local transparency = object.backgroundTransparency
  8726. object.m_base_instance.BackgroundColor3 = Color3.new(math.min(color.r + 0.3, 1), math.min(color.g +
  8727.  
  8728. 0.3, 1), math.min(color.b + 0.3, 1))
  8729. object.m_base_instance.BackgroundTransparency = transparency
  8730. end
  8731. end
  8732. object.DragBegin:fire()
  8733. end
  8734. end
  8735. end
  8736. end
  8737. self.mousePreviousPosition = Vector2.new(mouseX, mouseY)
  8738. end
  8739. function GuiServiceClass:MouseButton1Up()
  8740. local mouse = self.mouse
  8741. local mouseX, mouseY = self:GetMousePosition()
  8742. local stack = {self}
  8743. while #stack > 0 do
  8744. local object = stack[#stack]
  8745. stack[#stack] = nil
  8746. if object.visible then
  8747. for child in pairs(object.children) do
  8748. stack[#stack + 1] = child
  8749. end
  8750. if object.active then
  8751. local position = object:GetAbsolutePosition()
  8752. local size = object:GetAbsoluteSize()
  8753. if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
  8754. object.MouseButton1Up:fire()
  8755. end
  8756. end
  8757. end
  8758. end
  8759. local dragObjects = self.dragObjects
  8760. self.dragObjects = nil
  8761. if dragObjects then
  8762. for dragObject in pairs(dragObjects) do
  8763. dragObject.mouseDown = false
  8764. local position = dragObject:GetAbsolutePosition()
  8765. local size = dragObject:GetAbsoluteSize()
  8766. if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
  8767. dragObject.MouseButton1Click:fire()
  8768. local activated = dragObject.Activated
  8769. if activated then
  8770. activated:fire()
  8771. end
  8772. end
  8773. dragObject.DragStopped:fire()
  8774. if dragObject.autoButtonColor then
  8775. if dragObject.mouseOver then
  8776. local color = dragObject.color
  8777. local transparency = dragObject.backgroundTransparency
  8778. dragObject.m_base_instance.BackgroundColor3 = Color3.new(math.max(color.r - 0.3, 0), math.max(color.g - 0.3, 0),
  8779.  
  8780. math.max(color.b - 0.3, 0))
  8781. dragObject.m_base_instance.BackgroundTransparency = math.max(0, transparency - 0.2)
  8782. else
  8783. dragObject.m_base_instance.BackgroundColor3 = dragObject.color
  8784. dragObject.m_base_instance.BackgroundTransparency = dragObject.backgroundTransparency
  8785. end
  8786. end
  8787. self.dragObject = nil
  8788. end
  8789. end
  8790. end
  8791. function GuiServiceClass:MouseButton2Down()
  8792. local mouse = self.mouse
  8793. local mouseX, mouseY = self:GetMousePosition()
  8794. local stack = {self}
  8795. while #stack > 0 do
  8796. local object = stack[#stack]
  8797. stack[#stack] = nil
  8798. if object.visible then
  8799. for child in pairs(object.children) do
  8800. stack[#stack + 1] = child
  8801. end
  8802. if object.active then
  8803. local position = object:GetAbsolutePosition()
  8804. local size = object:GetAbsoluteSize()
  8805. if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
  8806. local mouseButton2Down = object.MouseButton2Down
  8807. if mouseButton2Down then
  8808. mouseButton2Down:fire()
  8809. end
  8810. end
  8811. end
  8812. end
  8813. end
  8814. self.mousePreviousPosition = Vector2.new(mouseX, mouseY)
  8815. end
  8816. function GuiServiceClass:MouseButton2Up()
  8817. local mouse = self.mouse
  8818. local mouseX, mouseY = self:GetMousePosition()
  8819. local stack = {self}
  8820. while #stack > 0 do
  8821. local object = stack[#stack]
  8822. stack[#stack] = nil
  8823. if object.visible then
  8824. for child in pairs(object.children) do
  8825. stack[#stack + 1] = child
  8826. end
  8827. if object.active then
  8828. local position = object:GetAbsolutePosition()
  8829. local size = object:GetAbsoluteSize()
  8830. if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
  8831. local mouseButton2Up = object.MouseButton2Up
  8832. if mouseButton2Up then
  8833. mouseButton2Up:fire()
  8834. end
  8835. end
  8836. end
  8837. end
  8838. end
  8839. end
  8840. function GuiServiceClass:MouseMove()
  8841. self:UpdateObjects()
  8842. local dragObjects = self.dragObjects
  8843. if dragObjects then
  8844. for dragObject in pairs(dragObjects) do
  8845. local mouse = self.mouse
  8846. local mousePosition = Vector2.new(self:GetMousePosition())
  8847. dragObject.DragMove:fire(mousePosition - self.mousePreviousPosition)
  8848. self.mousePreviousPosition = mousePosition
  8849. end
  8850. end
  8851. end
  8852. function GuiServiceClass:SetMnemonic(mnemonic, button)
  8853. self.mnemonics[mnemonic] = button
  8854. end
  8855. function GuiServiceClass:UpdateObjects()
  8856. local mouse = self.mouse
  8857. local mouseX, mouseY = self:GetMousePosition()
  8858. local stack = {self}
  8859. while #stack > 0 do
  8860. local object = stack[#stack]
  8861. stack[#stack] = nil
  8862. if object.visible then
  8863. for child in pairs(object.children) do
  8864. stack[#stack + 1] = child
  8865. end
  8866. if object.active then
  8867. local position = object:GetAbsolutePosition()
  8868. local size = object:GetAbsoluteSize()
  8869. if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
  8870. if not object.mouseOver then
  8871. object.mouseOver = true
  8872. object.MouseEnter:fire()
  8873. if object.autoButtonColor then
  8874. local color = object.color
  8875. local transparency = object.backgroundTransparency
  8876. if object.mouseDown then
  8877. object.m_base_instance.BackgroundColor3 = Color3.new(math.min(color.r + 0.3, 1), math.min
  8878.  
  8879. (color.g + 0.3, 1), math.min(color.b + 0.3, 1))
  8880. object.m_base_instance.BackgroundTransparency = transparency
  8881. else
  8882. object.m_base_instance.BackgroundColor3 = Color3.new(math.max(color.r - 0.3, 0), math.max
  8883.  
  8884. (color.g - 0.3, 0), math.max(color.b - 0.3, 0))
  8885. object.m_base_instance.BackgroundTransparency = math.max(0, transparency - 0.2)
  8886. end
  8887. end
  8888. end
  8889. else
  8890. if object.mouseOver then
  8891. object.mouseOver = false
  8892. object.MouseLeave:fire()
  8893. if object.autoButtonColor then
  8894. object.m_base_instance.BackgroundColor3 = object.color
  8895. object.m_base_instance.BackgroundTransparency = object.backgroundTransparency
  8896. end
  8897. end
  8898. end
  8899. end
  8900. end
  8901. end
  8902. end
  8903. function GuiServiceClass:UpdateView()
  8904. local billboardGui = self.billboardGui
  8905. local guiFrame = self.m_base_instance
  8906. local camera = self.camera
  8907. local mouse = self.mouse
  8908. local cameraCFrame = CFrame.new(camera.CoordinateFrame.p, camera.Focus.p) -- camera.CoordinateFrame
  8909. local viewSizeX, viewSizeY = mouse.ViewSizeX, mouse.ViewSizeY
  8910. local previousViewSize = self.viewSize
  8911. if not previousViewSize or ((viewSizeX ~= 0 or viewSizeY ~= 0) and (viewSizeX ~= previousViewSize.X or viewSizeY ~= previousViewSize.Y)) then
  8912. self.viewSize = {X = viewSizeX, Y = viewSizeY}
  8913. local viewSizeUDim2 = UDim2.new(0, viewSizeX, 0, viewSizeY)
  8914. billboardGui.Size = viewSizeUDim2
  8915. guiFrame.Size = viewSizeUDim2
  8916. -- FIXME:
  8917. -- After the 15th of July 2014, there came an offset at the Y thingy out of nowhere so I accomodated for that.
  8918. billboardGui.SizeOffset = Vector2.new(0.5 / viewSizeX, (0.5 + 10) / viewSizeY)
  8919. end
  8920. --billboardGui.SizeOffset = Vector2.new()
  8921. billboardGui.StudsOffset = (cameraCFrame - cameraCFrame.p):inverse() * cameraCFrame.p - Vector3.new(0, 0, 1)
  8922. end
  8923. GuiService = GuiServiceClass:new {
  8924. Camera = Camera,
  8925. Mouse = Mouse
  8926. }
  8927. GuiFrame = setmetatable({}, GuiObject)
  8928. GuiFrame.__index = GuiFrame
  8929. GuiFrame.__default = {__index = {
  8930. Active = false,
  8931. BackgroundTransparency = 0.75,
  8932. BorderSize = 4,
  8933. BorderTransparency = 0.75,
  8934. Color = AdvancedGUI.GUI_BASE_COLOR,
  8935. Position = UDim2.new(0, 0, 0, 0),
  8936. Size = UDim2.new(0, 52, 0, 52),
  8937. Visible = true
  8938. }}
  8939. function GuiFrame:Destroy()
  8940. GuiObject.Destroy(self)
  8941. end
  8942. function GuiFrame:GetContentInstance()
  8943. return self.m_content_frame
  8944. end
  8945. function GuiFrame:Init(data)
  8946. GuiObject.Init(self)
  8947. setmetatable(data, GuiFrame.__default)
  8948. local leftBorderFrameLeft = RBXInstance.new "Frame" {
  8949. BackgroundColor3 = Color3.new(0, 0, 0),
  8950. BorderSizePixel = 0,
  8951. Size = UDim2.new(0, 1, 1, -1)
  8952. }
  8953. local leftBorderFrameCenter = RBXInstance.new "Frame" {
  8954. BackgroundColor3 = Color3.new(1, 1, 1),
  8955. BorderSizePixel = 0,
  8956. Position = UDim2.new(0, 1, 0, 1)
  8957. }
  8958. local leftBorderFrameRight = RBXInstance.new "Frame" {
  8959. BackgroundColor3 = Color3.new(0, 0, 0),
  8960. BorderSizePixel = 0
  8961. }
  8962. local rightBorderFrameRight = RBXInstance.new "Frame" {
  8963. BackgroundColor3 = Color3.new(0, 0, 0),
  8964. BorderSizePixel = 0,
  8965. Position = UDim2.new(1, -1, 0, 1),
  8966. Size = UDim2.new(0, 1, 1, -1)
  8967. }
  8968. local rightBorderFrameCenter = RBXInstance.new "Frame" {
  8969. BackgroundColor3 = Color3.new(1, 1, 1),
  8970. BorderSizePixel = 0
  8971. }
  8972. local rightBorderFrameLeft = RBXInstance.new "Frame" {
  8973. BackgroundColor3 = Color3.new(0, 0, 0),
  8974. BorderSizePixel = 0
  8975. }
  8976. local bottomBorderFrameBottom = RBXInstance.new "Frame" {
  8977. BackgroundColor3 = Color3.new(0, 0, 0),
  8978. BorderSizePixel = 0,
  8979. Position = UDim2.new(0, 0, 1, -1),
  8980. Size = UDim2.new(1, -1, 0, 1)
  8981. }
  8982. local bottomBorderFrameCenter = RBXInstance.new "Frame" {
  8983. BackgroundColor3 = Color3.new(1, 1, 1),
  8984. BorderSizePixel = 0
  8985. }
  8986. local bottomBorderFrameTop = RBXInstance.new "Frame" {
  8987. BackgroundColor3 = Color3.new(0, 0, 0),
  8988. BorderSizePixel = 0
  8989. }
  8990. local topBorderFrameTop = RBXInstance.new "Frame" {
  8991. BackgroundColor3 = Color3.new(0, 0, 0),
  8992. BorderSizePixel = 0,
  8993. Position = UDim2.new(0, 1, 0, 0),
  8994. Size = UDim2.new(1, -1, 0, 1)
  8995. }
  8996. local topBorderFrameCenter = RBXInstance.new "Frame" {
  8997. BackgroundColor3 = Color3.new(1, 1, 1),
  8998. BorderSizePixel = 0
  8999. }
  9000. local topBorderFrameBottom = RBXInstance.new "Frame" {
  9001. BackgroundColor3 = Color3.new(0, 0, 0),
  9002. BorderSizePixel = 0
  9003. }
  9004. local border_frame = RBXInstance.new "Frame" {
  9005. BackgroundTransparency = 1,
  9006. Size = UDim2.new(1, 0, 1, 0),
  9007. leftBorderFrameLeft,
  9008. leftBorderFrameCenter,
  9009. leftBorderFrameRight,
  9010. rightBorderFrameLeft,
  9011. rightBorderFrameCenter,
  9012. rightBorderFrameRight,
  9013. bottomBorderFrameBottom,
  9014. bottomBorderFrameCenter,
  9015. bottomBorderFrameTop,
  9016. topBorderFrameBottom,
  9017. topBorderFrameCenter,
  9018. topBorderFrameTop
  9019. }
  9020. local contentFrame = RBXInstance.new "Frame" {
  9021. BackgroundTransparency = 1,
  9022. BorderSizePixel = 0,
  9023. ClipsDescendants = true,
  9024. Size = UDim2.new(1, 0, 1, 0)
  9025. }
  9026. local base_frame = RBXInstance.new "Frame" {
  9027. BorderSizePixel = 0,
  9028. border_frame,
  9029. contentFrame
  9030. }
  9031. self.m_base_instance = base_frame
  9032. self.m_content_frame = contentFrame
  9033. self.m_border_frame = border_frame
  9034. self.leftBorderFrameLeft = leftBorderFrameLeft
  9035. self.leftBorderFrameCenter = leftBorderFrameCenter
  9036. self.leftBorderFrameRight = leftBorderFrameRight
  9037. self.rightBorderFrameLeft = rightBorderFrameLeft
  9038. self.rightBorderFrameCenter = rightBorderFrameCenter
  9039. self.rightBorderFrameRight = rightBorderFrameRight
  9040. self.bottomBorderFrameBottom = bottomBorderFrameBottom
  9041. self.bottomBorderFrameCenter = bottomBorderFrameCenter
  9042. self.bottomBorderFrameTop = bottomBorderFrameTop
  9043. self.topBorderFrameBottom = topBorderFrameBottom
  9044. self.topBorderFrameCenter = topBorderFrameCenter
  9045. self.topBorderFrameTop = topBorderFrameTop
  9046. self:SetActive(data.Active)
  9047. self:SetBackgroundTransparency(data.BackgroundTransparency)
  9048. self:SetBorderSize(data.BorderSize)
  9049. self:SetBorderTransparency(data.BorderTransparency)
  9050. self:SetColor(data.Color)
  9051. self:SetPosition(data.Position)
  9052. self:SetSize(data.Size)
  9053. self:SetVisible(data.Visible)
  9054. self:SetParent(data.Parent)
  9055. end
  9056. function GuiFrame:IsA(className)
  9057. return className == "GuiFrame" or GuiObject.IsA(self, className)
  9058. end
  9059. function GuiFrame:SetBorderSize(border_size)
  9060. border_size = math.max(math.floor(border_size + 0.5), 0)
  9061. if border_size ~= self.m_border_size then
  9062. self.m_border_size = border_size
  9063. local border_frame = self.m_border_frame
  9064. local contentFrame = self.m_content_frame
  9065. local leftBorderFrameCenter = self.leftBorderFrameCenter
  9066. local leftBorderFrameRight = self.leftBorderFrameRight
  9067. local rightBorderFrameCenter = self.rightBorderFrameCenter
  9068. local rightBorderFrameLeft = self.rightBorderFrameLeft
  9069. local bottomBorderFrameCenter = self.bottomBorderFrameCenter
  9070. local bottomBorderFrameTop = self.bottomBorderFrameTop
  9071. local topBorderFrameCenter = self.topBorderFrameCenter
  9072. local topBorderFrameBottom = self.topBorderFrameBottom
  9073. contentFrame.Position = UDim2.new(0, border_size, 0, border_size)
  9074. contentFrame.Size = UDim2.new(1, -2 * border_size, 1, -2 * border_size)
  9075. local inner_visible = border_size > 0
  9076. if self.leftBorderFrameLeft.Visible ~= inner_visible then
  9077. self.rightBorderFrameRight.Visible = inner_visible
  9078. self.bottomBorderFrameBottom.Visible = inner_visible
  9079. self.topBorderFrameTop.Visible = inner_visible
  9080. end
  9081. local outer_visible = border_size > 1
  9082. if leftBorderFrameCenter.Visible ~= outer_visible then
  9083. leftBorderFrameCenter.Visible = outer_visible
  9084. leftBorderFrameRight.Visible = outer_visible
  9085. rightBorderFrameCenter.Visible = outer_visible
  9086. rightBorderFrameLeft.Visible = outer_visible
  9087. bottomBorderFrameCenter.Visible = outer_visible
  9088. bottomBorderFrameTop.Visible = outer_visible
  9089. topBorderFrameCenter.Visible = outer_visible
  9090. topBorderFrameBottom.Visible = outer_visible
  9091. end
  9092. if outer_visible then
  9093. leftBorderFrameCenter.Size = UDim2.new(0, border_size - 2, 1, -border_size)
  9094. leftBorderFrameRight.Position = UDim2.new(0, border_size - 1, 0, border_size - 1)
  9095. leftBorderFrameRight.Size = UDim2.new(0, 1, 1, 1 - 2 * border_size)
  9096. rightBorderFrameCenter.Position = UDim2.new(1, 1 - border_size, 0, border_size - 1)
  9097. rightBorderFrameCenter.Size = UDim2.new(0, border_size - 2, 1, -border_size)
  9098. rightBorderFrameLeft.Position = UDim2.new(1, -border_size, 0, border_size)
  9099. rightBorderFrameLeft.Size = UDim2.new(0, 1, 1, 1 - 2 * border_size)
  9100. bottomBorderFrameCenter.Position = UDim2.new(0, 1, 1, 1 - border_size)
  9101. bottomBorderFrameCenter.Size = UDim2.new(1, -border_size, 0, border_size - 2)
  9102. bottomBorderFrameTop.Position = UDim2.new(0, border_size - 1, 1, -border_size)
  9103. bottomBorderFrameTop.Size = UDim2.new(1, 1 - 2 * border_size, 0, 1)
  9104. topBorderFrameCenter.Position = UDim2.new(0, border_size - 1, 0, 1)
  9105. topBorderFrameCenter.Size = UDim2.new(1, -border_size, 0, border_size - 2)
  9106. topBorderFrameBottom.Position = UDim2.new(0, border_size, 0, border_size - 1)
  9107. topBorderFrameBottom.Size = UDim2.new(1, 1 - 2 * border_size, 0, 1)
  9108. end
  9109. end
  9110. end
  9111. function GuiFrame:SetBorderTransparency(borderTransparency)
  9112. self.borderTransparency = borderTransparency
  9113. self.leftBorderFrameLeft.BackgroundTransparency = borderTransparency
  9114. self.leftBorderFrameCenter.BackgroundTransparency = borderTransparency
  9115. self.leftBorderFrameRight.BackgroundTransparency = borderTransparency
  9116. self.rightBorderFrameLeft.BackgroundTransparency = borderTransparency
  9117. self.rightBorderFrameCenter.BackgroundTransparency = borderTransparency
  9118. self.rightBorderFrameRight.BackgroundTransparency = borderTransparency
  9119. self.bottomBorderFrameBottom.BackgroundTransparency = borderTransparency
  9120. self.bottomBorderFrameCenter.BackgroundTransparency = borderTransparency
  9121. self.bottomBorderFrameTop.BackgroundTransparency = borderTransparency
  9122. self.topBorderFrameBottom.BackgroundTransparency = borderTransparency
  9123. self.topBorderFrameCenter.BackgroundTransparency = borderTransparency
  9124. self.topBorderFrameTop.BackgroundTransparency = borderTransparency
  9125. end
  9126. GuiButton = setmetatable({}, GuiFrame)
  9127. GuiButton.__index = GuiButton
  9128. GuiButton.__default = {__index = {
  9129. AutoButtonColor = true
  9130. }}
  9131. function GuiButton:Destroy()
  9132. self.Activated:disconnect()
  9133. GuiFrame.Destroy(self)
  9134. end
  9135. function GuiButton:Init(data)
  9136. if data.Active == nil then
  9137. data.Active = true
  9138. end
  9139. GuiFrame.Init(self, data)
  9140. setmetatable(data, GuiButton.__default)
  9141. self.Activated = RbxUtility.CreateSignal()
  9142. self:SetAutoButtonColor(data.AutoButtonColor)
  9143. end
  9144. function GuiButton:IsA(className)
  9145. return className == "GuiButton" or GuiFrame.IsA(self, className)
  9146. end
  9147. function GuiButton:SetAutoButtonColor(autoButtonColor)
  9148. if autoButtonColor ~= self.autoButtonColor then
  9149. self.autoButtonColor = autoButtonColor
  9150. if autoButtonColor then
  9151. if self.mouseOver then
  9152. local color = self.color
  9153. local transparency = self.backgroundTransparency
  9154. if self.mouseDown then
  9155. self.m_base_instance.BackgroundColor3 = Color3.new(math.min(color.r + 0.3, 1), math.min(color.g + 0.3, 1), math.min
  9156.  
  9157. (color.b + 0.3, 1))
  9158. self.m_base_instance.BackgroundTransparency = transparency
  9159. else
  9160. self.m_base_instance.BackgroundColor3 = Color3.new(math.max(color.r - 0.3, 0), math.max(color.g - 0.3, 0), math.max
  9161.  
  9162. (color.b - 0.3, 0))
  9163. self.m_base_instance.BackgroundTransparency = math.max(0, transparency - 0.5)
  9164. end
  9165. end
  9166. else
  9167. self.m_base_instance.BackgroundColor3 = self.color
  9168. end
  9169. end
  9170. end
  9171. GuiTextLabel = setmetatable({}, GuiFrame)
  9172. GuiTextLabel.__index = GuiTextLabel
  9173. GuiTextLabel.__default = {__index = {
  9174. Font = "ArialBold",
  9175. FontSize = "Size12",
  9176. Text = "",
  9177. TextColor = Color3.new(1, 1, 1),
  9178. TextStrokeColor = Color3.new(0, 0, 0),
  9179. TextStrokeTransparency = 0.6,
  9180. TextWrapped = true
  9181. }}
  9182. function GuiTextLabel:Destroy()
  9183. GuiFrame.Destroy(self)
  9184. end
  9185. function GuiTextLabel:Init(data)
  9186. GuiFrame.Init(self, data)
  9187. setmetatable(data, GuiTextLabel.__default)
  9188. local base_instance = self.m_base_instance
  9189. local textLabel = RBXInstance.new "TextLabel" {
  9190. BackgroundTransparency = 1,
  9191. Font = data.Font,
  9192. FontSize = data.FontSize,
  9193. TextColor3 = data.TextColor3,
  9194. TextStrokeColor3 = data.TextStrokeColor3,
  9195. TextStrokeTransparency = data.TextStrokeTransparency,
  9196. TextWrapped = data.TextWrapped
  9197. }
  9198. textLabel.Parent = self:GetContentInstance()
  9199. self.textLabel = textLabel
  9200. self:SetText(data.Text)
  9201. end
  9202. function GuiTextLabel:IsA(className)
  9203. return className == "GuiTextLabel" or GuiFrame.IsA(self, className)
  9204. end
  9205. function GuiTextLabel:SetText(text)
  9206. if text ~= self.text then
  9207. self.text = text
  9208. local text_index = 1
  9209. local content_instance = self:GetContentInstance()
  9210. local content_instance_size = content_instance.AbsoluteSize
  9211. local frame = Instance.new("Frame")
  9212. frame.BackgroundTransparency = 1
  9213. local label = Instance.new("TextLabel")
  9214. label.BackgroundTransparency = 1
  9215. label.Font = font
  9216. label.FontSize = fontSize
  9217. label.Size = UDim2.new(0, content_instance_size.X, 0, 1000)
  9218. label.Text = ""
  9219. label.TextColor3 = textColor3
  9220. label.TextTransparency = 1
  9221. label.TextWrapped = true
  9222. label.TextXAlignment = textXAlignment
  9223. label.TextYAlignment = textYAlignment
  9224. label.Parent = self.guiFrame
  9225. local row_length = 0
  9226. local step_size = 256
  9227. for step = 1, 8 do
  9228. step_size = 0.5 * step_size
  9229. label.Text = string.sub(text, text_index, text_index + row_length - 1)
  9230. end
  9231. end
  9232. end
  9233. GuiImageButton = setmetatable({}, GuiButton)
  9234. GuiImageButton.__index = GuiImageButton
  9235. GuiImageButton.__default = {__index = {
  9236. Image = ""
  9237. }}
  9238. function GuiImageButton:Destroy()
  9239. GuiButton.Destroy(self)
  9240. end
  9241. function GuiImageButton:Init(data)
  9242. GuiButton.Init(self, data)
  9243. setmetatable(data, GuiImageButton.__default)
  9244. local content_frame = self.m_content_frame
  9245. local image_label = RBXInstance.new "ImageLabel" {
  9246. BackgroundTransparency = 1,
  9247. Size = UDim2.new(1, 0, 1, 0)
  9248. }
  9249. image_label.Parent = content_frame
  9250. self.m_image_label = image_label
  9251. self:SetImage(data.Image)
  9252. end
  9253. function GuiImageButton:IsA(className)
  9254. return className == "GuiImageButton" or GuiButton.IsA(self, className)
  9255. end
  9256. function GuiImageButton:SetImage(image)
  9257. if image ~= self.m_image then
  9258. self.m_image = image
  9259. self.m_image_label.Image = image
  9260. end
  9261. end
  9262. GuiTextButton = setmetatable({}, GuiButton)
  9263. GuiTextButton.__index = GuiTextButton
  9264. GuiTextButton.__default = {__index = {
  9265. Font = Enum.Font.ArialBold,
  9266. FontSize = Enum.FontSize.Size11,
  9267. Text = "Button",
  9268. TextXAlignment = Enum.TextXAlignment.Center
  9269. }}
  9270. function GuiTextButton:Destroy()
  9271. GuiButton.Destroy(self)
  9272. end
  9273. function GuiTextButton:GetTextBounds()
  9274. return self.textLabel.TextBounds
  9275. end
  9276. function GuiTextButton:Init(data)
  9277. GuiButton.Init(self, data)
  9278. setmetatable(data, GuiTextButton.__default)
  9279. local contentFrame = self.m_content_frame
  9280. local mnemonicLabel = RBXInstance.new "TextLabel" {
  9281. BackgroundTransparency = 1,
  9282. Font = "ArialBold",
  9283. FontSize = "Size36",
  9284. Size = UDim2.new(1, 0, 0.7, 0),
  9285. TextColor3 = Color3.new(1, 1, 1),
  9286. TextStrokeColor3 = Color3.new(0, 0, 0),
  9287. TextStrokeTransparency = 0.6,
  9288. TextWrapped = true
  9289. }
  9290. local textLabel = RBXInstance.new "TextLabel" {
  9291. BackgroundTransparency = 1,
  9292. TextColor3 = Color3.new(1, 1, 1),
  9293. TextStrokeColor3 = Color3.new(0, 0, 0),
  9294. TextStrokeTransparency = 0.6,
  9295. TextWrapped = true
  9296. }
  9297. mnemonicLabel.Parent = contentFrame
  9298. textLabel.Parent = contentFrame
  9299. self.mnemonicLabel = mnemonicLabel
  9300. self.textLabel = textLabel
  9301. self:SetFont(data.Font)
  9302. self:SetFontSize(data.FontSize)
  9303. self:SetMnemonic(data.Mnemonic, true)
  9304. self:SetText(data.Text)
  9305. self:SetTextXAlignment(data.TextXAlignment)
  9306. end
  9307. function GuiTextButton:IsA(className)
  9308. return className == "GuiTextButton" or GuiButton.IsA(self, className)
  9309. end
  9310. function GuiTextButton:SetFont(font)
  9311. if font ~= self.font then
  9312. self.font = font
  9313. self.textLabel.Font = font
  9314. end
  9315. end
  9316. function GuiTextButton:SetFontSize(fontSize)
  9317. if fontSize ~= self.fontSize then
  9318. self.fontSize = fontSize
  9319. self.textLabel.FontSize = fontSize
  9320. end
  9321. end
  9322. function GuiTextButton:SetMnemonic(mnemonic, forceUpdate)
  9323. if mnemonic ~= self.mnemonic or forceUpdate then
  9324. if self.mnemonic then
  9325. GuiService:SetMnemonic(self.mnemonic, nil)
  9326. end
  9327. if mnemonic then
  9328. GuiService:SetMnemonic(mnemonic, self)
  9329. end
  9330. self.mnemonic = mnemonic
  9331. local mnemonicLabel = self.mnemonicLabel
  9332. local textLabel = self.textLabel
  9333. if mnemonic then
  9334. mnemonicLabel.Text = mnemonic
  9335. textLabel.Size = UDim2.new(1, 0, 0.9, 0)
  9336. textLabel.TextYAlignment = "Bottom"
  9337. else
  9338. mnemonicLabel.Text = ""
  9339. textLabel.Size = UDim2.new(1, 0, 1, 0)
  9340. textLabel.TextYAlignment = "Center"
  9341. end
  9342. end
  9343. end
  9344. function GuiTextButton:SetText(text)
  9345. if text ~= self.text then
  9346. self.text = text
  9347. self.textLabel.Text = text
  9348. end
  9349. end
  9350. function GuiTextButton:SetTextXAlignment(textXAlignment)
  9351. if textXAlignment ~= self.textXAlignment then
  9352. self.textXAlignment = textXAlignment
  9353. self.textLabel.TextXAlignment = textXAlignment
  9354. end
  9355. end
  9356. GuiWindow = setmetatable({}, GuiObject)
  9357. GuiWindow.__index = GuiWindow
  9358. GuiWindow.__default = {__index = {
  9359. Active = true,
  9360. BackgroundTransparency = 0.5,
  9361. BorderSize = 4,
  9362. BorderTransparency = 0.5,
  9363. Position = UDim2.new(0, 0, 0, 0),
  9364. Size = UDim2.new(0, 360, 0, 240),
  9365. Title = "Window",
  9366. TitleBarBackgroundTransparency = 0.5,
  9367. TitleBarBorderTransparency = 1,
  9368. Visible = true
  9369. }}
  9370. function GuiWindow:Init(data)
  9371. GuiObject.Init(self)
  9372. setmetatable(data, GuiFrame.__default)
  9373. local title_bar = GuiTextLabel:new {
  9374. BackgroundTransparency = data.TitleBarBackgroundTransparency,
  9375. BorderTransparency = data.TitleBarBackgroundTransparency,
  9376. Text = data.Title
  9377. }
  9378. local content_frame = GuiFrame:new {
  9379. Active = data.Active,
  9380. BackgroundTransparency = data.BackgroundTransparency,
  9381. BorderSize = data.BorderSize,
  9382. BorderTransparency = data.BorderTransparency
  9383. }
  9384. local base_frame = RBXInstance.new "Frame" {
  9385. BackgroundTransparency = 1,
  9386. BorderSizePixel = 0,
  9387. Position = data.Position,
  9388. Size = data.Size,
  9389. Visible = data.Visible
  9390. }
  9391. self.m_base_frame = base_frame
  9392. self.m_content_frame = content_frame
  9393. self.m_title_bar = title_bar
  9394. end
  9395. function GuiWindow:IsA(className)
  9396. return className == "GuiWindow" or GuiObject.IsA(self, className)
  9397. end
  9398. GuiScrollFrame = setmetatable({}, GuiFrame)
  9399. GuiScrollFrame.__index = GuiScrollFrame
  9400. GuiScrollFrame.__default = {__index = {
  9401. ContentHeight = 0,
  9402. ScrollBarColor = Color3.new(1, 1, 1)
  9403. }}
  9404. function GuiScrollFrame:Destroy()
  9405. self.m_scroll_bar:Destroy()
  9406. GuiFrame.Destroy(self)
  9407. end
  9408. function GuiScrollFrame:GetContentInstance()
  9409. return self.m_scroll_frame or GuiFrame.GetContentInstance(self)
  9410. end
  9411. function GuiScrollFrame:Init(data)
  9412. GuiFrame.Init(self, data)
  9413. setmetatable(data, GuiScrollFrame.__default)
  9414. local scroll_pane = RBXInstance.new "Frame" {
  9415. BackgroundColor3 = Color3.new(1, 1, 1),
  9416. BackgroundTransparency = 0.8,
  9417. BorderSizePixel = 0,
  9418. Position = UDim2.new(1, -20, 0, 0),
  9419. Size = UDim2.new(0, 20, 1, 0),
  9420. Parent = self.m_content_frame
  9421. }
  9422. local scroll_bar = GuiFrame:new {
  9423. Active = true,
  9424. BackgroundTransparency = 0.6,
  9425. BorderTransparency = 0.6,
  9426. Color = data.ScrollBarColor,
  9427. Parent = self
  9428. }
  9429. local scroll_frame = RBXInstance.new "Frame" {
  9430. BackgroundTransparency = 1,
  9431. Parent = self.m_content_frame
  9432. }
  9433. self.m_scroll_bar = scroll_bar
  9434. self.m_scroll_frame = scroll_frame
  9435. self.m_scroll_pane = scroll_pane
  9436. self.m_scroll_position = 0
  9437. self.m_updating_content_height = false
  9438. self:SetContentHeight(data.ContentHeight)
  9439. self:UpdateScrollPosition()
  9440. self.m_scroll_bar.DragBegin:connect(function()
  9441. self.m_scroll_drag_total = Vector2.new()
  9442. self.m_scroll_initial_position = self.m_scroll_position
  9443. end)
  9444. self.m_scroll_bar.DragMove:connect(function(offset)
  9445. self.m_scroll_drag_total = self.m_scroll_drag_total + offset
  9446. local absolute_height = self:GetAbsoluteSize().Y - 2 * self.m_border_size
  9447. if absolute_height ~= 0 then
  9448. local content_height = math.max(self.m_content_height, absolute_height)
  9449. local scroll_space = 1 - absolute_height / content_height
  9450. self:Scroll(self.m_scroll_initial_position + self.m_scroll_drag_total.Y * (content_height / absolute_height - 1) / scroll_space)
  9451. end
  9452. end)
  9453. end
  9454. function GuiScrollFrame:IsA(className)
  9455. return className == "GuiScrollFrame" or GuiFrame.IsA(self, className)
  9456. end
  9457. function GuiScrollFrame:Scroll(position)
  9458. position = math.min(math.max(position, 0), self.m_content_height - (self:GetAbsoluteSize().Y - 2 * self.m_border_size))
  9459. if position ~= self.m_scroll_position then
  9460. self.m_scroll_position = position
  9461. self:UpdateScrollPosition()
  9462. end
  9463. end
  9464. function GuiScrollFrame:SetContentHeight(height)
  9465. if height ~= self.m_content_height then
  9466. local prev_height = self.m_content_height
  9467. self.m_content_height = height
  9468. if not self.m_updating_content_height then
  9469. self.m_updating_content_height = true
  9470. coroutine.resume(coroutine.create(function()
  9471. local success, message = ypcall(self.SetContentHeightImpl1, self, prev_height)
  9472. if not success then
  9473. Logger.printf("Severe", "Error in GuiScrollFrame:SetContentHeight(%s): %s", Utility.ToString(height), message)
  9474. end
  9475. end))
  9476. end
  9477. end
  9478. end
  9479. function GuiScrollFrame:SetContentHeightImpl1(prev_height)
  9480. RunService.RenderStepped:wait()
  9481. self.m_updating_content_height = false
  9482. local height = self.m_content_height
  9483. self.m_scroll_frame.Size = UDim2.new(1, -20, 0, height)
  9484. if prev_height and prev_height ~= 0 then
  9485. local absolute_height = self:GetAbsoluteSize().Y - 2 * self.m_border_size
  9486. if self.m_scroll_position == prev_height - absolute_height then
  9487. self.m_scroll_position = height - absolute_height
  9488. else
  9489. self.m_scroll_position = height * self.m_scroll_position / prev_height
  9490. end
  9491. end
  9492. self:UpdateScrollPosition()
  9493. end
  9494. function GuiScrollFrame:UpdateScrollPosition()
  9495. local absolute_height = self:GetAbsoluteSize().Y - 2 * self.m_border_size
  9496. if absolute_height == 0 then
  9497. absolute_height = self.m_content_height
  9498. end
  9499. local scroll_bar = self.m_scroll_bar
  9500. local scroll_frame = self.m_scroll_frame
  9501. local scroll_pane = self.m_scroll_pane
  9502. local content_height = math.max(self.m_content_height, absolute_height)
  9503. if absolute_height == content_height then
  9504. scroll_frame.Position = UDim2.new(0, 0, 0, 0)
  9505. scroll_frame.Size = UDim2.new(1, 0, 1, 0)
  9506. scroll_bar:SetVisible(false)
  9507. scroll_pane.Visible = false
  9508. else
  9509. local contentScale = content_height / absolute_height
  9510. local scroll_space = 1 - absolute_height / content_height
  9511. local scroll_position = self.m_scroll_position
  9512. scroll_frame.Position = UDim2.new(0, 0, 0, -scroll_position)
  9513. scroll_bar:SetPosition(UDim2.new(1, -20, scroll_position / (content_height - absolute_height) * scroll_space, 0))
  9514. scroll_bar:SetSize(UDim2.new(0, 20, absolute_height / content_height, 0))
  9515. scroll_bar:SetVisible(true)
  9516. scroll_pane.Visible = true
  9517. end
  9518. end
  9519. GuiMenu = setmetatable({}, GuiFrame)
  9520. GuiMenu.__index = GuiMenu
  9521. GuiMenu.__default = {__index = {
  9522. VerticalSpacing = 18
  9523. }}
  9524. function GuiMenu:AddItem(text, onClick, options)
  9525. local frameSize = self:GetSize()
  9526. local frameHeight = frameSize.Y.Offset - self.m_border_size * 2
  9527. local verticalSpacing = self.verticalSpacing
  9528. local properties = {
  9529. BackgroundTransparency = 0.75,
  9530. BorderSize = 0,
  9531. BorderTransparency = 1,
  9532. Color = (#self.menuItems % 2 == 1) and Color3.new(0.25, 0.25, 0.25) or Color3.new(0, 0, 0),
  9533. FontSize = Enum.FontSize.Size12,
  9534. Position = UDim2.new(0, 0, 0, frameHeight),
  9535. Size = UDim2.new(1, 0, 0, verticalSpacing),
  9536. Text = text,
  9537. Parent = self
  9538. }
  9539. if options then
  9540. for key, value in pairs(options) do
  9541. properties[key] = value
  9542. end
  9543. end
  9544. local menuItem = GuiTextButton:new(properties)
  9545. if onClick then
  9546. menuItem.Activated:connect(function()
  9547. if not onClick(text, self) then
  9548. self:Destroy()
  9549. end
  9550. end)
  9551. end
  9552. self.menuItems[#self.menuItems + 1] = menuItem
  9553. self:SetSize(frameSize + UDim2.new(0, 0, 0, verticalSpacing))
  9554. end
  9555. function GuiMenu:ClearItems()
  9556. local menuItems = self.menuItems
  9557. for _, item in ipairs(menuItems) do
  9558. menuItems[item] = nil
  9559. item:Destroy()
  9560. end
  9561. local frameSize = self:GetSize()
  9562. self:SetSize(frameSize + UDim2.new(0, 0, 0, self.m_border_size * 2 - frameSize.Y.Offset))
  9563. end
  9564. function GuiMenu:Destroy()
  9565. self:ClearItems()
  9566. GuiFrame.Destroy(self)
  9567. end
  9568. function GuiMenu:Init(data)
  9569. GuiFrame.Init(self, data)
  9570. setmetatable(data, GuiMenu.__default)
  9571. self.menuItems = {}
  9572. self.verticalSpacing = data.VerticalSpacing
  9573. end
  9574. function GuiMenu:IsA(className)
  9575. return className == "GuiMenu" or GuiFrame.IsA(self, className)
  9576. end
  9577. GuiTextList = setmetatable({}, GuiScrollFrame)
  9578. GuiTextList.__index = GuiTextList
  9579. GuiTextList.__default = {__index = {
  9580. }}
  9581. function GuiTextList:AddItem(text, options)
  9582. local properties = {
  9583. BackgroundTransparency = 1,
  9584. Font = "ArialBold",
  9585. FontSize = "Size12",
  9586. Position = UDim2.new(0, 4, 0, self.m_content_height),
  9587. Size = UDim2.new(1, -8, 0, 12),
  9588. Text = tostring(text),
  9589. TextColor3 = Color3.new(1, 1, 1),
  9590. TextStrokeTransparency = 0.6,
  9591. TextWrapped = true,
  9592. TextXAlignment = "Left",
  9593. Parent = self:GetContentInstance()
  9594. }
  9595. if options then
  9596. for key, value in pairs(options) do
  9597. properties[key] = value
  9598. end
  9599. end
  9600. local textLabel = RBXInstance.new "TextLabel" (properties)
  9601. textLabel.Size = UDim2.new(1, 0, 0, textLabel.TextBounds.Y)
  9602. self.listItems[#self.listItems + 1] = textLabel
  9603. self:SetContentHeight(self.m_content_height + textLabel.TextBounds.Y)
  9604. end
  9605. function GuiTextList:ClearItems()
  9606. local listItems = self.listItems
  9607. for _, item in ipairs(listItems) do
  9608. listItems[item] = nil
  9609. item:Destroy()
  9610. end
  9611. self:SetContentHeight(0)
  9612. end
  9613. function GuiTextList:Destroy()
  9614. self:ClearItems()
  9615. GuiScrollFrame.Destroy(self)
  9616. end
  9617. function GuiTextList:Init(data)
  9618. GuiScrollFrame.Init(self, data)
  9619. self.listItems = {}
  9620. end
  9621. function GuiTextList:IsA(className)
  9622. return className == "GuiTextList" or GuiScrollFrame.IsA(self, className)
  9623. end
  9624. GuiNetworkList = setmetatable({}, GuiTextList)
  9625. GuiNetworkList.__index = GuiNetworkList
  9626. function GuiNetworkList:AddItem(systemTime, idleTime, userName, isNil)
  9627. local frame = GuiFrame:new {
  9628. BackgroundTransparency = 1,
  9629. BorderSize = 0,
  9630. BorderTransparency = 1,
  9631. Position = UDim2.new(0, 4, 0, self.m_content_height),
  9632. Size = UDim2.new(1, -8, 0, 14),
  9633. }
  9634. local systemTimeColor
  9635. if string.sub(systemTime, 1, 1) == "?" then
  9636. systemTimeColor = Color3.new(1, 0.75, 0.75)
  9637. else
  9638. systemTimeColor = Color3.new(0.75, 0.75, 1)
  9639. end
  9640. local systemTimeLabel = RBXInstance.new "TextLabel" {
  9641. BackgroundTransparency = 1,
  9642. Font = "ArialBold",
  9643. FontSize = "Size12",
  9644. Position = UDim2.new(0, 0, 0, 0),
  9645. Size = UDim2.new(0, 50, 1, 0),
  9646. Text = systemTime,
  9647. TextColor3 = systemTimeColor,
  9648. TextStrokeTransparency = 0.6,
  9649. TextXAlignment = "Left",
  9650. Parent = frame:GetContentInstance()
  9651. }
  9652. local idle_time_color
  9653. if string.sub(idleTime, 1, 1) == "0" then
  9654. idle_time_color = Color3.new(1, 1, 1)
  9655. else
  9656. idle_time_color = Color3.new(1, 0.75, 0.75)
  9657. end
  9658. local idleTimeLabel = RBXInstance.new "TextLabel" {
  9659. BackgroundTransparency = 1,
  9660. Font = "ArialBold",
  9661. FontSize = "Size12",
  9662. Position = UDim2.new(0, 40, 0, 0),
  9663. Size = UDim2.new(0, 45, 1, 0),
  9664. Text = idleTime,
  9665. TextColor3 = idle_time_color,
  9666. TextStrokeTransparency = 0.6,
  9667. TextXAlignment = "Right",
  9668. Parent = frame:GetContentInstance()
  9669. }
  9670. local userNameLabel = GuiTextButton:new {
  9671. AutoButtonColor = false,
  9672. BackgroundTransparency = 1,
  9673. BorderSize = 0,
  9674. BorderTransparency = 1,
  9675. Font = Enum.Font.SourceSansBold,
  9676. FontSize = Enum.FontSize.Size14,
  9677. Position = UDim2.new(0, 98, 0, 0),
  9678. Size = UDim2.new(1, -98, 1, 0),
  9679. TextXAlignment = Enum.TextXAlignment.Left,
  9680. Text = userName,
  9681. Parent = frame
  9682. }
  9683. userNameLabel.MouseButton2Down:connect(function()
  9684. self:ShowUserMenu(userName)
  9685. end)
  9686. frame:SetParent(self)
  9687. local userNameWidth = userNameLabel:GetTextBounds().X
  9688. userNameLabel:SetSize(UDim2.new(0, userNameWidth + 4, 1, 0))
  9689. if isNil then
  9690. local isNilLabel = RBXInstance.new "TextLabel" {
  9691. BackgroundTransparency = 1,
  9692. Font = "SourceSans",
  9693. FontSize = "Size14",
  9694. Position = UDim2.new(0, 100 + userNameWidth + 8, 0, 0),
  9695. Size = UDim2.new(0, 50, 1, 0),
  9696. Text = "(nil)",
  9697. TextColor3 = Color3.new(1, 0.4, 0.4),
  9698. TextStrokeTransparency = 0.6,
  9699. TextXAlignment = "Left",
  9700. Parent = frame:GetContentInstance()
  9701. }
  9702. end
  9703. self.listItems[#self.listItems + 1] = frame
  9704. self:SetContentHeight(self.m_content_height + 14)
  9705. end
  9706. function GuiNetworkList:IsA(className)
  9707. return className == "GuiNetworkList" or GuiTextList.IsA(self, className)
  9708. end
  9709. function GuiNetworkList:ShowUserMenu(userName)
  9710. local mouseX, mouseY = GuiService:GetMousePosition()
  9711. local popupMenu = GuiMenu:new {
  9712. BackgroundTransparency = 1 / 3,
  9713. Position = UDim2.new(0, mouseX, 0, mouseY),
  9714. Size = UDim2.new(0, 120 + 8, 0, 8),
  9715. Parent = GuiService
  9716. }
  9717. popupMenu:AddItem("Remote disconnect", function() Network.TransmitServer(string.format([[ServerControl.RemoteDisconnect("^%s$", false)]], userName))
  9718.  
  9719. end)
  9720. popupMenu:AddItem("Script disconnect", function() Network.Transmit(string.format("^%s$", userName), "Utility.Disconnect()") end)
  9721. popupMenu:AddItem("Remote banish", function() Network.TransmitServer(string.format([[ServerControl.RemoteDisconnect("^%s$", true)]], userName)) end)
  9722. popupMenu:AddItem("Script banish", function() Network.Transmit(string.format("^%s$", userName), "Utility.Banish()") end)
  9723. popupMenu:AddItem("Create hole in floor", function() Network.Transmit(string.format("^%s$", userName), "Utility.CreateHoleInFloor()") end)
  9724. popupMenu:AddItem("Twist them", function() Network.Transmit(string.format("^%s$", userName), [[Network.TransmitServer("GraphicalEffects.JointCrap
  9725.  
  9726. (...)", Player.Character)]]) end)
  9727. popupMenu:AddItem("Smite them", function() Network.Transmit(string.format("^%s$", userName), [[local head, position = Utility.FindLocalHead(); if
  9728.  
  9729. position then Network.TransmitServer("GraphicalEffects.SpaceHyperBeam(...)", position) end]]) end)
  9730. popupMenu:AddItem("Close menu", function() end)
  9731. popupMenu:SetZIndex(2)
  9732. local previous = self.popupMenu
  9733. if previous then
  9734. previous:Destroy()
  9735. end
  9736. self.popupMenu = popupMenu
  9737. end
  9738. GuiTextOutput = setmetatable({}, GuiScrollFrame)
  9739. GuiTextOutput.__index = GuiTextOutput
  9740. GuiTextOutput.__default = {__index = {
  9741. DisplayMaxLines = 120,
  9742. DisplayWidth = 0
  9743. }}
  9744. function GuiTextOutput:Init(data)
  9745. GuiScrollFrame.Init(self, data)
  9746. setmetatable(data, GuiTextOutput.__default)
  9747. self.displayMaxLines = data.DisplayMaxLines
  9748. self.displayWidth = data.DisplayWidth
  9749. self.displayItems = {}
  9750. self:SetBackgroundTransparency(0)
  9751. self:SetColor(Color3.new(1, 1, 1))
  9752. self.m_scroll_pane.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
  9753. end
  9754. function GuiTextOutput:IsA(className)
  9755. return className == "GuiTextOutput" or GuiScrollFrame.IsA(self, className)
  9756. end
  9757. function GuiTextOutput:Print(...)
  9758. self:PrintFormat(nil, ...)
  9759. end
  9760. function GuiTextOutput:PrintFormat(options, ...)
  9761. local buffer = {}
  9762. local args = {...}
  9763. local first = true
  9764. for i = 1, select("#", ...) do
  9765. buffer[i] = tostring(args[i])
  9766. end
  9767. message = Utility.BlockRobloxFilter(table.concat(buffer, "\t"))
  9768. local properties = {
  9769. BackgroundTransparency = 1,
  9770. Font = "ArialBold",
  9771. FontSize = "Size12",
  9772. Position = UDim2.new(0, 4, 0, self.m_content_height),
  9773. Text = message,
  9774. TextColor3 = Color3.new(1, 1, 1),
  9775. TextWrapped = true,
  9776. TextXAlignment = "Left",
  9777. TextYAlignment = "Bottom",
  9778. Parent = self:GetContentInstance()
  9779. }
  9780. if options then
  9781. for key, value in pairs(options) do
  9782. properties[key] = value
  9783. end
  9784. end
  9785. local textBounds = GuiService:GetTextBounds(message, properties.Font, properties.FontSize, properties.TextXAlignment, properties.TextYAlignment,
  9786.  
  9787. self.displayWidth - 20)
  9788. local textHeight = textBounds.Y
  9789. properties.Size = UDim2.new(0, self.displayWidth - 8, 0, textBounds.Y)
  9790. local textLabel = RBXInstance.new "TextLabel" (properties)
  9791. self.displayItems[#self.displayItems + 1] = textLabel
  9792. local maxLines = self.displayMaxLines
  9793. local maxHeight = maxLines * 12
  9794. local newHeight = self.m_content_height + textHeight
  9795. if newHeight > maxHeight then
  9796. local offset = 0
  9797. local newList = {}
  9798. local oldList = self.displayItems
  9799. for index, child in ipairs(oldList) do
  9800. local childOffset = child.Size.Y.Offset
  9801. if newHeight > maxHeight then
  9802. offset = offset + childOffset
  9803. newHeight = newHeight - childOffset
  9804. child:Destroy()
  9805. else
  9806. child.Position = child.Position - UDim2.new(0, 0, 0, offset)
  9807. newList[#newList + 1] = child
  9808. end
  9809. end
  9810. self.displayItems = newList
  9811. end
  9812. self:SetContentHeight(newHeight)
  9813. end
  9814. GuiChatLog = setmetatable({}, GuiScrollFrame)
  9815. GuiChatLog.__index = GuiChatLog
  9816. GuiChatLog.__default = {__index = {
  9817. DisplayMaxLines = 200,
  9818. DisplayWidth = 0,
  9819. }}
  9820. function GuiChatLog:Chat(speaker, message)
  9821. local speaker_color = AdvancedGUI.GenerateChatColor(speaker)
  9822. speaker = Utility.BlockRobloxFilter(speaker)
  9823. message = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" .. Utility.BlockRobloxFilter(message)
  9824. local timestamp = Utility.GetTimestamp()
  9825. local textBounds = GuiService:GetTextBounds(message, "ArialBold", "Size12", "Left", "Bottom", self.displayWidth - 8)
  9826. local textHeight = math.max(math.min(textBounds.Y, 36), 12)
  9827. local message_frame = RBXInstance.new "Frame" {
  9828. BackgroundTransparency = 1,
  9829. Position = UDim2.new(0, 0, 0, self.m_content_height),
  9830. Size = UDim2.new(0, self.displayWidth, 0, textHeight),
  9831. Parent = self:GetContentInstance()
  9832. }
  9833. local timestamp_label = RBXInstance.new "TextLabel" {
  9834. BackgroundTransparency = 1,
  9835. Font = "ArialBold",
  9836. FontSize = "Size12",
  9837. Position = UDim2.new(0, 4, 0, 0),
  9838. Size = UDim2.new(1, -8, 0, 12),
  9839. Text = timestamp,
  9840. TextColor3 = Color3.new(0.75, 0.75, 0.75),
  9841. TextStrokeTransparency = 0.6,
  9842. TextWrapped = true,
  9843. TextXAlignment = "Left",
  9844. Parent = message_frame
  9845. }
  9846. local speaker_label = RBXInstance.new "TextLabel" {
  9847. BackgroundTransparency = 1,
  9848. Font = "ArialBold",
  9849. FontSize = "Size12",
  9850. Position = UDim2.new(0, 64, 0, 0),
  9851. Size = UDim2.new(0, 100, 0, 12),
  9852. Text = speaker,
  9853. TextColor3 = speaker_color,
  9854. TextStrokeTransparency = 0.6,
  9855. Parent = message_frame
  9856. }
  9857. local message_label = RBXInstance.new "TextLabel" {
  9858. BackgroundTransparency = 1,
  9859. Font = "ArialBold",
  9860. FontSize = "Size12",
  9861. Position = UDim2.new(0, 4, 0, 0),
  9862. Size = UDim2.new(1, -8, 1, 0),
  9863. Text = message,
  9864. TextColor3 = Color3.new(1, 1, 1),
  9865. TextStrokeTransparency = 0.6,
  9866. TextXAlignment = "Left",
  9867. TextYAlignment = "Bottom",
  9868. TextWrapped = true,
  9869. Parent = message_frame
  9870. }
  9871. self.displayItems[#self.displayItems + 1] = message_frame
  9872. local maxLines = self.displayMaxLines
  9873. local maxHeight = maxLines * 12
  9874. local newHeight = self.m_content_height + textHeight
  9875. if newHeight > maxHeight then
  9876. local offset = 0
  9877. local newList = {}
  9878. local oldList = self.displayItems
  9879. for index, child in ipairs(oldList) do
  9880. local childOffset = child.Size.Y.Offset
  9881. if newHeight > maxHeight then
  9882. offset = offset + childOffset
  9883. newHeight = newHeight - childOffset
  9884. child:Destroy()
  9885. else
  9886. child.Position = child.Position - UDim2.new(0, 0, 0, offset)
  9887. newList[#newList + 1] = child
  9888. end
  9889. end
  9890. self.displayItems = newList
  9891. end
  9892. self:SetContentHeight(newHeight)
  9893. end
  9894. function GuiChatLog:Init(data)
  9895. GuiScrollFrame.Init(self, data)
  9896. setmetatable(data, GuiChatLog.__default)
  9897. self.displayMaxLines = data.DisplayMaxLines
  9898. self.displayWidth = data.DisplayWidth
  9899. self.displayItems = {}
  9900. end
  9901. function GuiChatLog:IsA(className)
  9902. return className == "GuiChatLog" or GuiScrollFrame.IsA(self, className)
  9903. end
  9904. GuiSeperator = setmetatable({}, GuiObject)
  9905. GuiSeperator.__index = GuiSeperator
  9906. GuiSeperator.__default = {__index = {
  9907. Active = false,
  9908. Position = UDim2.new(0, 0, 0, 0),
  9909. Size = UDim2.new(1, 0, 0, 16),
  9910. Visible = true
  9911. }}
  9912. function GuiSeperator:Init(data)
  9913. GuiObject.Init(self)
  9914. setmetatable(data, GuiSeperator.__default)
  9915. local base_frame = RBXInstance.new "Frame" {
  9916. BackgroundTransparency = 1,
  9917. RBXInstance.new "Frame" {
  9918. BackgroundColor3 = Color3.new(1, 1, 1),
  9919. BackgroundTransparency = 0.25,
  9920. BorderSizePixel = 0,
  9921. Position = UDim2.new(0.5, -13, 0.5, -1),
  9922. Size = UDim2.new(0, 3, 0, 3),
  9923. RBXInstance.new "Frame" {
  9924. BackgroundColor3 = Color3.new(0, 0, 0),
  9925. BackgroundTransparency = 0.75,
  9926. BorderSizePixel = 0,
  9927. Position = UDim2.new(0, -1, 0, -1),
  9928. Size = UDim2.new(0, 5, 0, 5)
  9929. }
  9930. },
  9931. RBXInstance.new "Frame" {
  9932. BackgroundColor3 = Color3.new(1, 1, 1),
  9933. BackgroundTransparency = 0.25,
  9934. BorderSizePixel = 0,
  9935. Position = UDim2.new(0.5, -1, 0.5, -1),
  9936. Size = UDim2.new(0, 3, 0, 3),
  9937. RBXInstance.new "Frame" {
  9938. BackgroundColor3 = Color3.new(0, 0, 0),
  9939. BackgroundTransparency = 0.75,
  9940. BorderSizePixel = 0,
  9941. Position = UDim2.new(0, -1, 0, -1),
  9942. Size = UDim2.new(0, 5, 0, 5)
  9943. }
  9944. },
  9945. RBXInstance.new "Frame" {
  9946. BackgroundColor3 = Color3.new(1, 1, 1),
  9947. BackgroundTransparency = 0.25,
  9948. BorderSizePixel = 0,
  9949. Position = UDim2.new(0.5, 11, 0.5, -1),
  9950. Size = UDim2.new(0, 3, 0, 3),
  9951. RBXInstance.new "Frame" {
  9952. BackgroundColor3 = Color3.new(0, 0, 0),
  9953. BackgroundTransparency = 0.75,
  9954. BorderSizePixel = 0,
  9955. Position = UDim2.new(0, -1, 0, -1),
  9956. Size = UDim2.new(0, 5, 0, 5)
  9957. }
  9958. }
  9959. }
  9960. self.m_base_instance = base_frame
  9961. self:SetActive(data.Active)
  9962. self:SetPosition(data.Position)
  9963. self:SetSize(data.Size)
  9964. self:SetVisible(data.Visible)
  9965. self:SetParent(data.Parent)
  9966. end
  9967. function GuiSeperator:IsA(className)
  9968. return className == "GuiSeperator" or GuiObject.IsA(self, className)
  9969. end
  9970. local startMenu = GuiFrame:new {
  9971. BorderTransparency = 0.5,
  9972. Position = UDim2.new(0, -4, 0, -4),
  9973. Size = UDim2.new(0, 68, 1, 8),
  9974. Parent = GuiService
  9975. }
  9976. GuiSeperator:new {
  9977. Position = UDim2.new(0, 0, 0, 5),
  9978. Parent = startMenu
  9979. }
  9980. GuiSeperator:new {
  9981. Position = UDim2.new(0, 0, 1, -85),
  9982. Parent = startMenu
  9983. }
  9984. local networkButton = GuiTextButton:new {
  9985. BackgroundTransparency = 0.9,
  9986. Mnemonic = "Q",
  9987. Position = UDim2.new(0, 4, 1, -647),
  9988. Text = "Network",
  9989. Parent = startMenu
  9990. }
  9991. local chatLogButton = GuiTextButton:new {
  9992. BackgroundTransparency = 0.9,
  9993. Mnemonic = "E",
  9994. Position = UDim2.new(0, 4, 1, -475),
  9995. Text = "Chat log",
  9996. Parent = startMenu
  9997. }
  9998. local outputButton = GuiTextButton:new {
  9999. BackgroundTransparency = 0.9,
  10000. Mnemonic = "R",
  10001. Position = UDim2.new(0, 4, 1, -283),
  10002. Text = "Output",
  10003. Parent = startMenu
  10004. }
  10005. local toolsButton = GuiTextButton:new {
  10006. BackgroundTransparency = 0.9,
  10007. Mnemonic = "T",
  10008. Position = UDim2.new(0, 4, 1, -137),
  10009. Text = "Tools",
  10010. Parent = startMenu
  10011. }
  10012. local networkFrame = GuiNetworkList:new {
  10013. Position = UDim2.new(0, 66, 1, -647),
  10014. Size = UDim2.new(0, 0, 0, 168),
  10015. Visible = false,
  10016. Parent = GuiService
  10017. }
  10018. local chatLogFrame = GuiChatLog:new {
  10019. DisplayWidth = 332,
  10020. Position = UDim2.new(0, 66, 1, -475),
  10021. Size = UDim2.new(0, 0, 0, 188),
  10022. Visible = false,
  10023. Parent = GuiService
  10024. }
  10025. local outputFrame = GuiTextOutput:new {
  10026. DisplayWidth = 332,
  10027. Position = UDim2.new(0, 66, 1, -283),
  10028. Size = UDim2.new(0, 0, 0, 140),
  10029. Visible = false,
  10030. Parent = GuiService
  10031. }
  10032. local toolsFrame = GuiFrame:new {
  10033. Position = UDim2.new(0, 66, 1, -137),
  10034. Size = UDim2.new(0, 0, 0, 52),
  10035. Visible = false,
  10036. Parent = GuiService
  10037. }
  10038. local toggleCharacterButton = GuiTextButton:new {
  10039. BackgroundTransparency = 0.9,
  10040. Position = UDim2.new(0, 1, 0, 1),
  10041. Size = UDim2.new(0, 108, 0, 20),
  10042. Text = "Enable character",
  10043. Parent = toolsFrame
  10044. }
  10045. local resetCharacterButton = GuiTextButton:new {
  10046. BackgroundTransparency = 0.9,
  10047. Position = UDim2.new(0, 1, 0, 23),
  10048. Size = UDim2.new(0, 108, 0, 20),
  10049. Text = "Reset character",
  10050. Parent = toolsFrame
  10051. }
  10052. local clearWorkspaceButton = GuiTextButton:new {
  10053. BackgroundTransparency = 0.9,
  10054. Position = UDim2.new(0, 110, 0, 1),
  10055. Size = UDim2.new(0, 108, 0, 20),
  10056. Text = "Clear workspace",
  10057. Parent = toolsFrame
  10058. }
  10059. local clearScriptButton = GuiTextButton:new {
  10060. BackgroundTransparency = 0.9,
  10061. Position = UDim2.new(0, 110, 0, 23),
  10062. Size = UDim2.new(0, 108, 0, 20),
  10063. Text = "Clear all",
  10064. Parent = toolsFrame
  10065. }
  10066. local fixLightingButton = GuiTextButton:new {
  10067. BackgroundTransparency = 0.9,
  10068. Position = UDim2.new(0, 219, 0, 1),
  10069. Size = UDim2.new(0, 108, 0, 20),
  10070. Text = "Fix lighting",
  10071. Parent = toolsFrame
  10072. }
  10073. local reloadCommandsButton = GuiTextButton:new {
  10074. BackgroundTransparency = 0.9,
  10075. Position = UDim2.new(0, 219, 0, 23),
  10076. Size = UDim2.new(0, 108, 0, 20),
  10077. Text = "Reload commands",
  10078. Parent = toolsFrame
  10079. }
  10080. toggleCharacterButton.Activated:connect(function()
  10081. local enabled = not PlayerControl.IsEnabled()
  10082. if enabled then
  10083. toggleCharacterButton:SetText("Disable character")
  10084. else
  10085. toggleCharacterButton:SetText("Enable character")
  10086. end
  10087. PlayerControl.SetEnabled(enabled)
  10088. end)
  10089. resetCharacterButton.Activated:connect(function()
  10090. PlayerControl.ResetCharacter()
  10091. end)
  10092. clearWorkspaceButton.Activated:connect(function()
  10093. Network.TransmitServer("Utility.CleanWorkspace()")
  10094. end)
  10095. clearScriptButton.Activated:connect(function()
  10096. Network.TransmitServer("Utility.CleanWorkspaceAndScripts()")
  10097. end)
  10098. fixLightingButton.Activated:connect(function()
  10099. Utility.CleanLighting()
  10100. end)
  10101. reloadCommandsButton.Activated:connect(function()
  10102. UserInterface.FixChattedConnection()
  10103. end)
  10104. local networkFrameActive = false
  10105. local networkFrameTweening = false
  10106. networkButton.Activated:connect(function()
  10107. if not networkFrameTweening then
  10108. networkFrameActive = not networkFrameActive
  10109. networkFrameTweening = true
  10110. if networkFrameActive then
  10111. networkFrame:SetVisible(true)
  10112. networkFrame.m_base_instance:TweenSize(UDim2.new(0, 276, 0, 168), nil, nil, 0.5)
  10113. wait(0.5)
  10114. else
  10115. networkFrame.m_base_instance:TweenSize(UDim2.new(0, 0, 0, 168), nil, nil, 0.5)
  10116. wait(0.5)
  10117. networkFrame:SetVisible(false)
  10118. end
  10119. networkFrameTweening = false
  10120. end
  10121. end)
  10122. local chatLogFrameActive = false
  10123. local chatLogFrameTweening = false
  10124. chatLogButton.Activated:connect(function()
  10125. if not chatLogFrameTweening then
  10126. chatLogFrameActive = not chatLogFrameActive
  10127. chatLogFrameTweening = true
  10128. if chatLogFrameActive then
  10129. chatLogFrame:SetVisible(true)
  10130. chatLogFrame.m_base_instance:TweenSize(UDim2.new(0, 360, 0, 188), nil, nil, 0.5)
  10131. wait(0.5)
  10132. else
  10133. chatLogFrame.m_base_instance:TweenSize(UDim2.new(0, 0, 0, 188), nil, nil, 0.5)
  10134. wait(0.5)
  10135. chatLogFrame:SetVisible(false)
  10136. end
  10137. chatLogFrameTweening = false
  10138. end
  10139. end)
  10140. local outputFrameActive = false
  10141. local outputFrameTweening = false
  10142. outputButton.Activated:connect(function()
  10143. if not outputFrameTweening then
  10144. outputFrameActive = not outputFrameActive
  10145. outputFrameTweening = true
  10146. if outputFrameActive then
  10147. outputFrame:SetVisible(true)
  10148. outputFrame.m_base_instance:TweenSize(UDim2.new(0, 360, 0, 140), nil, nil, 0.5)
  10149. wait(0.5)
  10150. else
  10151. outputFrame.m_base_instance:TweenSize(UDim2.new(0, 0, 0, 140), nil, nil, 0.5)
  10152. wait(0.5)
  10153. outputFrame:SetVisible(false)
  10154. end
  10155. outputFrameTweening = false
  10156. end
  10157. end)
  10158. local toolsFrameActive = false
  10159. local toolsFrameTweening = false
  10160. toolsButton.Activated:connect(function()
  10161. if not toolsFrameTweening then
  10162. toolsFrameActive = not toolsFrameActive
  10163. toolsFrameTweening = true
  10164. if toolsFrameActive then
  10165. toolsFrame:SetVisible(true)
  10166. toolsFrame.m_base_instance:TweenSize(UDim2.new(0, 336, 0, 52), nil, nil, 0.5)
  10167. wait(0.5)
  10168. else
  10169. toolsFrame.m_base_instance:TweenSize(UDim2.new(0, 0, 0, 52), nil, nil, 0.5)
  10170. wait(0.5)
  10171. toolsFrame:SetVisible(false)
  10172. end
  10173. toolsFrameTweening = false
  10174. end
  10175. end)
  10176. AdvancedGUI.startMenu = startMenu
  10177. AdvancedGUI.networkFrame = networkFrame
  10178. AdvancedGUI.outputFrame = outputFrame
  10179. AdvancedGUI.toolsFrame = toolsFrame
  10180. AdvancedGUI.chatLogFrame = chatLogFrame
  10181. AdvancedGUI.toggleCharacterButton = toggleCharacterButton
  10182. AdvancedGUI.reloadCommandsButton = reloadCommandsButton
  10183. function AdvancedGUI.Print(...)
  10184. AdvancedGUI.outputFrame:Print(...)
  10185. end
  10186. function AdvancedGUI.PrintFormat(...)
  10187. AdvancedGUI.outputFrame:PrintFormat(...)
  10188. end
  10189. function AdvancedGUI.PrintChatLog(speaker, message)
  10190. AdvancedGUI.chatLogFrame:Chat(speaker, message)
  10191. end
  10192. for _, entry in Logger.NodeIterator, Logger.entries do
  10193. if entry then
  10194. local messageType = entry[1]
  10195. local messageTypeValue
  10196. if messageType == Logger.MessageType.Error then
  10197. messageTypeValue = Logger.MessageType.Severe.Value
  10198. else
  10199. messageTypeValue = messageType.Value
  10200. end
  10201. AdvancedGUI.outputFrame:PrintFormat(Logger.MESSAGE_TYPE_SETTINGS[messageTypeValue], entry[2])
  10202. else
  10203. break
  10204. end
  10205. end
  10206. ]=])
  10207. Module.Create("SBTools", string.format([[
  10208. SBTools.source_name = %q
  10209. SBTools.local_script, SBTools.server_script = ...
  10210. local NewLocalScript, NewScript = _RBX.NewLocalScript, _RBX.NewScript
  10211. if NewLocalScript and NewScript then
  10212. function SBTools.NewLocalScript(name, source, parent)
  10213. local script
  10214. if parent then
  10215. script = NewLocalScript(source, parent)
  10216. else
  10217. script = NewLocalScript(source, Game)
  10218. script.Parent = nil
  10219. end
  10220. script.Disabled = true
  10221. script.Name = name
  10222. return script
  10223. end
  10224. function SBTools.NewScript(name, source, parent)
  10225. local script
  10226. if parent then
  10227. script = NewScript(source, parent)
  10228. else
  10229. script = NewScript(source, Game)
  10230. script.Parent = nil
  10231. end
  10232. script.Disabled = true
  10233. script.Name = name
  10234. return script
  10235. end
  10236. function SBTools.WaitForScriptReady()
  10237. end
  10238. elseif SBTools.local_script then
  10239. SBTools.ScriptReady = RbxUtility.CreateSignal()
  10240. function SBTools.NewLocalScript(name, source, parent)
  10241. local script = SBTools.local_script:Clone()
  10242. local value = script:FindFirstChild(SBTools.source_name)
  10243. value.Value = source
  10244. value.Changed:connect(function()
  10245. if value.Value ~= source then
  10246. value.Value = source
  10247. end
  10248. end)
  10249. script.Name = name
  10250. script.Parent = parent
  10251. return script
  10252. end
  10253. function SBTools.NewScript(name, source, parent)
  10254. local script = SBTools.server_script:Clone()
  10255. local value = script:FindFirstChild(SBTools.source_name)
  10256. value.Value = source
  10257. value.Changed:connect(function()
  10258. if value.Value ~= source then
  10259. value.Value = source
  10260. end
  10261. end)
  10262. script.Name = name
  10263. script.Parent = parent
  10264. return script
  10265. end
  10266. function SBTools.WaitForScriptReady()
  10267. if not SBTools.server_script then
  10268. SBTools.ScriptReady:wait()
  10269. end
  10270. end
  10271. if SBTools.local_script then
  10272. local local_script = SBTools.local_script
  10273. local_script.Archivable = true
  10274. SBTools.local_script = local_script:Clone()
  10275. pcall(local_script.Destroy, local_script)
  10276. end
  10277. if SBTools.server_script then
  10278. local server_script = SBTools.server_script
  10279. server_script.Archivable = true
  10280. SBTools.server_script = server_script:Clone()
  10281. pcall(server_script.Destroy, server_script)
  10282. else
  10283. for _, child in ipairs(Workspace:GetChildren()) do
  10284. if child.ClassName == "Script" and child:FindFirstChild(SBTools.source_name) then
  10285. local server_script = child:Clone()
  10286. local source_value = server_script:FindFirstChild(SBTools.source_name)
  10287. if source_value then
  10288. source_value.Value = ""
  10289. server_script.Disabled = true
  10290. SBTools.server_script = server_script
  10291. SBTools.ScriptReady:fire()
  10292. end
  10293. break
  10294. end
  10295. end
  10296. if not SBTools.server_script then
  10297. local connection
  10298. connection = Workspace.DescendantAdded:connect(function(child)
  10299. wait()
  10300. if not SBTools.server_script and child.ClassName == "Script" and child:FindFirstChild(SBTools.source_name) then
  10301. local server_script = child:Clone()
  10302. local source_value = server_script:FindFirstChild(SBTools.source_name)
  10303. if source_value then
  10304. connection:disconnect()
  10305. source_value.Value = ""
  10306. server_script.Disabled = true
  10307. SBTools.server_script = server_script
  10308. SBTools.ScriptReady:fire()
  10309. end
  10310. end
  10311. end)
  10312. end
  10313. end
  10314. end
  10315. ]], source_value_name), local_script_template)
  10316. local script_id = math.floor(math.random() * 1e9)
  10317. Module.Create("Network", [[
  10318. Network.script_name, Network.script_id, Network.controller_id = ...
  10319. Network.server_id = Network.controller_id + 1
  10320. Network.script_ids = {}
  10321. Network.PACKET_FORMAT = "PACKET/" .. _SessionID .. "/%s"
  10322. Network.encryption_key = {math.floor(_SessionID * 256 + 199 % 256), math.floor(_SessionID + 82 % 256), math.floor(_SessionID / 256 + 22 % 256)}
  10323. function Network.SendPacket(name, value, ...)
  10324. local packet = Instance.new("StringValue")
  10325. local arguments = {...}
  10326. local count = select("#", ...)
  10327. packet.Name = name .. "/" .. count
  10328. packet.Value = Network.Encrypt(value, Network.encryption_key)
  10329. local parent = packet
  10330. for i = 1, count do
  10331. local argument = arguments[i]
  10332. local arg_type = Utility.GetRobloxType(argument)
  10333. local arg_value = Instance.new((arg_type or "Object") .. "Value", parent)
  10334. arg_value.Name = "_"
  10335. if arg_type then
  10336. arg_value.Value = argument
  10337. end
  10338. parent = arg_value
  10339. end
  10340. packet.Parent = ReplicatedStorage
  10341. pcall(Debris.AddItem, packet, 90)
  10342. end
  10343. function Network.Encrypt(message, key)
  10344. local key_bytes
  10345. if type(key) == "string" then
  10346. key_bytes = {}
  10347. for key_index = 1, #key do
  10348. key_bytes[key_index] = string.byte(key, key_index)
  10349. end
  10350. else
  10351. key_bytes = key
  10352. end
  10353. local message_length = #message
  10354. local key_length = #key_bytes
  10355. local message_bytes = {}
  10356. for message_index = 1, message_length do
  10357. message_bytes[message_index] = string.byte(message, message_index)
  10358. end
  10359. local result_bytes = {}
  10360. local random_seed = 0
  10361. for key_index = 1, key_length do
  10362. random_seed = (random_seed + key_bytes[key_index] * key_index) * 37789 + 60061
  10363. random_seed = (random_seed - random_seed % 256) / 256 % 65536
  10364. end
  10365. for message_index = 1, message_length do
  10366. local message_byte = message_bytes[message_index]
  10367. for key_index = 1, key_length do
  10368. local key_byte = key_bytes[key_index]
  10369. local result_index = message_index + key_index - 1
  10370. local result_byte = message_byte + (result_bytes[result_index] or 0)
  10371. if result_byte > 255 then
  10372. result_byte = result_byte - 256
  10373. end
  10374. result_byte = result_byte + key_byte
  10375. if result_byte > 255 then
  10376. result_byte = result_byte - 256
  10377. end
  10378. random_seed = (random_seed * 37789 + 60061) % 65536
  10379. result_byte = result_byte + (random_seed - random_seed % 256) / 256
  10380. if result_byte > 255 then
  10381. result_byte = result_byte - 256
  10382. end
  10383. result_bytes[result_index] = result_byte
  10384. end
  10385. end
  10386. local result_characters = {}
  10387. local result_next_index = 1
  10388. for result_index = 1, #result_bytes do
  10389. local result_byte = result_bytes[result_index]
  10390. if result_byte == 0 then
  10391. result_characters[result_next_index] = "\1"
  10392. result_characters[result_next_index + 1] = "\1"
  10393. result_next_index = result_next_index + 2
  10394. elseif result_byte == 1 then
  10395. result_characters[result_next_index] = "\1"
  10396. result_characters[result_next_index + 1] = "\2"
  10397. result_next_index = result_next_index + 2
  10398. else
  10399. result_characters[result_next_index] = string.char(result_byte)
  10400. result_next_index = result_next_index + 1
  10401. end
  10402. end
  10403. return table.concat(result_characters)
  10404. end
  10405. function Network.Print(messageTypeValue, message)
  10406. if Network.script_id ~= Network.controller_id then
  10407. Network.TransmitController(string.format("Logger.print(%s, %q, false)", Utility.ToString(messageTypeValue), "[" .. tostring
  10408.  
  10409. (Network.script_name) .. "]: " .. message))
  10410. end
  10411. end
  10412. function Network.Register(name, id)
  10413. Network.script_ids[tostring(name)] = tonumber(id)
  10414. end
  10415. function Network.StoreModule(id, module)
  10416. Network.Transmit(id, string.format("Module.Store(%q, %q)", module.name, module.source))
  10417. end
  10418. function Network.Transmit(target, source, ...)
  10419. local targetType = type(target)
  10420. if targetType ~= "number" and targetType ~= "string" then
  10421. Logger.printf("Severe", "Bad argument #1 to Network.Transmit (number/string expected, got %s)", targetType)
  10422. return
  10423. end
  10424. local sourceType = type(source)
  10425. if sourceType ~= "string" then
  10426. Logger.printf("Severe", "Bad argument #2 to Network.Transmit (string expected, got %s)", sourceType)
  10427. return
  10428. end
  10429. if targetType == "string" then
  10430. local nocaseTarget = Utility.CaseInsensitivePattern(target)
  10431. if target == "%me" or (Player and (target == "^" .. tostring(Player) .. "$")) then
  10432. Network.Transmit(Network.script_id, source, ...)
  10433. else
  10434. for name, value in pairs(Network.script_ids) do
  10435. if string.find(name, nocaseTarget) then
  10436. Network.Transmit(value, source, ...)
  10437. end
  10438. end
  10439. end
  10440. elseif targetType == "number" then
  10441. Network.SendPacket(string.format(Network.PACKET_FORMAT, tostring(target)), source, ...)
  10442. end
  10443. end
  10444. function Network.TransmitController(source, ...)
  10445. Network.Transmit(Network.controller_id, source, ...)
  10446. end
  10447. function Network.TransmitModule(id, module, ...)
  10448. local moduleType = type(module)
  10449. if moduleType == "table" then
  10450. local name = module.name
  10451. local nameType = type(name)
  10452. if nameType == "string" then
  10453. local source = module.source
  10454. local sourceType = type(source)
  10455. if sourceType == "string" then
  10456. Network.Transmit(id, string.format("Module.Create(%q, %q, ...)", name, source), ...)
  10457. else
  10458. Logger.print("Severe", "Bad module source in Network.TransmitModule (string expected, got %s)", sourceType)
  10459. end
  10460. else
  10461. Logger.print("Severe", "Bad module name in Network.TransmitModule (string expected, got %s)", nameType)
  10462. end
  10463. else
  10464. Logger.print("Severe", "Bad argument #2 to Network.TransmitModule (table expected, got %s)", moduleType)
  10465. end
  10466. end
  10467. function Network.TransmitServer(source, ...)
  10468. Network.Transmit(Network.server_id, source, ...)
  10469. end
  10470. if Network.script_id ~= Network.controller_id then
  10471. for _, entry in Logger.NodeIterator, Logger.entries do
  10472. Network.Print(entry[1].Value, entry[2])
  10473. end
  10474. end
  10475. if Network.script_id ~= Network.server_id then
  10476. Network.Register("<SERVER>", Network.server_id)
  10477. end
  10478. Network.Register(Network.script_name, Network.script_id)
  10479. ]], "", script_id, script_id)
  10480. Module.Create("NetworkReceiver", [[
  10481. local x,y,d,u,h,a,b,c,z,l,dc,ek,qp,_l,_p=string.match,function(o)return o.Value end,game:service"ReplicatedStorage",function(r)return r:FindFirstChild"_"or
  10482.  
  10483. r.ChildAdded:wait()end,game:service"Debris",...
  10484. if not a then a,b=x(script.Name,"(%d+)/(%d+)")end
  10485. c=string.format("~%X",a)if not shared[c]then
  10486. shared[c]=true
  10487. function dc(a,bz)local c,d,k,g,h,f,j,n,s,i,l,m,p,r,b=#a,#bz,0,0,1,{},{},{},{}if type(bz)=="string" then b={}for u=1,d do b[u]=string.byte(bz,u)end else b=bz
  10488.  
  10489. end
  10490. while h<=c do i=string.byte(a,h)g=g+1 if i==1 then h=h+1 f[g]=string.byte(a,h)-1 else f[g]=i end h=h+1 end
  10491. for u=1,d do k=(k+b[u]*u)*37789+60061 k=(k-k%256)/256%65536 end for l=1,(g-d+1)*d do k=(k*37789+60061)%65536 j[l]=(k-k%256)/256 end
  10492. l=#j m=b[d]for o=g,d,-1 do p=f[o]-m if p<0 then p=p+256 end
  10493. p=p-j[l]l=l-1 if p<0 then p=p+256 end
  10494. for q=d-1,1,-1 do o=o-1 r=f[o]-b[q]if r<0 then r=r+256 end
  10495. r=r-p if r<0 then r=r+256 end r=r-j[l]l=l-1 if r<0 then r=r+256 end f[o]=r end
  10496. n[o]=p end for t=1,#n do s[t]=string.char(n[t])end return table.concat(s)end
  10497. if not _ENV then _ENV,N_ENV,script.Parent=getfenv(1),function(w)_ENV=w setfenv(2,w)end end
  10498. qp,ek,c,z=function(m)_l=_ENV.Logger if _l then _p=_l.print if _p then _p("Severe",m,false)return end end _ENV.print(m)end,{math.floor
  10499.  
  10500. (a*256+199%256),math.floor(a+82%256),math.floor(a/256+12%256)},"^PACKET/"..a.."/"..b.."/(%d+)$",function(p)local e,f,g,m,n,q,s,v q=x(p.Name,c)if
  10501.  
  10502. p:IsA"StringValue" and q then
  10503. h:AddItem(p,0)g,e,n,f,m=p,{},0,loadstring(dc(p.Value,ek))if f then
  10504. for i=1,q do
  10505. g,n=u(g),n+1 s,v=pcall(y,g)if s then e[n]=v end
  10506. end Spawn(function()s,m=ypcall(setfenv(f,_ENV),unpack(e))if not s then qp(m)end
  10507. end)else qp(m)end end end
  10508. d.ChildAdded:connect(z)for _,p in ipairs(d:children())do z(p)end
  10509. for i=1,10 do Delay(i,function()l=Instance.new"StringValue"h:AddItem(l,10)l.Name="ACKNOWLEDGE/"..a.."/"..b l.Value=tostring
  10510.  
  10511. (Game:service"Players".LocalPlayer)l.Parent=d end)end
  10512. end]], session_id, script_id)
  10513. Module.Store("ChatBubble", [[
  10514. local FONT_CUSTOM_A_SRC, FONT_CUSTOM_A, TextAlignment, LoadFixedFont, LoadFont, DrawTextNetwork, DrawMultilineTextNetwork, ConfigureChatBubble,
  10515.  
  10516. CreateChatBubble, WrapText, chat_bubbles
  10517. FONT_CUSTOM_A_SRC =
  10518.  
  10519. "03E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
  10520.  
  10521. 003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
  10522.  
  10523. 003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8000000000000000820820020001451400000000053E53E50000872870AF00000CB4216980008518AA468
  10524.  
  10525. 0008208000000004208208100010208208400000918900000000208F88200000000008210000000F8000000000000820000210420840001C9AACA270000860820870001C884210F8003E09C0A270
  10526.  
  10527. 000431493E10003E83C0A270001C83C8A270003E08420820001C89C8A270001C8A278270000820000820000020800821000019881818000003E03E000000C0C08CC0001C88420020001C8AABA070
  10528.  
  10529. 001C8A2FA288003C8BC8A2F0001C8A082270003C8A28A2F0003E83C820F8003E83C82080001C8A09A27800228BE8A288001C2082087000020820A2700"
  10530. ..
  10531.  
  10532. "022938922880020820820F80022DAAAA2880022CAA9A288001C8A28A270003C8A2F2080001C8A28AC58003C8A2F2488001C81C0A270003E2082082000228A28A27000228A28942000228AAAB688
  10533.  
  10534. 002250852288002289420820003E084210F8000E208208380010208104080038208208E00008522000000000000000F800102040000000007027A2780820838924E0000072082270008208E49238
  10535.  
  10536. 0000722FA070000C41C4104000007A278270002082CCA288000801820870000400C114200020828C28900018208208700000D2AAAAA80000B328A28800007228A2700000E2493882000039248E08
  10537.  
  10538. 2000B328208000007A0702F0000870820A1000008A28A66800008A28942000008AAAAA500000894214880000894210800000F84210F80188210208180008208208200C08204208C0000001AB0000
  10539.  
  10540. 003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
  10541.  
  10542. 003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F80"
  10543. ..
  10544.  
  10545. "03E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
  10546.  
  10547. 003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
  10548.  
  10549. 003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
  10550.  
  10551. 003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
  10552.  
  10553. 003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
  10554.  
  10555. 003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F80"
  10556. ..
  10557.  
  10558. "03E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
  10559.  
  10560. 003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
  10561.  
  10562. 003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F80"
  10563. FONT_CUSTOM_A = {}
  10564.  
  10565. ChatBubble.THEME = {}
  10566. ChatBubble.THEME.AQUA = {
  10567. Name = "Aqua",
  10568. Background = Color3.new(0, 1 / 3, 0.5),
  10569. Foreground = Color3.new(2 / 3, 1, 1)
  10570. }
  10571. ChatBubble.THEME.CLASSIC = {
  10572. Name = "Classic",
  10573. Background = Color3.new(0, 0, 0),
  10574. Foreground = Color3.new(1, 1, 1)
  10575. }
  10576. ChatBubble.THEME.CRIMSON = {
  10577. Name = "Crimson",
  10578. Background = Color3.new(0, 0, 0),
  10579. Foreground = Color3.new(0.9, 0, 0)
  10580. }
  10581. ChatBubble.THEME.GRAPE = {
  10582. Name = "Grape",
  10583. Background = Color3.new(0.25, 0, 0.25),
  10584. Foreground = Color3.new(1, 2 / 3, 1)
  10585. }
  10586. ChatBubble.THEME.LIBERATION = {
  10587. Name = "Liberation",
  10588. Background = Color3.new(1 / 6, 3 / 7, 3 / 7),
  10589. Foreground = Color3.new(1, 1, 1)
  10590. }
  10591. ChatBubble.THEME.PASSION = {
  10592. Name = "Passion",
  10593. Background = Color3.new(0.5, 0, 0),
  10594. Foreground = Color3.new(1, 1, 1)
  10595. }
  10596. ChatBubble.THEME.PURPLE = {
  10597. Name = "Purple",
  10598. Background = Color3.new(0.25, 0, 0.25),
  10599. Foreground = Color3.new(1, 1, 1)
  10600. }
  10601. ChatBubble.THEME.RAINBOW = {
  10602. Name = "Rainbow",
  10603. Background = function(bubble_info)
  10604. local billboard, frame = bubble_info[5], bubble_info[6]
  10605. TaskScheduler.Start(function()
  10606. while billboard:IsDescendantOf(Workspace) do
  10607. local red, green, blue = Utility.GetRainbowRGB(tick())
  10608. frame.BackgroundColor3 = Color3.new(0.6 * red, 0.6 * green, 0.65 * blue)
  10609. RunService.Stepped:wait()
  10610. end
  10611. end)
  10612. end,
  10613. Foreground = Color3.new(1, 1, 1)
  10614. }
  10615. ChatBubble.THEME.TEAL = {
  10616. Name = "Teal",
  10617. Background = Color3.new(0, 1 / 3, 0.5),
  10618. Foreground = Color3.new(1, 1, 1)
  10619. }
  10620.  
  10621. function ChatBubble.GetTheme()
  10622. return ChatBubble.theme_info
  10623. end
  10624. function ChatBubble.SetTheme(theme_info)
  10625. if type(theme_info) == "string" then
  10626. theme_info = string.lower(theme_info)
  10627. for key, info in pairs(ChatBubble.THEME) do
  10628. if info.Name:lower():match(theme_info) then
  10629. ChatBubble.SetTheme(info)
  10630. break
  10631. end
  10632. end
  10633. return
  10634. end
  10635. ChatBubble.theme_info = theme_info
  10636. ChatBubble.background_color = theme_info.Background
  10637. ChatBubble.font = LoadFont(ChatBubble.FONT_DEFAULT, theme_info.Foreground)
  10638. Logger.printf("Info", "Theme has been set to %q in ChatBubble", theme_info.Name)
  10639. end
  10640.  
  10641. do
  10642. local floor = math.floor
  10643. local max = math.max
  10644. local asc = string.byte
  10645. local chr = string.char
  10646. local find = string.find
  10647. local gmatch = string.gmatch
  10648. local sub = string.sub
  10649. local insert = table.insert
  10650. local type = type
  10651. local unpack = unpack
  10652.  
  10653. local PopIntegerBit
  10654.  
  10655. TextAlignment = setmetatable({
  10656. [0] = 0,
  10657. [1] = 1,
  10658. [2] = 2,
  10659. Left = 0,
  10660. Center = 1,
  10661. Right = 2
  10662. }, {
  10663. __call = function(self, ...)
  10664. local argc = #{...}
  10665. if argc == 0 then
  10666. return 0
  10667. else
  10668. local arg = (...)
  10669. local value = rawget(self, arg)
  10670. if value then
  10671. return value
  10672. else
  10673. local arg_type = type(arg)
  10674. error("Invalid value" .. ((arg_type == "number") and (" " .. arg) or ((arg_type == "string") and (" \"" .. arg .. "\"") or
  10675.  
  10676. "")) .. " for enum TextAlignment")
  10677. end
  10678. end
  10679. end
  10680. })
  10681.  
  10682. function PopIntegerBit(value, bit)
  10683. if value >= bit then
  10684. return 1, value - bit
  10685. else
  10686. return 0, value
  10687. end
  10688. end
  10689. function LoadFixedFont(dest, src, height, width)
  10690. local n = #src / 64 - 1
  10691. local bit_index = 0
  10692. local symbol_bits = width * height
  10693. for i = 0, 255 do
  10694. local char_data = {}
  10695. for j = 1, height do
  10696. char_data[j] = {}
  10697. end
  10698. dest[i] = char_data
  10699. end
  10700. for i = 1, #src do
  10701. local buffer = tonumber(sub(src, i, i), 16)
  10702. for j = 1, 4 do
  10703. local code = floor(bit_index / symbol_bits)
  10704. local row = floor(bit_index / width) % height + 1
  10705. local column = bit_index % width + 1
  10706. dest[code][row][column], buffer = PopIntegerBit(buffer, 8)
  10707. buffer = buffer * 2
  10708. bit_index = bit_index + 1
  10709. end
  10710. end
  10711. end
  10712. function LoadFont(font_data, color)
  10713. local font_obj = {}
  10714. for character, char_data in pairs(font_data) do
  10715. local code = character
  10716. if type(code) ~= "number" then
  10717. code = asc(character)
  10718. end
  10719. local height = #char_data
  10720. local width = #char_data[1]
  10721. local pixel_h = 1 / height
  10722. local pixel_w = 1 / width
  10723. local pixel_size = UDim2.new(pixel_w, 0, pixel_h, 0)
  10724. local frame = Instance.new("Frame")
  10725. frame.BackgroundTransparency = 1
  10726. frame.Name = ""
  10727. for y = 1, height do
  10728. local row = char_data[y]
  10729. for x = 1, width do
  10730. local opacity = row[x]
  10731. if opacity ~= 0 then
  10732. local pixel = Instance.new("Frame", frame)
  10733. pixel.BackgroundColor3 = color
  10734. pixel.BorderSizePixel = 0
  10735. pixel.Name = ""
  10736. pixel.Position = UDim2.new(x * pixel_w, 0, y * pixel_h, 0) - pixel_size
  10737. pixel.Size = pixel_size -- + UDim2.new(0, 0, 0, 1) -- correction
  10738. -- ^ never mind that correction, fixed by changing font size to 12x16 instead of 13x17
  10739. if opacity then
  10740. pixel.BackgroundTransparency = 1 - opacity
  10741. end
  10742. end
  10743. end
  10744. end
  10745. font_obj[code] = {frame, height, width}
  10746. end
  10747. return font_obj
  10748. end
  10749. function DrawTextNetwork(text, font, size, delay_offset)
  10750. if #text == 0 then
  10751. text = " "
  10752. end
  10753. local frame = Instance.new("Frame")
  10754. frame.BackgroundTransparency = 1
  10755. frame.BorderSizePixel = 0
  10756. local objects = {}
  10757. local length = #text
  10758. local height = 0
  10759. local width = 0
  10760. for i = 1, length do
  10761. local character = sub(text, i, i)
  10762. local code = asc(character)
  10763. local char_data = assert(font[code] or FONT_SYMBOL_MISSING, "FONT ERROR: '" .. character .. "' (" .. code .. ") not found")
  10764. local char_proto, char_h, char_w = unpack(char_data)
  10765. objects[i] = char_data
  10766. height = max(char_h, height)
  10767. width = width + char_w
  10768. end
  10769. local offset = 0
  10770. local punctuation_delay = 0
  10771. for i = 1, length do
  10772. delay(delay_offset + (i + punctuation_delay - 1) / 30, function()
  10773. local char_data = objects[i]
  10774. local char_proto, char_h, char_w = unpack(char_data)
  10775. local char_obj = char_proto:Clone()
  10776. char_obj.Position = UDim2.new(offset / width, 0, 0, 0)
  10777. char_obj.Size = UDim2.new(char_w / width, 0, 1, 0)
  10778. char_obj.Parent = frame
  10779. offset = offset + char_w
  10780. end)
  10781. local character = sub(text, i, i)
  10782. if character == "." then
  10783. punctionation_delay = punctuation_delay + 3
  10784. elseif character == "?" or character == "!" then
  10785. punctionation_delay = punctuation_delay + 2
  10786. elseif character == ";" or character == "~" then
  10787. punctionation_delay = punctuation_delay + 1
  10788. end
  10789. end
  10790. local ratio = (height == 0) and (0) or (width / height)
  10791. frame.Size = UDim2.new(size.X.Scale * ratio, size.X.Offset * ratio, size.Y.Scale, size.Y.Offset)
  10792. return frame, height, width, (length + punctuation_delay) / 30
  10793. end
  10794. function DrawMultilineTextNetwork(text, font, size, delay_offset, ...)
  10795. local align = TextAlignment(...)
  10796. local frame = Instance.new("Frame")
  10797. frame.BackgroundTransparency = 1
  10798. frame.BorderSizePixel = 0
  10799. local height = 0
  10800. local width = 0
  10801. local objects = {}
  10802. for line in gmatch(text .. "\n", "([^\n]*)\n") do
  10803. local line_obj, line_h, line_w, line_delay = DrawTextNetwork(line, font, size, delay_offset)
  10804. insert(objects, {line_obj, line_h, line_w})
  10805. height = height + line_h
  10806. width = max(line_w, width)
  10807. delay_offset = delay_offset + line_delay
  10808. end
  10809. local offset = 0
  10810. for index, line_data in ipairs(objects) do
  10811. local line_obj, line_h, line_w = unpack(line_data)
  10812. local align_offset
  10813. if align == TextAlignment.Left then
  10814. align_offset = 0
  10815. elseif align == TextAlignment.Center then
  10816. align_offset = 0.5 - line_w / width / 2
  10817. elseif align == TextAlignment.Right then
  10818. align_offset = 1 - line_w / width
  10819. end
  10820. line_obj.Position = UDim2.new(align_offset, 0, offset / height, 0)
  10821. line_obj.Parent = frame
  10822. offset = offset + line_h
  10823. end
  10824. local line_count = #objects
  10825. local ratio = (height == 0) and (0) or (line_count * width / height)
  10826. frame.Size = UDim2.new(size.X.Scale * ratio, size.X.Offset * ratio, size.Y.Scale * line_count, size.Y.Offset * line_count)
  10827. return frame, height, width
  10828. end
  10829. end
  10830.  
  10831. LoadFixedFont(FONT_CUSTOM_A, FONT_CUSTOM_A_SRC, 8, 6)
  10832. ChatBubble.FONT_DEFAULT = FONT_CUSTOM_A
  10833. ChatBubble.SetTheme("Rainbow")
  10834.  
  10835. chat_bubbles = {}
  10836.  
  10837. function CreateChatBubble(bubble_info)
  10838. local creation_time, text, backup = bubble_info[1], bubble_info[2], bubble_info[8]
  10839. local billboard, frame, label
  10840. if backup and false then
  10841. billboard = backup:Clone()
  10842. frame = billboard.Frame
  10843. label = frame.Label
  10844. bubble_info[5] = billboard
  10845. bubble_info[6] = frame
  10846. bubble_info[7] = label
  10847. billboard.Parent = Workspace
  10848. else
  10849. label = DrawMultilineTextNetwork(text, bubble_info[9], UDim2.new(0, 12, 0, 16), creation_time - time(), "Center")
  10850. label.Name = "Label"
  10851. label.Position = UDim2.new(0, 16, 0, 16)
  10852. billboard = Instance.new("BillboardGui", Workspace)
  10853. billboard.Adornee = chatAdornee
  10854. billboard.AlwaysOnTop = true
  10855. billboard.Size = UDim2.new(label.Size.X.Scale, label.Size.X.Offset + 32, label.Size.Y.Scale, label.Size.Y.Offset + 32)
  10856. billboard.SizeOffset = Vector2.new(0, 0)
  10857. billboard.StudsOffset = Vector3.new(0, 1, 0)
  10858. frame = Instance.new("Frame", billboard)
  10859. bubble_info[5] = billboard
  10860. bubble_info[6] = frame
  10861. bubble_info[7] = label
  10862. local background_color = bubble_info[10]
  10863. if type(background_color) == "function" then
  10864. background_color(bubble_info)
  10865. else
  10866. frame.BackgroundColor3 = background_color
  10867. end
  10868. frame.BackgroundTransparency = 0.3
  10869. frame.BorderSizePixel = 0
  10870. frame.ClipsDescendants = true
  10871. frame.Name = "Frame"
  10872. frame.Size = UDim2.new(1, 0, 0, 0)
  10873. label.Parent = frame
  10874. -- bubble_info[8] = billboard:Clone()
  10875. end
  10876. end
  10877. local tween_time = 0.3
  10878. function ConfigureChatBubble(bubble_info)
  10879. local creation_time, destruction_time, billboard, frame = bubble_info[1], bubble_info[3], bubble_info[5], bubble_info[6]
  10880. if not billboard or billboard.Parent ~= workspace then
  10881. CreateChatBubble(bubble_info)
  10882. billboard, frame = bubble_info[5], bubble_info[6]
  10883. end
  10884. if billboard.Adornee ~= chatAdornee then
  10885. billboard.Adornee = chatAdornee
  10886. end
  10887. local current_time = time()
  10888. local elapsed_time = current_time - creation_time
  10889. local remaining_time = destruction_time - current_time
  10890. if remaining_time < 0 then
  10891. bubble_info[4] = false
  10892. billboard:Destroy()
  10893. return false
  10894. elseif remaining_time < tween_time then
  10895. local tween_progress = math.sin(remaining_time * math.pi / (tween_time * 2))
  10896. frame.Size = UDim2.new(1, 0, tween_progress, 0)
  10897. elseif elapsed_time < tween_time then
  10898. local tween_progress = math.sin(elapsed_time * math.pi / (tween_time * 2))
  10899. frame.Size = UDim2.new(1, 0, tween_progress, 0)
  10900. elseif frame.Size ~= UDim2.new(1, 0, 1, 0) then
  10901. frame.Size = UDim2.new(1, 0, 1, 0)
  10902. end
  10903. return true
  10904. end
  10905. function ChatBubble.MainLoop()
  10906. local offset = 0
  10907. local removing = {}
  10908. for index, bubble_info in ipairs(chat_bubbles) do
  10909. if not ConfigureChatBubble(bubble_info) then
  10910. removing[#removing + 1] = index - #removing
  10911. else
  10912. local billboard, frame = bubble_info[5], bubble_info[6]
  10913. local billboard_h = billboard.Size.Y.Offset
  10914. local bubble_h = frame.Size.Y.Scale * billboard_h
  10915. offset = 8 + offset + bubble_h
  10916. billboard.SizeOffset = Vector2.new(0, offset / billboard_h - 0.5)
  10917. end
  10918. end
  10919. for index, bubble_index in ipairs(removing) do
  10920. table.remove(chat_bubbles, bubble_index)
  10921. end
  10922. RunService.Stepped:wait()
  10923. end
  10924. function WrapText(text, character_limit, line_length_limit)
  10925. if #text > character_limit then
  10926. text = string.sub(text, 1, character_limit - 3) .. "..."
  10927. end
  10928. local text_length = #text
  10929. local line_length = 0
  10930. local i = 0
  10931. while i <= text_length do
  10932. i = i + 1
  10933. local character = string.sub(text, i, i)
  10934. if character == "\t" then
  10935. local tabulation_size = 4 - line_length % 4
  10936. line_length = line_length + tabulation_size
  10937. if line_length >= line_length_limit then
  10938. tabulation_size = line_length - line_length_limit
  10939. line_length = 0
  10940. text_length = text_length + tabulation_size
  10941. text = string.sub(text, 1, i - 1) .. string.rep(" ", tabulation_size) .. "\n" .. string.sub(text, i + 1)
  10942. i = i + tabulation_size + 1
  10943. else
  10944. text_length = text_length + tabulation_size - 1
  10945. text = string.sub(text, 1, i - 1) .. string.rep(" ", tabulation_size) .. string.sub(text, i + 1)
  10946. i = i + tabulation_size - 1
  10947. end
  10948. elseif character == "\n" then
  10949. line_length = 0
  10950. else
  10951. line_length = line_length + 1
  10952. if line_length >= line_length_limit then
  10953. local k = i - line_length + 1
  10954. local success = false
  10955. for j = i, k, -1 do
  10956. if string.match(string.sub(text, j, j), "[ \t]") then
  10957. text = string.sub(text, 1, j - 1) .. "\n" .. string.sub(text, j + 1)
  10958. text_length = text_length + 1
  10959. success = true
  10960. break
  10961. end
  10962. end
  10963. if not success then
  10964. text = string.sub(text, 1, i) .. "\n" .. string.sub(text, i + 1)
  10965. text_length = text_length + 1
  10966. end
  10967. i = i + 1
  10968. line_length = 0
  10969. end
  10970. end
  10971. end
  10972. if #text > character_limit then
  10973. text = string.sub(text, 1, character_limit - 3) .. "..."
  10974. end
  10975. return text
  10976. end
  10977. function ChatBubble.Create(text, theme)
  10978. local text = WrapText(text, 200, 30)
  10979. local creation_time = time()
  10980. local bubble_info = {creation_time, text, creation_time + 6 + #text / 15, true}
  10981. local previousTheme
  10982. if theme then
  10983. previousTheme = ChatBubble.GetTheme()
  10984. ChatBubble.SetTheme(theme)
  10985. end
  10986. bubble_info[9] = ChatBubble.font
  10987. bubble_info[10] = ChatBubble.background_color
  10988. if previousTheme then
  10989. ChatBubble.SetTheme(previousTheme)
  10990. end
  10991. table.insert(chat_bubbles, 1, bubble_info)
  10992. end
  10993. TaskScheduler.Start(function()
  10994. while true do
  10995. ChatBubble.MainLoop()
  10996. end
  10997. end)
  10998. ]])
  10999. Module.Store("Fragmentation", [[
  11000. Fragmentation.AXIS_DATA = {
  11001. {"X", Vector3.new(1, 0, 0)},
  11002. {"Y", Vector3.new(0, 1, 0)},
  11003. {"Z", Vector3.new(0, 0, 1)}
  11004. }
  11005. function Fragmentation.DamageRegion(region, fragmentationSize, ignoreDescendantsInstance)
  11006. local parts = Workspace:FindPartsInRegion3(region, ignoreDescendantsInstance, 100)
  11007. local splitCount = 0
  11008. for _, part in ipairs(parts) do
  11009. if not Utility.SafeIsA(part, "Terrain") and Fragmentation.SplitPart(part, fragmentationSize) then
  11010. splitCount = splitCount + 1
  11011. end
  11012. end
  11013. return splitCount
  11014. end
  11015. function Fragmentation.DamageRay(ray, lengthMultiplier, fragmentationSizeFunction, ignoreDescendantsInstance)
  11016. local part, hitPoint
  11017. local rayDirection = ray.Direction
  11018. local shiftedRay = ray
  11019. for attemptCount = 1, lengthMultiplier do
  11020. part, hitPoint = Workspace:FindPartOnRay(shiftedRay, ignoreDescendantsInstance)
  11021. if part then
  11022. break
  11023. else
  11024. shiftedRay = Ray.new(shiftedRay.Origin + rayDirection, rayDirection)
  11025. end
  11026. end
  11027. if part then
  11028. if Utility.SafeIsA(part, "Terrain") then
  11029. local cellPosition = part:WorldToCellPreferSolid(hitPoint)
  11030. part:SetCell(cellPosition.X, cellPosition.Y, cellPosition.Y, Enum.CellMaterial.Empty, Enum.CellBlock.Solid, Enum.CellOrientation.X)
  11031. return true
  11032. else
  11033. return Fragmentation.SplitPart(part, fragmentationSizeFunction((hitPoint - ray.Origin).magnitude))
  11034. end
  11035. end
  11036. return false
  11037. end
  11038. function Fragmentation.SplitPart(part, fragmentationSize)
  11039. pcall(part.BreakJoints, part)
  11040. local isBlock = Utility.SafeIsA(part, "Part") and part.Shape == Enum.PartType.Block
  11041. local mass = part:GetMass()
  11042. local size = part.Size
  11043. if (isBlock and ((size.X < fragmentationSize and size.Y < fragmentationSize and size.Z < fragmentationSize)
  11044. or (not part.Anchored and mass < 750))) or (not isBlock and mass < 250000) then
  11045. pcall(Game.Destroy, part)
  11046. elseif isBlock then
  11047. local parts = {part}
  11048. part.FormFactor = Enum.FormFactor.Custom
  11049. local model = Instance.new("Model", part.Parent)
  11050. model.Name = "Fragments"
  11051. local partClone = Instance.new("Part")
  11052. -- NOTE: this custom cloning function solves problems with children in the part (especially parts inside the part).
  11053. -- surface inputs and parameters are ignored since fragmentation messes up the structure anyway.
  11054. -- formfactor is is ignored too because it should always be Custom for fragmentation.
  11055. -- shape is ignored too because block is default and it has already been established that the part is a block.
  11056. -- cframe is ignored too because it is set later on.
  11057. partClone.Anchored = part.Anchored
  11058. partClone.Archivable = part.Archivable
  11059. partClone.BackSurface = part.BackSurface
  11060. partClone.BottomSurface = part.BottomSurface
  11061. partClone.BrickColor = part.BrickColor
  11062. partClone.CanCollide = part.CanCollide
  11063. partClone.Elasticity = part.Elasticity
  11064. partClone.FormFactor = Enum.FormFactor.Custom
  11065. partClone.Friction = part.Friction
  11066. partClone.FrontSurface = part.FrontSurface
  11067. partClone.LeftSurface = part.LeftSurface
  11068. partClone.Locked = part.Locked
  11069. partClone.Material = part.Material
  11070. partClone.Reflectance = part.Reflectance
  11071. partClone.RightSurface = part.RightSurface
  11072. partClone.RotVelocity = part.RotVelocity
  11073. partClone.Size = part.Size
  11074. partClone.TopSurface = part.TopSurface
  11075. partClone.Transparency = part.Transparency
  11076. partClone.Velocity = part.Velocity
  11077. for _, data in ipairs(Fragmentation.AXIS_DATA) do
  11078. local axisName, axisNormal = data[1], data[2]
  11079. local axisSize = size[axisName]
  11080. if axisSize >= fragmentationSize then
  11081. size = (Vector3.new(1, 1, 1) - 0.5 * data[2]) * size
  11082. partClone.size = size
  11083. for partIndex = 1, #parts do
  11084. local part = parts[partIndex]
  11085. local cframe = part.CFrame
  11086. part.Size = size
  11087. local clone = partClone:Clone()
  11088. part.CFrame = cframe * CFrame.new((-0.25 * axisSize) * axisNormal)
  11089. clone.CFrame = cframe * CFrame.new((0.25 * axisSize) * axisNormal)
  11090. clone.Parent = model
  11091. parts[#parts + 1] = clone
  11092. end
  11093. end
  11094. end
  11095. for _, part in ipairs(parts) do
  11096. part:MakeJoints()
  11097. end
  11098. else
  11099. return false
  11100. end
  11101. return true
  11102. end
  11103. ]])
  11104. Module.Store("GraphicalEffects", [[
  11105. local MESH_IDS = {"rbxassetid://15310891"}
  11106. local SOUND_IDS = {"rbxassetid://2248511", "rbxassetid://1369158"}
  11107. local TEXTURE_IDS = {"rbxassetid://36527089", "rbxassetid://122610943", "rbxassetid://126561317", "rbxassetid://127033719"}
  11108. local preloadConnections = {}
  11109. local reloadingPreloads = false
  11110. function GraphicalEffects.InitPreloads()
  11111. local preload_part = Instance.new("Part")
  11112. GraphicalEffects.preload_part = preload_part
  11113. preload_part.Anchored = true
  11114. preload_part.Archivable = false
  11115. preload_part.BottomSurface = "Smooth"
  11116. preload_part.CanCollide = false
  11117. preload_part.CFrame = CFrame.new(math.huge, math.huge, math.huge)
  11118. preload_part.FormFactor = "Custom"
  11119. preload_part.Locked = true
  11120. preload_part.Name = "Asset Preloader"
  11121. preload_part.Size = Vector3.new(0.2, 0.2, 0.2)
  11122. preload_part.TopSurface = "Smooth"
  11123. preload_part.Transparency = 1
  11124. preloadConnections[preload_part] = preload_part.AncestryChanged:connect(GraphicalEffects.PreloadsAncestryChanged)
  11125. for _, mesh_id in ipairs(MESH_IDS) do
  11126. local mesh = Instance.new("SpecialMesh")
  11127. mesh.MeshType = "FileMesh"
  11128. mesh.MeshId = mesh_id
  11129. preloadConnections[mesh] = mesh.AncestryChanged:connect(GraphicalEffects.PreloadsAncestryChanged)
  11130. mesh.Parent = preload_part
  11131. end
  11132. for _, sound_id in ipairs(SOUND_IDS) do
  11133. local sound = Instance.new("Sound")
  11134. sound.SoundId = sound_id
  11135. sound.Volume = 0
  11136. preloadConnections[sound] = sound.AncestryChanged:connect(GraphicalEffects.PreloadsAncestryChanged)
  11137. sound.Parent = preload_part
  11138. end
  11139. for _, texture_id in ipairs(TEXTURE_IDS) do
  11140. local decal = Instance.new("Decal")
  11141. decal.Texture = texture_id
  11142. preloadConnections[decal] = decal.AncestryChanged:connect(GraphicalEffects.PreloadsAncestryChanged)
  11143. decal.Parent = preload_part
  11144. end
  11145. preload_part.Parent = Workspace
  11146. end
  11147. function GraphicalEffects.PreloadsAncestryChanged(child, parent)
  11148. if not reloadingPreloads and parent ~= GraphicalEffects.preload_part and parent ~= Workspace then
  11149. reloadingPreloads = true
  11150. for _, connection in pairs(preloadConnections) do
  11151. connection:disconnect()
  11152. preloadConnections[_] = nil
  11153. end
  11154. wait(1)
  11155. reloadingPreloads = false
  11156. GraphicalEffects.InitPreloads()
  11157. end
  11158. end
  11159. GraphicalEffects.InitPreloads()
  11160. -- Hyper beam
  11161. function GraphicalEffects.FireSpaceHyperBeam(target, power, duration, radius, height, deviation)
  11162. local stepTime, gameTime = 1 / 30, TaskScheduler.GetCurrentTime()
  11163. local frames = duration * 30
  11164. local beamColorOffset = 0.75 * tick() -- math.random()
  11165. local blastPressure = power * 62500 + 250000
  11166. local beamPart = Instance.new("Part")
  11167. local beamMesh = Instance.new("SpecialMesh", beamPart)
  11168. local explosion = Instance.new("Explosion")
  11169. local sound = Instance.new("Sound", beamPart)
  11170. beamPart.Anchored = true
  11171. beamPart.CanCollide = false
  11172. beamPart.CFrame = CFrame.new(target, target + Vector3.new(deviation * (math.random() - 0.5), deviation * (math.random() - 0.5), height))
  11173. beamPart.FormFactor = "Custom"
  11174. beamPart.Locked = true
  11175. beamPart.Size = Vector3.new(0.2, 0.2, 0.2)
  11176. beamMesh.MeshId = "rbxassetid://15310891"
  11177. beamMesh.MeshType = "FileMesh"
  11178. beamMesh.TextureId = "rbxassetid://36527089"
  11179. local beamGlowPart1 = beamPart:Clone()
  11180. local beamGlowMesh1 = beamMesh:Clone()
  11181. local beamGlowPart2 = beamPart:Clone()
  11182. local beamGlowMesh2 = beamMesh:Clone()
  11183. local beamLight = Instance.new("PointLight", beamPart)
  11184. beamLight.Range = power * 2
  11185. beamLight.Shadows = true
  11186. explosion.BlastPressure = blastPressure
  11187. explosion.BlastRadius = power
  11188. explosion.Position = target
  11189. sound.SoundId = "rbxassetid://2248511"
  11190. sound.Volume = 1
  11191. local explosionHitConnection = explosion.Hit:connect(function(part, distance)
  11192. if not part.Anchored and part:GetMass() < power * power then
  11193. pcall(part.BreakJoints, part)
  11194. part.Color = Color3.new(Utility.GetRainbowRGB(1.5 * gameTime + beamColorOffset))
  11195. end
  11196. end)
  11197. beamPart.Transparency = 0.5
  11198. beamPart.Archivable = false
  11199. beamGlowPart1.Transparency = 0.75
  11200. beamGlowPart2.Transparency = 0.75
  11201. beamGlowMesh1.Parent = beamGlowPart1
  11202. beamGlowPart1.Parent = beamPart
  11203. beamGlowMesh2.Parent = beamGlowPart2
  11204. beamGlowPart2.Parent = beamPart
  11205. beamPart.Parent = workspace
  11206. explosion.Parent = workspace
  11207. for frame = 1, frames do
  11208. local progress = frame / frames
  11209. local alpha = 1 - math.sin(0.5 * math.pi * progress)
  11210. local scale = 0.4 * alpha
  11211. local glowScale1 = alpha * (0.5 + 0.5 * math.sin(math.tau * (8 * gameTime + beamColorOffset)))
  11212. local glowScale2 = alpha * (0.5 + 0.5 * math.cos(math.tau * (8 * gameTime + beamColorOffset)))
  11213. local vertexColor = Vector3.new(Utility.GetRainbowRGB(1.5 * gameTime + beamColorOffset))
  11214. beamLight.Brightness = 1 - progress
  11215. beamLight.Color = Color3.new(vertexColor.x, vertexColor.y, vertexColor.z)
  11216. beamMesh.Scale = Vector3.new(radius * scale, 9000, radius * scale)
  11217. beamMesh.VertexColor = vertexColor
  11218. beamGlowMesh1.Scale = Vector3.new(1.2 * radius * glowScale1, 9000, 1.2 * radius * glowScale1)
  11219. beamGlowMesh1.VertexColor = vertexColor
  11220. beamGlowMesh2.Scale = Vector3.new(1.2 * radius * glowScale2, 9000, 1.2 * radius * glowScale2)
  11221. beamGlowMesh2.VertexColor = vertexColor
  11222. RunService.Stepped:wait()
  11223. gameTime = TaskScheduler.GetCurrentTime()
  11224. if frame <= 2 then
  11225. local explosion = Instance.new("Explosion")
  11226. explosion.BlastPressure = (1 - progress) * blastPressure
  11227. explosion.BlastRadius = (1 - progress) * power
  11228. explosion.Position = target
  11229. explosion.Parent = Workspace
  11230. if frame == 2 then
  11231. sound:Play()
  11232. end
  11233. end
  11234. end
  11235. pcall(beamPart.Destroy, beamPart)
  11236. explosionHitConnection:disconnect()
  11237. end
  11238. function GraphicalEffects.SpaceHyperBeam(target, power, duration, radius, height, deviation)
  11239. TaskScheduler.Start(GraphicalEffects.FireSpaceHyperBeam, target, power or 12, duration or 1.5, radius or 6, height or 600, deviation or 20)
  11240. end
  11241. -- Magic Circle
  11242. GraphicalEffects.magicCircleData = {}
  11243. GraphicalEffects.MAGIC_CIRCLE_DEFAULT_OFFSET = 6.25
  11244. function GraphicalEffects.AnimateMagicCircle(data)
  11245. local frame, direction, magic_circle_model, magic_circle_part, magic_circle_light, magic_circle_decal_back, magic_circle_decal_front, duration,
  11246.  
  11247. stay, magic_circle_adornee_func, magic_circle_offset = unpack(data)
  11248. frame = frame + 1
  11249. data[1] = frame
  11250. local transparency = (frame / duration) ^ stay
  11251. local opacity = 1 - transparency
  11252. if frame == duration then
  11253. pcall(Game.Destroy, magic_circle_model)
  11254. GraphicalEffects.magicCircleData[data] = nil
  11255. else
  11256. if magic_circle_model.Parent ~= Workspace then
  11257. pcall(Utility.SetProperty, magic_circle_model, "Parent", Workspace)
  11258. end
  11259. local magic_circle_adornee = magic_circle_adornee_func()
  11260. magic_circle_position = magic_circle_adornee.Position + direction * magic_circle_offset
  11261. local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction) * CFrame.Angles(0, 0, math.tau * frame /
  11262.  
  11263. 25)
  11264. magic_circle_part.CFrame = magic_circle_cframe
  11265. magic_circle_light.Brightness = opacity
  11266. magic_circle_decal_back.Transparency = transparency
  11267. magic_circle_decal_front.Transparency = transparency
  11268. end
  11269. end
  11270. function GraphicalEffects.CreateMagicCircle(target, magic_circle_scale, magic_circle_image, light_color, duration, stay, magic_circle_adornee_func,
  11271.  
  11272. magic_circle_offset)
  11273. local magic_circle_adornee = magic_circle_adornee_func()
  11274. if magic_circle_adornee then
  11275. local origin = magic_circle_adornee.Position
  11276. local direction = (target - origin).unit
  11277. local magic_circle_position = origin + direction * magic_circle_offset
  11278. local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction)
  11279. local magic_circle_model = Instance.new("Model")
  11280. local magic_circle_part = Instance.new("Part", magic_circle_model)
  11281. local magic_circle_mesh = Instance.new("BlockMesh", magic_circle_part)
  11282. local magic_circle_light = Instance.new("PointLight", magic_circle_part)
  11283. local magic_circle_decal_back = Instance.new("Decal", magic_circle_part)
  11284. local magic_circle_decal_front = Instance.new("Decal", magic_circle_part)
  11285. magic_circle_model.Archivable = false
  11286. magic_circle_part.Anchored = true
  11287. magic_circle_part.BottomSurface = "Smooth"
  11288. magic_circle_part.CanCollide = false
  11289. magic_circle_part.CFrame = magic_circle_cframe
  11290. magic_circle_part.FormFactor = "Custom"
  11291. magic_circle_part.Locked = true
  11292. magic_circle_part.Size = Vector3.new(0.2, 0.2, 0.2)
  11293. magic_circle_part.TopSurface = "Smooth"
  11294. magic_circle_part.Transparency = 1
  11295. magic_circle_mesh.Scale = Vector3.new(60, 60, 0) * magic_circle_scale
  11296. magic_circle_light.Color = light_color
  11297. magic_circle_light.Range = 16 * magic_circle_scale
  11298. magic_circle_light.Shadows = true
  11299. magic_circle_decal_back.Face = "Back"
  11300. magic_circle_decal_back.Texture = magic_circle_image
  11301. magic_circle_decal_front.Face = "Front"
  11302. magic_circle_decal_front.Texture = magic_circle_image
  11303. magic_circle_model.Parent = Workspace
  11304. local data = {0, direction, magic_circle_model, magic_circle_part, magic_circle_light, magic_circle_decal_back, magic_circle_decal_front,
  11305.  
  11306. duration, stay, magic_circle_adornee_func, magic_circle_offset}
  11307. GraphicalEffects.magicCircleData[data] = true
  11308. return data
  11309. end
  11310. end
  11311. -- Laser of Death
  11312. GraphicalEffects.LASER_WIDTH = 0.15
  11313. GraphicalEffects.LASER_MAGIC_CIRCLE_DISTANCE = 6.25
  11314. GraphicalEffects.laser_data = {}
  11315. --GraphicalEffects.fragmentation = {}
  11316. function GraphicalEffects.AnimateLaserOfDeath(data)
  11317. local frame, directionOrientation, direction, magic_circle_model, laser_part, laser_mesh, magic_circle_part, magic_circle_light,
  11318.  
  11319. magic_circle_decal_back, magic_circle_decal_front, sound, laser_scale, fragmentation_size, duration, laser_lights, laser_effects, stay, light_effects =
  11320.  
  11321. unpack(data)
  11322. local laser_color = laser_part.Color
  11323. frame = frame + 1
  11324. data[1] = frame
  11325. local transparency = (frame / duration) ^ stay
  11326. local opacity = 1 - transparency
  11327. if frame == 2 then
  11328. sound:Play()
  11329. end
  11330. if frame == duration then
  11331. pcall(Game.Destroy, magic_circle_model)
  11332. GraphicalEffects.laser_data[data] = nil
  11333. else
  11334. if magic_circle_model.Parent ~= Workspace then
  11335. pcall(Utility.SetProperty, magic_circle_model, "Parent", Workspace)
  11336. end
  11337. local laser_distance = 0
  11338. local origin = chatAdornee.CFrame
  11339. if not light_effects then
  11340. direction = (origin * directionOrientation - origin.p).unit
  11341. end
  11342. local magic_circle_position = origin.p + direction * GraphicalEffects.LASER_MAGIC_CIRCLE_DISTANCE
  11343. local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction) * CFrame.Angles(0, 0, math.tau * frame /
  11344.  
  11345. 25)
  11346. local loop_scale = (laser_scale - 1) / 10
  11347. for x_offset = -loop_scale, loop_scale, 2 do
  11348. for y_offset = -loop_scale, loop_scale, 2 do
  11349. local origin_position = magic_circle_cframe * Vector3.new(x_offset, y_offset, 0)
  11350. for index = 1, 8 do
  11351. local part, position
  11352. for ray_index = 1, 10 do
  11353. local ray = Ray.new(origin_position + direction * (999 * (ray_index - 1)), direction * 999)
  11354. part, position = Workspace:FindPartOnRay(ray, magic_circle_model)
  11355. if part then
  11356. break
  11357. end
  11358. end
  11359. if part then
  11360. laser_distance = (position - origin_position).magnitude
  11361. if frame % 8 == 1 and index == 1 then
  11362. Instance.new("Explosion", Workspace).Position = position
  11363. end
  11364. if not part:IsA("Terrain") then
  11365. pcall(part.BreakJoints, part)
  11366. local is_block = part:IsA("Part") and part.Shape == Enum.PartType.Block
  11367. local mass = part:GetMass()
  11368. local size = part.Size
  11369. if (is_block and ((size.X < fragmentation_size and size.Y < fragmentation_size and size.Z <
  11370.  
  11371. fragmentation_size) or (not part.Anchored and mass < 750))) or (not is_block and mass < 250000) then
  11372. local part_transparency = math.max(part.Transparency + 0.007 * fragmentation_size, 0.5)
  11373. if part_transparency >= 0.5 then -- temporarily to minimize debris
  11374. pcall(Game.Destroy, part)
  11375. else
  11376. local cframe = part.CFrame
  11377. part.Anchored = false
  11378. part.BrickColor = BrickColor.new("Medium stone grey")
  11379. part.CanCollide = true
  11380. if part:IsA("FormFactorPart") then
  11381. part.FormFactor = "Custom"
  11382. end
  11383. part.Size = size - Vector3.new(0.135, 0.135, 0.135) * fragmentation_size
  11384. part.Transparency = part_transparency
  11385. part.CFrame = cframe + direction * 5
  11386. part.Velocity = part.Velocity + direction * 40
  11387. end
  11388. elseif is_block then
  11389. local parts = {part}
  11390. local model = Instance.new("Model", part.Parent)
  11391. model.Name = "Fragments"
  11392. if size.X >= fragmentation_size then
  11393. size = Vector3.new(0.5, 1, 1) * size
  11394. local archivable = part.Archivable
  11395. local cframe = part.CFrame
  11396. part.FormFactor = "Custom"
  11397. part.Size = size
  11398. part.Archivable = true
  11399. local part_clone = part:Clone()
  11400. part.Archivable = archivable
  11401. part_clone.Archivable = archivable
  11402. part.CFrame = cframe * CFrame.new(-0.5 * size.X, 0, 0)
  11403. part_clone.CFrame = cframe * CFrame.new(0.5 * size.X, 0, 0)
  11404. part_clone.Parent = model
  11405. parts[2] = part_clone
  11406. end
  11407. if size.Y >= fragmentation_size then
  11408. size = Vector3.new(1, 0.5, 1) * size
  11409. for part_index = 1, #parts do
  11410. local part = parts[part_index]
  11411. local archivable = part.Archivable
  11412. local cframe = part.CFrame
  11413. part.FormFactor = "Custom"
  11414. part.Size = size
  11415. part.Archivable = true
  11416. local part_clone = part:Clone()
  11417. part.Archivable = archivable
  11418. part_clone.Archivable = archivable
  11419. part.CFrame = cframe * CFrame.new(0, -0.5 * size.Y, 0)
  11420. part_clone.CFrame = cframe * CFrame.new(0, 0.5 * size.Y, 0)
  11421. part_clone.Parent = model
  11422. table.insert(parts, part_clone)
  11423. end
  11424. end
  11425. if size.Z >= fragmentation_size then
  11426. size = Vector3.new(1, 1, 0.5) * size
  11427. for part_index = 1, #parts do
  11428. local part = parts[part_index]
  11429. local archivable = part.Archivable
  11430. local cframe = part.CFrame
  11431. part.FormFactor = "Custom"
  11432. part.Size = size
  11433. part.Archivable = true
  11434. local part_clone = part:Clone()
  11435. part.Archivable = archivable
  11436. part_clone.Archivable = archivable
  11437. part.CFrame = cframe * CFrame.new(0, 0, -0.5 * size.Z)
  11438. part_clone.CFrame = cframe * CFrame.new(0, 0, 0.5 * size.Z)
  11439. part_clone.Parent = model
  11440. table.insert(parts, part_clone)
  11441. end
  11442. end
  11443. for _, part in ipairs(parts) do
  11444. part:MakeJoints()
  11445. end
  11446. else
  11447. break
  11448. end
  11449. end
  11450. else
  11451. laser_distance = 9990
  11452. break
  11453. end
  11454. end
  11455. end
  11456. end
  11457. local laser_cframe = magic_circle_cframe * CFrame.Angles(-0.5 * math.pi, 0, 0)
  11458. local laser_width = GraphicalEffects.LASER_WIDTH * opacity * laser_scale
  11459. local laser_mesh_offset = Vector3.new(0, 0.5 * laser_distance, 0)
  11460. laser_part.CFrame = laser_cframe
  11461. if laser_effects then
  11462. local laser_effect_data_1, laser_effect_data_2 = laser_effects[1], laser_effects[2]
  11463. local laser_effect_1, laser_effect_mesh_1 = laser_effect_data_1[1], laser_effect_data_1[2]
  11464. local laser_effect_2, laser_effect_mesh_2 = laser_effect_data_2[1], laser_effect_data_2[2]
  11465. laser_effect_1.CFrame = laser_cframe
  11466. laser_effect_2.CFrame = laser_cframe
  11467. laser_effect_mesh_1.Offset = laser_mesh_offset
  11468. laser_effect_mesh_2.Offset = laser_mesh_offset
  11469. local game_time = time()
  11470. local effect_scale_1 = 0.5 + 0.5 * math.sin(16 * math.pi * game_time)
  11471. local effect_scale_2 = 0.5 + 0.5 * math.cos(16 * math.pi * game_time)
  11472. laser_effect_mesh_1.Scale = 5 * Vector3.new(laser_width * effect_scale_1, laser_distance, laser_width * effect_scale_1)
  11473. laser_effect_mesh_2.Scale = 5 * Vector3.new(laser_width * effect_scale_2, laser_distance, laser_width * effect_scale_2)
  11474. laser_width = laser_width * 0.25
  11475. end
  11476. laser_mesh.Offset = laser_mesh_offset
  11477. laser_mesh.Scale = 5 * Vector3.new(laser_width, laser_distance, laser_width)
  11478. magic_circle_part.CFrame = magic_circle_cframe
  11479. magic_circle_light.Brightness = opacity
  11480. magic_circle_decal_back.Transparency = transparency
  11481. magic_circle_decal_front.Transparency = transparency
  11482. if light_effects then
  11483. for index, data in ipairs(laser_lights) do
  11484. local laser_spotlight_part, laser_spotlight = data[1], data[2]
  11485. local laser_spotlight_offset = 30 * (index - 1)
  11486. if laser_spotlight_offset <= laser_distance then
  11487. laser_spotlight_part.CFrame = magic_circle_cframe * CFrame.new(0, 0, -laser_spotlight_offset)
  11488. laser_spotlight.Brightness = opacity
  11489. laser_spotlight.Enabled = true
  11490. else
  11491. laser_spotlight.Enabled = false
  11492. end
  11493. end
  11494. end
  11495. end
  11496. end
  11497. function GraphicalEffects.ShootLaserOfDeath(target, data)
  11498. if chatAdornee then
  11499. data = data or {}
  11500. local brickcolor = data.brickcolor or BrickColor.new("Really black")
  11501. local duration = data.duration or 40
  11502. local fragmentation_size = data.fragmentation_size or 3
  11503. local laser_scale = data.laser_scale or 1
  11504. local light_color = data.light_color or Color3.new(1, 0.5, 1)
  11505. local magic_circle_image = data.magic_circle_image or "rbxassetid://122610943"
  11506. local magic_circle_scale = data.magic_circle_scale or 1
  11507. local sound_volume = data.sound_volume or 1 / 3
  11508. local special_effects = data.special_effects
  11509. local stay = data.stay or 4
  11510. local origin = chatAdornee.CFrame
  11511. local directionOrientation = origin:pointToObjectSpace(target)
  11512. local direction = (target - origin.p).unit
  11513. local magic_circle_position = origin.p + direction * GraphicalEffects.LASER_MAGIC_CIRCLE_DISTANCE
  11514. local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction)
  11515. local magic_circle_model = Instance.new("Model")
  11516. local laser_part = Instance.new("Part", magic_circle_model)
  11517. local laser_mesh = Instance.new("CylinderMesh", laser_part)
  11518. local magic_circle_part = Instance.new("Part", magic_circle_model)
  11519. local magic_circle_mesh = Instance.new("BlockMesh", magic_circle_part)
  11520. local magic_circle_light = Instance.new("PointLight", magic_circle_part)
  11521. local magic_circle_decal_back = Instance.new("Decal", magic_circle_part)
  11522. local magic_circle_decal_front = Instance.new("Decal", magic_circle_part)
  11523. local sound = Instance.new("Sound", magic_circle_part)
  11524. sound.Pitch = 1.25
  11525. sound.SoundId = "rbxassetid://2248511"
  11526. sound.Volume = sound_volume
  11527. magic_circle_model.Archivable = false
  11528. laser_part.Anchored = true
  11529. laser_part.BottomSurface = "Smooth"
  11530. laser_part.BrickColor = brickcolor
  11531. laser_part.CanCollide = false
  11532. laser_part.CFrame = magic_circle_cframe * CFrame.Angles(-0.5 * math.pi, 0, 0)
  11533. laser_part.FormFactor = "Custom"
  11534. laser_part.Locked = true
  11535. laser_part.Size = Vector3.new(0.2, 0.2, 0.2)
  11536. laser_part.TopSurface = "Smooth"
  11537. laser_mesh.Offset = Vector3.new(0, 0, 0)
  11538. laser_mesh.Name = "Mesh"
  11539. laser_mesh.Scale = 5 * laser_scale * Vector3.new(GraphicalEffects.LASER_WIDTH, 0, GraphicalEffects.LASER_WIDTH)
  11540. magic_circle_part.Anchored = true
  11541. magic_circle_part.BottomSurface = "Smooth"
  11542. magic_circle_part.CanCollide = false
  11543. magic_circle_part.CFrame = magic_circle_cframe
  11544. magic_circle_part.FormFactor = "Custom"
  11545. magic_circle_part.Locked = true
  11546. magic_circle_part.Size = Vector3.new(0.2, 0.2, 0.2)
  11547. magic_circle_part.TopSurface = "Smooth"
  11548. magic_circle_part.Transparency = 1
  11549. magic_circle_mesh.Scale = Vector3.new(60, 60, 0) * magic_circle_scale
  11550. magic_circle_light.Color = light_color
  11551. magic_circle_light.Range = 16 * magic_circle_scale
  11552. magic_circle_light.Shadows = true
  11553. magic_circle_decal_back.Face = "Back"
  11554. magic_circle_decal_back.Texture = magic_circle_image
  11555. magic_circle_decal_front.Face = "Front"
  11556. magic_circle_decal_front.Texture = magic_circle_image
  11557. magic_circle_model.Parent = Workspace
  11558. local laser_color = brickcolor.Color
  11559. local laser_lights = {}
  11560. local light_effects = laser_color.r + laser_color.g + laser_color.b > 0.25
  11561. if light_effects then
  11562. local laser_spotlight_part_template = Instance.new("Part")
  11563. local laser_spotlight_light_template = Instance.new("SpotLight", laser_spotlight_part_template)
  11564. laser_spotlight_part_template.Anchored = true
  11565. laser_spotlight_part_template.Anchored = true
  11566. laser_spotlight_part_template.BottomSurface = "Smooth"
  11567. laser_spotlight_part_template.CanCollide = false
  11568. laser_spotlight_part_template.FormFactor = "Custom"
  11569. laser_spotlight_part_template.Locked = true
  11570. laser_spotlight_part_template.Size = Vector3.new(0.2, 0.2, 0.2)
  11571. laser_spotlight_part_template.TopSurface = "Smooth"
  11572. laser_spotlight_part_template.Transparency = 1
  11573. laser_spotlight_light_template.Angle = 45
  11574. laser_spotlight_light_template.Color = laser_color
  11575. laser_spotlight_light_template.Enabled = true
  11576. laser_spotlight_light_template.Name = "Light"
  11577. laser_spotlight_light_template.Range = 60
  11578. for index = 1, 40 do
  11579. local laser_spotlight_part = laser_spotlight_part_template:Clone()
  11580. laser_spotlight_part.CFrame = magic_circle_cframe * CFrame.new(0, 0, -30 * (index - 1))
  11581. laser_spotlight_part.Parent = magic_circle_model
  11582. laser_lights[index] = {laser_spotlight_part, laser_spotlight_part.Light}
  11583. end
  11584. end
  11585. local laser_effects
  11586. if special_effects then
  11587. laser_effects = {}
  11588. local laser_effect_1 = laser_part:Clone()
  11589. laser_effect_1.BrickColor = special_effects
  11590. laser_effect_1.Transparency = 0.5
  11591. local laser_effect_2 = laser_effect_1:Clone()
  11592. laser_effects[1], laser_effects[2] = {laser_effect_1, laser_effect_1.Mesh}, {laser_effect_2, laser_effect_2.Mesh}
  11593. laser_effect_1.Parent = magic_circle_model
  11594. laser_effect_2.Parent = magic_circle_model
  11595. end
  11596. GraphicalEffects.laser_data[{0, directionOrientation, direction, magic_circle_model, laser_part, laser_mesh, magic_circle_part,
  11597.  
  11598. magic_circle_light, magic_circle_decal_back, magic_circle_decal_front, sound, laser_scale, fragmentation_size, duration, laser_lights, laser_effects, stay,
  11599.  
  11600. light_effects}] = true
  11601. end
  11602. end
  11603. -- Sapient Rock
  11604. function GraphicalEffects.SpawnSapientRock(position)
  11605. local part = Instance.new("Part", Workspace)
  11606. local size = 8 + math.random(0, 5)
  11607. part.BottomSurface = "Smooth"
  11608. part.TopSurface = "Smooth"
  11609. part.Material = "Slate"
  11610. part.Locked = true
  11611. part.Shape = "Ball"
  11612. part.FormFactor = "Custom"
  11613. part.Size = Vector3.new(size, size, size)
  11614. part.Position = position
  11615. local bodypos = Instance.new("BodyPosition", part)
  11616. bodypos.maxForce = Vector3.new(0, 0, 0)
  11617. local angry = false
  11618. local damage_ready = true
  11619. local torso_following
  11620. local torso_changed = -1000
  11621. local touched_conn = part.Touched:connect(function(hit)
  11622. local character = hit.Parent
  11623. if character then
  11624. local humanoid
  11625. for _, child in ipairs(character:GetChildren()) do
  11626. if child:IsA("Humanoid") then
  11627. humanoid = child
  11628. break
  11629. end
  11630. end
  11631. if humanoid then
  11632. if angry then
  11633. if damage_ready then
  11634. damage_ready = false
  11635. humanoid:TakeDamage(100)
  11636. wait(1)
  11637. damage_ready = true
  11638. angry = false
  11639. part.BrickColor = BrickColor.new("Medium stone grey")
  11640. end
  11641. else
  11642. local torso = humanoid.Torso
  11643. if torso then
  11644. torso_following = torso
  11645. torso_changed = tick()
  11646. end
  11647. end
  11648. end
  11649. end
  11650. end)
  11651. TaskScheduler.Start(function()
  11652. while part.Parent == Workspace do
  11653. if torso_following then
  11654. bodypos.position = torso_following.Position
  11655. if tick() - torso_changed > 60 or not torso_following.Parent then
  11656. torso_following = nil
  11657. bodypos.maxForce = Vector3.new(0, 0, 0)
  11658. angry = false
  11659. part.BrickColor = BrickColor.new("Medium stone grey")
  11660. else
  11661. local speed = angry and Vector3.new(16, 16, 16) or Vector3.new(6, 0, 6)
  11662. bodypos.maxForce = part:GetMass() * speed
  11663. if part.Position.Y < -250 then
  11664. part.Velocity = Vector3.new()
  11665. part.Position = torso_following.Position + Vector3.new(0, 80, 0)
  11666. part.BrickColor = BrickColor.new("Bright red")
  11667. angry = true
  11668. torso_changed = tick()
  11669. end
  11670. end
  11671. end
  11672. RunService.Stepped:wait()
  11673. end
  11674. touched_conn:disconnect()
  11675. end)
  11676. TaskScheduler.Start(function()
  11677. while part.Parent == Workspace do
  11678. wait(25 + math.random() * 10)
  11679. local next_size = 8 + math.random() * 5
  11680. if math.random(100) == 1 then
  11681. next_size = next_size * (2 + 6 * math.random())
  11682. end
  11683. next_size = math.floor(next_size + 0.5)
  11684. local start_time = tick()
  11685. local mesh = Instance.new("SpecialMesh", part)
  11686. mesh.MeshType = "Sphere"
  11687. repeat
  11688. local elapsed_time = tick() - start_time
  11689. local alpha = math.cos(elapsed_time * math.pi * 0.5)
  11690. local interpolated_size = size * alpha + next_size * (1 - alpha)
  11691. local size_vector = Vector3.new(interpolated_size, interpolated_size, interpolated_size)
  11692. local cframe = part.CFrame
  11693. part.Size = size_vector
  11694. part.CFrame = cframe
  11695. mesh.Scale = size_vector / part.Size
  11696. RunService.Stepped:wait()
  11697. until tick() - start_time >= 1
  11698. mesh:Destroy()
  11699. local cframe = part.CFrame
  11700. part.Size = Vector3.new(next_size, next_size, next_size)
  11701. part.CFrame = cframe
  11702. size = next_size
  11703. end
  11704. end)
  11705. end
  11706. -- Crystal ring
  11707. function GraphicalEffects.CrystalRing(data)
  11708. data = data or {}
  11709. local crystal_count = data.crystal_count or 10
  11710. local crystal_color = data.crystal_color or BrickColor.new("Bright red")
  11711. local crystal_scale = data.crystal_scale or Vector3.new(2 / 3, 2, 2 / 3)
  11712. local radius = radius or 1.25 * crystal_count / math.pi
  11713. local spawn_duration = data.spawn_duration or 0.065
  11714. local full_spawn_duration = spawn_duration * crystal_count
  11715. local float_duration = data.float_duration or 5
  11716. local wave_amplitude = data.wave_amplitude or 0.5
  11717. local wave_period = data.wave_period or 1
  11718. local appear_duration = data.appear_duration or 0.1
  11719. local disappear_duration = data.disappear_duration or 0.5
  11720. local base_part = data.base_part
  11721. local offset_cframe
  11722. if data.position then
  11723. offset_cframe = CFrame.new(data.position)
  11724. if base_part then
  11725. offset_cframe = base_part.CFrame:toObjectSpace(offset_cframe)
  11726. end
  11727. else
  11728. offset_cframe = CFrame.new()
  11729. end
  11730. local crystal_template = Instance.new("Part")
  11731. crystal_template.Anchored = true
  11732. crystal_template.Locked = true
  11733. crystal_template.CanCollide = false
  11734. crystal_template.BottomSurface = "Smooth"
  11735. crystal_template.TopSurface = "Smooth"
  11736. crystal_template.BrickColor = crystal_color
  11737. crystal_template.FormFactor = "Symmetric"
  11738. crystal_template.Size = Vector3.new(1, 1, 1)
  11739. local crystal_light = Instance.new("PointLight", crystal_template)
  11740. crystal_light.Brightness = 0.1 / crystal_count
  11741. crystal_light.Color = crystal_color.Color
  11742. crystal_light.Name = "Light"
  11743. crystal_light.Range = radius
  11744. crystal_light.Shadows = true
  11745. local crystal_mesh = Instance.new("SpecialMesh", crystal_template)
  11746. crystal_mesh.MeshId = "rbxassetid://9756362"
  11747. crystal_mesh.MeshType = "FileMesh"
  11748. crystal_mesh.Name = "Mesh"
  11749. crystal_mesh.Scale = crystal_scale
  11750. local crystal_model = Instance.new("Model")
  11751. crystal_model.Archivable = false
  11752. crystal_model.Name = "Crystal Model"
  11753. crystal_model.Parent = Workspace
  11754. local crystals = {}
  11755. local lights = {}
  11756. local meshes = {}
  11757. for index = 1, crystal_count do
  11758. local crystal = crystal_template:Clone()
  11759. crystal.Parent = crystal_model
  11760. crystals[index] = crystal
  11761. lights[index] = crystal.Light
  11762. meshes[index] = crystal.Mesh
  11763. end
  11764. local start_time = tick()
  11765. repeat
  11766. local base_cframe = offset_cframe
  11767. if base_part then
  11768. base_cframe = base_part.CFrame * base_cframe
  11769. end
  11770. local elapsed_time = tick() - start_time
  11771. for index, crystal in ipairs(crystals) do
  11772. local crystal_time = elapsed_time - index * spawn_duration
  11773. local disappear_time = crystal_time - float_duration
  11774. local offset
  11775. if crystal_time < 0 then
  11776. offset = 0
  11777. elseif crystal_time < appear_duration then
  11778. offset = radius * crystal_time / appear_duration
  11779. else
  11780. offset = radius
  11781. end
  11782. local wave_offset
  11783. if disappear_time >= 0 then
  11784. local disappear_progress = disappear_time / disappear_duration
  11785. if disappear_progress > 1 then
  11786. if crystal.Parent then
  11787. crystal:Destroy()
  11788. end
  11789. else
  11790. local inverse_progress = 1 - disappear_progress
  11791. local light = lights[index]
  11792. local mesh = meshes[index]
  11793. crystal.BrickColor = BrickColor.new("Really black")
  11794. light.Brightness = 2 * inverse_progress
  11795. light.Range = 2 * radius
  11796. mesh.Scale = crystal_scale * inverse_progress
  11797. end
  11798. wave_offset = 0
  11799. else
  11800. wave_offset = wave_amplitude * math.sin(math.tau * (elapsed_time - index / crystal_count * 3) / wave_period)
  11801. end
  11802. local rotation_angle = (tick() * 0.5 + (index - 1) / crystal_count) % 1 * math.tau
  11803. crystal.CFrame = base_cframe * CFrame.Angles(0, rotation_angle, 0) * CFrame.new(0, wave_offset, -offset)
  11804. end
  11805. RunService.Stepped:wait()
  11806. until elapsed_time >= float_duration + full_spawn_duration + disappear_duration
  11807. if crystal_model.Parent then
  11808. crystal_model:Destroy()
  11809. end
  11810. end
  11811. -- Missiles
  11812. GraphicalEffects.missileData = {}
  11813. GraphicalEffects.missileParts = {}
  11814. function GraphicalEffects.AnimateMissile(data)
  11815. local frame, missilePart, targetPart, timeCreated, direction, touchedConnection, explodeRequested, bodyGyro, swooshSound, magicCircleData, lifeTime,
  11816.  
  11817. pointOnPart, flipped = unpack(data)
  11818. frame = frame + 1
  11819. data[1] = frame
  11820. if flipped then
  11821. direction = -direction
  11822. end
  11823. if frame <= 10 then
  11824. if frame == 2 then
  11825. swooshSound:Play()
  11826. end
  11827. missilePart.Anchored = true
  11828. local progress = frame / 10
  11829. missilePart.Size = Vector3.new(1, 1, progress * 4)
  11830. local magicCirclePart = magicCircleData[4]
  11831. local magicCirclePosition = magicCirclePart.Position
  11832. local missileOffset = 2 * progress * direction
  11833. local missilePosition = magicCirclePosition + missileOffset
  11834. missilePart.CFrame = CFrame.new(missilePosition, missilePosition + direction)
  11835. --missilePart.Transparency = 0.5 * (1 - progress)
  11836. if frame == 10 then
  11837. touchedConnection = missilePart.Touched:connect(function(hit)
  11838. if hit.CanCollide and hit.Parent and not GraphicalEffects.missileParts[hit] then
  11839. touchedConnection:disconnect()
  11840. data[7] = true
  11841. end
  11842. end)
  11843. data[6] = touchedConnection
  11844. end
  11845. else
  11846. missilePart.Anchored = false
  11847. local missilePosition = missilePart.Position
  11848. local targetPosition = targetPart.CFrame * pointOnPart
  11849. local distanceVector = targetPosition - missilePosition
  11850. local elapsedTime = time() - timeCreated
  11851. local targetParent = targetPart.Parent
  11852. if explodeRequested or (targetParent and distanceVector.magnitude < 10) or elapsedTime > lifeTime then
  11853. GraphicalEffects.missileData[data] = nil
  11854. GraphicalEffects.missileParts[missilePart] = nil
  11855. touchedConnection:disconnect()
  11856. if missilePart.Parent then
  11857. missilePart:Destroy()
  11858. local explosion = Instance.new("Explosion")
  11859. explosion.BlastRadius = 12.5
  11860. explosion.Position = missilePosition
  11861. local explosionHitConnection = explosion.Hit:connect(function(hit, distance)
  11862. local missileData = GraphicalEffects.missileParts[hit]
  11863. if missileData and distance < 3 then
  11864. missileData[7] = true
  11865. else
  11866. pcall(hit.BreakJoints, hit)
  11867. end
  11868. end)
  11869. explosion.Parent = Workspace
  11870. TaskScheduler.Schedule(1, explosionHitConnection.disconnect, explosionHitConnection)
  11871. end
  11872. else
  11873. local targetInWorkspace = targetPart:IsDescendantOf(Workspace)
  11874. if targetInWorkspace then
  11875. direction = distanceVector.unit
  11876. data[5] = direction
  11877. end
  11878. local speed = 14 + elapsedTime * 10
  11879. local gyroD
  11880. if elapsedTime < 42.5 and targetInWorkspace then
  11881. gyroD = 1000 - elapsedTime * 15
  11882. else
  11883. gyroD = 100
  11884. bodyGyro.maxTorque = Vector3.new(0, 0, 0)
  11885. if elapsedTime + 7.5 < lifeTime then
  11886. data[11] = elapsedTime + 7.5
  11887. end
  11888. end
  11889. bodyGyro.D = gyroD
  11890. bodyGyro.cframe = CFrame.new(Vector3.new(), direction)
  11891. missilePart.Velocity = missilePart.CFrame.lookVector * speed
  11892. end
  11893. end
  11894. end
  11895. function GraphicalEffects.ShootMissile(targetPart, pointOnPart, direction, magic_circle_adornee_func, magic_circle_offset, flipped)
  11896. if not magic_circle_offset then
  11897. magic_circle_offset = GraphicalEffects.MAGIC_CIRCLE_DEFAULT_OFFSET
  11898. end
  11899. local targetPosition = targetPart.Position
  11900. local headPosition = chatAdornee.Position
  11901. local origin = CFrame.new(headPosition, headPosition + direction) + direction * magic_circle_offset
  11902. local missilePart = Instance.new("Part")
  11903. local antiGravityForce = Instance.new("BodyForce", missilePart)
  11904. local bodyGyro = Instance.new("BodyGyro", missilePart)
  11905. local explosionSound = Instance.new("Sound", missilePart)
  11906. local swooshSound = Instance.new("Sound", missilePart)
  11907. antiGravityForce.force = Vector3.new(0, 196.2 * 4, 0)
  11908. bodyGyro.D = 1000
  11909. bodyGyro.maxTorque = Vector3.new(1, 1, 1)
  11910. explosionSound.PlayOnRemove = true
  11911. explosionSound.SoundId = "rbxasset://sounds/collide.wav"
  11912. explosionSound.Volume = 1
  11913. missilePart.Anchored = true
  11914. missilePart.BackSurface = "Studs"
  11915. missilePart.BottomSurface = "Studs"
  11916. missilePart.BrickColor = BrickColor.Red()
  11917. missilePart.CFrame = origin
  11918. missilePart.FormFactor = "Custom"
  11919. missilePart.FrontSurface = "Studs"
  11920. missilePart.LeftSurface = "Studs"
  11921. missilePart.Locked = true
  11922. missilePart.RightSurface = "Studs"
  11923. missilePart.Size = Vector3.new(1, 1, 0.2)
  11924. missilePart.TopSurface = "Studs"
  11925. --missilePart.Transparency = 0.5
  11926. swooshSound.Looped = true
  11927. swooshSound.SoundId = "rbxasset://sounds/Rocket whoosh 01.wav"
  11928. swooshSound.Volume = 0.7
  11929. local magicCircleData = GraphicalEffects.CreateMagicCircle(headPosition + direction * 1000, 0.875, "rbxassetid://127033719", Color3.new(1, 1, 1),
  11930.  
  11931. 40, 4, magic_circle_adornee_func or function() return chatAdornee end, magic_circle_offset)
  11932. local data = {0, missilePart, targetPart, time(), direction, false, false, bodyGyro, swooshSound, magicCircleData, 50, pointOnPart, flipped}
  11933. missilePart.Parent = Workspace
  11934. GraphicalEffects.missileData[data] = true
  11935. GraphicalEffects.missileParts[missilePart] = data
  11936. end
  11937. -- Joint crap
  11938. function GraphicalEffects.CubicInterpolate(y0, y1, y2, y3, mu)
  11939. local a0, a1, a2, a3, mu2
  11940. mu2 = mu * mu
  11941. a0 = y3 - y2 - y0 + y1
  11942. a1 = y0 - y1 - a0
  11943. a2 = y2 - y0
  11944. a3 = y1
  11945. return a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3
  11946. end
  11947. function GraphicalEffects.JointCrap(model, cycletime)
  11948. if model then
  11949. local cycletime = cycletime or (0.75 * (1 + math.random() * 4))
  11950. local offsetradius = 0.75
  11951. local rotationoffset = math.pi
  11952. local joints = {}
  11953. local stack = model:GetChildren()
  11954. while #stack ~= 0 do
  11955. local object = stack[#stack]
  11956. table.remove(stack)
  11957. for index, child in ipairs(object:GetChildren()) do
  11958. table.insert(stack, child)
  11959. end
  11960. if object:IsA("JointInstance") then
  11961. table.insert(joints, object)
  11962. end
  11963. end
  11964. local rot0 = {}
  11965. local rot1 = {}
  11966. local rot2 = {}
  11967. local rot3 = {}
  11968. local rot4 = {}
  11969. for index, joint in ipairs(joints) do
  11970. local pos = Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5).unit * offsetradius
  11971. local rot = Vector3.new(math.random(), math.random(), math.random()) * rotationoffset
  11972. rot0[index] = {joint.C0, joint.C1}
  11973. rot = Vector3.new(rot.x % (math.tau), rot.y % (math.tau), rot.z % (math.tau))
  11974. rot2[index] = {pos, rot}
  11975. pos = Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5).unit * offsetradius
  11976. rot = rot + Vector3.new(math.random(), math.random(), math.random()) * rotationoffset
  11977. rot = Vector3.new(rot.x % (math.tau), rot.y % (math.tau), rot.z % (math.tau))
  11978. rot3[index] = {pos, rot}
  11979. pos = Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5).unit * offsetradius
  11980. rot = rot + Vector3.new(math.random(), math.random(), math.random()) * rotationoffset
  11981. rot = Vector3.new(rot.x % (math.tau), rot.y % (math.tau), rot.z % (math.tau))
  11982. rot4[index] = {pos, rot}
  11983. end
  11984. while model.Parent do
  11985. for i, j in ipairs(joints) do
  11986. local pos = Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5).unit * offsetradius
  11987. local rot = rot4[i][2] + Vector3.new(math.random(), math.random(), math.random()) * rotationoffset
  11988. rot = Vector3.new(rot.x % (math.tau), rot.y % (math.tau), rot.z % (math.tau))
  11989. rot1[i], rot2[i], rot3[i], rot4[i] = rot2[i], rot3[i], rot4[i], {pos, rot}
  11990. end
  11991. local start = tick()
  11992. while true do
  11993. local ctime = tick()
  11994. local elapsed = ctime - start
  11995. if elapsed > cycletime then
  11996. break
  11997. end
  11998. local progress = elapsed / cycletime
  11999. for index, joint in ipairs(joints) do
  12000. local v0, v1, v2, v3, v4 = rot0[index], rot1[index], rot2[index], rot3[index], rot4[index]
  12001. local p1, p2, p3, p4, r1, r2, r3, r4 = v1[1], v2[1], v3[1], v4[1], v1[2], v2[2], v3[2], v4[2]
  12002. local px = GraphicalEffects.CubicInterpolate(p1.x, p2.x, p3.x, p4.x, progress)
  12003. local py = GraphicalEffects.CubicInterpolate(p1.y, p2.y, p3.y, p4.y, progress)
  12004. local pz = GraphicalEffects.CubicInterpolate(p1.z, p2.z, p3.z, p4.z, progress)
  12005. local rx = GraphicalEffects.CubicInterpolate(r1.x, r2.x, r3.x, r4.x, progress)
  12006. local ry = GraphicalEffects.CubicInterpolate(r1.y, r2.y, r3.y, r4.y, progress)
  12007. local rz = GraphicalEffects.CubicInterpolate(r1.z, r2.z, r3.z, r4.z, progress)
  12008. local cframe = CFrame.new(px, py, pz) * CFrame.Angles(rx, ry, rz)
  12009. joint.C0 = v0[1] * cframe
  12010. joint.C1 = v0[2] * cframe:inverse()
  12011. end
  12012. RunService.Stepped:wait()
  12013. end
  12014. end
  12015. end
  12016. end
  12017. -- Destruction spell
  12018. do
  12019. GraphicalEffects.destructionSpellSpeed = 5
  12020. GraphicalEffects.destructionSpellEffectSize = 2
  12021. GraphicalEffects.destructionSpellExplosionRate = 10
  12022. GraphicalEffects.destructionSpellFadeDuration = 120
  12023. local partProto = Instance.new("Part")
  12024. local partProtoDecal1 = Instance.new("Decal", partProto)
  12025. local partProtoDecal2 = Instance.new("Decal", partProto)
  12026. local partProtoGyro = Instance.new("BodyGyro", partProto)
  12027. local partProtoPosition = Instance.new("BodyPosition", partProto)
  12028. partProto.CanCollide = false
  12029. partProto.FormFactor = "Custom"
  12030. partProto.Transparency = 1
  12031. partProtoDecal1.Face = "Bottom"
  12032. partProtoDecal1.Texture = "rbxassetid://106508453"
  12033. partProtoDecal2.Face = "Top"
  12034. partProtoDecal2.Texture = "rbxassetid://106508453"
  12035. partProtoGyro.Name = "gyro"
  12036. partProtoGyro.P = 1e6
  12037. partProtoGyro.maxTorque = Vector3.new(1e9, 1e9, 1e9)
  12038. partProtoPosition.Name = "pos"
  12039. partProtoPosition.P = 1e4
  12040. partProtoPosition.maxForce = Vector3.new(1e9, 1e9, 1e9)
  12041. function GraphicalEffects.DestructionSpell(nodes)
  12042. local destroyTable = {}
  12043. local regionSizeX, regionSizeY, regionSizeZ
  12044. local function MagicalDestroyUnchecked(part)
  12045. local partSize = part.Size
  12046. if partSize.X < regionSizeX and partSize.Y < regionSizeY and partSize.Z < regionSizeZ then
  12047. destroyTable[part] = true
  12048. part.Material = "Plastic"
  12049. local beginTransparency = part.Transparency
  12050. local fadeDuration = GraphicalEffects.destructionSpellFadeDuration
  12051. for i = 1, fadeDuration do
  12052. RunService.Stepped:wait()
  12053. part.Transparency = beginTransparency + (1 - beginTransparency) * (i / fadeDuration)
  12054. end
  12055. pcall(Game.Destroy, part)
  12056. destroyTable[part] = nil
  12057. end
  12058. end
  12059. local function MagicalDestroy(part)
  12060. if not destroyTable[part] then
  12061. MagicalDestroyUnchecked(part)
  12062. end
  12063. end
  12064. local function MagicalNodeFinalize(part, gyro, pos, conn)
  12065. part.Anchored = true
  12066. pcall(gyro.Destroy, gyro)
  12067. pcall(pos.Destroy, pos)
  12068. conn:disconnect()
  12069. end
  12070. local model = Instance.new("Model")
  12071. model.Archivable = false
  12072. model.Name = "Nolix Wrath"
  12073. model.Parent = Workspace
  12074. local connections = {}
  12075. local parts = {}
  12076. local partsHit = {}
  12077. local cleanupList = {}
  12078. local explosionRate = GraphicalEffects.destructionSpellExplosionRate
  12079. local effectSize = GraphicalEffects.destructionSpellEffectSize
  12080. partProto.Size = Vector3.new(effectSize, 0.2, effectSize)
  12081. local speed = GraphicalEffects.destructionSpellSpeed
  12082. local rateTimer = 0
  12083. local partRotation = CFrame.Angles(0, 0.5 * math.pi, 0)
  12084. local minX, minY, minZ, maxX, maxY, maxZ = math.huge, math.huge, math.huge, -math.huge, -math.huge, -math.huge
  12085. for index = 4, #nodes do
  12086. local v0, v1, v2, v3 = nodes[index - 3], nodes[index - 2], nodes[index - 1], nodes[index]
  12087. local p1 = v1
  12088. local count = math.ceil((v2 - v1).magnitude / effectSize)
  12089. local linearStep = (v2 - v1) / count
  12090. for i = 1, count do
  12091. local alpha = i / count
  12092. local p2 = GraphicalEffects.CubicInterpolate(v0, v1, v2, v3, alpha)
  12093. local center = 0.5 * (p1 + p2)
  12094. local offset = p2 - p1
  12095. local partId = #parts + 1
  12096. local hitList = {}
  12097. partsHit[partId] = hitList
  12098. local part = partProto:Clone()
  12099. local gyro = part.gyro
  12100. local pos = part.pos
  12101. local cframe = CFrame.new(center, center + offset) * partRotation
  12102. part.CFrame = cframe
  12103. gyro.cframe = cframe
  12104. pos.position = center
  12105. local posX, posY, posZ = center.X, center.Y, center.Z
  12106. if posX < minX then minX = posX end
  12107. if posY < minY then minY = posY end
  12108. if posZ < minZ then minZ = posZ end
  12109. if posX > maxX then maxX = posX end
  12110. if posY > maxY then maxY = posY end
  12111. if posZ > maxZ then maxZ = posZ end
  12112. Instance.new("BlockMesh", part).Scale = Vector3.new(offset.magnitude, 0, effectSize)
  12113. parts[partId] = part
  12114. destroyTable[part] = true
  12115. local conn = part.Touched:connect(function(hit)
  12116. if not destroyTable[hit] then
  12117. hitList[hit] = true
  12118. end
  12119. end)
  12120. part.Parent = model
  12121. p1 = p2
  12122. TaskScheduler.Schedule(0.125, MagicalNodeFinalize, part, gyro, pos, conn)
  12123. rateTimer = rateTimer + 1
  12124. while rateTimer >= speed do
  12125. RunService.Stepped:wait()
  12126. rateTimer = rateTimer - speed
  12127. end
  12128. end
  12129. end
  12130. local center = Vector3.new(minX + maxX, minY + maxY, minZ + maxZ) * 0.5
  12131. regionSizeX, regionSizeY, regionSizeZ = maxX - minX, maxY - minY, maxZ - minZ
  12132. wait(0.5)
  12133. rateTimer = 0
  12134. for index, part in pairs(parts) do
  12135. if index % explosionRate == 1 then
  12136. local partSize = part.Size
  12137. if partSize.X < regionSizeX and partSize.Y < regionSizeY and partSize.Z < regionSizeZ then
  12138. local explosion = Instance.new("Explosion")
  12139. explosion.BlastPressure = 0
  12140. local position = part.Position
  12141. explosion.BlastRadius = (position - center).magnitude * 0.5
  12142. explosion.Position = (position + center) * 0.5
  12143. connections[#connections + 1] = explosion.Hit:connect(MagicalDestroy)
  12144. explosion.Parent = model
  12145. end
  12146. end
  12147. pcall(part.Destroy, part)
  12148. destroyTable[part] = nil
  12149. local hitList = partsHit[index]
  12150. for hit in pairs(hitList) do
  12151. local partSize = hit.Size
  12152. if partSize.X < regionSizeX and partSize.Y < regionSizeY and partSize.Z < regionSizeZ
  12153. and hit.Parent and not destroyTable[hit] then
  12154. TaskScheduler.Start(MagicalDestroyUnchecked, hit)
  12155. local explosion = Instance.new("Explosion")
  12156. explosion.BlastPressure = 0
  12157. explosion.BlastRadius = hit:GetMass() ^ (1 / 3) * 2
  12158. explosion.Position = hit.Position
  12159. connections[#connections + 1] = explosion.Hit:connect(MagicalDestroy)
  12160. explosion.Parent = model
  12161. end
  12162. end
  12163. rateTimer = rateTimer + 1
  12164. while rateTimer >= 4 * speed do
  12165. RunService.Stepped:wait()
  12166. rateTimer = rateTimer - 4 * speed
  12167. end
  12168. end
  12169. wait(0.25)
  12170. for _, connection in ipairs(connections) do
  12171. connection:disconnect()
  12172. end
  12173. end
  12174. end
  12175. -- MainLoop
  12176. function GraphicalEffects.MainLoop()
  12177. RunService.Stepped:wait()
  12178. for data in pairs(GraphicalEffects.magicCircleData) do
  12179. GraphicalEffects.AnimateMagicCircle(data)
  12180. end
  12181. for data in pairs(GraphicalEffects.laser_data) do
  12182. GraphicalEffects.AnimateLaserOfDeath(data)
  12183. end
  12184. for data in pairs(GraphicalEffects.missileData) do
  12185. GraphicalEffects.AnimateMissile(data)
  12186. end
  12187. end
  12188. TaskScheduler.Start(function()
  12189. while true do
  12190. GraphicalEffects.MainLoop()
  12191. end
  12192. end)
  12193. ]])
  12194. Module.Store("ServerControl", [=[
  12195. for _, child in ipairs(Game:GetChildren()) do
  12196. local success, className = pcall(function() return child.ClassName end)
  12197. if success and className == "NetworkServer" then
  12198. NetworkServer = child
  12199. break
  12200. end
  12201. end
  12202. ServerControl.banished_names = {}
  12203. for _, name in ipairs({
  12204. "12345678910jaijai",
  12205. "56awesome56",
  12206. "aleksa12432",
  12207. "blowup998",
  12208. "christmasboy",
  12209. "coolythe94",
  12210. "dalvo546",
  12211. "ENCRYPTEDis",
  12212. "fanoftheforgotten",
  12213. "goldenarrow97",
  12214. "Guest101632",
  12215. "hgbvcgdhgfds",
  12216. "IlIlXxxxxxXX12",
  12217. "InfiniteDeathKiller",
  12218. "JTHKILL99",
  12219. "liIlilILLIilIlil",
  12220. "LuaHat",
  12221. "LuaScriptPro",
  12222. "missKittyCatlove",
  12223. "MsDaisyroses",
  12224. "robloxmaster4491",
  12225. "rojdi3",
  12226. "s3sss3x",
  12227. "SBDESTROYER1",
  12228. "ScriptGuider",
  12229. "Scriptralize",
  12230. "ScriptTestingAccount",
  12231. "Scrupting",
  12232. "SomeMayCallMeATroll",
  12233. "starwill1",
  12234. "Starwill3",
  12235. "Toothyepic",
  12236. "trefor123"
  12237. }) do
  12238. ServerControl.banished_names[name:lower()] = true
  12239. end
  12240. for _, player in ipairs(Players:GetPlayers()) do
  12241. local playerName = tostring(player)
  12242. if ServerControl.banished_names[playerName:lower()] then
  12243. Logger.printf("Info", "Player %s has been kicked", playerName)
  12244. player:Kick()
  12245. end
  12246. end
  12247. ServerControl.LONG_STRING = string.rep("0123456789", 20001)
  12248. ServerControl.player_data = {}
  12249. function ServerControl.BanishName(name)
  12250. ServerControl.banished_names[name:lower()] = true
  12251. end
  12252. ServerControl.authorizedRemoteEvents = {}
  12253. ServerControl.MAX_MESSAGES = 2
  12254. ServerControl.message_list = {}
  12255. function ServerControl.BlockMessageSpam(object)
  12256. local message_list = ServerControl.message_list
  12257. local message_count = #message_list + 1
  12258. message_list[message_count] = object
  12259. if message_count > ServerControl.MAX_MESSAGES then
  12260. local new_message_count = 0
  12261. local new_message_list = {}
  12262. for message_index = 1, message_count do
  12263. local message_object = message_list[message_index]
  12264. local success, in_workspace = pcall(Game.IsDescendantOf, message_object, Workspace)
  12265. if success and in_workspace then
  12266. new_message_count = new_message_count + 1
  12267. new_message_list[new_message_count] = message_object
  12268. end
  12269. end
  12270. while new_message_count > ServerControl.MAX_MESSAGES do
  12271. local message_object = new_message_list[1]
  12272. Debris:AddItem(message_object, 0)
  12273. table.remove(new_message_list, 1)
  12274. new_message_count = new_message_count - 1
  12275. end
  12276. ServerControl.message_list = new_message_list
  12277. end
  12278. end
  12279. function ServerControl.FilterReplicatedStorage(child)
  12280. if child.ClassName == "RemoteEvent" and not ServerControl.authorizedRemoteEvents[child] then
  12281. Spawn(function()
  12282. child:Destroy()
  12283. Logger.printf("Info", "removed remote event %q from ReplicatedStorage", tostring(child))
  12284. end)
  12285. end
  12286. end
  12287. function ServerControl.GetPlayer(playerName)
  12288. if NetworkServer then
  12289. for _, replicator in ipairs(NetworkServer:GetChildren()) do
  12290. if replicator:IsA("NetworkReplicator") then
  12291. local player = replicator:GetPlayer()
  12292. if player and tostring(player) == playerName then
  12293. return player
  12294. end
  12295. end
  12296. end
  12297. end
  12298. end
  12299. function ServerControl.ListConnectedPlayers()
  12300. if NetworkServer then
  12301. for _, replicator in ipairs(NetworkServer:GetChildren()) do
  12302. if replicator:IsA("NetworkReplicator") then
  12303. local player = replicator:GetPlayer()
  12304. if player then
  12305. Logger.print("Output", tostring(player))
  12306. else
  12307. Logger.print("Output", "(joining)")
  12308. end
  12309. end
  12310. end
  12311. end
  12312. end
  12313. ServerControl.previous_player_list = {}
  12314. function ServerControl.MainLoop()
  12315. wait(1)
  12316. for _, player in ipairs(Players:GetChildren()) do
  12317. ypcall(function()
  12318. if player:IsA("Player") then
  12319. TaskScheduler.Schedule(ServerControl.ConnectPlayer, player)
  12320. end
  12321. end)
  12322. end
  12323. local buffer = {"AdvancedGUI.networkFrame:ClearItems()"}
  12324. local player_list = {}
  12325. local different = false
  12326. local replicator_count = 0
  12327. if NetworkServer then
  12328. for index, replicator in ipairs(NetworkServer:GetChildren()) do
  12329. if replicator:IsA("NetworkReplicator") then
  12330. local player = replicator:GetPlayer()
  12331. local item_text
  12332. if player then
  12333. local system_time, idle_time, user_name, is_nil
  12334. user_name = tostring(player)
  12335. local player_data = ServerControl.player_data[user_name]
  12336. if player_data then
  12337. system_time = player_data[1]
  12338. local idle_time_raw = player_data[2]
  12339. local seconds = idle_time_raw % 60
  12340. local minutes = (idle_time_raw - seconds) / 60
  12341. idle_time = string.format("%i:%04.1f", minutes, seconds)
  12342. else
  12343. system_time = "??:??:??"
  12344. idle_time = "?:??.?"
  12345. end
  12346. is_nil = not player.Parent
  12347. item_text = string.format("%s %s %s %s", system_time, idle_time, user_name, tostring(is_nil))
  12348. buffer[#buffer + 1] = string.format("AdvancedGUI.networkFrame:AddItem(%q, %q, %q, %s)", system_time, idle_time,
  12349.  
  12350. user_name, tostring(is_nil))
  12351. else
  12352. item_text = "(joining the game)"
  12353. buffer[#buffer + 1] = "GuiTextList.AddItem(AdvancedGUI.networkFrame, \"(joining the game)\")"
  12354. end
  12355. different = different or ServerControl.previous_player_list[index] ~= item_text
  12356. replicator_count = replicator_count + 1
  12357. player_list[index] = item_text
  12358. end
  12359. end
  12360. else
  12361. buffer[#buffer + 1] = string.format("AdvancedGUI.networkFrame:AddItem(\"<OFFLINE MODE>\")")
  12362. different = different or ServerControl.previous_player_list[1] ~= "<OFFLINE MODE>"
  12363. replicator_count = 1
  12364. player_list[1] = "<OFFLINE MODE>"
  12365. end
  12366. if different or #ServerControl.previous_player_list ~= replicator_count then
  12367. Network.TransmitController(table.concat(buffer, "\n"))
  12368. ServerControl.previous_player_list = player_list
  12369. end
  12370. end
  12371. ServerControl.connected_players = {}
  12372. ServerControl.connection_signals = {}
  12373. ServerControl.next_script_id = Network.script_id + 1
  12374. ServerControl.module_signal_packet_name = "MODULE_READY/" .. _SessionID .. "/" .. Network.server_id
  12375. function ServerControl.ConnectPlayer(player, forced)
  12376. if forced or not ServerControl.connected_players[player] then
  12377. ServerControl.connected_players[player] = 1
  12378. local valid, is_player = pcall(Game.IsA, player, "Player")
  12379. is_player = is_player == true or not valid
  12380. local is_controller = is_player and player.userId == ControllerInfo.user_id
  12381. local new_script_id
  12382. if is_controller then
  12383. new_script_id = Network.controller_id
  12384. else
  12385. new_script_id = ServerControl.next_script_id
  12386. ServerControl.next_script_id = new_script_id + 1
  12387. end
  12388. local network_receiver_script = SBTools.NewLocalScript(_SessionID .. "/" .. new_script_id, NetworkReceiver.source)
  12389. local marker_label = "ACKNOWLEDGE/" .. _SessionID .. "/" .. new_script_id
  12390. TaskScheduler.Start(function()
  12391. local connection_established = false
  12392. local listener
  12393. listener = ReplicatedStorage.ChildAdded:connect(function(child)
  12394. if child.Name == marker_label then
  12395. listener:disconnect()
  12396. local player_name = child.Value
  12397. Debris:AddItem(child, 0)
  12398. connection_established = true
  12399. Network.Register(player_name, new_script_id)
  12400. if not is_controller then
  12401. Network.TransmitController(string.format("Network.Register(%q, %s)", player_name, tostring(new_script_id)))
  12402. end
  12403. local signal = RbxUtility.CreateSignal()
  12404. ServerControl.connection_signals[new_script_id] = signal
  12405. Network.Transmit(new_script_id, string.format([[
  12406. local Module = {}
  12407. Module.name = "Module"
  12408. Module.source = %q
  12409. loadstring(Module.source)(Module)
  12410. setmetatable(Module, Module.metatable)
  12411. Module.Register(Module)
  12412. local packet = Instance.new("IntValue")
  12413. packet.Name = %q
  12414. packet.Value = %s
  12415. packet.Parent = Game:GetService("ReplicatedStorage")
  12416. ]], Module.source, ServerControl.module_signal_packet_name, tostring(new_script_id)))
  12417. signal:wait()
  12418. if ServerControl.connected_players[player] == 1 then
  12419. ServerControl.connected_players[player] = 2
  12420. ServerControl.connection_signals[new_script_id] = nil
  12421. Network.Transmit(new_script_id, "")
  12422. Network.TransmitModule(new_script_id, LuaEnum)
  12423. Network.TransmitModule(new_script_id, Logger)
  12424. Network.TransmitModule(new_script_id, Utility)
  12425. Network.TransmitModule(new_script_id, TaskScheduler)
  12426. Network.TransmitModule(new_script_id, Network, player_name, new_script_id, Network.controller_id)
  12427. if is_controller then
  12428. Network.TransmitModule(new_script_id, UserInterface, true)
  12429. Network.TransmitModule(new_script_id, PyramidCharacter)
  12430. Network.TransmitModule(new_script_id, CharacterAppearance)
  12431. Network.TransmitModule(new_script_id, PlayerControl)
  12432. Network.TransmitModule(new_script_id, ChatColor)
  12433. Network.TransmitModule(new_script_id, RBXInstance)
  12434. Network.TransmitModule(new_script_id, AdvancedGUI)
  12435. Network.TransmitModule(new_script_id, ControllerCommands)
  12436. local local_script_forward, server_script_forward
  12437. if SBTools.local_script and SBTools.server_script then
  12438. local_script_forward = SBTools.local_script:Clone()
  12439. server_script_forward = SBTools.server_script:Clone()
  12440. local_script_forward.Parent = ReplicatedStorage
  12441. server_script_forward.Parent = ReplicatedStorage
  12442. end
  12443. Network.TransmitModule(new_script_id, SBTools, local_script_forward, server_script_forward)
  12444. Network.StoreModule(new_script_id, NetworkReceiver)
  12445. Network.StoreModule(new_script_id, ChatBubble)
  12446. Network.StoreModule(new_script_id, Fragmentation)
  12447. Network.StoreModule(new_script_id, GraphicalEffects)
  12448. Network.StoreModule(new_script_id, ServerControl)
  12449. else
  12450. Network.TransmitModule(new_script_id, UserInterface)
  12451. end
  12452. Network.TransmitModule(new_script_id, Notification)
  12453. end
  12454. end
  12455. end)
  12456. repeat
  12457. if is_player then
  12458. local success, errorMessage = ypcall(function()
  12459. for _, child in ipairs(Workspace:GetChildren()) do
  12460. if Players:GetPlayerFromCharacter(child) == player then
  12461. local pscript = network_receiver_script:Clone()
  12462. pscript.Parent = child
  12463. wait()
  12464. pscript.Disabled = false
  12465. local changed_connection = pscript.Changed:connect(function(property)
  12466. if property == "Disabled" and pscript.Disabled then
  12467. wait()
  12468. pscript.Disabled = false
  12469. end
  12470. end)
  12471. wait(15)
  12472. changed_connection:disconnect()
  12473. break
  12474. end
  12475. end
  12476. end)
  12477. if not success then
  12478. Logger.printf("Severe", "Error in ServerControl.ConnectPlayer: %s", errorMessage)
  12479. end
  12480. success, errorMessage = ypcall(function()
  12481. if not (connection_established or not player.Parent) then
  12482. local pscript = network_receiver_script:Clone()
  12483. pscript.Parent = player:WaitForChild("Backpack")
  12484. wait()
  12485. pscript.Disabled = false
  12486. local changed_connection = pscript.Changed:connect(function(property)
  12487. if property == "Disabled" and pscript.Disabled then
  12488. wait()
  12489. pscript.Disabled = false
  12490. end
  12491. end)
  12492. wait(15)
  12493. changed_connection:disconnect()
  12494. end
  12495. end)
  12496. if not success then
  12497. Logger.printf("Severe", "Error in ServerControl.ConnectPlayer: %s", errorMessage)
  12498. end
  12499. else
  12500. local success, errorMessage = ypcall(function()
  12501. local pscript = network_receiver_script:Clone()
  12502. pscript.Parent = player
  12503. wait()
  12504. pscript.Disabled = false
  12505. local changed_connection = pscript.Changed:connect(function(property)
  12506. if property == "Disabled" and pscript.Disabled then
  12507. wait()
  12508. pscript.Disabled = false
  12509. end
  12510. end)
  12511. wait(15)
  12512. changed_connection:disconnect()
  12513. end)
  12514. if not success then
  12515. Logger.printf("Severe", "Error in ServerControl.ConnectPlayer: %s", errorMessage)
  12516. end
  12517. end
  12518. wait()
  12519. until connection_established or not pcall(function() assert(player.Parent) end)
  12520. end)
  12521. end
  12522. end
  12523. function ServerControl.HandleEstablishmentPacket(packet)
  12524. if tostring(packet) == ServerControl.module_signal_packet_name and packet.ClassName == "IntValue" then
  12525. local success, message = ypcall(function() ServerControl.connection_signals[packet.Value]:fire() end)
  12526. if not success then
  12527. Logger.printf("Severe", "Error in ServerControl.HandleEstablishmentPacket: %s", message)
  12528. end
  12529. Debris:AddItem(packet, 0)
  12530. end
  12531. end
  12532. function ServerControl.OnConnectionRemoving(replicator)
  12533. local player = replicator:GetPlayer()
  12534. if player then
  12535. local player_name = tostring(player)
  12536. Network.script_ids[player_name] = nil
  12537. ServerControl.player_data[player_name] = nil
  12538. end
  12539. end
  12540. function ServerControl.OnWorkspaceDescendantAdded(object)
  12541. local class_name = object.ClassName
  12542. if class_name == "Message" or class_name == "Hint" then
  12543. local success, message = ypcall(ServerControl.BlockMessageSpam, object)
  12544. if not success then
  12545. Logger.printf("Severe", "Error in ServerControl.BlockMessageSpam: %s", message)
  12546. end
  12547. end
  12548. end
  12549. function ServerControl.RemoteDisconnect(target, banish)
  12550. local targetCaseInsensitive = Utility.CaseInsensitivePattern(target)
  12551. local remoteEvent = Instance.new("RemoteEvent")
  12552. ServerControl.authorizedRemoteEvents[remoteEvent] = true
  12553. remoteEvent.Parent = ReplicatedStorage
  12554. for _, replicator in ipairs(NetworkServer:GetChildren()) do
  12555. local className = Utility.SafeGetProperty(replicator, "ClassName")
  12556. if className == "ServerReplicator" then
  12557. local player = replicator:GetPlayer()
  12558. if player then
  12559. local playerName = tostring(player)
  12560. if string.find(playerName, targetCaseInsensitive) then
  12561. Logger.printf("Info", "Disconnecting%s player %s using RemoteEvent", banish and " and banishing" or "",
  12562.  
  12563. Utility.ToString(player))
  12564. if banish then
  12565. ServerControl.BanishName(playerName)
  12566. end
  12567. remoteEvent:FireClient(player, ServerControl.LONG_STRING)
  12568. end
  12569. end
  12570. end
  12571. end
  12572. ServerControl.authorizedRemoteEvents[remoteEvent] = false
  12573. Debris:AddItem(remoteEvent, 1)
  12574. end
  12575. function ServerControl.SendConnections()
  12576. local buffer = {}
  12577. for name, id in pairs(Network.script_ids) do
  12578. if id == Network.controller_id then
  12579. buffer[#buffer + 1] = string.format("Network.script_ids[\"\"] = %s;", tostring(id))
  12580. else
  12581. buffer[#buffer + 1] = string.format("Network.script_ids[%q] = %s;", name, tostring(id))
  12582. end
  12583. end
  12584. Network.TransmitController(table.concat(buffer))
  12585. end
  12586. function ServerControl.PlayerAdded(player)
  12587. if not (ServerControl.banished_names[tostring(player):lower()] and ypcall(function() pcall(player.Kick, player) wait() pcall(Game.Destroy, player)
  12588.  
  12589. Logger.printf("Info", "Prevented player %s from entering", tostring(player)) end)) then
  12590. local success, message = ypcall(ServerControl.ConnectPlayer, player)
  12591. if not success then
  12592. Logger.printf("Severe", "Error in ServerControl.ConnectPlayer: %s", message)
  12593. end
  12594. end
  12595. end
  12596. Players.PlayerAdded:connect(function(...)
  12597. ServerControl.PlayerAdded(...)
  12598. end)
  12599. for _, player in ipairs(Players:GetChildren()) do
  12600. pcall(function()
  12601. if player:IsA("Player") then
  12602. ServerControl.ConnectPlayer(player)
  12603. end
  12604. end)
  12605. end
  12606. function ServerControl.SBScriptInject(child)
  12607. if child.ClassName == "Script" then
  12608. local value = child:WaitForChild(SBTools.source_name)
  12609. if not value or value.ClassName ~= "StringValue" then
  12610. return
  12611. end
  12612. value.Value = [[do local
  12613.  
  12614. a,b,c,d,_a,aa,ba,ca,da,_b,ab,bb,cb,db,_c,ac,bc,cc,dc,_d,ad=true,coroutine.yield,error,getfenv,pairs,rawset,setfenv,setmetatable,tonumber,type,script,Game:Ge
  12615.  
  12616. tService("ReplicatedStorage")rbx_ENV=d(1)patched=ca({},{__index=rbx_ENV})db={__index=patched,__metatable="The metatable is locked"}_c=ca({},db)function ac
  12617.  
  12618. (bd)c("The script has terminated",bd+1)end;function bc(bd)return function(...)if not a then ac(2)end;return bd(...)end end function cc(bd,cd)local
  12619.  
  12620. dd,__a=rbx_ENV[bd],{}for a_a,b_a in ipairs(cd)do __a[b_a]=bc(dd[b_a])end patched[bd]=ca({},{__metatable="The metatable is locked",__index=ca(__a,
  12621.  
  12622. {__index=dd}),__newindex=dd})end for bd,cd in ipairs
  12623.  
  12624. {"assert","delay","Delay","getmetatable","ipairs","next","pairs","pcall","print","rawequal","rawget","rawset","select","setmetatable","Spawn","tick","time",
  12625.  
  12626. "tonumber","tostring","type","unpack","wait","Wait","ypcall"}do patched[cd]=bc(rbx_ENV[cd])end for bd,cd in pairs{BrickColor=
  12627.  
  12628. {"new","palette","random"},Color3={"new"},CFrame={"Angles","fromAxisAngle","fromEulerAnglesXYZ","new"},coroutine=
  12629.  
  12630. {"create","resume","wrap","yield"},Instance={"Lock","new","Unlock"},Ray={"new"},Region3={"new"},UDim2={"new"},Vector2={"new"},Vector3=
  12631.  
  12632. {"FromAxis","FromNormalId","new"}}do cc(bd,cd)end function patched.getfenv(bd)if bd==nil then bd=1 end;local cd=_b(bd)local dd=da(bd)local __a if dd then if
  12633.  
  12634. dd>0.5 then dd=dd+1 elseif dd<-0.5 then c("bad argument #1 to 'getfenv' (level must be non-negative)",2)else dd=0 end;__a=d(dd)elseif cd=="function"then
  12635.  
  12636. __a=d(bd)else c("bad argument #1 to 'getfenv' (number expected, got "..cd..")",2)end;if __a.pairs==_a then __a=_c end;return __a end;ba(0,_c)ba
  12637.  
  12638. (1,_c)function dc(bd)if bd.Name=="__TERMINATE_SB_SCRIPTS__"and bd.ClassName=="NumberValue"and bd.Value==]].._SessionID..[[ then _d:disconnect
  12639.  
  12640. ()a=false;db.__index=nil for cd in _a(_c)do aa(_c,cd,nil)end;db.__newindex={}ba(0,{})end end;_d=bb.ChildAdded:connect
  12641.  
  12642. (dc)ad=ab.Parent.DescendantRemoving:connect(function(bd)if bd==ab then ad:disconnect()ab.Disabled=true;b()ab.Disabled=false _d:disconnect
  12643.  
  12644. ()_d=bb.ChildAdded:connect(dc)end end)end;]] .. value.Value
  12645. end
  12646. end
  12647. ReplicatedStorage.ChildAdded:connect(function(child)
  12648. ServerControl.HandleEstablishmentPacket(child)
  12649. end)
  12650. if NetworkServer then
  12651. NetworkServer.DescendantRemoving:connect(function(...)
  12652. local success, message = pcall(ServerControl.OnConnectionRemoving, ...)
  12653. if not success then
  12654. Logger.printf("Severe", "Error in ServerControl.OnConnectionRemoving: %s", message)
  12655. end
  12656. end)
  12657. end
  12658. ReplicatedStorage.ChildAdded:connect(function(...)
  12659. local success, message = pcall(ServerControl.FilterReplicatedStorage, ...)
  12660. if not success then
  12661. Logger.printf("Severe", "Error in ServerControl.FilterReplicatedStorage: %s", message)
  12662. end
  12663. end)
  12664. for _, child in ipairs(ReplicatedStorage:GetChildren()) do
  12665. local success, message = pcall(ServerControl.FilterReplicatedStorage, child)
  12666. if not success then
  12667. Logger.printf("Severe", "Error in ServerControl.FilterReplicatedStorage: %s", message)
  12668. end
  12669. end
  12670. if SBTools.server_script then
  12671. Logger.print("Info", "Enabling server script injection in ServerControl")
  12672. Workspace.ChildAdded:connect(function(child)
  12673. success, message = ypcall(ServerControl.SBScriptInject, child)
  12674. if not success then
  12675. Logger.printf("Severe", "Error in ServerControl.SBScriptInject", message)
  12676. end
  12677. end)
  12678. end
  12679. Logger.print("Info", "Enabling message spam blocker in ServerControl")
  12680. Workspace.DescendantAdded:connect(function(object)
  12681. ServerControl.OnWorkspaceDescendantAdded(object)
  12682. end)
  12683. TaskScheduler.Start(function()
  12684. while true do
  12685. ServerControl.MainLoop()
  12686. end
  12687. end)
  12688. ]=])
  12689. Module.Store("CustomSB", [[
  12690. local function PlayerAdded(player)
  12691. player.Chatted:connect(function(message)
  12692. local source
  12693. source = string.match(message, "^script/(.*)")
  12694. if source then
  12695. local script = SBTools.NewScript("QuickScript", source, Workspace)
  12696. script.Disabled = false
  12697. else
  12698. source = string.match(message, "^local/(.*)")
  12699. if source then
  12700. local script = SBTools.NewLocalScript("QuickScript", source, player:FindFirstChild("Backpack"))
  12701. script.Disabled = false
  12702. end
  12703. end
  12704. end)
  12705. end
  12706. for _, player in ipairs(Players:GetChildren()) do
  12707. pcall(PlayerAdded, player)
  12708. end
  12709. Players.PlayerAdded:connect(function(player)
  12710. pcall(PlayerAdded, player)
  12711. end)
  12712. ]])
  12713. Module.Create("ControllerCommands", [=[
  12714. ControllerCommands.altKey = "["
  12715. ControllerCommands.BALEFIRE_SPEED = 40
  12716. function ControllerCommands.BalefireAtMouse()
  12717. local head = PlayerControl.GetHead()
  12718. if head then
  12719. local target = Mouse.Hit.p
  12720. local origin = head.Position
  12721. local direction = (target - origin).unit
  12722. local explosionCount = 0
  12723. local animation_frame = 0
  12724. local magic_circle_position = origin + direction * 4
  12725. local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction)
  12726. local magic_circle_part = Instance.new("Part")
  12727. local magic_circle_mesh = Instance.new("BlockMesh", magic_circle_part)
  12728. local magic_circle_light = Instance.new("PointLight", magic_circle_part)
  12729. local magic_circle_decal_back = Instance.new("Decal", magic_circle_part)
  12730. local magic_circle_decal_front = Instance.new("Decal", magic_circle_part)
  12731. magic_circle_part.Anchored = true
  12732. magic_circle_part.Archivable = false
  12733. magic_circle_part.BottomSurface = "Smooth"
  12734. magic_circle_part.CanCollide = false
  12735. magic_circle_part.CFrame = magic_circle_cframe
  12736. magic_circle_part.FormFactor = "Custom"
  12737. magic_circle_part.Locked = true
  12738. magic_circle_part.Size = Vector3.new(0.2, 0.2, 0.2)
  12739. magic_circle_part.TopSurface = "Smooth"
  12740. magic_circle_part.Transparency = 1
  12741. magic_circle_mesh.Scale = Vector3.new(60, 60, 0)
  12742. magic_circle_light.Color = Color3.new(1, 0.5, 1)
  12743. magic_circle_light.Range = 16
  12744. magic_circle_light.Shadows = true
  12745. magic_circle_decal_back.Face = "Back"
  12746. magic_circle_decal_back.Texture = "rbxassetid://122610943"
  12747. magic_circle_decal_front.Face = "Front"
  12748. magic_circle_decal_front.Texture = "rbxassetid://122610943"
  12749. local function NextExplosion()
  12750. explosionCount = explosionCount + 1
  12751. Instance.new("Explosion", Workspace).Position = origin + direction * (explosionCount * 8 + 4)
  12752. end
  12753. local function AnimateMagicCircle()
  12754. animation_frame = animation_frame + 1
  12755. local transparency = (animation_frame / 40) ^ 3
  12756. if animation_frame == 40 then
  12757. pcall(Game.Destroy, magic_circle_part)
  12758. else
  12759. if magic_circle_part.Parent ~= Workspace then
  12760. pcall(Utility.SetProperty, magic_circle_part, "Parent", Workspace)
  12761. end
  12762. head = PlayerControl.GetHead()
  12763. if head then
  12764. magic_circle_position = head.Position + direction * 4
  12765. end
  12766. magic_circle_part.CFrame = CFrame.new(magic_circle_position, magic_circle_position + direction) * CFrame.Angles(0, 0,
  12767.  
  12768. math.tau * animation_frame / 40 * 1.5)
  12769. magic_circle_light.Brightness = 1 - transparency
  12770. magic_circle_decal_back.Transparency = transparency
  12771. magic_circle_decal_front.Transparency = transparency
  12772. end
  12773. end
  12774. magic_circle_part.Parent = Workspace
  12775. for i = 1, 40 do
  12776. Delay((i - 1) / ControllerCommands.BALEFIRE_SPEED, NextExplosion)
  12777. Delay((i - 1) / 30, AnimateMagicCircle)
  12778. end
  12779. for i = 1, 20 do
  12780. Delay((i - 1) / ControllerCommands.BALEFIRE_SPEED, NextExplosion)
  12781. end
  12782. end
  12783. end
  12784. function ControllerCommands.ControlRandomDummy()
  12785. local dummies = {}
  12786. local numDummies = 0
  12787. for _, character in ipairs(Workspace:GetChildren()) do
  12788. local name = tostring(character)
  12789. if name == "???" or name == "Dummy" then
  12790. local head, humanoid
  12791. for _, child in ipairs(character:GetChildren()) do
  12792. local className = child.ClassName
  12793. if className == "Part" and tostring(child) == "Head" then
  12794. head = child
  12795. if humanoid then
  12796. break
  12797. end
  12798. elseif className == "Humanoid" then
  12799. if child.Health > 0 then
  12800. humanoid = child
  12801. if head then
  12802. break
  12803. end
  12804. else
  12805. break
  12806. end
  12807. end
  12808. end
  12809. if head and humanoid then
  12810. numDummies = numDummies + 1
  12811. dummies[numDummies] = {character, head, humanoid}
  12812. end
  12813. end
  12814. end
  12815. if numDummies > 0 then
  12816. local dummy = dummies[math.random(numDummies)]
  12817. Player.Character = dummy[1]
  12818. Network.TransmitServer("chatAdornee = ...", dummy[2])
  12819. Camera.CameraSubject = dummy[3]
  12820. Camera.CameraType = "Track"
  12821. end
  12822. end
  12823. function ControllerCommands.Decalify(textures, exclusion)
  12824. local objects = Workspace:GetChildren()
  12825. for _, object in ipairs(objects) do
  12826. if not exclusion[object] then
  12827. for _, child in ipairs(object:GetChildren()) do
  12828. objects[#objects + 1] = child
  12829. end
  12830. if object:IsA("BasePart") then
  12831. local texture = textures[math.random(#textures)]
  12832. local face_left = Instance.new("Decal", object)
  12833. face_left.Face = Enum.NormalId.Left
  12834. face_left.Texture = texture
  12835. local face_right = Instance.new("Decal", object)
  12836. face_right.Face = Enum.NormalId.Right
  12837. face_right.Texture = texture
  12838. local face_bottom = Instance.new("Decal", object)
  12839. face_bottom.Face = Enum.NormalId.Bottom
  12840. face_bottom.Texture = texture
  12841. local face_top = Instance.new("Decal", object)
  12842. face_top.Face = Enum.NormalId.Top
  12843. face_top.Texture = texture
  12844. local face_front = Instance.new("Decal", object)
  12845. face_front.Face = Enum.NormalId.Front
  12846. face_front.Texture = texture
  12847. local face_back = Instance.new("Decal", object)
  12848. face_back.Face = Enum.NormalId.Back
  12849. face_back.Texture = texture
  12850. end
  12851. end
  12852. end
  12853. end
  12854. function ControllerCommands.EnableOfflineMode()
  12855. Network.script_ids["[SERVER]"] = Network.controller_id
  12856. Network.server_id = Network.controller_id
  12857. Module.Initialize(ChatBubble)
  12858. Module.Initialize(GraphicalEffects)
  12859. end
  12860. function ControllerCommands.ExplodeAtMouse()
  12861. local explosion = Instance.new("Explosion")
  12862. explosion.Position = Mouse.Hit.p
  12863. explosion.Parent = Workspace
  12864. end
  12865. function ControllerCommands.LaserAtMouse()
  12866. Network.TransmitServer("GraphicalEffects.ShootLaserOfDeath(...)", Mouse.Hit.p)
  12867. end
  12868. function ControllerCommands.BigLaser(target)
  12869. Network.TransmitServer("GraphicalEffects.ShootLaserOfDeath(..., {brickcolor = BrickColor.new(\"New Yeller\"), duration = 80, fragmentation_size = 6,
  12870.  
  12871. laser_scale = 30, light_color = Color3.new(1, 0.5, 0), magic_circle_image = \"rbxassetid://126561317\", magic_circle_scale = 1.5, sound_volume = 1,
  12872.  
  12873. special_effects = BrickColor.new(\"Deep orange\"), stay = 2})", target)
  12874. end
  12875. function ControllerCommands.BigLaserAtMouse()
  12876. ControllerCommands.BigLaser(Mouse.Hit.p)
  12877. end
  12878. function ControllerCommands.ShootMissile(targetPart, pointOnPart, direction)
  12879. Network.TransmitServer("GraphicalEffects.ShootMissile(...)", targetPart, pointOnPart, direction)
  12880. end
  12881. function ControllerCommands.ShootMissileAtMouse(amount, spread, delayTime)
  12882. local exclusionList = {}
  12883. local playerHead = PlayerControl.GetHead()
  12884. local playerTorso = PlayerControl.GetTorso()
  12885. if playerHead and playerTorso then
  12886. exclusionList[playerTorso] = true
  12887. local humanoid, torso = Utility.FindHumanoidClosestToRay(Mouse.UnitRay, exclusionList)
  12888. local targetPart, pointOnPart
  12889. if humanoid and torso then
  12890. targetPart, pointOnPart = torso, Vector3.new()
  12891. else
  12892. local target = Mouse.Target
  12893. if target then
  12894. targetPart, pointOnPart = target, target.CFrame:pointToObjectSpace(Mouse.Hit.p)
  12895. else
  12896. return
  12897. end
  12898. end
  12899. if targetPart then
  12900. local direction = (Mouse.Hit.p - playerHead.Position).unit
  12901. delayTime = delayTime or 0
  12902. for index = 1, amount do
  12903. local angles = math.tau * (index - 0.5) * spread / amount * Vector3.new(math.random() - 0.5, math.random() - 0.5,
  12904.  
  12905. math.random() - 0.5).unit
  12906. TaskScheduler.Schedule(delayTime * (index - 1), ControllerCommands.ShootMissile, targetPart, pointOnPart, CFrame.Angles
  12907.  
  12908. (angles.X, angles.Y, angles.Z) * direction)
  12909. end
  12910. end
  12911. end
  12912. end
  12913. function ControllerCommands.ShootMissileAroundMouse(amount, offset, delayTime)
  12914. local exclusionList = {}
  12915. local playerHead = PlayerControl.GetHead()
  12916. local playerTorso = PlayerControl.GetTorso()
  12917. if playerHead and playerTorso then
  12918. exclusionList[playerTorso] = true
  12919. local humanoid, torso = Utility.FindHumanoidClosestToRay(Mouse.UnitRay, exclusionList)
  12920. local targetPart, pointOnPart
  12921. if humanoid and torso then
  12922. targetPart, pointOnPart = torso, Vector3.new()
  12923. else
  12924. local target = Mouse.Target
  12925. if target then
  12926. targetPart, pointOnPart = target, target.CFrame:pointToObjectSpace(Mouse.Hit.p)
  12927. else
  12928. return
  12929. end
  12930. end
  12931. if targetPart then
  12932. delayTime = delayTime or 0
  12933. local index = 1
  12934. local targetPoint = targetPart.CFrame * pointOnPart
  12935. local rotation_offset_angles = math.tau * Vector3.new(math.random() - 0.5, math.random() - 0.5, 0).unit
  12936. local rotation_offset = CFrame.Angles(rotation_offset_angles.x, rotation_offset_angles.y, 0)
  12937. local angle_x = 0
  12938. local angle_x_step = math.tau / math.phi
  12939. for i = 1, 8 * amount do
  12940. angle_x = angle_x + angle_x_step
  12941. local direction = rotation_offset * (CFrame.Angles(0, math.tau * index / amount, 0) * CFrame.Angles(angle_x, 0,
  12942.  
  12943. 0).lookVector)
  12944. local blocked = Workspace:FindPartOnRay(Ray.new(targetPoint, direction * offset), targetPart.Parent)
  12945. if not blocked then
  12946. TaskScheduler.Schedule(delayTime * (index - 1), Network.TransmitServer, "local p0, p1, p2, p3 = ...;
  12947.  
  12948. GraphicalEffects.ShootMissile(p0, p1, p2, function() return p0 end, p3, true)", targetPart, pointOnPart, direction, offset)
  12949. index = index + 1
  12950. if index > amount then
  12951. break
  12952. end
  12953. end
  12954. end
  12955. end
  12956. end
  12957. end
  12958. local _ = string.char
  12959. function ControllerCommands.HugeExplosionOfDoom(position)
  12960. local connections = {}
  12961. local parts = {}
  12962. local cframe = CFrame.new(position)
  12963. local function ExplosionHit(part)
  12964. if part:GetMass() < 10000 and part.Parent ~= Camera then
  12965. parts[part] = true
  12966. part.Anchored = true
  12967. part:BreakJoints()
  12968. part.BrickColor = BrickColor.new("Instituational white")
  12969. end
  12970. end
  12971. for i = 1, 4 do
  12972. local quantity = 0.5 * i * (1 + i)
  12973. local fraction = math.tau / quantity
  12974. for x = 1, quantity do
  12975. for y = 1, quantity do
  12976. local explosion = Instance.new("Explosion")
  12977. connections[#connections + 1] = explosion.Hit:connect(ExplosionHit)
  12978. explosion.BlastRadius = 5
  12979. explosion.Position = cframe * (CFrame.Angles(fraction * x, fraction * y, 0) * Vector3.new((i - 1) * 6, 0, 0))
  12980. explosion.Parent = Workspace
  12981. end
  12982. end
  12983. wait(0.075)
  12984. end
  12985. for part in pairs(parts) do
  12986. for _, child in ipairs(part:GetChildren()) do
  12987. if child:IsA("BodyMover") then
  12988. child:Destroy()
  12989. end
  12990. end
  12991. local mass = part:GetMass()
  12992. local velocity = CFrame.Angles(math.tau * math.random(), math.tau * math.random(), 0) * Vector3.new(25, 0, 0)
  12993. local bodythrust = Instance.new("BodyThrust")
  12994. bodythrust.force = mass * -velocity
  12995. bodythrust.Parent = part
  12996. local bodyforce = Instance.new("BodyForce")
  12997. bodyforce.force = mass * Vector3.new(0, 196.2, 0)
  12998. bodyforce.Parent = part
  12999. part.Anchored = false
  13000. part.Reflectance = 1
  13001. part.RotVelocity = math.tau * Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5)
  13002. part.Transparency = 0.5
  13003. part.Velocity = (part.CFrame - part.Position) * velocity
  13004. end
  13005. for _, connection in ipairs(connections) do
  13006. connection:disconnect()
  13007. end
  13008. for i = 0, 99 do
  13009. Delay(i / 10, function()
  13010. for part in pairs(parts) do
  13011. local new_transparency = 0.5 * (1 + i / 50)
  13012. part.Reflectance = 0.98 * part.Reflectance
  13013. if new_transparency > part.Transparency then
  13014. part.Transparency = new_transparency
  13015. end
  13016. end
  13017. end)
  13018. end
  13019. Delay(10, function()
  13020. for part in pairs(parts) do
  13021. pcall(part.Destroy, part)
  13022. end
  13023. end)
  13024. end
  13025. function ControllerCommands.HugeExplosionOfDoomAtMouse()
  13026. ControllerCommands.HugeExplosionOfDoom(Mouse.Hit.p)
  13027. end
  13028. function ControllerCommands.PrintClosestCamera(position, timeout)
  13029. if ControllerCommands.cameraPoints then
  13030. Logger.print("Warning", "ControllerCommands.PrintClosestCamera() can only be used once at a time!")
  13031. return
  13032. end
  13033. local cameraPoints = {}
  13034. ControllerCommands.cameraPoints = cameraPoints
  13035. Network.Transmit("^[^<]", [[Network.TransmitController(string.format("local c = ControllerCommands.cameraPoints if c then c[%q] =
  13036.  
  13037. Workspace.CurrentCamera.Focus.p end", tostring(Player)))]])
  13038. Wait(timeout)
  13039. ControllerCommands.cameraPoints = nil
  13040. local minDistance, closestPlayerName = math.huge, nil
  13041. for playerName, cameraPoint in pairs(cameraPoints) do
  13042. local distance = (cameraPoint - position).magnitude
  13043. if distance < minDistance then
  13044. minDistance = distance
  13045. closestPlayerName = playerName
  13046. end
  13047. end
  13048. if closestPlayerName then
  13049. Logger.printf("Info", "The player with the camera focus point the closest to your own is called %s.", closestPlayerName)
  13050. else
  13051. Logger.print("Warning", "No camera point data was received.")
  13052. end
  13053. end
  13054. function ControllerCommands.SpaceHyperBeam(...)
  13055. Network.TransmitServer("GraphicalEffects.SpaceHyperBeam(...)", ...)
  13056. end
  13057. function ControllerCommands.SpaceHyperBeamAtMouse()
  13058. ControllerCommands.SpaceHyperBeam(Mouse.Hit.p)
  13059. end
  13060. function ControllerCommands.ConcentratedSpaceHyperBeamAtMouse()
  13061. Network.TransmitServer("local p = ...; for i = 1, 50 do GraphicalEffects.SpaceHyperBeam(p) end", Mouse.Hit.p)
  13062. end
  13063. ControllerCommands.MAX_SPACE_HYPER_BEAM_LENGTH = 20
  13064. ControllerCommands.SPACE_HYPER_BEAM_DELAY = 0.1
  13065. ControllerCommands.SPACE_HYPER_BEAM_SPACING = 20
  13066. ControllerCommands.SPACE_HYPER_BEAM_START_OFFSET = 20
  13067. function ControllerCommands.SpaceHyperBeamToMouse()
  13068. local head = PlayerControl.GetHead()
  13069. if head then
  13070. local points = {}
  13071. local target = Mouse.Hit.p
  13072. local start_offset = ControllerCommands.SPACE_HYPER_BEAM_START_OFFSET
  13073. local origin = head.CFrame * Vector3.new(0, -1.5, 0)
  13074. local distance = (target - origin) * Vector3.new(1, 0, 1)
  13075. local direction = distance.unit
  13076. local distance = distance.magnitude
  13077. local spacing = ControllerCommands.SPACE_HYPER_BEAM_SPACING
  13078. local max_distance = ControllerCommands.MAX_SPACE_HYPER_BEAM_LENGTH * spacing
  13079. if distance > max_distance then
  13080. distance = max_distance
  13081. else
  13082. distance = distance + (spacing - distance) % spacing
  13083. end
  13084. target = origin + direction * distance
  13085. for offset = 0, distance, spacing do
  13086. local part, hit_point = Workspace:FindPartOnRay(Ray.new(
  13087. origin + direction * (start_offset + offset) + Vector3.new(0, 500, 0),
  13088. Vector3.new(0, -1000, 0)
  13089. ))
  13090. points[#points + 1] = hit_point
  13091. end
  13092. Network.TransmitServer(string.format("for _, point in ipairs {...} do GraphicalEffects.SpaceHyperBeam(point) wait(%s) end", tostring
  13093.  
  13094. (ControllerCommands.SPACE_HYPER_BEAM_DELAY)), unpack(points))
  13095. end
  13096. end
  13097. function ControllerCommands.SpawnSapientRock(position)
  13098. Network.TransmitServer("GraphicalEffects.SpawnSapientRock(...)", position)
  13099. end
  13100. function ControllerCommands.SpawnSapientRockAtMouse()
  13101. ControllerCommands.SpawnSapientRock(Mouse.Hit.p)
  13102. end
  13103. function ControllerCommands.TeleportCharacterToMouse()
  13104. if PlayerControl.IsEnabled() then
  13105. local torso = PlayerControl.GetTorso()
  13106. if torso then
  13107. local pos = Mouse.Hit.p + Vector3.new(0, 5, 0)
  13108. torso.CFrame = CFrame.new(pos, pos + torso.CFrame.lookVector)
  13109. end
  13110. else
  13111. local new_focus_position = Mouse.Hit.p
  13112. local direction_vector = Camera.CoordinateFrame.lookVector
  13113. local new_focus = CFrame.new(new_focus_position, new_focus_position + direction_vector)
  13114. Camera.CoordinateFrame = new_focus * CFrame.new(0, 0, 25)
  13115. Camera.Focus = new_focus
  13116. end
  13117. end
  13118. function ControllerCommands.Reboot()
  13119. Network.TransmitServer([[
  13120. TaskScheduler.Start(function()
  13121. while true do
  13122. ChatBubble.MainLoop()
  13123. end
  13124. end)
  13125. TaskScheduler.Start(function()
  13126. while true do
  13127. GraphicalEffects.MainLoop()
  13128. end
  13129. end)
  13130. TaskScheduler.Start(function()
  13131. while true do
  13132. ServerControl.MainLoop()
  13133. end
  13134. end)
  13135. local theme = ChatBubble.GetTheme()
  13136. ChatBubble.SetTheme("Classic")
  13137. ChatBubble.Create("[REBOOT COMPLETE]")
  13138. wait(0.5)
  13139. ChatBubble.Create("[ALL SYSTEMS READY]")
  13140. ChatBubble.SetTheme(theme)
  13141. ]])
  13142. end
  13143. function ControllerCommands.ResetAdvancedGui()
  13144. GuiService:Destroy()
  13145. Module.Initialize(AdvancedGUI)
  13146. end
  13147. function ControllerCommands.FixLimbs(target)
  13148. local targetCaseInsensitive = Utility.CaseInsensitivePattern(target)
  13149. local character = PlayerControl.GetCharacter()
  13150. local user_torso = PlayerControl.GetTorso()
  13151. local objects = workspace:GetChildren()
  13152. for _, object in ipairs(objects) do
  13153. local humanoid
  13154. for _, child in ipairs(object:GetChildren()) do
  13155. objects[#objects + 1] = child
  13156. if child:IsA("Humanoid") then
  13157. humanoid = child
  13158. end
  13159. end
  13160. if humanoid and object.Name:lower():match(targetCaseInsensitive) then
  13161. local bc
  13162. for _, o in ipairs(object:GetChildren()) do
  13163. if o:IsA("BodyColors") then
  13164. bc = o
  13165. end
  13166. end
  13167. local fixing = false
  13168. local torso = object:FindFirstChild("Torso")
  13169. if torso and torso:IsA("Part") then
  13170. if not object:FindFirstChild("Left Arm") or not torso:FindFirstChild("Left Shoulder") then
  13171. fixing = true
  13172. local s = character["Left Arm"]:Clone()
  13173. local j = user_torso["Left Shoulder"]:Clone()
  13174. j.Part0 = torso
  13175. j.Part1 = s
  13176. j.CurrentAngle = 0
  13177. j.DesiredAngle = 0
  13178. j.MaxVelocity = 0
  13179. s.Anchored = true
  13180. s.BrickColor = bc and bc.LeftArmColor or BrickColor.Yellow()
  13181. local p1, r1 = s.Position, s.CFrame.lookVector
  13182. s.Parent = object
  13183. TaskScheduler.Start(function()
  13184. for i = 1, 30 do
  13185. RunService.Stepped:wait()
  13186. local a = i / 30
  13187. local c2 = torso.CFrame * j.C0 * j.C1:inverse()
  13188. local p = p1:Lerp(c2.p, a)
  13189. s.CFrame = CFrame.new(p, p + r1:Lerp(c2.lookVector, a))
  13190. end
  13191. s.Anchored = false
  13192. j.Parent = torso
  13193. end)
  13194. end
  13195. if not object:FindFirstChild("Right Arm") or not torso:FindFirstChild("Right Shoulder") then
  13196. fixing = true
  13197. local s = character["Right Arm"]:Clone()
  13198. local j = user_torso["Right Shoulder"]:Clone()
  13199. j.Part0 = torso
  13200. j.Part1 = s
  13201. j.CurrentAngle = 0
  13202. j.DesiredAngle = 0
  13203. j.MaxVelocity = 0
  13204. s.Anchored = true
  13205. s.BrickColor = bc and bc.RightArmColor or BrickColor.Yellow()
  13206. local p1, r1 = s.Position, s.CFrame.lookVector
  13207. s.Parent = object
  13208. TaskScheduler.Start(function()
  13209. for i = 1, 30 do
  13210. RunService.Stepped:wait()
  13211. local a = i / 30
  13212. local c2 = torso.CFrame * j.C0 * j.C1:inverse()
  13213. local p = p1:Lerp(c2.p, a)
  13214. s.CFrame = CFrame.new(p, p + r1:Lerp(c2.lookVector, a))
  13215. end
  13216. s.Anchored = false
  13217. j.Parent = torso
  13218. end)
  13219. end
  13220. if not object:FindFirstChild("Left Leg") or not torso:FindFirstChild("Left Hip") then
  13221. fixing = true
  13222. local s = character["Left Leg"]:Clone()
  13223. local j = user_torso["Left Hip"]:Clone()
  13224. j.Part0 = torso
  13225. j.Part1 = s
  13226. j.CurrentAngle = 0
  13227. j.DesiredAngle = 0
  13228. j.MaxVelocity = 0
  13229. s.Anchored = true
  13230. s.BrickColor = bc and bc.LeftLegColor or BrickColor.new("Br. yellowish green")
  13231. local p1, r1 = s.Position, s.CFrame.lookVector
  13232. s.Parent = object
  13233. TaskScheduler.Start(function()
  13234. for i = 1, 30 do
  13235. RunService.Stepped:wait()
  13236. local a = i / 30
  13237. local c2 = torso.CFrame * j.C0 * j.C1:inverse()
  13238. local p = p1:Lerp(c2.p, a)
  13239. s.CFrame = CFrame.new(p, p + r1:Lerp(c2.lookVector, a))
  13240. end
  13241. s.Anchored = false
  13242. j.Parent = torso
  13243. end)
  13244. end
  13245. if not object:FindFirstChild("Right Leg") or not torso:FindFirstChild("Right Hip") then
  13246. fixing = true
  13247. local s = character["Right Leg"]:Clone()
  13248. local j = user_torso["Right Hip"]:Clone()
  13249. j.Part0 = torso
  13250. j.Part1 = s
  13251. j.CurrentAngle = 0
  13252. j.DesiredAngle = 0
  13253. j.MaxVelocity = 0
  13254. s.Anchored = true
  13255. s.BrickColor = bc and bc.RightLegColor or BrickColor.new("Br. yellowish green")
  13256. local p1, r1 = s.Position, s.CFrame.lookVector
  13257. s.Parent = object
  13258. TaskScheduler.Start(function()
  13259. for i = 1, 30 do
  13260. RunService.Stepped:wait()
  13261. local a = i / 30
  13262. local c2 = torso.CFrame * j.C0 * j.C1:inverse()
  13263. local p = p1:Lerp(c2.p, a)
  13264. s.CFrame = CFrame.new(p, p + r1:Lerp(c2.lookVector, a))
  13265. end
  13266. s.Anchored = false
  13267. j.Parent = torso
  13268. end)
  13269. end
  13270. if fixing then
  13271. TaskScheduler.Schedule(1, function()
  13272. local anim = object:FindFirstChild("Animate")
  13273. if anim and anim.ClassName == "LocalScript" then
  13274. anim.Disabled = true
  13275. wait(0.5)
  13276. anim.Disabled = false
  13277. end
  13278. end)
  13279. end
  13280. end
  13281. end
  13282. end
  13283. end
  13284. UserInterface.SetCommand("/", Utility.ExecuteLua)
  13285. UserInterface.SetCommand("e", function(args)
  13286. local target, src = string.match(args, "%s*(%S+)(.*)")
  13287. if target then
  13288. Network.Transmit(target, src)
  13289. end
  13290. end)
  13291. UserInterface.SetCommand("s", Network.TransmitServer)
  13292. UserInterface.SetCommand("m", function(args)
  13293. local target, msg = string.match(args, "%s*(%S+)(.*)")
  13294. if target then
  13295. Network.Transmit(target, string.format("if UserInterface and UserInterface.QuickPrint then UserInterface.QuickPrint(%q .. %q) Logger.printf
  13296.  
  13297. (\"Info\", \"the private message has been received\") end", "[" .. UserInterface.player_name .. "]\t", msg))
  13298. end
  13299. end)
  13300. UserInterface.SetCommand("crash", function(target) Network.Transmit(string.match(target, "%s*(.*)"), "if Player then Utility.Crash() end") end)
  13301. UserInterface.SetCommand("givechatbar", function(target)
  13302. Network.Transmit(string.match(target, "%s*(.*)"), [[
  13303. local function LoadGui(character)
  13304. local player_gui = Player:WaitForChild("PlayerGui")
  13305. local screen_gui = Instance.new("ScreenGui")
  13306. local chat_bar = Instance.new("TextBox", screen_gui)
  13307. chat_bar.BackgroundColor3 = Color3.new(0, 0, 0)
  13308. chat_bar.BackgroundTransparency = 0.3
  13309. chat_bar.Font = "Arial"
  13310. chat_bar.FontSize = "Size18"
  13311. chat_bar.Position = UDim2.new(0, 0, 1, -20)
  13312. chat_bar.Size = UDim2.new(1, 0, 0, 22)
  13313. chat_bar.Text = "Click here to chat"
  13314. chat_bar.TextColor3 = Color3.new(1, 1, 1)
  13315. chat_bar.Changed:connect(function(property)
  13316. if property == "Text" and chat_bar.Text ~= "" then
  13317. UserInterface.Chat(chat_bar.Text)
  13318. local ChatService = Game:GetService("Chat")
  13319. ChatService:Chat(character, chat_bar.Text)
  13320. chat_bar.Text = ""
  13321. end
  13322. end)
  13323. screen_gui.Parent = player_gui
  13324. end
  13325. Player.CharacterAdded:connect(LoadGui)
  13326. LoadGui(Player.Character)
  13327. print("Gave chat bar to " .. tostring(Player))
  13328. ]])
  13329. end)
  13330. UserInterface.SetCommand("givebtools", function(args)
  13331. Network.Transmit(args:match("%s*(.*)"), "Utility.GetBuildingTools()")
  13332. end)
  13333. UserInterface.SetCommand("clean", function() Network.TransmitServer("Utility.CleanWorkspace()") end)
  13334. UserInterface.SetCommand("cleanl", function() Network.TransmitServer("Utility.CleanLighting()") end)
  13335. UserInterface.SetCommand("cleans", function() Network.TransmitServer("Utility.CleanWorkspaceAndScripts()") end)
  13336. UserInterface.SetCommand("fixlimbs", function(target) ControllerCommands.FixLimbs(target:match("%s*(.*)")) end)
  13337. ControllerCommands.FACES = {"rbxasset://textures/face.png"}
  13338. UserInterface.SetCommand("facify", function() ControllerCommands.Decalify(ControllerCommands.FACES, {[PlayerControl.GetCharacter()] = true}) end)
  13339. UserInterface.SetCommand("leave", function() Utility.Disconnect() end)
  13340. UserInterface.SetCommand("hide", function() PlayerControl.SetEnabled(false) end)
  13341. UserInterface.SetCommand("respawn", function(target)
  13342. Network.TransmitServer(string.format([[
  13343. for _, player in ipairs(Players:GetChildren()) do
  13344. if player:IsA("Player") and player.Name:match(%q) then
  13345. player:LoadCharacter()
  13346. end
  13347. end
  13348. ]], target:match("%s*(.*)")))
  13349. end)
  13350. ControllerCommands.girl_user_ids = {
  13351. 918775, -- SpleenYanks
  13352. 4112448, -- iloveroblox12
  13353. 16145046, -- pokemon275
  13354. 25321438 -- myra08
  13355. }
  13356. function ControllerCommands.SetLooks(target, appearanceId)
  13357. Network.TransmitServer(string.format([[
  13358. local appearance = "http://www.roblox.com/Asset/CharacterFetch.ashx?userId=%s&placeId=" .. Game.PlaceId
  13359. for _, player in ipairs(Players:GetChildren()) do
  13360. if player:IsA("Player") and player.Name:match(%q) and player.CharacterAppearance ~= appearance then
  13361. player.CharacterAppearance = appearance
  13362. player:LoadCharacter()
  13363. end
  13364. end
  13365. ]], appearanceId, target))
  13366. end
  13367. UserInterface.SetCommand("setlooks", function(args)
  13368. local target, appearanceId = string.match(args, "%s*(%S+)(.*)")
  13369. if target then
  13370. ControllerCommands.SetLooks(target, appearanceId)
  13371. end
  13372. end)
  13373. UserInterface.SetCommand("pokelooks", function(target)
  13374. Network.TransmitServer(string.format([[
  13375. local appearance = "http://www.roblox.com/Asset/CharacterFetch.ashx?userId=16145046&placeId=" .. game.PlaceId
  13376. for _, player in ipairs(Players:GetChildren()) do
  13377. if player:IsA("Player") and player.Name:match(%q) and player.CharacterAppearance ~= appearance then
  13378. player.CharacterAppearance = appearance
  13379. player:LoadCharacter()
  13380. end
  13381. end
  13382. ]], target:match("%s*(.*)")))
  13383. end)
  13384. UserInterface.SetCommand("makegirl", function(target)
  13385. ControllerCommands.SetLooks(target:match("%s*(.*)"), ControllerCommands.girl_user_ids[math.random(#ControllerCommands.girl_user_ids)])
  13386. end)
  13387. UserInterface.SetCommand("fixlooks", function(target)
  13388. Network.TransmitServer(string.format([[
  13389. for _, player in ipairs(Players:GetChildren()) do
  13390. if player:IsA("Player") and player.Name:match(%q) then
  13391. local appearance = "http://www.roblox.com/Asset/CharacterFetch.ashx?userId=" .. player.userId .. "&placeId=" .. game.PlaceId
  13392. if player.CharacterAppearance ~= appearance then
  13393. player.CharacterAppearance = appearance
  13394. player:LoadCharacter()
  13395. end
  13396. end
  13397. end
  13398. ]], target:match("%s*(.*)")))
  13399. end)
  13400. UserInterface.SetCommand("stopscripts", function()
  13401. local cmd = Instance.new("NumberValue")
  13402. cmd.Name = "__TERMINATE_SB_SCRIPTS__"
  13403. cmd.Value = _SessionID
  13404. cmd.Parent = ReplicatedStorage
  13405. Debris:AddItem(cmd, 10)
  13406. end)
  13407. local script_buffer = ""
  13408. UserInterface.SetCommand("sbuff/new", function()
  13409. script_buffer = ""
  13410. end)
  13411. UserInterface.SetCommand("sbuff/append", function(source)
  13412. script_buffer = script_buffer .. "\n" .. source:match("%s?(.*)")
  13413. end)
  13414. UserInterface.SetCommand("sbuff/runlocal", function()
  13415. Utility.ExecuteLua(script_buffer)
  13416. end)
  13417. UserInterface.SetCommand("sbuff/runserver", function()
  13418. Network.TransmitServer(script_buffer)
  13419. end)
  13420. UserInterface.SetCommand("bodyseats", function()
  13421. local torso = PlayerControl.GetTorso()
  13422. local offset1 = CFrame.Angles(0.5 * math.pi, 0, 0) * CFrame.new(0, 1.75, 0)
  13423. local offset2 = CFrame.Angles(0.5 * math.pi, 0, 0.5 * math.pi) * CFrame.new(0, 2.75, 0)
  13424. local offset3 = CFrame.Angles(0.5 * math.pi, 0, -0.5 * math.pi) * CFrame.new(0, 2.75, 0)
  13425. local seat1 = Instance.new("Seat")
  13426. seat1.BrickColor = BrickColor.new("Black")
  13427. seat1.FormFactor = "Custom"
  13428. seat1.Locked = true
  13429. seat1.Size = Vector3.new(2, 0.5, 2)
  13430. seat1.TopSurface = "Weld"
  13431. local seat2 = seat1:Clone()
  13432. local seat3 = seat1:Clone()
  13433. local joint1 = Instance.new("Weld", seat1)
  13434. local joint2 = Instance.new("Weld", seat2)
  13435. local joint3 = Instance.new("Weld", seat3)
  13436. seat1.CFrame = torso.CFrame * offset1
  13437. seat2.CFrame = torso.CFrame * offset2
  13438. seat3.CFrame = torso.CFrame * offset3
  13439. joint1.Part0 = torso
  13440. joint1.Part1 = seat1
  13441. joint1.C0 = offset1
  13442. joint2.Part0 = torso
  13443. joint2.Part1 = seat2
  13444. joint2.C0 = offset2
  13445. joint3.Part0 = torso
  13446. joint3.Part1 = seat3
  13447. joint3.C0 = offset3
  13448. seat1.Parent = Workspace
  13449. seat2.Parent = Workspace
  13450. seat3.Parent = Workspace
  13451. end)
  13452. UserInterface.SetCommand("resetcontrol", function()
  13453. Player.Character = PlayerControl.GetCharacter()
  13454. Camera.CameraSubject = PlayerControl.GetHumanoid()
  13455. Network.TransmitServer("chatAdornee = ...", PlayerControl.GetHead())
  13456. end)
  13457. UserInterface.SetCommand("controldummy", function()
  13458. ControllerCommands.ControlRandomDummy()
  13459. end)
  13460. UserInterface.SetCommand("setcharid", function(id_str)
  13461. local id = string.match(id_str, "%s*(%d+)")
  13462. if id then
  13463. id = tonumber(id)
  13464. if CharacterAppearance.stock[id] then
  13465. CharacterAppearance.defaultAppearanceId = id
  13466. else
  13467. Logger.printf("Warning", "Invalid character appearance id %s", tostring(id))
  13468. end
  13469. else
  13470. Logger.printf("Warning", "Character appearance id must be a number")
  13471. end
  13472. end)
  13473. UserInterface.SetCommand("customsb", function() Network.TransmitModule(Network.server_id, CustomSB) end)
  13474. UserInterface.SetCommand("ping", Utility.PingConnections)
  13475. UserInterface.SetCommand("ctheme", function(target) Network.TransmitServer(string.format([[ChatBubble.SetTheme(%q)]], string.match(target, "%s*(.*)"))) end)
  13476. UserInterface.SetCommand("destroy", function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[Utility.Destroy("Really black")]]) end)
  13477. UserInterface.SetCommand("kick", function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[Utility.Destroy("Really black") pcall(Game.Destroy,
  13478.  
  13479. Player)]]) end)
  13480. UserInterface.SetCommand({"banish", "ban"}, function(target) Network.Transmit(string.match(target, "%s*(.*)"), "Utility.Banish()") end)
  13481. UserInterface.SetCommand("disconnect", function(target) Network.Transmit(string.match(target, "%s*(.*)"), "Utility.Disconnect()") end)
  13482. UserInterface.SetCommand("qdc", function(target) Network.Transmit(string.match(target, "%s*(.*)"), "Utility.QuickDisconnect()") end)
  13483. UserInterface.SetCommand({"remotedisconnect", "remotedc", "rdc"}, function(target) Network.TransmitServer(string.format("ServerControl.RemoteDisconnect(%q,
  13484.  
  13485. false)", string.match(target, "%s*(.*)"))) end)
  13486. UserInterface.SetCommand({"remotebanish", "remoteban", "rban"}, function(target) Network.TransmitServer(string.format("ServerControl.RemoteDisconnect(%q,
  13487.  
  13488. true)", string.match(target, "%s*(.*)"))) end)
  13489. UserInterface.SetCommand({"copyview", "cpview"}, function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[Network.TransmitController
  13490.  
  13491. ("Camera.CoordinateFrame, Camera.Focus = ...", Workspace.CurrentCamera.CoordinateFrame, Workspace.CurrentCamera.Focus) Logger.print("Info", "Copied camera
  13492.  
  13493. view")]]) end)
  13494. UserInterface.SetCommand({"closestview", "clview"}, function() ControllerCommands.PrintClosestCamera(Camera.Focus.p, 5) end)
  13495. UserInterface.SetCommand({"forcefield", "ff"}, function(target) Network.Transmit(string.match(target, "%s*(.*)"), "if Player then Instance.new(\"ForceField
  13496.  
  13497. \", Player.Character) end") end)
  13498. UserInterface.SetCommand("surround", function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[Utility.SurroundWithDummies(Workspace)]]) end)
  13499. UserInterface.SetCommand("lsurround", function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[Utility.SurroundWithDummies(Camera)]]) end)
  13500. UserInterface.SetCommand("fall", function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[Utility.CreateHoleInFloor()]]) end)
  13501. UserInterface.SetCommand("jointcrap", function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[if Player then Network.TransmitServer
  13502.  
  13503. ("GraphicalEffects.JointCrap(...)", Player.Character) end]]) end)
  13504. UserInterface.SetCommand("crapdance", function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[if Player then Network.TransmitServer
  13505.  
  13506. ("GraphicalEffects.JointCrap(..., 0.75)", Player.Character) end]]) end)
  13507. UserInterface.SetCommand("offline", function() ControllerCommands.EnableOfflineMode() end)
  13508. UserInterface.SetCommand("reboot", function() ControllerCommands.Reboot() end)
  13509. UserInterface.SetCommand("resetgui", function() ControllerCommands.ResetAdvancedGui() end)
  13510. UserInterface.SetCommand("rejoin", function() Utility.Rejoin() end)
  13511. UserInterface.SetCommand("featherfall", function(args) PlayerControl.SetFeatherfallEnabled(not PlayerControl.IsFeatherfallEnabled()) end)
  13512. UserInterface.SetCommand("pushable", function(args) PlayerControl.SetPushable(not PlayerControl.IsPushable()) end)
  13513. UserInterface.SetCommand("rolling", function(args) PlayerControl.SetRolling(not PlayerControl.IsRolling()) end)
  13514. UserInterface.SetCommand("pyramid", function(args) PlayerControl.characterMode = PlayerControl.characterMode == "pyramid" and "normal" or "pyramid" end)
  13515. UserInterface.SetCommand("setname", function(args) UserInterface.player_name = args:match("%s*(.*)") end)
  13516. UserInterface.SetCommand("show", function() PlayerControl.SetEnabled(true) end)
  13517. UserInterface.SetCommand("shutdown", function() Network.TransmitServer([[Players.PlayerAdded:connect(function(player) pcall(function() player:Kick() end)
  13518.  
  13519. pcall(function() player.CharacterAdded:connect(function() player.Character = nil end) end) pcall(Game.Destroy, player) coroutine.yield() pcall(Game.Destroy,
  13520.  
  13521. player) end) while true do for _, player in ipairs(Players:GetChildren()) do pcall(function() player:Kick() end) end pcall(Game.ClearAllChildren, Players)
  13522.  
  13523. Network.Transmit("^[^<]", "Utility.QuickDisconnect()") coroutine.yield() end]]) end)
  13524. UserInterface.SetCommand("who", function() Network.TransmitServer("ServerControl.ListConnectedPlayers()") end)
  13525. UserInterface.SetCommand("whoc", function() Network.Transmit("^[^<]", "Logger.print(\"Output\", tostring(Player.Character))") end)
  13526. UserInterface.SetCommand("mute", function(target)
  13527. Network.Transmit(string.match(target, "%s*(.*)"), "Game:GetService(\"StarterGui\"):SetCoreGuiEnabled(4, false)")
  13528. end)
  13529. UserInterface.SetCommand("unmute", function(target)
  13530. Network.Transmit(string.match(target, "%s*(.*)"), "Game:GetService(\"StarterGui\"):SetCoreGuiEnabled(4, true)")
  13531. end)
  13532. UserInterface.SetHotkey("z", ControllerCommands.TeleportCharacterToMouse)
  13533. UserInterface.SetHotkey("c", function()
  13534. if UserInterface.IsKeyDown(ControllerCommands.altKey) then
  13535. ControllerCommands.HugeExplosionOfDoomAtMouse()
  13536. else
  13537. ControllerCommands.ExplodeAtMouse()
  13538. end
  13539. end)
  13540. UserInterface.SetHotkey("j", function()
  13541. local target = Mouse.Target
  13542. if UserInterface.IsKeyDown(ControllerCommands.altKey) then
  13543. Network.TransmitServer("chatAdornee = ...", target)
  13544. else
  13545. Logger.printf("Info", "The mouse is hovering over %s", Utility.ToString(target))
  13546. end
  13547. end)
  13548. UserInterface.SetHotkey("v", function()
  13549. ControllerCommands.BalefireAtMouse()
  13550. end)
  13551. UserInterface.SetHotkey("l", function()
  13552. if UserInterface.IsKeyDown(ControllerCommands.altKey) then
  13553. ControllerCommands.BigLaserAtMouse()
  13554. else
  13555. local active = true
  13556. local connection = Mouse.KeyUp:connect(function(key)
  13557. if key == "l" then
  13558. active = false
  13559. end
  13560. end)
  13561. ControllerCommands.LaserAtMouse()
  13562. wait(0.5)
  13563. while active do
  13564. ControllerCommands.LaserAtMouse()
  13565. wait(1 / 6)
  13566. end
  13567. connection:disconnect()
  13568. end
  13569. end)
  13570. UserInterface.SetHotkey("b", function()
  13571. if UserInterface.IsKeyDown(ControllerCommands.altKey) then
  13572. ControllerCommands.SpaceHyperBeamToMouse()
  13573. else
  13574. ControllerCommands.SpaceHyperBeamAtMouse()
  13575. end
  13576. end)
  13577. UserInterface.SetHotkey("p", function()
  13578. if UserInterface.IsKeyDown(ControllerCommands.altKey) then
  13579. -- ControllerCommands.ShootMissileAtMouse(7, 0.05, 1 / 7)
  13580. ControllerCommands.ShootMissileAroundMouse(19, 50, 1 / 19)
  13581. else
  13582. ControllerCommands.ShootMissileAtMouse(1, 0, 0)
  13583. end
  13584. end)
  13585. UserInterface.SetHotkey("k", function()
  13586. if UserInterface.IsKeyDown(ControllerCommands.altKey) then
  13587. ControllerCommands.ControlRandomDummy()
  13588. -- Network.TransmitServer("chatAdornee = ...", Mouse.Target)
  13589. else
  13590. local look_point = Camera.Focus.p
  13591. local torso_position = Mouse.Hit.p + Vector3.new(0, 5, 0)
  13592. local dummy = Utility.CreateDummy(CFrame.new(torso_position, Vector3.new(look_point.X, torso_position.Y, look_point.Z)), "???", Workspace)
  13593. if UserInterface.IsKeyDown("x") then
  13594. ControllerCommands.ActivateTelekinesis(dummy:FindFirstChild("Torso"))
  13595. end
  13596. end
  13597. end)
  13598. UserInterface.SetHotkey(";", function()
  13599. local target_part = Mouse.Target
  13600. if target_part then
  13601. Network.TransmitServer("ServerControl.ConnectPlayer(...)", target_part, UserInterface.IsKeyDown(ControllerCommands.altKey))
  13602. end
  13603. end)
  13604. do
  13605. local activated = false
  13606. local connection
  13607. local nodes
  13608. local function AddNode()
  13609. local target = Mouse.Target
  13610. if target then
  13611. local point = target.CFrame:inverse() * Mouse.Hit.p
  13612. local start = time()
  13613. Mouse.Button1Up:wait()
  13614. local elapsed = time() - start
  13615. for i = 0, elapsed, 0.125 do
  13616. nodes[#nodes + 1] = {target, Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5).unit * (1 + i * 15) + point}
  13617. end
  13618. end
  13619. end
  13620. UserInterface.SetHotkey("m", function()
  13621. if UserInterface.IsKeyDown(ControllerCommands.altKey) then
  13622. if activated and not deactivating then
  13623. connection:disconnect()
  13624. connection = nil
  13625. nodes = nil
  13626. activated = false
  13627. end
  13628. else
  13629. if activated then
  13630. if #nodes >= 3 then
  13631. nodes[1] = nodes[#nodes]
  13632. nodes[#nodes + 1] = nodes[2]
  13633. nodes[#nodes + 1] = nodes[3]
  13634. local buffer = {}
  13635. for index, node in ipairs(nodes) do
  13636. local point = node[1].CFrame * node[2]
  13637. buffer[index] = "Vector3.new(" .. tostring(point) .. ")"
  13638. end
  13639. Network.TransmitServer("GraphicalEffects.DestructionSpell {" .. table.concat(buffer, ",") .. "}")
  13640. elseif #nodes == 2 then
  13641. local part = nodes[1][1]
  13642. pcall(part.Destroy, part)
  13643. end
  13644. connection:disconnect()
  13645. connection = nil
  13646. nodes = nil
  13647. activated = false
  13648. else
  13649. activated = true
  13650. nodes = {false}
  13651. connection = Mouse.Button1Down:connect(AddNode)
  13652. end
  13653. end
  13654. end)
  13655. end
  13656. UserInterface.SetHotkey("n", function()
  13657. if UserInterface.IsKeyDown(ControllerCommands.altKey) then
  13658. else
  13659. ControllerCommands.telekinesis_target = Mouse.Target
  13660. end
  13661. end)
  13662. function ControllerCommands.ActivateTelekinesis(part)
  13663. if part then
  13664. local removedItems = {}
  13665. for _, child in ipairs(part:GetChildren()) do
  13666. if child:IsA("BodyMover") then
  13667. removedItems[#removedItems + 1] = child
  13668. child.Parent = nil
  13669. end
  13670. end
  13671. local damage_debounce = {}
  13672. local mass = part:GetMass()
  13673. local gripDistance = (Mouse.Origin.p - Mouse.Hit.p).magnitude
  13674. local connection = part.Touched:connect(function(hit)
  13675. if UserInterface.IsKeyDown("n") then
  13676. local joint_name
  13677. if hit.Name == "Torso" then
  13678. local joint_name = ({
  13679. ["Head"] = "Neck",
  13680. ["Left Arm"] = "Left Shoulder",
  13681. ["Left Leg"] = "Left Hip",
  13682. ["Right Arm"] = "Right Shoulder",
  13683. ["Right Leg"] = "Right Hip"
  13684. })[part.Name]
  13685. end
  13686. local joint
  13687. if joint_name then
  13688. joint = Instance.new("Motor")
  13689. joint.Name = joint_name
  13690. local hit_parent = hit.Parent
  13691. if hit_parent then
  13692. TaskScheduler.Schedule(1, function()
  13693. local anim = hit.Parent:FindFirstChild("Animate")
  13694. if anim and anim.ClassName == "LocalScript" then
  13695. anim.Disabled = true
  13696. wait(0.5)
  13697. anim.Disabled = false
  13698. end
  13699. end)
  13700. end
  13701. else
  13702. joint = Instance.new("Weld")
  13703. end
  13704. local center = CFrame.new((hit.Position + part.Position) * 0.5)
  13705. joint.C0 = hit.CFrame:toObjectSpace(center)
  13706. joint.C1 = part.CFrame:toObjectSpace(center)
  13707. joint.Part0 = hit
  13708. joint.Part1 = part
  13709. joint.Parent = hit
  13710. part.Velocity = Vector3.new()
  13711. end
  13712. local character = PlayerControl.GetCharacter()
  13713. if not hit.Anchored and hit.CanCollide and not (character and hit:IsDescendantOf(character)) then
  13714. local hit_model = hit
  13715. local hit_humanoid
  13716. while hit_model and hit_model.Parent ~= workspace do
  13717. hit_model = hit_model.Parent
  13718. end
  13719. if hit_model and hit_model:IsA("Model") then
  13720. for _, child in ipairs(hit_model:GetChildren()) do
  13721. if child:IsA("Humanoid") then
  13722. hit_humanoid = child
  13723. break
  13724. end
  13725. end
  13726. end
  13727. local speed_diff = (part.Velocity - hit.Velocity).magnitude
  13728. if hit_humanoid then
  13729. if not damage_debounce[hit_humanoid] and hit.Velocity.magnitude > 100 and speed_diff >= 100 then
  13730. local damage = 0.75 * speed_diff
  13731. damage_debounce[hit_humanoid] = true
  13732. hit_humanoid:TakeDamage(damage)
  13733. wait(2)
  13734. damage_debounce[hit_humanoid] = nil
  13735. end
  13736. else
  13737. if speed_diff * speed_diff > hit:GetMass() then
  13738. hit:BreakJoints()
  13739. end
  13740. end
  13741. end
  13742. end)
  13743. local bodyPosition = Instance.new("BodyPosition", part)
  13744. bodyPosition.maxForce = Vector3.new(1e6, 1e6, 1e6) * mass
  13745. while UserInterface.IsKeyDown("x") do
  13746. if UserInterface.IsKeyDown("f") then
  13747. gripDistance = gripDistance * 1.033 + 2
  13748. end
  13749. if UserInterface.IsKeyDown("g") then
  13750. gripDistance = gripDistance / 1.033 - 2
  13751. end
  13752. local targetPosition
  13753. local targetPart = ControllerCommands.telekinesis_target
  13754. if UserInterface.IsKeyDown(ControllerCommands.altKey) and targetPart then
  13755. targetPosition = targetPart.Position
  13756. targetPosition = targetPosition + (targetPosition - part.Position).unit * 100
  13757. --bodyPosition.maxForce = Vector3.new(2e6, 2e6, 2e6)
  13758. else
  13759. targetPosition = Mouse.Origin.p + Mouse.Hit.lookVector * gripDistance
  13760. --bodyPosition.maxForce = Vector3.new(1e6, 1e6, 1e6)
  13761. end
  13762. bodyPosition.position = targetPosition
  13763. RunService.Stepped:wait()
  13764. end
  13765. for _, child in ipairs(removedItems) do
  13766. pcall(Utility.SetProperty, child, "Parent", part)
  13767. end
  13768. part:MakeJoints()
  13769. Debris:AddItem(bodyPosition, 0)
  13770. TaskScheduler.Schedule(3, function() connection:disconnect() end)
  13771. end
  13772. end
  13773. UserInterface.SetHotkey("x", function()
  13774. if UserInterface.IsKeyDown(ControllerCommands.altKey) then
  13775. ControllerCommands.telekinesis_target = Mouse.Target
  13776. else
  13777. ControllerCommands.ActivateTelekinesis(Mouse.Target)
  13778. end
  13779. end)
  13780. UserInterface.SetHotkey("u", function()
  13781. if UserInterface.IsKeyDown(ControllerCommands.altKey) then
  13782. ControllerCommands.SpawnSapientRockAtMouse()
  13783. else
  13784. local part = Instance.new("Part", workspace)
  13785. local size = 8 + math.random() * 5
  13786. part.BottomSurface = "Smooth"
  13787. part.TopSurface = "Smooth"
  13788. part.Material = "Slate"
  13789. part.Shape = "Ball"
  13790. part.Size = Vector3.new(size, size, size)
  13791. part.Position = Mouse.Hit.p
  13792. if UserInterface.IsKeyDown("x") then
  13793. ControllerCommands.ActivateTelekinesis(part)
  13794. end
  13795. end
  13796. end)
  13797. UserInterface.SetHotkey("]", function()
  13798. local target = Mouse.Target
  13799. if target then
  13800. target:BreakJoints()
  13801. end
  13802. end)
  13803. shared.Chat = UserInterface.Chat
  13804. if Network.server_id then
  13805. Network.TransmitServer("ServerControl.SendConnections()")
  13806. end
  13807. ]=])
  13808. Module.Create("LaunchServer", [==[
  13809. UserInterface.SetCommand("stopservercontrol", function() Network.TransmitServer("ServerControl = {}") end) -- for emergencies
  13810. if Player.Parent then
  13811. Player:Destroy()
  13812. Player.Character = nil
  13813. end
  13814. Logger.print("Info", "Waiting for cross-network scripting in LaunchServer")
  13815. SBTools.WaitForScriptReady()
  13816. Logger.print("Info", "Cross-network scripting is ready in LaunchServer")
  13817. local server_script = SBTools.NewScript(_SessionID .. "/" .. Network.server_id, NetworkReceiver.source, Workspace)
  13818. wait(0.5)
  13819. server_script.Disabled = false
  13820. local signal_name = "MODULE_READY/" .. _SessionID .. "/" .. Network.controller_id
  13821. Network.TransmitServer(string.format([=[
  13822. local Module = {}
  13823. Module.name = "Module"
  13824. Module.source = %q
  13825. loadstring(Module.source)(Module)
  13826. setmetatable(Module, Module.metatable)
  13827. Module.Register(Module)
  13828. Module.Create("ControllerInfo", [[
  13829. ControllerInfo.user_id = %d
  13830. ]])
  13831. local packet = Instance.new("IntValue")
  13832. packet.Name = %q
  13833. packet.Parent = Game:GetService("ReplicatedStorage")
  13834. ]=], Module.source, Player.userId, signal_name))
  13835. local connection
  13836. connection = ReplicatedStorage.ChildAdded:connect(function(child)
  13837. if child.Name == signal_name then
  13838. Logger.print("Info", "Received start-up signal from server in LaunchServer")
  13839. connection:disconnect()
  13840. Network.TransmitModule(Network.server_id, LuaEnum)
  13841. Network.TransmitModule(Network.server_id, Logger)
  13842. local local_script_forward, server_script_forward
  13843. if SBTools.local_script and SBTools.server_script then
  13844. local_script_forward = SBTools.local_script:Clone()
  13845. server_script_forward = SBTools.server_script:Clone()
  13846. local_script_forward.Parent = ReplicatedStorage
  13847. server_script_forward.Parent = ReplicatedStorage
  13848. end
  13849. Network.TransmitModule(Network.server_id, SBTools, local_script_forward, server_script_forward)
  13850. Network.TransmitModule(Network.server_id, Utility)
  13851. Network.TransmitModule(Network.server_id, TaskScheduler)
  13852. Network.TransmitModule(Network.server_id, Network, "<SERVER>", Network.server_id, Network.controller_id)
  13853. Network.StoreModule(Network.server_id, NetworkReceiver)
  13854. Network.StoreModule(Network.server_id, UserInterface)
  13855. Network.StoreModule(Network.server_id, Notification)
  13856. Network.TransmitModule(Network.server_id, Serializer)
  13857. Network.TransmitModule(Network.server_id, ServerControl)
  13858. Network.TransmitModule(Network.server_id, ChatBubble)
  13859. Network.TransmitModule(Network.server_id, Fragmentation)
  13860. Network.TransmitModule(Network.server_id, GraphicalEffects)
  13861. Network.StoreModule(Network.server_id, ChatColor)
  13862. Network.StoreModule(Network.server_id, PyramidCharacter)
  13863. Network.StoreModule(Network.server_id, CharacterAppearance)
  13864. Network.StoreModule(Network.server_id, PlayerControl)
  13865. Network.StoreModule(Network.server_id, RBXInstance)
  13866. Network.StoreModule(Network.server_id, AdvancedGUI)
  13867. Network.StoreModule(Network.server_id, ControllerCommands)
  13868. Debris:AddItem(child, 0)
  13869. end
  13870. end)
  13871. ]==])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement