diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5d41d92..854b532 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,35 +2,52 @@ name: Build rbxlx-to-rojo on: push: branches: - - master + - master pull_request: branches: - - master + - master jobs: build_windows: runs-on: windows-latest steps: - - uses: actions/checkout@v1 - - name: Build (All features) - run: | - cargo build --locked --release --all-features - - name: Upload selene - uses: actions/upload-artifact@v1 - with: - name: rbxlx-to-rojo-windows - path: ./target/release/rbxlx-to-rojo.exe + - uses: actions/checkout@v1 + - name: Build (All features) + run: | + cargo build --locked --release --all-features + - name: Upload selene + uses: actions/upload-artifact@v4 + with: + name: rbxlx-to-rojo-windows + path: ./target/release/rbxlx-to-rojo.exe build_mac: runs-on: macos-latest steps: - - uses: actions/checkout@v1 - - name: Install Rust - run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - - name: Build (All features) - run: | - source $HOME/.cargo/env - cargo build --locked --release --all-features - - name: Upload rbxlx-to-rojo - uses: actions/upload-artifact@v1 - with: - name: rbxlx-to-rojo-macos - path: ./target/release/rbxlx-to-rojo \ No newline at end of file + - uses: actions/checkout@v1 + - name: Install Rust + run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + - name: Build (All features) + run: | + source $HOME/.cargo/env + cargo build --locked --release --all-features + - name: Upload rbxlx-to-rojo + uses: actions/upload-artifact@v4 + with: + name: rbxlx-to-rojo-macos + path: ./target/release/rbxlx-to-rojo + build_linux: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Install Rust + run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + - name: Install GTK + run: sudo apt install libgtk-3-dev -y + - name: Build (All features) + run: | + source $HOME/.cargo/env + cargo build --locked --release --all-features + - name: Upload rbxlx-to-rojo + uses: actions/upload-artifact@v4 + with: + name: rbxlx-to-rojo-linux + path: ./target/release/rbxlx-to-rojo diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..26fb74b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,68 @@ +name: Release + +on: + push: + tags: + - "v*" + +jobs: + build_windows: + runs-on: windows-latest + steps: + - uses: actions/checkout@v1 + - name: Build (All features) + run: | + cargo build --locked --release --all-features + - name: Upload Windows artifact + uses: actions/upload-artifact@v4 + with: + name: rbxlx-to-rojo-windows + path: ./target/release/rbxlx-to-rojo.exe + + build_mac: + runs-on: macos-latest + steps: + - uses: actions/checkout@v1 + - name: Install Rust + run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + - name: Build (All features) + run: | + source $HOME/.cargo/env + cargo build --locked --release --all-features + - name: Upload Mac artifact + uses: actions/upload-artifact@v4 + with: + name: rbxlx-to-rojo-macos + path: ./target/release/rbxlx-to-rojo + + build_linux: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Install Rust + run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + - name: Install GTK + run: sudo apt install libgtk-3-dev -y + - name: Build (All features) + run: | + source $HOME/.cargo/env + cargo build --locked --release --all-features + - name: Upload Linux artifact + uses: actions/upload-artifact@v4 + with: + name: rbxlx-to-rojo-linux + path: ./target/release/rbxlx-to-rojo + release: + needs: [build_mac, build_linux, build_windows] + runs-on: ubuntu-latest + steps: + - name: Download all workflow run artifacts + uses: actions/download-artifact@v4 + - run: mkdir files + - run: zip -r files/rbxlx-to-rojo-linux.zip rbxlx-to-rojo-linux/* + - run: zip -r files/rbxlx-to-rojo-macos.zip rbxlx-to-rojo-macos/* + - run: zip -r files/rbxlx-to-rojo-windows.zip rbxlx-to-rojo-windows/* + - name: Release + uses: softprops/action-gh-release@v2 + with: + files: files/* diff --git a/.gitignore b/.gitignore index 7f451f6..494f534 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target -**/*.rs.bk \ No newline at end of file +**/*.rs.bk +test-files/**/*.luau \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..948d9da --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "rust-analyzer.cargo.features": ["gui"] +} diff --git a/Cargo.lock b/Cargo.lock index 829133e..373f1f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,550 +1,577 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" -version = "0.7.15" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] -name = "ansi_term" -version = "0.11.0" +name = "anstream" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" dependencies = [ - "winapi", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", ] [[package]] -name = "arrayref" -version = "0.3.6" +name = "anstyle" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] -name = "arrayvec" -version = "0.5.2" +name = "anstyle-parse" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] [[package]] -name = "atty" -version = "0.2.14" +name = "anstyle-query" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "hermit-abi", - "libc", - "winapi", + "windows-sys 0.59.0", ] [[package]] -name = "autocfg" -version = "1.0.1" +name = "anstyle-wincon" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] [[package]] -name = "base64" -version = "0.11.0" +name = "arrayref" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] -name = "bitflags" -version = "1.2.1" +name = "arrayvec" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] -name = "blake3" -version = "0.1.5" +name = "ashpd" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46080006c1505f12f64dd2a09264b343381ed3190fa02c8005d5d662ac571c63" +checksum = "e9c39d707614dbcc6bed00015539f488d8e3fe3e66ed60961efc0c90f4b380b3" dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if 0.1.10", - "constant_time_eq", - "crypto-mac", - "digest", + "async-fs", + "async-net", + "enumflags2", + "futures-channel", + "futures-util", + "rand", + "raw-window-handle", + "serde", + "serde_repr", + "url", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "zbus", ] [[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "cc" -version = "1.0.67" +name = "async-broadcast" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] [[package]] -name = "cfg-if" -version = "0.1.10" +name = "async-channel" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] [[package]] -name = "cfg-if" -version = "1.0.0" +name = "async-executor" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] [[package]] -name = "constant_time_eq" -version = "0.1.5" +name = "async-fs" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] [[package]] -name = "crypto-mac" -version = "0.7.0" +name = "async-io" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" dependencies = [ - "generic-array", - "subtle", + "async-lock", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "tracing", + "windows-sys 0.59.0", ] [[package]] -name = "ctor" -version = "0.1.20" +name = "async-lock" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "quote", - "syn", + "event-listener", + "event-listener-strategy", + "pin-project-lite", ] [[package]] -name = "difference" +name = "async-net" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" dependencies = [ - "generic-array", + "async-io", + "blocking", + "futures-lite", ] [[package]] -name = "env_logger" -version = "0.6.2" +name = "async-process" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", + "tracing", ] [[package]] -name = "gcc" -version = "0.3.55" +name = "async-recursion" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "generic-array" -version = "0.12.4" +name = "async-signal" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ - "typenum", + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", ] [[package]] -name = "getrandom" -version = "0.1.16" +name = "async-task" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] -name = "getrandom" -version = "0.2.2" +name = "async-trait" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "hermit-abi" -version = "0.1.18" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" -dependencies = [ - "libc", -] +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] -name = "humantime" -version = "1.3.0" +name = "autocfg" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error", -] +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] -name = "itoa" -version = "0.4.7" +name = "base64" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] -name = "lazy_static" -version = "1.4.0" +name = "bitflags" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "libc" -version = "0.2.93" +name = "bitflags" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] -name = "log" -version = "0.4.14" +name = "blake3" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" dependencies = [ - "cfg-if 1.0.0", + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", ] [[package]] -name = "lz4" -version = "1.23.2" +name = "block2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac20ed6991e01bf6a2e68cc73df2b389707403662a8ba89f68511fb340f724c" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" dependencies = [ - "libc", - "lz4-sys", + "objc2", ] [[package]] -name = "lz4-sys" -version = "1.9.2" +name = "blocking" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca79aa95d8b3226213ad454d328369853be3a1382d89532a854f4d69640acae" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ - "cc", - "libc", + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", ] [[package]] -name = "md5" -version = "0.7.0" +name = "bumpalo" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] -name = "memchr" -version = "2.3.4" +name = "byteorder" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" - -[[package]] -name = "nfd" -version = "0.0.4" -source = "git+https://github.com/saurvs/nfd-rs#07578c5fea4d7b1f35fbf128f04b6264c3bf3c5a" -dependencies = [ - "gcc", -] +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] -name = "num-traits" -version = "0.2.14" +name = "cc" +version = "1.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9" dependencies = [ - "autocfg", + "jobserver", + "libc", + "shlex", ] [[package]] -name = "output_vt100" -version = "0.1.2" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" -dependencies = [ - "winapi", -] +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "ppv-lite86" -version = "0.2.10" +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] -name = "pretty_assertions" -version = "0.6.1" +name = "colorchoice" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" -dependencies = [ - "ansi_term", - "ctor", - "difference", - "output_vt100", -] +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] -name = "proc-macro2" -version = "1.0.26" +name = "concurrent-queue" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ - "unicode-xid", + "crossbeam-utils", ] [[package]] -name = "quick-error" -version = "1.2.3" +name = "constant_time_eq" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] -name = "quote" -version = "1.0.9" +name = "core-foundation" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" dependencies = [ - "proc-macro2", + "core-foundation-sys", + "libc", ] [[package]] -name = "rand" -version = "0.7.3" +name = "core-foundation-sys" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "rand_chacha" -version = "0.2.2" +name = "crossbeam-utils" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] -name = "rand_core" -version = "0.5.1" +name = "diff" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] -name = "rand_hc" +name = "dispatch" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] -name = "rbx_binary" -version = "0.6.0-alpha.4" -source = "git+https://github.com/rojo-rbx/rbx-dom/?branch=master#05fd11f18e05fa68c1c79aa5ef74a23ab4845242" +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "log", - "lz4", - "rbx_dom_weak 2.0.0-alpha.1", - "rbx_reflection 4.0.0-alpha.1", - "rbx_reflection_database", - "thiserror", + "libloading", ] [[package]] -name = "rbx_dom_weak" -version = "1.10.1" +name = "downcast-rs" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978b65ce742f3cb38c0b64ca48601a5590e6be9a14d12025b9cba2fe553b78c4" -dependencies = [ - "base64", - "lazy_static", - "md5", - "serde", - "serde_derive", - "serde_repr", - "uuid", -] +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] -name = "rbx_dom_weak" -version = "2.0.0-alpha.1" -source = "git+https://github.com/rojo-rbx/rbx-dom/?branch=master#05fd11f18e05fa68c1c79aa5ef74a23ab4845242" -dependencies = [ - "rbx_types", - "serde", -] +name = "endi" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" [[package]] -name = "rbx_reflection" -version = "3.3.454" +name = "enumflags2" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9ccdde2a675eb13a8ecfe1f60879bf11ab29e9a671459d833929298873eedc4" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" dependencies = [ - "bitflags", - "lazy_static", - "rbx_dom_weak 1.10.1", + "enumflags2_derive", "serde", ] [[package]] -name = "rbx_reflection" -version = "4.0.0-alpha.1" -source = "git+https://github.com/rojo-rbx/rbx-dom/?branch=master#05fd11f18e05fa68c1c79aa5ef74a23ab4845242" +name = "enumflags2_derive" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ - "rbx_types", - "serde", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "rbx_reflection_database" -version = "0.1.0+roblox-465" -source = "git+https://github.com/rojo-rbx/rbx-dom/?branch=master#05fd11f18e05fa68c1c79aa5ef74a23ab4845242" +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" dependencies = [ - "lazy_static", - "rbx_reflection 4.0.0-alpha.1", - "rmp-serde", - "serde", + "log", + "regex", ] [[package]] -name = "rbx_types" -version = "0.3.0" -source = "git+https://github.com/rojo-rbx/rbx-dom/?branch=master#05fd11f18e05fa68c1c79aa5ef74a23ab4845242" +name = "env_logger" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" dependencies = [ - "base64", - "bitflags", - "blake3", - "lazy_static", - "rand", - "serde", + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", ] [[package]] -name = "rbx_xml" -version = "0.12.0-alpha.4" -source = "git+https://github.com/rojo-rbx/rbx-dom/?branch=master#05fd11f18e05fa68c1c79aa5ef74a23ab4845242" +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ - "base64", - "log", - "rbx_dom_weak 2.0.0-alpha.1", - "rbx_reflection 4.0.0-alpha.1", - "rbx_reflection_database", - "xml-rs", + "libc", + "windows-sys 0.52.0", ] [[package]] -name = "rbxlx-to-rojo" -version = "1.0.1" +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ - "env_logger", - "lazy_static", - "log", - "nfd", - "pretty_assertions", - "rbx_binary", - "rbx_dom_weak 2.0.0-alpha.1", - "rbx_reflection 3.3.454", - "rbx_xml", - "serde", - "serde_json", + "concurrent-queue", + "parking", + "pin-project-lite", ] [[package]] -name = "regex" -version = "1.4.5" +name = "event-listener-strategy" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", + "event-listener", + "pin-project-lite", ] [[package]] -name = "regex-syntax" -version = "0.6.23" +name = "fastrand" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] -name = "rmp" -version = "0.8.10" +name = "form_urlencoded" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f55e5fa1446c4d5dd1f5daeed2a4fe193071771a2636274d0d7a3b082aa7ad6" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ - "byteorder", - "num-traits", + "percent-encoding", ] [[package]] -name = "rmp-serde" -version = "0.14.4" +name = "futures-channel" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ce7d70c926fe472aed493b902010bccc17fa9f7284145cb8772fd22fdb052d8" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ - "byteorder", - "rmp", - "serde", + "futures-core", ] [[package]] -name = "ryu" -version = "1.0.5" +name = "futures-core" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] -name = "serde" -version = "1.0.125" +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-lite" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" +checksum = "3f1fa2f9765705486b33fd2acf1577f8ec449c2ba1f318ae5447697b7c08d210" dependencies = [ - "serde_derive", + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", ] [[package]] -name = "serde_derive" -version = "1.0.125" +name = "futures-macro" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -552,106 +579,1179 @@ dependencies = [ ] [[package]] -name = "serde_json" -version = "1.0.64" +name = "futures-task" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" -dependencies = [ - "itoa", - "ryu", - "serde", -] +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] -name = "serde_repr" -version = "0.1.6" +name = "futures-util" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ - "proc-macro2", + "futures-core", + "futures-io", + "futures-macro", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" + +[[package]] +name = "lz4" +version = "1.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d1febb2b4a79ddd1980eede06a8f7902197960aa0383ffcfdd62fe723036725" +dependencies = [ + "lz4-sys", +] + +[[package]] +name = "lz4-sys" +version = "1.11.1+lz4-1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.6.0", + "block2", + "libc", + "objc2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-encode" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.6.0", + "block2", + "dispatch", + "libc", + "objc2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "polling" +version = "3.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "quick-xml" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "rbx_binary" +version = "0.7.7" +source = "git+https://github.com/rojo-rbx/rbx-dom/?branch=master#d9f0841374697a372b0ff1a89d152061bf91afd3" +dependencies = [ + "ahash", + "log", + "lz4", + "profiling", + "rbx_dom_weak", + "rbx_reflection 4.7.0 (git+https://github.com/rojo-rbx/rbx-dom/?branch=master)", + "rbx_reflection_database 0.2.12+roblox-638 (git+https://github.com/rojo-rbx/rbx-dom/?branch=master)", + "thiserror", + "zstd", +] + +[[package]] +name = "rbx_dom_weak" +version = "2.9.0" +source = "git+https://github.com/rojo-rbx/rbx-dom/?branch=master#d9f0841374697a372b0ff1a89d152061bf91afd3" +dependencies = [ + "ahash", + "rbx_types 1.10.0 (git+https://github.com/rojo-rbx/rbx-dom/?branch=master)", + "serde", + "ustr", +] + +[[package]] +name = "rbx_reflection" +version = "4.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8118ac6021d700e8debe324af6b40ecfd2cef270a00247849dbdfeebb0802677" +dependencies = [ + "rbx_types 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", + "thiserror", +] + +[[package]] +name = "rbx_reflection" +version = "4.7.0" +source = "git+https://github.com/rojo-rbx/rbx-dom/?branch=master#d9f0841374697a372b0ff1a89d152061bf91afd3" +dependencies = [ + "rbx_types 1.10.0 (git+https://github.com/rojo-rbx/rbx-dom/?branch=master)", + "serde", + "thiserror", +] + +[[package]] +name = "rbx_reflection_database" +version = "0.2.12+roblox-638" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e29381d675420e841f8c02db5755cbb2545ed3e13f56c539546dc58702b512a" +dependencies = [ + "lazy_static", + "rbx_reflection 4.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rmp-serde", + "serde", +] + +[[package]] +name = "rbx_reflection_database" +version = "0.2.12+roblox-638" +source = "git+https://github.com/rojo-rbx/rbx-dom/?branch=master#d9f0841374697a372b0ff1a89d152061bf91afd3" +dependencies = [ + "lazy_static", + "rbx_reflection 4.7.0 (git+https://github.com/rojo-rbx/rbx-dom/?branch=master)", + "rmp-serde", + "serde", +] + +[[package]] +name = "rbx_types" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e30f49b2a3bb667e4074ba73c2dfb8ca0873f610b448ccf318a240acfdec6c73" +dependencies = [ + "base64", + "bitflags 1.3.2", + "blake3", + "lazy_static", + "rand", + "serde", + "thiserror", +] + +[[package]] +name = "rbx_types" +version = "1.10.0" +source = "git+https://github.com/rojo-rbx/rbx-dom/?branch=master#d9f0841374697a372b0ff1a89d152061bf91afd3" +dependencies = [ + "base64", + "bitflags 1.3.2", + "blake3", + "lazy_static", + "rand", + "serde", + "thiserror", +] + +[[package]] +name = "rbx_xml" +version = "0.13.5" +source = "git+https://github.com/rojo-rbx/rbx-dom/?branch=master#d9f0841374697a372b0ff1a89d152061bf91afd3" +dependencies = [ + "ahash", + "base64", + "log", + "rbx_dom_weak", + "rbx_reflection 4.7.0 (git+https://github.com/rojo-rbx/rbx-dom/?branch=master)", + "rbx_reflection_database 0.2.12+roblox-638 (git+https://github.com/rojo-rbx/rbx-dom/?branch=master)", + "xml-rs", +] + +[[package]] +name = "rbxlx-to-rojo" +version = "1.0.1" +dependencies = [ + "env_logger", + "lazy_static", + "log", + "pretty_assertions", + "rbx_binary", + "rbx_dom_weak", + "rbx_reflection 4.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection_database 0.2.12+roblox-638 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml", + "rfd", + "serde", + "serde_json", +] + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rfd" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a24763657bff09769a8ccf12c8b8a50416fb035fe199263b4c5071e4e3f006f" +dependencies = [ + "ashpd", + "block2", + "core-foundation", + "core-foundation-sys", + "js-sys", + "log", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "pollster", + "raw-window-handle", + "urlencoding", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rmp" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + +[[package]] +name = "rustix" +version = "0.38.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "2.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" +dependencies = [ + "proc-macro2", "quote", "syn", ] [[package]] -name = "subtle" -version = "1.0.0" +name = "tinyvec" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] [[package]] -name = "syn" -version = "1.0.69" +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow 0.6.20", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "syn", ] [[package]] -name = "termcolor" -version = "1.1.2" +name = "tracing-core" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ - "winapi-util", + "once_cell", ] [[package]] -name = "thiserror" -version = "1.0.24" +name = "uds_windows" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" dependencies = [ - "thiserror-impl", + "memoffset", + "tempfile", + "winapi", ] [[package]] -name = "thiserror-impl" -version = "1.0.24" +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "ustr" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18b19e258aa08450f93369cf56dd78063586adf19e92a75b338a800f799a0208" +dependencies = [ + "ahash", + "byteorder", + "lazy_static", + "parking_lot", + "serde", +] + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ + "bumpalo", + "log", + "once_cell", "proc-macro2", "quote", "syn", + "wasm-bindgen-shared", ] [[package]] -name = "typenum" -version = "1.13.0" +name = "wasm-bindgen-futures" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] [[package]] -name = "unicode-xid" -version = "0.2.1" +name = "wasm-bindgen-macro" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] [[package]] -name = "uuid" -version = "0.8.2" +name = "wasm-bindgen-macro-support" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ - "getrandom 0.2.2", - "serde", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", ] [[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" +name = "wasm-bindgen-shared" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +name = "wayland-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" +dependencies = [ + "cc", + "downcast-rs", + "rustix", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66249d3fc69f76fd74c82cc319300faa554e9d865dab1f7cd66cc20db10b280" +dependencies = [ + "bitflags 2.6.0", + "rustix", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd0ade57c4e6e9a8952741325c30bf82f4246885dca8bf561898b86d0c1f58e" +dependencies = [ + "bitflags 2.6.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" +dependencies = [ + "dlib", + "log", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +dependencies = [ + "js-sys", + "wasm-bindgen", +] [[package]] name = "winapi" @@ -670,22 +1770,284 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] -name = "winapi-util" -version = "0.1.5" +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "winapi", + "windows-targets", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows-sys" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59690dea168f2198d1a3b0cac23b8063efcd11012f10ae4698f284808c8ef603" +dependencies = [ + "memchr", +] + +[[package]] +name = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] [[package]] name = "xml-rs" -version = "0.8.3" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "zbus" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbddd8b6cb25d5d8ec1b23277b45299a98bfb220f1761ca11e186d5c702507f8" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-util", + "hex", + "nix", + "ordered-stream", + "serde", + "serde_repr", + "static_assertions", + "tracing", + "uds_windows", + "windows-sys 0.59.0", + "winnow 0.7.2", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a" +checksum = "dac404d48b4e9cf193c8b49589f3280ceca5ff63519e7e64f55b4cf9c47ce146" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" +dependencies = [ + "serde", + "static_assertions", + "winnow 0.7.2", + "zvariant", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zstd" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.13+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "zvariant" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2df9ee044893fcffbdc25de30546edef3e32341466811ca18421e3cd6c5a3ac" +dependencies = [ + "endi", + "enumflags2", + "serde", + "static_assertions", + "url", + "winnow 0.7.2", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74170caa85b8b84cc4935f2d56a57c7a15ea6185ccdd7eadb57e6edd90f94b2f" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16edfee43e5d7b553b77872d99bc36afdda75c223ca7ad5e3fbecd82ca5fc34" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "static_assertions", + "syn", + "winnow 0.7.2", +] diff --git a/Cargo.toml b/Cargo.toml index 82cd4e4..56702dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,24 +11,24 @@ path = "src/lib.rs" [[bin]] name = "rbxlx-to-rojo" path = "src/cli.rs" -required-features = ["cli"] [dependencies] -env_logger = "0.6" +env_logger = "0.11.6" lazy_static = "1.4" -log = "0.4" +log = "0.4.25" rbx_binary = { git = "https://github.com/rojo-rbx/rbx-dom/", branch = "master" } rbx_dom_weak = { git = "https://github.com/rojo-rbx/rbx-dom/", branch = "master" } -rbx_reflection = "3" # TODO: This won't always be latest, and that's an issue +rbx_reflection = "4" rbx_xml = { git = "https://github.com/rojo-rbx/rbx-dom/", branch = "master" } -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" +serde = { version = "1.0.217", features = ["derive"] } +serde_json = "1.0.138" # CLI -nfd = { git = "https://github.com/saurvs/nfd-rs", optional = true } +rbx_reflection_database = "0.2.12" +rfd = { version = "0.15.2", optional = true } [dev-dependencies] -pretty_assertions = "0.6" +pretty_assertions = "1.4.0" [features] -cli = ["nfd"] +gui = ["rfd"] diff --git a/README.md b/README.md index 3051f5d..1038750 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,13 @@ -# rbxlx-to-rojo (now supports .rbxl!) +# rbxlx-to-rojo + +**This is a fork of the [original project](https://github.com/rojo-rbx/rbxlx-to-rojo) due to the original being unmaintained.** + Tool to convert existing Roblox games into Rojo projects by reading their `rbxl` or `rbxlx` place files. # Using rbxlx-to-rojo + ## Setup + Before you can use rbxlx-to-rojo, you need the following: - At least Rojo 0.5.0 Alpha 12 or higher to use the tool. @@ -10,14 +15,26 @@ Before you can use rbxlx-to-rojo, you need the following: If there aren't any scripts in the rbxlx file, rbxlx-to-rojo will return an error. -Download the latest release of rbxlx-to-rojo here: https://github.com/rojo-rbx/rbxlx-to-rojo/releases +Download the [source code](https://github.com/Striker2783/rbxlx-to-rojo/releases). + +Compile it with GUI using + +``` +cargo build --release --features gui +``` + +In the `target/release` directory, the executable `rbxlx-to-rojo` is the file to run. You can move it anywhere on your system. + ## Porting the game + Before you can port your game into Rojo projects, you need a place/model file. If you have an existing game that isn't exported: - Go to studio, click on any place, and then click on File -> Save to file as. - Create a folder and name it whatever you want. + ### Steps to port the game: + 1. Double-click on rbxlx-to-rojo on wherever you installed it. 2. Select the .rbxl file you saved earlier. 3. Now, select the folder that you just created. @@ -28,4 +45,5 @@ If you followed the steps correctly, you should see something that looks like th Congratulations, you successfully ported an existing game using rbxlx-to-rojo! ## License + rbxlx-to-rojo is available under The Mozilla Public License, Version 2. Details are available in [LICENSE.md](LICENSE.md). diff --git a/src/cli.rs b/src/cli.rs index cd9abb2..9b562e0 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -4,7 +4,6 @@ use std::{ borrow::Cow, fmt, fs, io::{self, BufReader, Write}, - path::PathBuf, sync::{Arc, RwLock}, }; @@ -13,8 +12,8 @@ enum Problem { BinaryDecodeError(rbx_binary::DecodeError), InvalidFile, IoError(&'static str, io::Error), - NFDCancel, - NFDError(String), + FileDialogueCancel, + FileDialogueError(String), XMLDecodeError(rbx_xml::DecodeError), } @@ -34,10 +33,9 @@ impl fmt::Display for Problem { Problem::IoError(doing_what, error) => { write!(formatter, "While attempting to {}, {}", doing_what, error) } + Problem::FileDialogueCancel => write!(formatter, "Didn't choose a file."), - Problem::NFDCancel => write!(formatter, "Didn't choose a file."), - - Problem::NFDError(error) => write!( + Problem::FileDialogueError(error) => write!( formatter, "Something went wrong when choosing a file: {}", error, @@ -94,16 +92,24 @@ fn routine() -> Result<(), Problem> { info!("rbxlx-to-rojo {}", env!("CARGO_PKG_VERSION")); info!("Select a place file."); - let file_path = PathBuf::from(match std::env::args().nth(1) { - Some(text) => text, - None => match nfd::open_file_dialog(Some("rbxl,rbxm,rbxlx,rbxmx"), None) - .map_err(|error| Problem::NFDError(error.to_string()))? - { - nfd::Response::Okay(path) => path, - nfd::Response::Cancel => Err(Problem::NFDCancel)?, - _ => unreachable!(), - }, - }); + let file_path: std::path::PathBuf = { + let path = std::env::args().nth(1); + Ok(match path { + Some(text) => text.into(), + None => { + #[cfg(feature = "gui")] + match rfd::FileDialog::new() + .add_filter("rbx", &["rbxl", "rbxlx", "rbxm", "rbxmx"]) + .pick_file() + { + Some(p) => p, + None => Err(Problem::FileDialogueError("File Error".into()))?, + } + #[cfg(not(feature = "gui"))] + Err(Problem::InvalidFile)? + } + }) + }?; info!("Opening place file"); let file_source = BufReader::new( @@ -120,24 +126,29 @@ fn routine() -> Result<(), Problem> { rbx_xml::from_reader_default(file_source).map_err(Problem::XMLDecodeError) } Some(Cow::Borrowed("rbxm")) | Some(Cow::Borrowed("rbxl")) => { - rbx_binary::from_reader_default(file_source).map_err(Problem::BinaryDecodeError) + rbx_binary::from_reader(file_source).map_err(Problem::BinaryDecodeError) } _ => Err(Problem::InvalidFile), }?; info!("Select the path to put your Rojo project in."); - let root = PathBuf::from(match std::env::args().nth(2) { - Some(text) => text, - None => match nfd::open_pick_folder(Some(&file_path.parent().unwrap().to_string_lossy())) - .map_err(|error| Problem::NFDError(error.to_string()))? - { - nfd::Response::Okay(path) => path, - nfd::Response::Cancel => Err(Problem::NFDCancel)?, - _ => unreachable!(), - }, - }); - - let mut filesystem = FileSystem::from_root(root.join(file_path.file_stem().unwrap()).into()); + let root: std::path::PathBuf = { + let path = std::env::args().nth(2); + Ok(match path { + Some(text) => text.into(), + None => { + #[cfg(feature = "gui")] + match rfd::FileDialog::new().pick_folder() { + Some(p) => p, + None => Err(Problem::FileDialogueError("Folder Error".into()))?, + } + #[cfg(not(feature = "gui"))] + Err(Problem::InvalidFile)? + } + }) + }?; + + let mut filesystem = FileSystem::from_root(root.join(file_path.file_stem().unwrap())); log_file.write().unwrap().replace( fs::File::create(root.join("rbxlx-to-rojo.log")) diff --git a/src/filesystem.rs b/src/filesystem.rs index b3f1d91..7e18cec 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -6,7 +6,6 @@ use std::{ io::Write, path::PathBuf, }; - const SRC: &str = "src"; fn serialize_project_tree( @@ -60,7 +59,7 @@ impl FileSystem { } impl InstructionReader for FileSystem { - fn read_instruction<'a>(&mut self, instruction: Instruction<'a>) { + fn read_instruction(&mut self, instruction: Instruction) { match instruction { Instruction::AddToTree { name, @@ -76,7 +75,7 @@ impl InstructionReader for FileSystem { partition.path = Some(PathBuf::from(SRC).join(path)); } - for mut child in partition.children.values_mut() { + for child in partition.children.values_mut() { if let Some(path) = &child.path { child.path = Some(PathBuf::from(SRC).join(path)); } @@ -106,7 +105,7 @@ impl InstructionReader for FileSystem { let mut file = File::create(self.root.join("default.project.json")) .expect("can't create default.project.json"); file.write_all( - &serde_json::to_string_pretty(&self.project) + serde_json::to_string_pretty(&self.project) .expect("couldn't serialize project") .as_bytes(), ) diff --git a/src/lib.rs b/src/lib.rs index f9930a1..912d0b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ use log::debug; use rbx_dom_weak::{ types::{Ref, Variant}, - Instance, WeakDom, + ustr, Instance, WeakDom, }; use std::{ borrow::Cow, @@ -71,7 +71,7 @@ fn repr_instance<'a>( _ => unreachable!(), }; - let source = match child.properties.get("Source").expect("no Source") { + let source = match child.properties.get(&ustr("Source")).expect("no Source") { Variant::String(value) => value, _ => unreachable!(), } @@ -80,7 +80,7 @@ fn repr_instance<'a>( if child.children().is_empty() { Some(( vec![Instruction::CreateFile { - filename: Cow::Owned(base.join(format!("{}{}.lua", child.name, extension))), + filename: Cow::Owned(base.join(format!("{}{}.luau", child.name, extension))), contents: Cow::Borrowed(source), }], Cow::Borrowed(base), @@ -118,7 +118,7 @@ fn repr_instance<'a>( }, Instruction::CreateFile { filename: Cow::Owned( - folder_path.join(format!("init{}.lua", extension)), + folder_path.join(format!("init{}.luau", extension)), ), contents: Cow::Borrowed(source), }, @@ -130,7 +130,7 @@ fn repr_instance<'a>( vec![ Instruction::CreateFile { filename: Cow::Owned( - base.join(format!("{}{}.lua", child.name, extension)), + base.join(format!("{}{}.luau", child.name, extension)), ), contents: Cow::Borrowed(source), }, @@ -151,7 +151,7 @@ fn repr_instance<'a>( }, Instruction::CreateFile { filename: Cow::Owned( - folder_path.join(format!("init{}.lua", extension)), + folder_path.join(format!("init{}.luau", extension)), ), contents: Cow::Borrowed(source), }, @@ -168,11 +168,13 @@ fn repr_instance<'a>( other_class => { // When all else fails, we can make a meta folder if there's scripts in it - match rbx_reflection::get_class_descriptor(other_class) { + match rbx_reflection_database::get().classes.get(other_class) { Some(reflected) => { let treat_as_service = RESPECTED_SERVICES.contains(other_class); // Don't represent services not in respected-services - if reflected.is_service() && !treat_as_service { + if reflected.tags.contains(&rbx_reflection::ClassTag::Service) + && !treat_as_service + { return None; } @@ -187,7 +189,7 @@ fn repr_instance<'a>( if !NON_TREE_SERVICES.contains(other_class) { instructions - .push(Instruction::add_to_tree(&child, new_base.to_path_buf())); + .push(Instruction::add_to_tree(child, new_base.to_path_buf())); } if !child.children().is_empty() { @@ -208,7 +210,7 @@ fn repr_instance<'a>( // If there are scripts, we'll need to make a .meta.json folder let folder_path: Cow<'a, Path> = Cow::Owned(base.join(&child.name)); let meta = MetaFile { - class_name: Some(child.class.clone()), + class_name: Some(child.class.to_string()), // properties: properties.into_iter().collect(), ignore_unknown_instances: true, }; @@ -253,7 +255,7 @@ impl<'a, I: InstructionReader + ?Sized> TreeIterator<'a, I> { instructions.push(Instruction::AddToTree { name: child.name.clone(), partition: TreePartition { - class_name: child.class.clone(), + class_name: child.class.to_string(), children: child .children() .iter() @@ -263,7 +265,7 @@ impl<'a, I: InstructionReader + ?Sized> TreeIterator<'a, I> { ( child.name.clone(), Instruction::partition( - &child, + child, folder_path.join(&child.name), ), ) @@ -277,7 +279,7 @@ impl<'a, I: InstructionReader + ?Sized> TreeIterator<'a, I> { (instructions, folder_path) } else { - match repr_instance(&self.path, child, has_scripts) { + match repr_instance(self.path, child, has_scripts) { Some((instructions_to_create_base, path)) => { (instructions_to_create_base, path) } @@ -337,7 +339,7 @@ pub fn process_instructions(tree: &WeakDom, instruction_reader: &mut dyn Instruc path: &path, tree, } - .visit_instructions(&root_instance, &has_scripts); + .visit_instructions(root_instance, &has_scripts); instruction_reader.finish_instructions(); } diff --git a/src/respected-services.txt b/src/respected-services.txt index 46213f9..c701787 100644 --- a/src/respected-services.txt +++ b/src/respected-services.txt @@ -1,8 +1,7 @@ -Chat Lighting -LocalizationService ReplicatedFirst ReplicatedStorage +MaterialService ServerScriptService ServerStorage SoundService @@ -12,4 +11,5 @@ StarterPack StarterPlayerScripts Teams TestService -Workspace \ No newline at end of file +TextChatService +Workspace diff --git a/src/structures.rs b/src/structures.rs index fa4053b..1744ff0 100644 --- a/src/structures.rs +++ b/src/structures.rs @@ -14,7 +14,7 @@ fn replace_backslashes( match path { Some(value) => value .to_string_lossy() - .replace("\\", "/") + .replace('\\', "/") .serialize(serializer), None => serializer.serialize_none(), @@ -76,13 +76,13 @@ impl<'a> Instruction<'a> { pub fn add_to_tree(instance: &Instance, path: PathBuf) -> Self { Instruction::AddToTree { name: instance.name.clone(), - partition: Instruction::partition(&instance, path), + partition: Instruction::partition(instance, path), } } pub fn partition(instance: &Instance, path: PathBuf) -> TreePartition { TreePartition { - class_name: instance.class.clone(), + class_name: instance.class.to_string(), children: BTreeMap::new(), ignore_unknown_instances: true, path: Some(path), @@ -92,9 +92,9 @@ impl<'a> Instruction<'a> { pub trait InstructionReader { fn finish_instructions(&mut self) {} - fn read_instruction<'a>(&mut self, instruction: Instruction<'a>); + fn read_instruction(&mut self, instruction: Instruction); - fn read_instructions<'a>(&mut self, instructions: Vec>) { + fn read_instructions(&mut self, instructions: Vec) { for instruction in instructions { self.read_instruction(instruction); } diff --git a/src/tests.rs b/src/tests.rs index 7c48034..baaa36c 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,7 +1,7 @@ use crate::{filesystem::FileSystem, process_instructions, structures::*}; use log::info; use pretty_assertions::assert_eq; -use rbx_dom_weak::types::Variant; +use rbx_dom_weak::{types::Variant, UstrMap}; use serde::{Deserialize, Serialize}; use std::{ collections::{BTreeMap, HashMap}, @@ -13,7 +13,7 @@ use std::{ #[derive(Deserialize, Serialize, Debug, PartialEq)] enum VirtualFileContents { Bytes(String), - Instance(HashMap), + Instance(UstrMap), Vfs(VirtualFileSystem), } @@ -41,7 +41,7 @@ impl InstructionReader for VirtualFileSystem { self.finished = true; } - fn read_instruction<'a>(&mut self, instruction: Instruction<'a>) { + fn read_instruction(&mut self, instruction: Instruction) { match instruction { Instruction::AddToTree { name, partition } => { self.tree.insert(name, partition); @@ -52,14 +52,14 @@ impl InstructionReader for VirtualFileSystem { .parent() .expect("no parent?") .to_string_lossy() - .replace("\\", "/"); + .replace('\\', "/"); let filename = filename .file_name() .expect("no filename?") .to_string_lossy() - .replace("\\", "/"); + .replace('\\', "/"); - let system = if parent == "" { + let system = if parent.is_empty() { self } else { match self @@ -82,7 +82,7 @@ impl InstructionReader for VirtualFileSystem { let tree = rbx_xml::from_str_default(&contents_string) .expect("couldn't decode encoded xml"); let child_id = tree.root().children()[0]; - let child_instance = tree.get_by_ref(child_id).unwrap().clone(); + let child_instance = tree.get_by_ref(child_id).unwrap(); VirtualFileContents::Instance(child_instance.properties.to_owned()) } else { VirtualFileContents::Bytes(contents_string) @@ -92,7 +92,7 @@ impl InstructionReader for VirtualFileSystem { } Instruction::CreateFolder { folder } => { - let name = folder.to_string_lossy().replace("\\", "/"); + let name = folder.to_string_lossy().replace('\\', "/"); self.files.insert( name, VirtualFile { @@ -106,7 +106,7 @@ impl InstructionReader for VirtualFileSystem { #[test] fn run_tests() { - let _ = env_logger::init(); + env_logger::init(); for entry in fs::read_dir("./test-files").expect("couldn't read test-files") { let entry = entry.unwrap(); let path = entry.path(); diff --git a/test-files/folders-with-scripts/filesystem/src/Folder/LocalScript.client.lua b/test-files/folders-with-scripts/filesystem/src/Folder/LocalScript.client.lua deleted file mode 100644 index f1a1813..0000000 --- a/test-files/folders-with-scripts/filesystem/src/Folder/LocalScript.client.lua +++ /dev/null @@ -1 +0,0 @@ -print("Hello world!") diff --git a/test-files/folders-with-scripts/filesystem/src/Folder/ModuleScript.lua b/test-files/folders-with-scripts/filesystem/src/Folder/ModuleScript.lua deleted file mode 100644 index f4098ad..0000000 --- a/test-files/folders-with-scripts/filesystem/src/Folder/ModuleScript.lua +++ /dev/null @@ -1,3 +0,0 @@ -local module = {} - -return module diff --git a/test-files/folders-with-scripts/filesystem/src/Folder/Script.server.lua b/test-files/folders-with-scripts/filesystem/src/Folder/Script.server.lua deleted file mode 100644 index f1a1813..0000000 --- a/test-files/folders-with-scripts/filesystem/src/Folder/Script.server.lua +++ /dev/null @@ -1 +0,0 @@ -print("Hello world!") diff --git a/test-files/folders-with-scripts/output.json b/test-files/folders-with-scripts/output.json index 502aa47..42fb39c 100644 --- a/test-files/folders-with-scripts/output.json +++ b/test-files/folders-with-scripts/output.json @@ -4,17 +4,17 @@ "contents": { "Vfs": { "files": { - "LocalScript.client.lua": { + "LocalScript.client.luau": { "contents": { "Bytes": "print(\"Hello world!\")\n" } }, - "ModuleScript.lua": { + "ModuleScript.luau": { "contents": { "Bytes": "local module = {}\n\nreturn module\n" } }, - "Script.server.lua": { + "Script.server.luau": { "contents": { "Bytes": "print(\"Hello world!\")\n" } diff --git a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/Boost.lua b/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/Boost.lua deleted file mode 100644 index c6db45d..0000000 --- a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/Boost.lua +++ /dev/null @@ -1,38 +0,0 @@ -local module = {} - -local equalizingForce = 236 / 1.2 -- amount of force required to levitate a mass -local gravity = .90 -- things float at > 1 - -function recursiveGetLift(node) - local m = 0 - local c = node:GetChildren() - for i=1,#c do - if c[i]:IsA("BasePart") then - if c[i].Name == "Handle" then - m = m + (c[i]:GetMass() * equalizingForce * 1) -- makes hats weightless, so different hats don't change your jump height - else - m = m + (c[i]:GetMass() * equalizingForce * gravity) - end - end - m = m + recursiveGetLift(c[i]) - end - return m -end - -function module:ExecuteBehaviour(brickTouched, character) - if character:FindFirstChild("HumanoidRootPart") ~= nil then - if character.Humanoid.Health > 0 then - if character.HumanoidRootPart:FindFirstChild("BoostEffect") == nil then - local boostEffect = Instance.new("BodyForce") - boostEffect.Name = "BoostEffect" - boostEffect.force = Vector3.new(0, recursiveGetLift(character) ,0) - boostEffect.Parent = character.HumanoidRootPart - game:GetService("Debris"):AddItem(boostEffect, .8) - wait(.5) - boostEffect.Name = "OldBoostEffect" - end - end - end -end - -return module diff --git a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/CoinCollected.lua b/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/CoinCollected.lua deleted file mode 100644 index f521815..0000000 --- a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/CoinCollected.lua +++ /dev/null @@ -1,28 +0,0 @@ -local module = {} - -function module:ExecuteBehaviour(brickTouched, character) - if character:FindFirstChild("Humanoid") ~= nil then - if character.Humanoid.Health > 0 then - if brickTouched ~= nil then - if brickTouched.Parent ~= nil then - local player = game.Players:GetPlayerFromCharacter(character) - if player ~= nil then - if brickTouched.Parent:FindFirstChild("Coin") then - if brickTouched.Parent.Coin:FindFirstChild("Sound") then - local sound = brickTouched.Parent.Coin.Sound:Clone() - sound.Parent = player.PlayerGui - sound:Play() - game:GetService("Debris"):AddItem(sound, 1) - end - end - brickTouched.Parent:Destroy() - player.RunStats.CoinsCollected.Value = player.RunStats.CoinsCollected.Value + 1 - end - end - end - end - end -end - -return module - diff --git a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/Explode.lua b/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/Explode.lua deleted file mode 100644 index 1ed2e19..0000000 --- a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/Explode.lua +++ /dev/null @@ -1,17 +0,0 @@ -local module = {} - -function module:ExecuteBehaviour(brickTouched, character) - if character:FindFirstChild("HumanoidRootPart") ~= nil then - if character.HumanoidRootPart:FindFirstChild("Explosion") == nil then - local explosion = Instance.new("Explosion") - explosion.Name = "Explosion" - explosion.BlastRadius = 10 - explosion.BlastPressure = 0 - explosion.Position = character.HumanoidRootPart.Position - explosion.Parent = character.HumanoidRootPart - end - end -end - -return module - diff --git a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/Kill.lua b/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/Kill.lua deleted file mode 100644 index d1461e9..0000000 --- a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/Kill.lua +++ /dev/null @@ -1,23 +0,0 @@ -local module = {} - -function module:ExecuteBehaviour(brickTouched, character) - if character:FindFirstChild("Humanoid") ~= nil then - local shield = character:FindFirstChild("Shield") - if shield == nil then - if character.Humanoid.Health > 0 then - character.Humanoid.Health = 0 - character:BreakJoints() - end - else - if shield:isA("ForceField") then - local tempShield = Instance.new("BoolValue") - tempShield.Name = "Shield" - tempShield.Parent = character - game:GetService("Debris"):AddItem(tempShield, 1) - shield:Destroy() - end - end - end -end - -return module diff --git a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/KillWithShield.lua b/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/KillWithShield.lua deleted file mode 100644 index 7bf7e7d..0000000 --- a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/KillWithShield.lua +++ /dev/null @@ -1,13 +0,0 @@ -local module = {} - ---Kills users even if they have a shield - -function module:ExecuteBehaviour(brickTouched, character) - if character:FindFirstChild("Humanoid") ~= nil then - if character.Humanoid.Health > 0 then - character.Humanoid.Health = 0 - end - end -end - -return module diff --git a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/LadderBoost.lua b/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/LadderBoost.lua deleted file mode 100644 index 701f867..0000000 --- a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/LadderBoost.lua +++ /dev/null @@ -1,39 +0,0 @@ -local module = {} - -local equalizingForce = 236 / 1.2 -- amount of force required to levitate a mass -local gravity = .90 -- things float at > 1 - -function recursiveGetLift(node) - local m = 0 - local c = node:GetChildren() - for i=1,#c do - if c[i]:IsA("BasePart") then - if c[i].Name == "Handle" then - m = m + (c[i]:GetMass() * equalizingForce * 1) -- makes hats weightless, so different hats don't change your jump height - else - m = m + (c[i]:GetMass() * equalizingForce * gravity) - end - end - m = m + recursiveGetLift(c[i]) - end - return m -end - -function module:ExecuteBehaviour(brickTouched, character) - if character:FindFirstChild("HumanoidRootPart") ~= nil then - if character.Humanoid.Health > 0 then - if character.HumanoidRootPart:FindFirstChild("LadderBoostEffect") == nil then - local boostEffectDebounce = Instance.new("IntValue") - boostEffectDebounce.Name = "LadderBoostEffect" - boostEffectDebounce.Parent = character.HumanoidRootPart - game:GetService("Debris"):AddItem(boostEffectDebounce, 2) - local boostEffect = Instance.new("BodyForce") - boostEffect.force = Vector3.new(0, recursiveGetLift(character) ,0) - boostEffect.Parent = character.HumanoidRootPart - game:GetService("Debris"):AddItem(boostEffect, .2) - end - end - end -end - -return module diff --git a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/Trapdoor.lua b/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/Trapdoor.lua deleted file mode 100644 index f6461cd..0000000 --- a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/Behaviours/Trapdoor.lua +++ /dev/null @@ -1,19 +0,0 @@ -local module = {} - -function module:ExecuteBehaviour(brickTouched, character) - for _, part in pairs(brickTouched.Parent:GetChildren()) do - if part:isA("BasePart") then - part.Anchored = false - end - end - wait(.3) - if brickTouched ~= nil and brickTouched.Parent ~= nil then - for _, part in pairs(brickTouched.Parent:GetChildren()) do - if part:isA("BasePart") then - part.CanCollide = false - end - end - end -end - -return module diff --git a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/PathCreator/CharacterHandler.lua b/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/PathCreator/CharacterHandler.lua deleted file mode 100644 index eab829b..0000000 --- a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/PathCreator/CharacterHandler.lua +++ /dev/null @@ -1,120 +0,0 @@ -function makeCharacterHandler() - local characterHandler = {} - - characterHandler.SpawnPoint = nil - - characterHandler.newHighScore = false - --characterHandler.newHighScore = characterHandler.player.leaderstats["High Score"].Value > 0 - characterHandler.player = nil - characterHandler.character = nil - - --Updates the score based on how far from the SpawnPoint the character is - function characterHandler:UpdateScore() - local player = characterHandler.player - local character = characterHandler.character - local leaderstats = player and player:FindFirstChild("leaderstats") or nil - if player and character and leaderstats then - local humanoid = character:FindFirstChildOfClass("Humanoid") - if not humanoid or not (humanoid.Health > 0) then - return - end - - local torso = character:FindFirstChild("HumanoidRootPart") - - if not torso then - return - end - - -- Sanity check for large score increases - if characterHandler.SpawnPoint.Z - torso.Position.Z > leaderstats.Score.Value + 100 then - return - end - - -- Update Score - player.RunStats.Distance.Value = characterHandler.SpawnPoint.Z - torso.Position.Z - leaderstats.Score.Value = player.RunStats.Distance.Value + player.RunStats.CoinsCollected.Value * 50 - - -- Update High Score - if leaderstats.Score.Value > leaderstats["High Score"].Value then - -- First time player, don't show New High Score GUI - if characterHandler.player.leaderstats["High Score"].Value == 0 then - characterHandler.newHighScore = true - end - - leaderstats["High Score"].Value = leaderstats.Score.Value - - -- Show New High Score GUI if they beat their High Score for the first time in this run - if characterHandler.newHighScore == false then - characterHandler.newHighScore = true - game.ServerStorage.GUIs.HighScore:Clone().Parent = characterHandler.player.PlayerGui - end - end - end - end - - characterHandler.BodyPartPositions = { - ["Head"] = {}, - ["Torso"] = {}, - ["Right Arm"] = {}, - ["Left Arm"] = {}, - ["Right Leg"] = {}, - ["Left Leg"] = {}, - ["HumanoidRootPart"] = {} - } - - - function characterHandler:UpdateBodyPartPositions() - if characterHandler.character then - for _, part in pairs(characterHandler.character:GetChildren()) do - if part:isA("BasePart") then - if characterHandler.BodyPartPositions[part.Name] == nil then - characterHandler.BodyPartPositions[part.Name] = {} - end - table.insert(characterHandler.BodyPartPositions[part.Name], 1, part.CFrame) - if #characterHandler.BodyPartPositions[part.Name] > 120 then - table.remove(characterHandler.BodyPartPositions[part.Name], 121) - end - end - end - end - end - - --Can collide is false for the previously cloned handles of the hats - local function canCollideParts(character) - local parts = character:GetChildren() - for i = 1, #parts do - if parts[i]:isA("BasePart") then - if parts[i].CanCollide == false then - parts[i].CanCollide = true - end - end - end - end - - function characterHandler:init(startPathModel, playerName) - characterHandler.player = game.Players:FindFirstChild(playerName) - if characterHandler.player ~= nil then - characterHandler.character = characterHandler.player.Character - - if not characterHandler.character then - characterHandler.player.CharacterAdded:wait() - characterHandler.character = characterHandler.player.Character - end - - characterHandler.newHighScore = characterHandler.player.leaderstats["High Score"].Value > 0 - characterHandler.SpawnPoint = startPathModel.Start.Position + Vector3.new(0, 4, -3) - characterHandler.character:MoveTo(characterHandler.SpawnPoint) - local updateScoreConnection = game:GetService("RunService").Heartbeat:connect(function() self:UpdateScore() end) - characterHandler.updatePositionsConnection = game:GetService("RunService").Heartbeat:connect(function() self:UpdateBodyPartPositions() end) - characterHandler.character.Humanoid.Died:connect(function() - updateScoreConnection:disconnect() - canCollideParts(characterHandler.character) - end) - characterHandler.player.CharacterRemoving:connect(function() characterHandler.updatePositionsConnection:disconnect() end) - end - end - - return characterHandler -end - -return makeCharacterHandler \ No newline at end of file diff --git a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/PathCreator/init.lua b/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/PathCreator/init.lua deleted file mode 100644 index 8a81df4..0000000 --- a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/PathCreator/init.lua +++ /dev/null @@ -1,285 +0,0 @@ -local function makePathObject() - local Path = {} - - local pathModels = nil - - local MODELS_AHEAD = 5 - - Path.LastAdded = {} - Path.pathModels = {} - - Path.Branches = {} - - Path.multipleBranches = false - Path.BranchAt = nil - Path.LastBranch = nil - - Path.AvailableModules = {} - - Path.CharacterHandler = require(script.CharacterHandler)() - - --Set up AvailableModules so all modules can be accessed easily - for _, pathCategory in pairs(game.ReplicatedStorage.PathModules:GetChildren()) do - for _, pathModule in pairs(pathCategory:GetChildren()) do - table.insert(Path.AvailableModules, pathModule) - end - end - - --Takes the given Vector3 value away from the position value of every part in a given model - local function moveOffset(model, vector) - if model:isA("Model") or model:isA("Folder") then - for _, object in pairs(model:GetChildren()) do - moveOffset(object, vector) - end - elseif model:isA("BasePart") then - model.Position = model.Position - vector - end - end - - --Adds a new branch to the path, adds multiple path models at all the possible EndParts of the model - function Path:AddNewBranch(lastPathModel, playerName, pathType) - Path.Branches = {} - local endParts = lastPathModel:FindFirstChild("EndParts") - endParts = endParts:GetChildren() - if #endParts == 2 then - --Special case for 2 endParts, 1 endPart should go up and the other should go down - --even if one end part continues at the same height as the Start part of the model - local top = nil - local bottom = nil - if endParts[1].Position.Y > endParts[2].Position.Y then - top = endParts[1] - bottom = endParts[2] - else - top = endParts[2] - bottom = endParts[1] - end - top.Parent = lastPathModel - local newBranch = self:addNewPathModel(lastPathModel, playerName, "GoingUp") - newBranch.CurrentBranchValue.Value = newBranch.CurrentBranchValue.Value + 1 - Path.Branches[newBranch.CurrentBranchValue.Value] = top.Position - top.Parent = lastPathModel.EndParts - bottom.Parent = lastPathModel - local newBranch = self:addNewPathModel(lastPathModel, playerName, "GoingDown") - newBranch.CurrentBranchValue.Value = newBranch.CurrentBranchValue.Value + 2 - Path.Branches[newBranch.CurrentBranchValue.Value] = bottom.Position - else - --Continues the path up, down or straight depending on where the End part is relative to the middle endPart of the branch - table.sort(endParts,function(a, b) return a.Position.Y < b.Position.Y end) - for i = 1, #endParts do - endParts[i].Parent = lastPathModel - if endParts[i].Position.Y > endParts[math.floor((#endParts + 1)/2)].Position.Y then - local newBranch = self:addNewPathModel(lastPathModel, playerName, "GoingUp") - newBranch.CurrentBranchValue.Value = newBranch.CurrentBranchValue.Value + i - Path.Branches[newBranch.CurrentBranchValue.Value] = endParts[i].Position - elseif endParts[i].Position.Y < endParts[math.floor((#endParts + 1)/2)].Position.Y then - local newBranch = self:addNewPathModel(lastPathModel, playerName, "GoingDown") - newBranch.CurrentBranchValue.Value = newBranch.CurrentBranchValue.Value + i - Path.Branches[newBranch.CurrentBranchValue.Value] = endParts[i].Position - else - local newBranch = self:addNewPathModel(lastPathModel, playerName, "SameHeight") - newBranch.CurrentBranchValue.Value = newBranch.CurrentBranchValue.Value + i - Path.Branches[newBranch.CurrentBranchValue.Value] = endParts[i].Position - end - if i ~= #endParts then - endParts[i].Parent = lastPathModel.EndParts - end - end - end - end - - --Adds a new model to the part, pathType is the folder in ReplicatedStorage.PathModules - --from which to select a random path model. pathType "random" selects from all the available path models - function Path:addNewPathModel(lastPathModel, playerName, pathType) - if lastPathModel:FindFirstChild("End") then - local pathModelToAdd = nil - if pathType == "random" then - --if there are currently multiple branches we continue each branch at the height it's at until it can be closed - if Path.multipleBranches == false then - pathModelToAdd = Path.AvailableModules[math.random(1, #Path.AvailableModules)]:Clone() - else - local pathModelsSameHeight = game.ReplicatedStorage.PathModules.SameHeight:GetChildren() - pathModelToAdd = pathModelsSameHeight[math.random(1, #pathModelsSameHeight)]:Clone() - end - else - local availModules = game.ReplicatedStorage.PathModules[pathType]:GetChildren() - pathModelToAdd = availModules[math.random(1, #availModules)]:Clone() - end - local positionDifference = pathModelToAdd.Start.Position - lastPathModel.End.Position + Vector3.new(0, 0, (pathModelToAdd.Start.Size.Z + lastPathModel.End.Size.Z)/2) - local addedPath = pathModelToAdd:Clone() - moveOffset(addedPath, positionDifference) - --The CurrentBranchValue IntValue is used for closing branches of the path once the player passes the decision point - lastPathModel.CurrentBranchValue:Clone().Parent = addedPath - addedPath.Parent = game.Workspace.Tracks[playerName] - table.insert(Path.pathModels, addedPath) - table.insert(Path.LastAdded, addedPath) - if addedPath:FindFirstChild("EndParts") then - Path.multipleBranches = true - Path.BranchAt = addedPath.EndParts:FindFirstChild("End").Position.Z - end - return addedPath - else - self:AddNewBranch(lastPathModel, playerName, pathType) - end - end - - local function removeFromTable(item, theTable) - for i = 1, #theTable do - if theTable[i] == item then - table.remove(theTable, i) - break - end - end - end - - -- Checks if the player has made a decision on the currently open branch - -- closes the branch if the player has already made a decision - function Path:tryCloseBranches(playerName) - local player = game.Players:FindFirstChild(playerName) - if player.Character.HumanoidRootPart.Position.Z < Path.BranchAt then - Path.multipleBranches = false - Path.LastBranch = Path.BranchAt - local closest = nil - local closestValue = nil - -- Check which branch the player selected based on the distance of the character from the End part of the branch - for i, v in pairs(Path.Branches) do - if closest == nil then - closest = i - closestValue = (player.Character.HumanoidRootPart.Position - v).magnitude - else - if (player.Character.HumanoidRootPart.Position - v).magnitude < closestValue then - closest = i - closestValue = (player.Character.HumanoidRootPart.Position - v).magnitude - end - end - end - -- Remove all path models that have a different CurrentBranchValue than the path the player selected - for _, pathModel in pairs(game.Workspace.Tracks[player.Name]:GetChildren()) do - if pathModel:isA("Model") then - if pathModel:FindFirstChild("CurrentBranchValue") then - if pathModel.CurrentBranchValue.Value ~= closest then - game:GetService("Debris"):AddItem(pathModel, 3) - removeFromTable(pathModel, Path.pathModels) - removeFromTable(pathModel, Path.LastAdded) - end - end - end - end - end - end - - -- Check if the path needs to be extended based on the position of the player - function Path:CheckExtendPath(playerName) - local player = game.Players:FindFirstChild(playerName) - if Path.LastAdded[1] then - if player.Character.HumanoidRootPart.Position.Z < Path.LastAdded[1].Start.Position.Z + Path.LastAdded[1].PathBase.Size.Z*2 then - self:addNewPathModel(Path.LastAdded[1], playerName, "random") - table.remove(Path.LastAdded, 1) - end - else - table.remove(Path.LastAdded, 1) - end - end - - -- Check if a path model is far enough of screen to be removed - function Path:CheckRemovePart(playerName) - local player = game.Players:FindFirstChild(playerName) - if player.Character.HumanoidRootPart.Position.Z < Path.pathModels[1].End.Position.Z - Path.pathModels[1].PathBase.Size.Z*3 then - Path.pathModels[1]:Destroy() - table.remove(Path.pathModels, 1) - end - end - - -- Extends the path as the player moves - function Path:AddPathAsPlayerMoves(playerName) - local player = game.Players:FindFirstChild(playerName) - if player then - if not player.Character then - player.CharacterAdded:wait() - end - - local extendPathConnection = game:GetService("RunService").Heartbeat:connect(function() - if player.Character:FindFirstChild("HumanoidRootPart") then - if Path.multipleBranches == true then - self:tryCloseBranches(playerName) - end - self:CheckExtendPath(playerName) - self:CheckRemovePart(playerName) - end - end) - - player.CharacterRemoving:connect(function() extendPathConnection:disconnect() end) - player.Character.Humanoid.Died:connect(function() extendPathConnection:disconnect() end) - end - end - - -- Creates the initial path model for the path - function Path:AddFirstPathModel(trackModel) - local pathToAdd = nil - if game.ReplicatedStorage.PathModules:FindFirstChild("StartModule") ~= nil then - pathToAdd = game.ReplicatedStorage.PathModules.StartModule:FindFirstChild("Start") - else - pathToAdd = Path.AvailableModules[math.random(1, #Path.AvailableModules)] - end - pathToAdd = pathToAdd:Clone() - pathToAdd.Parent = trackModel - pathToAdd:MoveTo(trackModel.Location.Value) - - local branchModifier = Instance.new("IntValue") - branchModifier.Name = "CurrentBranchValue" - branchModifier.Value = 0 - branchModifier.Parent = pathToAdd - - table.insert(Path.pathModels, pathToAdd) - table.insert(Path.LastAdded, pathToAdd) - return pathToAdd - end - - -- Finds an open slot for the track, for possible multiplayer - local function findOpenSlot() - local takenLocations = {} - local defaultLocation = Vector3.new(0, 100, 0) - for _, track in pairs(game.Workspace.Tracks:GetChildren()) do - table.insert(takenLocations, track.Location.Value) - end - table.sort(takenLocations, function(a, b) return (a.X < b.X) end) - for i = 1, #takenLocations do - if (takenLocations[i].X > defaultLocation.X) then - break - else - defaultLocation = Vector3.new(defaultLocation.X + 50, 100, 0) - end - end - return defaultLocation - end - - function Path:init(playerName) - local previousTrack = game.Workspace.Tracks:FindFirstChild(playerName) - if (previousTrack) then - previousTrack:Destroy() - end - - local trackModel = Instance.new("Model") - trackModel.Name = playerName - local location = Instance.new("Vector3Value") - location.Name = "Location" - location.Value = findOpenSlot() - location.Parent = trackModel - trackModel.Parent = game.Workspace.Tracks - - local firstAddedPath = self:AddFirstPathModel(trackModel) - - for i = 1, MODELS_AHEAD do - self:addNewPathModel(Path.LastAdded[1], playerName, "random") - table.remove(Path.LastAdded, 1) - end - - wait() - Path.CharacterHandler:init(firstAddedPath, playerName) - self:AddPathAsPlayerMoves(playerName) - end - - return Path -end - -return makePathObject - \ No newline at end of file diff --git a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/PathPackager.lua b/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/PathPackager.lua deleted file mode 100644 index 318df87..0000000 --- a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/PathPackager.lua +++ /dev/null @@ -1,206 +0,0 @@ --- Credit to Davidii for creating the orginal module which I slightly modified for my purposes - -local RoomPackager = {} - ---returns a table of vector3s that represent the corners of any given part -function RoomPackager:CornersOfPart(part) - local cframe = part.CFrame - local halfSizeX = part.Size.X / 2 - local halfSizeY = part.Size.Y / 2 - local halfSizeZ = part.Size.Z / 2 - - local corners = { - RightTopBack = cframe:pointToWorldSpace(Vector3.new(halfSizeX, halfSizeY, halfSizeZ)), - RightBottomBack = cframe:pointToWorldSpace(Vector3.new(halfSizeX, -halfSizeY, halfSizeZ)), - RightTopFront = cframe:pointToWorldSpace(Vector3.new(halfSizeX, halfSizeY, -halfSizeZ)), - RightBottomFront = cframe:pointToWorldSpace(Vector3.new(halfSizeX, -halfSizeY, -halfSizeZ)), - LeftTopBack = cframe:pointToWorldSpace(Vector3.new(-halfSizeX, halfSizeY, halfSizeZ)), - LeftBottomBack = cframe:pointToWorldSpace(Vector3.new(-halfSizeX, -halfSizeY, halfSizeZ)), - LeftTopFront = cframe:pointToWorldSpace(Vector3.new(-halfSizeX, halfSizeY, -halfSizeZ)), - LeftBottomFront = cframe:pointToWorldSpace(Vector3.new(-halfSizeX, -halfSizeY, -halfSizeZ)), - } - - return corners -end - ---returns the four corners with the highest y components ---this is to catch when a user has flipped the baseplate upside down -function RoomPackager:TopCornersOfBasePlate(basePlate) - local corners = self:CornersOfPart(basePlate) - local centerY = basePlate.Position.Y - local topCorners = {} - for _, corner in pairs(corners) do - --if a corner is higher globally than the center of the part, then - --it is along the top-facing surface of the part - if corner.Y > centerY then - table.insert(topCorners, corner) - end - end - return topCorners -end - ---this returns a region3 that lines up on top of the baseplate to capture ---whatever room has been constructed on top of it, it is smart enough ---to capture a room that has been less-than-ideally set up -function RoomPackager:RegionsFromBasePlate(basePlate) - local topCorners = self:TopCornersOfBasePlate(basePlate) - - --we farm the min and max x's and z's from the top corners - --to get x and z coordinates for the region3 that will contain the room - --we choose an arbitrary corner so that the initial values are in the data set - local arbitraryCorner = topCorners[1] - local minX = arbitraryCorner.X - local minZ = arbitraryCorner.Z - local maxX = arbitraryCorner.X - local maxZ = arbitraryCorner.Z - for _, corner in pairs(topCorners) do - minX = math.min(minX, corner.X) - minZ = math.min(minZ, corner.Z) - maxX = math.max(maxX, corner.X) - maxZ = math.max(maxZ, corner.Z) - end - - --construct the region using these new corners we have constructed - --keeping in mind that all corners in topCorners *should* have the same y value - local minY = topCorners[1].Y - local lowerCorner = Vector3.new(minX, minY, minZ) - local maxY = minY + 70 - local upperCorner = Vector3.new(maxX, maxY, maxZ) - - local segmentHeight = math.floor(100000/(math.abs(maxX-minX)*math.abs(maxZ-minZ))) - - local regions = {} - - local currentHeight = minY - while currentHeight - minY < 70 do - currentHeight = currentHeight + segmentHeight - lowerCorner = Vector3.new(lowerCorner.x, currentHeight - segmentHeight, lowerCorner.z) - upperCorner = Vector3.new(upperCorner.x, currentHeight, upperCorner.z) - table.insert(regions, Region3.new(lowerCorner, upperCorner)) - end - - return regions -end - ---Finds the model the current part is in which is closest to workspace ---Returns the part is the part is in Workspace ---Returns nil if the object is already in the roomModel we are constructing -local function closestParentToWorkspace(object, roomModel) - if object.Parent == roomModel then - return nil - end - if object.Parent == game.Workspace then - return object - else - return closestParentToWorkspace(object.Parent, roomModel) - end -end - ---Categorises a model based on the location of the start and end points of the path in the model -function RoomPackager:CategoriseModel(pathModel) - if pathModel:FindFirstChild("EndParts") then - return game.ReplicatedStorage.PathModules.Branch - elseif pathModel.Start.Position.Y < pathModel.End.Position.Y - 5 then - return game.ReplicatedStorage.PathModules.GoingUp - elseif pathModel.Start.Position.Y > pathModel.End.Position.Y + 5 then - return game.ReplicatedStorage.PathModules.GoingDown - else - return game.ReplicatedStorage.PathModules.SameHeight - end -end - -local function addBehavioursRecur(model, behaviourFolder) - local children = model:GetChildren() - for i = 1, #children do - if children[i]:isA("BasePart") then - behaviourFolder:Clone().Parent = children[i] - else - addBehavioursRecur(children[i], behaviourFolder) - end - end -end - -RoomPackager.setUpBehaviours = function(roomModel) - if roomModel:FindFirstChild("Behaviours") then - addBehavioursRecur(roomModel, roomModel.Behaviours) - return - end - local children = roomModel:GetChildren() - for i = 1, #children do - RoomPackager.setUpBehaviours(children[i]) - end -end - -local function processPart(roomModel, part, parts) - if part.Parent == roomModel then return end - if part.Name == "End" and roomModel:FindFirstChild("End") then - local endsModel = Instance.new("Model") --Used for branching the path - endsModel.Name = "EndParts" - endsModel.Parent = roomModel - part.Parent = endsModel - roomModel:FindFirstChild("End").Parent = endsModel - elseif part.Name == "End" and roomModel:FindFirstChild("EndParts") then - part.Parent = roomModel:FindFirstChild("EndParts") - elseif part.Name == "End" then - part.Parent = roomModel - else - local topLevelParent = closestParentToWorkspace(part, roomModel) - if topLevelParent ~= nil then - if topLevelParent:isA("BasePart") then - local connectedParts = topLevelParent:GetConnectedParts(true) - for _, connectedPart in pairs(connectedParts) do - if connectedPart.Name == "End" then - table.insert(parts, connectedPart) - else - local conTopLevelParent = closestParentToWorkspace(connectedPart, roomModel) - if conTopLevelParent and conTopLevelParent ~= topLevelParent then - conTopLevelParent.Parent = roomModel - end - end - end - end - topLevelParent.Parent = roomModel - end - end -end - -function RoomPackager:PackageRoom(roomBasePlate) - local roomModel = Instance.new("Model") - roomModel.Name = "Path" - roomModel.Parent = game.ReplicatedStorage.PathModules - - local regions = self:RegionsFromBasePlate(roomBasePlate) - - for i = 1, #regions do - --Repeatedly finds 100 parts in the region until none are left - while true do - local parts = game.Workspace:FindPartsInRegion3(regions[i], nil, 100) - if #parts == 0 then - break - end - for _, part in pairs(parts) do - processPart(roomModel, part, parts) - end - end - end - - --Set-up model for use in the path (parts for locating the path are made transparent) - roomBasePlate.Transparency = 1 - roomBasePlate.Parent = roomModel - roomModel:FindFirstChild("Start", true).Parent = roomModel - roomModel:FindFirstChild("Start", true).Transparency = 1 - if roomModel:FindFirstChild("EndParts") then - local ends = roomModel:FindFirstChild("EndParts"):GetChildren() - for i = 1, #ends do - ends[i].Transparency = 1 - end - else - roomModel.End.Transparency = 1 - end - roomModel.PrimaryPart = roomBasePlate - roomModel.Parent = self:CategoriseModel(roomModel) - RoomPackager.setUpBehaviours(roomModel) - return roomModel -end - -return RoomPackager \ No newline at end of file diff --git a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/init.server.lua b/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/init.server.lua deleted file mode 100644 index f169e33..0000000 --- a/test-files/line-runner/filesystem/src/ServerScriptService/Server_Main/init.server.lua +++ /dev/null @@ -1,201 +0,0 @@ --- Line Runner --- TheGamer101 - -local path = nil -coroutine.wrap(function() path = require(script.PathCreator) end)() - --- Handle remote functions/events -function runStarting(player) - if player.Character then - if player.Character:FindFirstChild("FastStartScript") then - player.Character.FastStartScript.Disabled = false - end - end -end -game.ReplicatedStorage.RemoteEvents.RunStarting.OnServerEvent:connect(runStarting) - -local behaviourModules = {} - -coroutine.wrap(function() - for _, behaviourScript in ipairs(script.Behaviours:GetChildren()) do - local success, errMessage = pcall(function() - behaviourModules[behaviourScript.Name] = require(behaviourScript) - end) - if not success then - warn("Failed to load module" ..behaviourScript.Name.. ".\n" ..errMessage) - end - end -end)() - -function executeBehaviour(player, character, brickTouched, behaviourName) - if behaviourModules[behaviourName] ~= nil then - behaviourModules[behaviourName]:ExecuteBehaviour(brickTouched, character) - end -end -game.ReplicatedStorage.RemoteEvents.ExecuteBehaviour.OnServerEvent:connect(executeBehaviour) - --- Initialization -local lastActivePath = {} - -if game.Workspace:FindFirstChild("BasePlate") then - game.Workspace.BasePlate:Destroy() -end - -local tracksModel = Instance.new("Model") -tracksModel.Name = "Tracks" -tracksModel.Parent = game.Workspace - -function packagePathModels() - local pathPackager = require(script.PathPackager) - while true do - local pathBase = game.Workspace:FindFirstChild("PathBase", true) - if pathBase then - pathPackager:PackageRoom(pathBase) - else - break - end - end -end - -coroutine.wrap(function() packagePathModels() end)() - --- Leaderboard -function updateHighScorePlayerPoints(newValue, player) - local pointsService = game:GetService("PointsService") - local currentBalance = pointsService:GetGamePointBalance(player.userId) - local amountToAward = newValue - currentBalance - pcall(function() pointsService:AwardPoints(player.userId, amountToAward) end) -end - -function checkNewHighScore(player) - if player:FindFirstChild("leaderstats") then - if player.userId > 0 then - local storedScore = 0 - pcall(function() storedScore = game:GetService("PointsService"):GetGamePointBalance(player.userId) end) - if storedScore < player.leaderstats["High Score"].Value then - updateHighScorePlayerPoints(player.leaderstats["High Score"].Value, player) - end - end - end -end - -function loadLeaderstats(player) - local stats = Instance.new("IntValue") - stats.Name = "leaderstats" - - local highScore = Instance.new("IntValue") - highScore.Name = "High Score" - highScore.Parent = stats - highScore.Value = 0 - - coroutine.wrap(function() - pcall(function() - highScore.Value = game:GetService("PointsService"):GetGamePointBalance(player.userId) - end) - end)() - - local currentScore = Instance.new("IntValue") - currentScore.Name = "Score" - currentScore.Parent = stats - - stats.Parent = player -end - -function initialiseRunStats(player) - if player:FindFirstChild("RunStats") then - player.RunStats.Distance.Value = 0 - player.RunStats.CoinsCollected.Value = 0 - end -end - -function showResults(player) - local resultsGUI = game.ServerStorage.GUIs.PostRunGUI:Clone() - resultsGUI.Frame.DistanceValue.Text = player.RunStats.Distance.Value - resultsGUI.Frame.CoinsValue.Text = player.RunStats.CoinsCollected.Value - resultsGUI.Frame.ScoreValue.Text = player.leaderstats.Score.Value - - resultsGUI.Parent = player.PlayerGui - return resultsGUI -end - -function initialiseNewRun(player, delayTime, charExpected, showLastResults) - if not path then - while not path do - wait() - end - end - - local lastResultsGUI = nil - if showLastResults then - lastResultsGUI = showResults(player) - end - - if delayTime ~= 0 then - wait(delayTime) - end - - if lastResultsGUI ~= nil then - lastResultsGUI:Destroy() - end - - if player and player.Parent then - -- charExpected is needed to avoid calling LoadCharacter on players leaving the game - if player.Character or charExpected == false then - player:LoadCharacter() - - initialiseRunStats(player) - - local playersPath = path() - lastActivePath[player.Name] = playersPath - playersPath:init(player.Name) - end - end -end - -function setUpPostRunStats(player) - local folder = Instance.new("Folder") - folder.Name = "RunStats" - folder.Parent = player - local currentDistance = Instance.new("IntValue") - currentDistance.Name = "Distance" - currentDistance.Value = 0 - currentDistance.Parent = folder - local coinsCollected = Instance.new("IntValue") - coinsCollected.Name = "CoinsCollected" - coinsCollected.Value = 0 - coinsCollected.Parent = folder -end - -function onPlayerEntered(player) - player.CharacterAdded:connect(function(character) - local humanoid = character:WaitForChild("Humanoid") - if humanoid then - humanoid.Died:connect(function() - initialiseNewRun(player, 4, true, true) - checkNewHighScore(player) - end) - end - end) - - -- Initial loading - loadLeaderstats(player) - setUpPostRunStats(player) - - -- Start game - initialiseNewRun(player, 0, false, false) -end -game.Players.PlayerAdded:connect(onPlayerEntered) - -function onPlayerRemoving(player) - local track = game.Workspace.Tracks:FindFirstChild(player.Name) - if track ~= nil then - track:Destroy() - end -end -game.Players.PlayerRemoving:connect(onPlayerRemoving) - -for _, player in pairs(game.Players:GetChildren()) do - onPlayerEntered(player) -end - - diff --git a/test-files/line-runner/filesystem/src/ServerStorage/GUIs/HighScore/GUITweenIn.client.lua b/test-files/line-runner/filesystem/src/ServerStorage/GUIs/HighScore/GUITweenIn.client.lua deleted file mode 100644 index e20ce02..0000000 --- a/test-files/line-runner/filesystem/src/ServerStorage/GUIs/HighScore/GUITweenIn.client.lua +++ /dev/null @@ -1,9 +0,0 @@ -local onScreenPosition = UDim2.new(0.5, -375, 0, 36) -local offScreenPosition = UDim2.new(0.5, -375, 0, -140) - -script.Parent.Frame:TweenPosition(onScreenPosition, "Out", "Quad", 1, true) -wait(1.5) -script.Parent.Frame:TweenPosition(offScreenPosition, "Out", "Quad", 1, true) -wait(1) - -script.Parent:Destroy() diff --git a/test-files/line-runner/filesystem/src/ServerStorage/GUIs/RevivingGUI/GUITweenIn.client.lua b/test-files/line-runner/filesystem/src/ServerStorage/GUIs/RevivingGUI/GUITweenIn.client.lua deleted file mode 100644 index 2b534c6..0000000 --- a/test-files/line-runner/filesystem/src/ServerStorage/GUIs/RevivingGUI/GUITweenIn.client.lua +++ /dev/null @@ -1,9 +0,0 @@ -local onScreenPosition = UDim2.new(0.5, -375, 0, 36) -local offScreenPosition = UDim2.new(0.5, -375, 0, -140) - -script.Parent.Frame:TweenPosition(onScreenPosition, "Out", "Quad", 1, true) -wait(1.5) -script.Parent.Frame:TweenPosition(offScreenPosition, "Out", "Quad", 1.5, true) -wait(1.5) - -script.Parent:Destroy() diff --git a/test-files/line-runner/filesystem/src/ServerStorage/Scripts/CoinMagnet.server.lua b/test-files/line-runner/filesystem/src/ServerStorage/Scripts/CoinMagnet.server.lua deleted file mode 100644 index b087d9b..0000000 --- a/test-files/line-runner/filesystem/src/ServerStorage/Scripts/CoinMagnet.server.lua +++ /dev/null @@ -1,32 +0,0 @@ -local character = script.Parent -local player = game.Players:GetPlayerFromCharacter(character) -script.Parent:WaitForChild("HumanoidRootPart") -local torso = script.Parent.HumanoidRootPart - -game:GetService("RunService").Heartbeat:connect(function() - local playersTrack = game.Workspace.Tracks:FindFirstChild(player.Name) - if playersTrack then - if playersTrack:FindFirstChild("Coins") then - local coins = playersTrack.Coins:GetChildren() - for i = 1, #coins do - if (coins[i].Coin.Position - torso.Position).magnitude < 50 then - coins[i].Coin.BodyPosition.maxForce = Vector3.new(500000000, 500000000, 500000000) - if torso.Position.Z > coins[i].Coin.Position.Z then - coins[i].Coin.BodyPosition.position = torso.Position - coins[i].Coin.BodyPosition.P = 1500 - else - --Needs to anticipate where the player is going - coins[i].Coin.BodyPosition.position = Vector3.new(torso.Position.X, torso.Position.Y, torso.Position.Z - 10) - coins[i].Coin.BodyPosition.P = 2500 - end - coins[i].CoinBoundingBox.Position = coins[i].Coin.Position - if (coins[i].Coin.Position - torso.Position).magnitude < 5 then - coins[i].CoinBoundingBox.Position = Vector3.new(torso.Position.X, torso.Position.Y, torso.Position.Z - 3) - end - end - end - end - end -end) - - diff --git a/test-files/line-runner/filesystem/src/ServerStorage/Scripts/CoinScript.server.lua b/test-files/line-runner/filesystem/src/ServerStorage/Scripts/CoinScript.server.lua deleted file mode 100644 index d27236c..0000000 --- a/test-files/line-runner/filesystem/src/ServerStorage/Scripts/CoinScript.server.lua +++ /dev/null @@ -1,29 +0,0 @@ -local coin = script.Parent -local coinModel = coin.Parent -local trackModel = coinModel.Parent -local tracksModel = trackModel.Parent - -coin.BodyPosition.position = script.Parent.Position -coin.BodyGyro.cframe = CFrame.new( - 0, 0, 0, - 0, -1, 0, - 0, 0, 0, - 0, 0, 0 -) -coin.RotVelocity = Vector3.new(0, 5, 0) - -if coinModel.Parent ~= game.Workspace then - if game.Workspace:FindFirstChild("Tracks") then - if tracksModel:FindFirstChild("Coins") == nil then - local coinsModel = Instance.new("Model") - coinsModel.Name = "Coins" - coinsModel.Parent = tracksModel - end - - tracksModel.ChildRemoved:connect(function(child) if child == trackModel then coinModel:Destroy() end end) - coinModel.Parent = tracksModel:FindFirstChild("Coins") - end -end - -wait(1) -coin.RotVelocity = Vector3.new(0, 5, 0) diff --git a/test-files/line-runner/filesystem/src/ServerStorage/Scripts/FastStartScript.server.lua b/test-files/line-runner/filesystem/src/ServerStorage/Scripts/FastStartScript.server.lua deleted file mode 100644 index ebf95ac..0000000 --- a/test-files/line-runner/filesystem/src/ServerStorage/Scripts/FastStartScript.server.lua +++ /dev/null @@ -1,65 +0,0 @@ -local character = script.Parent -local humanoid = character.Humanoid -local spawnLocation = character.HumanoidRootPart.Position -local player = game.Players:GetPlayerFromCharacter(character) - -local started = false - ---Casts a ray to find the height for the character to hover at even if the path is going up or down -function findHeight(distanceInFront) - local torso = character.HumanoidRootPart - local ray = Ray.new( - Vector3.new(torso.Position.X, torso.Position.Y + 50, torso.Position.Z - distanceInFront), -- origin - (Vector3.new(0, -1, 0)).unit * 300) -- direction - local ignore = character - local hit, position = game.Workspace:FindPartOnRay(ray, ignore) - return position.Y + 40 -end - -function highest(tableOfValues) - local highestSoFar = tableOfValues[1] - for i = 2, #tableOfValues do - if tableOfValues[i] > highestSoFar then - highestSoFar = tableOfValues[i] - end - end - return highestSoFar -end - -function fastStart() - if started == false then - started = true - local fastStartPosition = Instance.new("BodyPosition") - fastStartPosition.Name = "FastStart" - fastStartPosition.maxForce = Vector3.new(0, 15000, 0) - fastStartPosition.Parent = character.HumanoidRootPart - local fastStartVelocity = Instance.new("BodyVelocity") - fastStartVelocity.maxForce = Vector3.new(0, 0, 15000) - fastStartVelocity.velocity = Vector3.new(0, 0, -150) - fastStartVelocity.Parent = character.HumanoidRootPart - fastStartPosition.position = Vector3.new(0, highest({findHeight(0), findHeight(10), findHeight(20), findHeight(30)}), 0) - while character.HumanoidRootPart.Position.Z > spawnLocation.Z - 1000 do - wait(1) - if character:FindFirstChild("HumanoidRootPart") == nil then - break - end - fastStartPosition.position = Vector3.new(0, highest({findHeight(0), findHeight(10), findHeight(20), findHeight(30)}), 0) - end - fastStartVelocity.velocity = Vector3.new(0, 0, 0) - wait(2) - if character:FindFirstChild("HumanoidRootPart") then - fastStartPosition:Destroy() - fastStartVelocity:Destroy() - local shield = Instance.new("ForceField") - shield.Name = "Shield" - shield.Parent = character - game:GetService("Debris"):AddItem(shield, 3) - end - fastStart:Destroy() - script:Destroy() - end -end - -fastStart() --Script starts disabled, only enabled when a player starts running - - diff --git a/test-files/line-runner/filesystem/src/StarterPlayer/StarterPlayerScripts/CameraScript.client.lua b/test-files/line-runner/filesystem/src/StarterPlayer/StarterPlayerScripts/CameraScript.client.lua deleted file mode 100644 index 73988f0..0000000 --- a/test-files/line-runner/filesystem/src/StarterPlayer/StarterPlayerScripts/CameraScript.client.lua +++ /dev/null @@ -1,27 +0,0 @@ -local camera = game.Workspace.CurrentCamera -local player = game.Players.LocalPlayer - -camera.CameraType = Enum.CameraType.Scriptable - -local targetDistance = 30 -local cameraDistance = -30 -local cameraDirection = Vector3.new(-1,0,0) - -local currentTarget = cameraDirection*targetDistance -local currentPosition = cameraDirection*cameraDistance - -game:GetService("RunService").RenderStepped:connect(function() - local character = player.Character - if character and character:FindFirstChild("Humanoid") and character:FindFirstChild("HumanoidRootPart") then - local torso = character.HumanoidRootPart - camera.Focus = torso.CFrame - if torso:FindFirstChild("FastStart") == nil then - camera.CoordinateFrame = CFrame.new(Vector3.new(torso.Position.X, torso.Position.Y + 10, torso.Position.Z - 20) + currentPosition, - Vector3.new(torso.Position.X, torso.Position.Y, torso.Position.Z - 20) + currentTarget) - else - --Lower camera for fast start - camera.CoordinateFrame = CFrame.new(Vector3.new(torso.Position.X, torso.Position.Y - 15, torso.Position.Z - 20) + currentPosition, - Vector3.new(torso.Position.X, torso.Position.Y - 15, torso.Position.Z - 20) + currentTarget) - end - end -end) diff --git a/test-files/line-runner/filesystem/src/StarterPlayer/StarterPlayerScripts/ControlScript.client.lua b/test-files/line-runner/filesystem/src/StarterPlayer/StarterPlayerScripts/ControlScript.client.lua deleted file mode 100644 index a53af47..0000000 --- a/test-files/line-runner/filesystem/src/StarterPlayer/StarterPlayerScripts/ControlScript.client.lua +++ /dev/null @@ -1,97 +0,0 @@ -local player = game.Players.LocalPlayer -local UserInputService = game:GetService("UserInputService") -local ContextActionService = game:GetService("ContextActionService") - -local doJump = false -local reviving = false -local characterWalkSpeed = 40 - -game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Chat, false) -game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Health, false) -game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false) - -player:WaitForChild("PlayerGui") - -local function jump() - if player.Character ~= nil then - if player.Character.Humanoid.WalkSpeed == 0 then - -- Character is not yet moving, start screen was shown - doJump = false - if player.PlayerGui.StartScreen.StartInstructions.Visible == true then - player.PlayerGui.StartScreen:Destroy() - player.Character.Humanoid.WalkSpeed = characterWalkSpeed - game.ReplicatedStorage.RemoteEvents.RunStarting:FireServer() - end - else - player.Character.Humanoid.Jump = true - end - end -end - --- Handles behaviours -local function characterTouchedBrick(partTouched) - local behaviours = partTouched:FindFirstChild("Behaviours") - if behaviours ~= nil then - behaviours = behaviours:GetChildren() - for i = 1, #behaviours do - if behaviours[i].Value == true then - game.ReplicatedStorage.RemoteEvents.ExecuteBehaviour:FireServer(player.Character, partTouched, behaviours[i].Name) - end - end - end -end - -function characterAdded(newCharacter) - local humanoid = newCharacter:WaitForChild("Humanoid") - humanoid.WalkSpeed = 0 - humanoid.Touched:connect(characterTouchedBrick) - - local splashScreen = player.PlayerGui:WaitForChild("StartScreen") - - if UserInputService.TouchEnabled == false then - if UserInputService.GamepadEnabled then - splashScreen.StartInstructions.StartLabel.Text = "Press Space or Gamepad A Button to Start" - else - splashScreen.StartInstructions.StartLabel.Text = "Press Space to Start" - end - - end - if reviving == true then - reviving = false - splashScreen:Destroy() - humanoid.WalkSpeed = characterWalkSpeed - end - - humanoid.WalkSpeed = 0 -end -player.CharacterAdded:connect(characterAdded) - -if player.Character then - characterAdded(player.Character) -end - -function checkReviving(addedGui) - if addedGui.Name == "RevivingGUI" then - reviving = true - end -end -player.PlayerGui.ChildAdded:connect(checkReviving) - -if UserInputService.TouchEnabled then - UserInputService.ModalEnabled = true - UserInputService.TouchStarted:connect(function(inputObject, gameProcessedEvent) if gameProcessedEvent == false then doJump = true end end) - UserInputService.TouchEnded:connect(function() doJump = false end) -else - ContextActionService:BindAction("Jump", function(action, userInputState, inputObject) doJump = (userInputState == Enum.UserInputState.Begin) end, false, Enum.KeyCode.Space, Enum.KeyCode.ButtonA) -end - -game:GetService("RunService").RenderStepped:connect(function() - if player.Character ~= nil then - if player.Character:FindFirstChild("Humanoid") then - if doJump == true then - jump() - end - player.Character.Humanoid:Move(Vector3.new(0,0,-1), false) - end - end -end) diff --git a/test-files/line-runner/filesystem/src/Workspace/Bridge/Parts/Coin/Coin/GetCoinScript.server.lua b/test-files/line-runner/filesystem/src/Workspace/Bridge/Parts/Coin/Coin/GetCoinScript.server.lua deleted file mode 100644 index 2b1a12e..0000000 --- a/test-files/line-runner/filesystem/src/Workspace/Bridge/Parts/Coin/Coin/GetCoinScript.server.lua +++ /dev/null @@ -1,5 +0,0 @@ -local newScript = game.ServerStorage.Scripts.CoinScript:Clone() -newScript.Parent = script.Parent -newScript.Disabled = false - -script:Destroy() diff --git a/test-files/line-runner/filesystem/src/Workspace/Ladder/Parts/Coin/Coin/GetCoinScript.server.lua b/test-files/line-runner/filesystem/src/Workspace/Ladder/Parts/Coin/Coin/GetCoinScript.server.lua deleted file mode 100644 index 2b1a12e..0000000 --- a/test-files/line-runner/filesystem/src/Workspace/Ladder/Parts/Coin/Coin/GetCoinScript.server.lua +++ /dev/null @@ -1,5 +0,0 @@ -local newScript = game.ServerStorage.Scripts.CoinScript:Clone() -newScript.Parent = script.Parent -newScript.Disabled = false - -script:Destroy() diff --git a/test-files/line-runner/filesystem/src/Workspace/Mines/Parts/Coin/Coin/GetCoinScript.server.lua b/test-files/line-runner/filesystem/src/Workspace/Mines/Parts/Coin/Coin/GetCoinScript.server.lua deleted file mode 100644 index 2b1a12e..0000000 --- a/test-files/line-runner/filesystem/src/Workspace/Mines/Parts/Coin/Coin/GetCoinScript.server.lua +++ /dev/null @@ -1,5 +0,0 @@ -local newScript = game.ServerStorage.Scripts.CoinScript:Clone() -newScript.Parent = script.Parent -newScript.Disabled = false - -script:Destroy() diff --git a/test-files/line-runner/filesystem/src/Workspace/SpikesGoingDown/Parts/Coin/Coin/GetCoinScript.server.lua b/test-files/line-runner/filesystem/src/Workspace/SpikesGoingDown/Parts/Coin/Coin/GetCoinScript.server.lua deleted file mode 100644 index 2b1a12e..0000000 --- a/test-files/line-runner/filesystem/src/Workspace/SpikesGoingDown/Parts/Coin/Coin/GetCoinScript.server.lua +++ /dev/null @@ -1,5 +0,0 @@ -local newScript = game.ServerStorage.Scripts.CoinScript:Clone() -newScript.Parent = script.Parent -newScript.Disabled = false - -script:Destroy() diff --git a/test-files/line-runner/filesystem/src/Workspace/SpikesGoingUp/Parts/Coin/Coin/GetCoinScript.server.lua b/test-files/line-runner/filesystem/src/Workspace/SpikesGoingUp/Parts/Coin/Coin/GetCoinScript.server.lua deleted file mode 100644 index 2b1a12e..0000000 --- a/test-files/line-runner/filesystem/src/Workspace/SpikesGoingUp/Parts/Coin/Coin/GetCoinScript.server.lua +++ /dev/null @@ -1,5 +0,0 @@ -local newScript = game.ServerStorage.Scripts.CoinScript:Clone() -newScript.Parent = script.Parent -newScript.Disabled = false - -script:Destroy() diff --git a/test-files/line-runner/filesystem/src/Workspace/Trapdoor/Parts/Coin/Coin/GetCoinScript.server.lua b/test-files/line-runner/filesystem/src/Workspace/Trapdoor/Parts/Coin/Coin/GetCoinScript.server.lua deleted file mode 100644 index 2b1a12e..0000000 --- a/test-files/line-runner/filesystem/src/Workspace/Trapdoor/Parts/Coin/Coin/GetCoinScript.server.lua +++ /dev/null @@ -1,5 +0,0 @@ -local newScript = game.ServerStorage.Scripts.CoinScript:Clone() -newScript.Parent = script.Parent -newScript.Disabled = false - -script:Destroy() diff --git a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/Animate.server.lua b/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/Animate.server.lua deleted file mode 100644 index 0b0fc8f..0000000 --- a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/Animate.server.lua +++ /dev/null @@ -1,504 +0,0 @@ -function waitForChild(parent, childName) - local child = parent:findFirstChild(childName) - if child then return child end - while true do - child = parent.ChildAdded:wait() - if child.Name==childName then return child end - end -end - -local Figure = script.Parent -local Torso = waitForChild(Figure, "Torso") -local RightShoulder = waitForChild(Torso, "Right Shoulder") -local LeftShoulder = waitForChild(Torso, "Left Shoulder") -local RightHip = waitForChild(Torso, "Right Hip") -local LeftHip = waitForChild(Torso, "Left Hip") -local Neck = waitForChild(Torso, "Neck") -local Humanoid = waitForChild(Figure, "Humanoid") -local pose = "Standing" - -local currentAnim = "" -local currentAnimTrack = nil -local currentAnimKeyframeHandler = nil -local currentAnimSpeed = 1.0 -local animTable = {} -local animNames = { - idle = { - { id = "http://www.roblox.com/asset/?id=125750544", weight = 9 }, - { id = "http://www.roblox.com/asset/?id=125750618", weight = 1 } - }, - walk = { - { id = "http://www.roblox.com/asset/?id=125749145", weight = 10 } - }, - run = { - { id = "run.xml", weight = 10 } - }, - jump = { - { id = "http://www.roblox.com/asset/?id=125750702", weight = 10 } - }, - fall = { - { id = "http://www.roblox.com/asset/?id=125750759", weight = 10 } - }, - climb = { - { id = "http://www.roblox.com/asset/?id=125750800", weight = 10 } - }, - toolnone = { - { id = "http://www.roblox.com/asset/?id=125750867", weight = 10 } - }, - toolslash = { - { id = "http://www.roblox.com/asset/?id=129967390", weight = 10 } --- { id = "slash.xml", weight = 10 } - }, - toollunge = { - { id = "http://www.roblox.com/asset/?id=129967478", weight = 10 } - }, - wave = { - { id = "http://www.roblox.com/asset/?id=128777973", weight = 10 } - }, - point = { - { id = "http://www.roblox.com/asset/?id=128853357", weight = 10 } - }, - dance = { - { id = "http://www.roblox.com/asset/?id=130018893", weight = 10 }, - { id = "http://www.roblox.com/asset/?id=132546839", weight = 10 }, - { id = "http://www.roblox.com/asset/?id=132546884", weight = 10 } - }, - dance2 = { - { id = "http://www.roblox.com/asset/?id=160934142", weight = 10 }, - { id = "http://www.roblox.com/asset/?id=160934298", weight = 10 }, - { id = "http://www.roblox.com/asset/?id=160934376", weight = 10 } - }, - dance3 = { - { id = "http://www.roblox.com/asset/?id=160934458", weight = 10 }, - { id = "http://www.roblox.com/asset/?id=160934530", weight = 10 }, - { id = "http://www.roblox.com/asset/?id=160934593", weight = 10 } - }, - laugh = { - { id = "http://www.roblox.com/asset/?id=129423131", weight = 10 } - }, - cheer = { - { id = "http://www.roblox.com/asset/?id=129423030", weight = 10 } - }, -} - --- Existance in this list signifies that it is an emote, the value indicates if it is a looping emote -local emoteNames = { wave = false, point = false, dance = true, dance2 = true, dance3 = true, laugh = false, cheer = false} - -math.randomseed(tick()) - -function configureAnimationSet(name, fileList) - if (animTable[name] ~= nil) then - for _, connection in pairs(animTable[name].connections) do - connection:disconnect() - end - end - animTable[name] = {} - animTable[name].count = 0 - animTable[name].totalWeight = 0 - animTable[name].connections = {} - - -- check for config values - local config = script:FindFirstChild(name) - if (config ~= nil) then --- print("Loading anims " .. name) - table.insert(animTable[name].connections, config.ChildAdded:connect(function(child) configureAnimationSet(name, fileList) end)) - table.insert(animTable[name].connections, config.ChildRemoved:connect(function(child) configureAnimationSet(name, fileList) end)) - local idx = 1 - for _, childPart in pairs(config:GetChildren()) do - if (childPart:IsA("Animation")) then - table.insert(animTable[name].connections, childPart.Changed:connect(function(property) configureAnimationSet(name, fileList) end)) - animTable[name][idx] = {} - animTable[name][idx].anim = childPart - local weightObject = childPart:FindFirstChild("Weight") - if (weightObject == nil) then - animTable[name][idx].weight = 1 - else - animTable[name][idx].weight = weightObject.Value - end - animTable[name].count = animTable[name].count + 1 - animTable[name].totalWeight = animTable[name].totalWeight + animTable[name][idx].weight - -- print(name .. " [" .. idx .. "] " .. animTable[name][idx].anim.AnimationId .. " (" .. animTable[name][idx].weight .. ")") - idx = idx + 1 - end - end - end - - -- fallback to defaults - if (animTable[name].count <= 0) then - for idx, anim in pairs(fileList) do - animTable[name][idx] = {} - animTable[name][idx].anim = Instance.new("Animation") - animTable[name][idx].anim.Name = name - animTable[name][idx].anim.AnimationId = anim.id - animTable[name][idx].weight = anim.weight - animTable[name].count = animTable[name].count + 1 - animTable[name].totalWeight = animTable[name].totalWeight + anim.weight --- print(name .. " [" .. idx .. "] " .. anim.id .. " (" .. anim.weight .. ")") - end - end -end - --- Setup animation objects -function scriptChildModified(child) - local fileList = animNames[child.Name] - if (fileList ~= nil) then - configureAnimationSet(child.Name, fileList) - end -end - -script.ChildAdded:connect(scriptChildModified) -script.ChildRemoved:connect(scriptChildModified) - - -for name, fileList in pairs(animNames) do - configureAnimationSet(name, fileList) -end - --- ANIMATION - --- declarations -local toolAnim = "None" -local toolAnimTime = 0 - -local jumpAnimTime = 0 -local jumpAnimDuration = 0.3 - -local toolTransitionTime = 0.1 -local fallTransitionTime = 0.3 -local jumpMaxLimbVelocity = 0.75 - --- functions - -function stopAllAnimations() - local oldAnim = currentAnim - - -- return to idle if finishing an emote - if (emoteNames[oldAnim] ~= nil and emoteNames[oldAnim] == false) then - oldAnim = "idle" - end - - currentAnim = "" - if (currentAnimKeyframeHandler ~= nil) then - currentAnimKeyframeHandler:disconnect() - end - - if (currentAnimTrack ~= nil) then - currentAnimTrack:Stop() - currentAnimTrack:Destroy() - currentAnimTrack = nil - end - return oldAnim -end - -function setAnimationSpeed(speed) - if speed ~= currentAnimSpeed then - currentAnimSpeed = speed - currentAnimTrack:AdjustSpeed(currentAnimSpeed) - end -end - -function keyFrameReachedFunc(frameName) - if (frameName == "End") then --- print("Keyframe : ".. frameName) - local repeatAnim = stopAllAnimations() - local animSpeed = currentAnimSpeed - playAnimation(repeatAnim, 0.0, Humanoid) - setAnimationSpeed(animSpeed) - end -end - --- Preload animations -function playAnimation(animName, transitionTime, humanoid) - local idleFromEmote = (animName == "idle" and emoteNames[currentAnim] ~= nil) - if (animName ~= currentAnim and not idleFromEmote) then - - if (currentAnimTrack ~= nil) then - currentAnimTrack:Stop(transitionTime) - currentAnimTrack:Destroy() - end - - currentAnimSpeed = 1.0 - local roll = math.random(1, animTable[animName].totalWeight) - local origRoll = roll - local idx = 1 - while (roll > animTable[animName][idx].weight) do - roll = roll - animTable[animName][idx].weight - idx = idx + 1 - end --- print(animName .. " " .. idx .. " [" .. origRoll .. "]") - local anim = animTable[animName][idx].anim - - -- load it to the humanoid; get AnimationTrack - currentAnimTrack = humanoid:LoadAnimation(anim) - - -- play the animation - currentAnimTrack:Play(transitionTime) - currentAnim = animName - - -- set up keyframe name triggers - if (currentAnimKeyframeHandler ~= nil) then - currentAnimKeyframeHandler:disconnect() - end - currentAnimKeyframeHandler = currentAnimTrack.KeyframeReached:connect(keyFrameReachedFunc) - end -end - -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- - -local toolAnimName = "" -local toolAnimTrack = nil -local currentToolAnimKeyframeHandler = nil - -function toolKeyFrameReachedFunc(frameName) - if (frameName == "End") then --- print("Keyframe : ".. frameName) - local repeatAnim = stopToolAnimations() - playToolAnimation(repeatAnim, 0.0, Humanoid) - end -end - - -function playToolAnimation(animName, transitionTime, humanoid) - if (animName ~= toolAnimName) then - - if (toolAnimTrack ~= nil) then - toolAnimTrack:Stop() - toolAnimTrack:Destroy() - transitionTime = 0 - end - - local roll = math.random(1, animTable[animName].totalWeight) - local origRoll = roll - local idx = 1 - while (roll > animTable[animName][idx].weight) do - roll = roll - animTable[animName][idx].weight - idx = idx + 1 - end --- print(animName .. " * " .. idx .. " [" .. origRoll .. "]") - local anim = animTable[animName][idx].anim - - -- load it to the humanoid; get AnimationTrack - toolAnimTrack = humanoid:LoadAnimation(anim) - - -- play the animation - toolAnimTrack:Play(transitionTime) - toolAnimName = animName - - currentToolAnimKeyframeHandler = toolAnimTrack.KeyframeReached:connect(toolKeyFrameReachedFunc) - end -end - -function stopToolAnimations() - local oldAnim = toolAnimName - - if (currentToolAnimKeyframeHandler ~= nil) then - currentToolAnimKeyframeHandler:disconnect() - end - - toolAnimName = "" - if (toolAnimTrack ~= nil) then - toolAnimTrack:Stop() - toolAnimTrack:Destroy() - toolAnimTrack = nil - end - - - return oldAnim -end - -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- - - -function onRunning(speed) - if speed>0.01 then - playAnimation("walk", 0.1, Humanoid) - pose = "Running" - else - playAnimation("idle", 0.1, Humanoid) - pose = "Standing" - end -end - -function onDied() - pose = "Dead" -end - -function onJumping() - playAnimation("jump", 0.1, Humanoid) - jumpAnimTime = jumpAnimDuration - pose = "Jumping" -end - -function onClimbing(speed) - playAnimation("climb", 0.1, Humanoid) - setAnimationSpeed(speed / 12.0) - pose = "Climbing" -end - -function onGettingUp() - pose = "GettingUp" -end - -function onFreeFall() - if (jumpAnimTime <= 0) then - playAnimation("fall", fallTransitionTime, Humanoid) - end - pose = "FreeFall" -end - -function onFallingDown() - pose = "FallingDown" -end - -function onSeated() - pose = "Seated" -end - -function onPlatformStanding() - pose = "PlatformStanding" -end - -function onSwimming(speed) - if speed>0 then - pose = "Running" - else - pose = "Standing" - end -end - -function getTool() - for _, kid in ipairs(Figure:GetChildren()) do - if kid.className == "Tool" then return kid end - end - return nil -end - -function getToolAnim(tool) - for _, c in ipairs(tool:GetChildren()) do - if c.Name == "toolanim" and c.className == "StringValue" then - return c - end - end - return nil -end - -function animateTool() - - if (toolAnim == "None") then - playToolAnimation("toolnone", toolTransitionTime, Humanoid) - return - end - - if (toolAnim == "Slash") then - playToolAnimation("toolslash", 0, Humanoid) - return - end - - if (toolAnim == "Lunge") then - playToolAnimation("toollunge", 0, Humanoid) - return - end -end - -function moveSit() - RightShoulder.MaxVelocity = 0.15 - LeftShoulder.MaxVelocity = 0.15 - RightShoulder:SetDesiredAngle(3.14 /2) - LeftShoulder:SetDesiredAngle(-3.14 /2) - RightHip:SetDesiredAngle(3.14 /2) - LeftHip:SetDesiredAngle(-3.14 /2) -end - -local lastTick = 0 - -function move(time) - local amplitude = 1 - local frequency = 1 - local deltaTime = time - lastTick - lastTick = time - - local climbFudge = 0 - local setAngles = false - - if (jumpAnimTime > 0) then - jumpAnimTime = jumpAnimTime - deltaTime - end - - if (pose == "FreeFall" and jumpAnimTime <= 0) then - playAnimation("fall", fallTransitionTime, Humanoid) - elseif (pose == "Seated") then - stopAllAnimations() - moveSit() - return - elseif (pose == "Running") then - playAnimation("walk", 0.1, Humanoid) - elseif (pose == "Dead" or pose == "GettingUp" or pose == "FallingDown" or pose == "Seated" or pose == "PlatformStanding") then --- print("Wha " .. pose) - amplitude = 0.1 - frequency = 1 - setAngles = true - end - - if (setAngles) then - local desiredAngle = amplitude * math.sin(time * frequency) - - RightShoulder:SetDesiredAngle(desiredAngle + climbFudge) - LeftShoulder:SetDesiredAngle(desiredAngle - climbFudge) - RightHip:SetDesiredAngle(-desiredAngle) - LeftHip:SetDesiredAngle(-desiredAngle) - end - - -- Tool Animation handling - local tool = getTool() - if tool then - - local animStringValueObject = getToolAnim(tool) - - if animStringValueObject then - toolAnim = animStringValueObject.Value - -- message recieved, delete StringValue - animStringValueObject.Parent = nil - toolAnimTime = time + .3 - end - - if time > toolAnimTime then - toolAnimTime = 0 - toolAnim = "None" - end - - animateTool() - else - stopToolAnimations() - toolAnim = "None" - toolAnimTime = 0 - end -end - --- connect events -Humanoid.Died:connect(onDied) -Humanoid.Running:connect(onRunning) -Humanoid.Jumping:connect(onJumping) -Humanoid.Climbing:connect(onClimbing) -Humanoid.GettingUp:connect(onGettingUp) -Humanoid.FreeFalling:connect(onFreeFall) -Humanoid.FallingDown:connect(onFallingDown) -Humanoid.Seated:connect(onSeated) -Humanoid.PlatformStanding:connect(onPlatformStanding) -Humanoid.Swimming:connect(onSwimming) - --- main program - -local runService = game:service("RunService"); - --- initialize to idle -playAnimation("idle", 0.1, Humanoid) -pose = "Standing" - -while Figure.Parent~=nil do - local _, time = wait(0.1) - move(time) -end - - diff --git a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_AIUtilities.lua b/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_AIUtilities.lua deleted file mode 100644 index aef8279..0000000 --- a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_AIUtilities.lua +++ /dev/null @@ -1,106 +0,0 @@ -local utility = {} - -function utility:WideRayCast(start, target, offset, ignoreList) - local parts = {} - - local ray = Ray.new(start, target - start) - local part, point = game.Workspace:FindPartOnRayWithIgnoreList(ray, ignoreList) - if part then table.insert(parts, part) end - - local offsetVector = offset * (target - start):Cross(Vector3.FromNormalId(Enum.NormalId.Top)).unit - local ray = Ray.new(start + offsetVector, target - start + offsetVector) - local part, point = game.Workspace:FindPartOnRayWithIgnoreList(ray, ignoreList) - if part then table.insert(parts, part) end - - local ray = Ray.new(start - offsetVector, target - start - offsetVector) - local part, point = game.Workspace:FindPartOnRayWithIgnoreList(ray, ignoreList) - if part then table.insert(parts, part) end - - return parts -end - -function utility:FindNearestPathPoint(path, point, start, target, ignoreList) - local occludePoint = path:CheckOcclusionAsync(point) - if occludePoint > 0 then - utility:WideRayCast(start) - end -end - -local maxForce = 75 - -function utility:GetRepulsionVector(unitPosition, otherUnitsPositions) - local repulsionVector = Vector3.new(0,0,0) - local count = 0 - for _, other in pairs(otherUnitsPositions) do - local fromOther = unitPosition - other - --fromOther = fromOther.unit * ((-maxForce / 5) * math.pow(fromOther.magnitude,2) + maxForce) - fromOther = fromOther.unit * 1000 / math.pow((fromOther.magnitude + 1), 2) - repulsionVector = repulsionVector + fromOther - end - return repulsionVector * maxForce -end - -function utility:GetIdleState(StateMachine) - local IdleState = StateMachine.NewState() - IdleState.Name = "Idle" - IdleState.Action = function() end - IdleState.Init = function() end - return IdleState -end - -function utility:GetClosestVisibleTarget(npcModel, characters, ignoreList, fieldOfView) - local closestTarget = nil - local closestDistance = math.huge - for _, character in pairs(characters) do - local toTarget = character.HumanoidRootPart.Position - npcModel.HumanoidRootPart.Position - local toTargetWedge = toTarget * Vector3.new(1,0,1) - local angle = math.acos(toTargetWedge:Dot(npcModel.HumanoidRootPart.CFrame.lookVector)/toTargetWedge.magnitude) - if math.deg(angle) < fieldOfView then - local targetRay = Ray.new(npcModel.HumanoidRootPart.Position, toTarget) - local part, position = game.Workspace:FindPartOnRayWithIgnoreList(targetRay, ignoreList) - if part and part.Parent == character then - if toTarget.magnitude < closestDistance then - closestTarget = character - closestDistance = toTarget.magnitude - end - end - end - end - return closestTarget -end - -local function isSpaceEmpty(position) - local region = Region3.new(position - Vector3.new(2,2,2), position + Vector3.new(2,2,2)) - return game.Workspace:IsRegion3Empty(region) -end - -function utility:FindCloseEmptySpace(model) - local targetPos = Vector3.new(0,0,0) - local count = 0 - math.randomseed(os.time()) - repeat - local xoff = math.random(5,10) - if math.random() > .5 then - xoff = xoff * -1 - end - local zoff = math.random(5, 10) - if math.random() > .5 then - zoff = zoff * -1 - end - - targetPos = Vector3.new(model.HumanoidRootPart.Position.X + xoff,model.HumanoidRootPart.Position.Y,model.HumanoidRootPart.Position.Z + zoff) - if isSpaceEmpty(targetPos) then - return targetPos - else - targetPos = targetPos + Vector3.new(0,4,0) - end - - if isSpaceEmpty(targetPos) then - return targetPos - end - count = count + 1 - until count > 10 - return nil -end - -return utility \ No newline at end of file diff --git a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_DestroyService.lua b/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_DestroyService.lua deleted file mode 100644 index bc7371d..0000000 --- a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_DestroyService.lua +++ /dev/null @@ -1,43 +0,0 @@ -local destroyService = {} - -local destroyQueue = {} - -function destroyService:AddItem(theobject, delay) - local now = os.time() - local destroyObject = {object = theobject, destroyTime = delay + now} - for i, storedObject in pairs(destroyQueue) do - if destroyQueue[i].destroyTime > destroyObject.destroyTime then - table.insert(destroyQueue, i, destroyObject) - return true - end - end - table.insert(destroyQueue, destroyObject) - return true -end - -local updateThread = coroutine.create(function() - while true do - local now = os.time() - for _, storedObject in pairs(destroyQueue) do - if now >= storedObject.destroyTime then - table.remove(destroyQueue, 1) - if storedObject.object then - storedObject.object:Destroy() - end - elseif now >= storedObject.destroyTime - 1 then - - if storedObject.object and storedObject.object:IsA("Part") then - local trans = storedObject.object.Transparency + 1/30 - storedObject.object.Transparency = trans - end - else - break - end - end - wait() - end -end) - -coroutine.resume(updateThread) - -return destroyService \ No newline at end of file diff --git a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_HumanoidList.lua b/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_HumanoidList.lua deleted file mode 100644 index 2e99eea..0000000 --- a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_HumanoidList.lua +++ /dev/null @@ -1,30 +0,0 @@ -local humanoidList = {} -local storage = {} - -function humanoidList:GetCurrent() - return storage -end - -local function findHumanoids(object, list) - if object then - if object:IsA("Humanoid") then - table.insert(list, object) - end - - for _, child in pairs(object:GetChildren()) do - local childList = findHumanoids(child, list) - end - end -end - -local updateThread = coroutine.create(function() - while true do - storage = {} - findHumanoids(game.Workspace, storage) - wait(3) - end -end) - -coroutine.resume(updateThread) - -return humanoidList \ No newline at end of file diff --git a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_PathfindingLibrary.lua b/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_PathfindingLibrary.lua deleted file mode 100644 index ea186ff..0000000 --- a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_PathfindingLibrary.lua +++ /dev/null @@ -1,93 +0,0 @@ -local PathfindingUtility = {} -local TargetOffsetMax = 10--5 -local JumpThreshold = 1.5 --2.5 -local NextPointThreshold = 4 -local PathfindingService = game:GetService("PathfindingService") -PathfindingService.EmptyCutoff = .3 - -function PathfindingUtility.new() - local this = {} - - local currentTargetPos = nil - local lastTargetPos = Vector3.new(math.huge, math.huge, math.huge) - local path = nil - local currentPointIndex = 1 - - function this:MoveToTarget(character, target) - local targetOffset = (lastTargetPos - target).magnitude --- --- local targetOffsetVector = (lastTargetPos - target) --- if targetOffsetVector.magnitude < math.huge then --- targetOffsetVector = (lastTargetPos - target) * Vector3.new(1,0,1) --- end - if targetOffset > TargetOffsetMax then - --if targetOffsetVector.magnitude > TargetOffsetMax then - --print("moveto") - local startPoint = character.HumanoidRootPart.Position - local humanoidState = character.Humanoid:GetState() - if humanoidState == Enum.HumanoidStateType.Jumping or humanoidState == Enum.HumanoidStateType.Freefall then - --print("this") - local ray = Ray.new(character.HumanoidRootPart.Position, Vector3.new(0, -100, 0)) - local hitPart, hitPoint = game.Workspace:FindPartOnRay(ray, character) - if hitPart then - startPoint = hitPoint - end - end - --print("making new path") - local newTarget = target - local ray = Ray.new(target + Vector3.new(0,-3,0), Vector3.new(0, -100, 0)) - local hitPart, hitPoint = game.Workspace:FindPartOnRay(ray, character) - if hitPoint then - if (hitPoint - target).magnitude > 4 then - newTarget = newTarget * Vector3.new(1,0,1) + Vector3.new(0,3,0) - end - end - - --local newTarget = Vector3.new(1,0,1) * target + Vector3.new(0, 2, 0) - path = PathfindingService:ComputeSmoothPathAsync(startPoint, newTarget, 500) - if path.Status ~= Enum.PathStatus.Success then - --print(tostring(path.Status)) - end - --path = PathfindingService:ComputeRawPathAsync(startPoint, target, 500) - --- game.Workspace.Points:ClearAllChildren() --- local ps = path:GetPointCoordinates() --- for _, point in pairs(ps) do --- local part = Instance.new("Part", game.Workspace.Points) --- part.CanCollide = false --- part.Anchored = true --- part.FormFactor = Enum.FormFactor.Custom --- part.Size = Vector3.new(1,1,1) --- part.Position = point --- end - - currentPointIndex = 1 - lastTargetPos = target - end - - if path then - local points = path:GetPointCoordinates() - if currentPointIndex < #points then - local currentPoint = points[currentPointIndex] - if character:FindFirstChild("HumanoidRootPart") then - local distance = (character.HumanoidRootPart.Position - currentPoint).magnitude - if distance < NextPointThreshold then - currentPointIndex = currentPointIndex + 1 - end - - character.Humanoid:MoveTo(points[currentPointIndex]) - if points[currentPointIndex].Y - character.HumanoidRootPart.Position.Y > JumpThreshold then - character.Humanoid.Jump = true - end - end - else - if character:FindFirstChild("Humanoid") then - character.Humanoid:MoveTo(target) - end - end - end - end - - return this -end -return PathfindingUtility \ No newline at end of file diff --git a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_StateMachine.lua b/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_StateMachine.lua deleted file mode 100644 index 88444ea..0000000 --- a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_StateMachine.lua +++ /dev/null @@ -1,70 +0,0 @@ -local machine = {} - -machine.new = function() - local StateMachine = {} - - StateMachine.WaitTime = .2 - StateMachine.CurrentState = nil - StateMachine.SwitchState = function(newState) - if StateMachine.CurrentState then - StateMachine.CurrentState.Stop() - end - StateMachine.CurrentState = newState - if newState then - newState.Start() - end - end - - StateMachine.NewState = function() - local state = {} - state.Name = "" - state.Conditions = {} - state.isRunning = false - state.Action = function() end - state.Run = function() - state.isRunning = true - while state.isRunning do - --check conditions - --print("checking conditions") - for _, condition in pairs(state.Conditions) do - --print("Checking " .. condition.Name) - if condition.Evaluate() then - --print(condition.Name .. " is true. Switching states") - StateMachine.SwitchState(condition.TransitionState) - return - end - end - - --if no conditions satisfied, perform action - state.Action() - wait(StateMachine.WaitTime) - end - end - state.Init = function() - - end - state.Start = function() - --print("Starting " .. state.Name) - state.Init() - local thread = coroutine.create(state.Run) - coroutine.resume(thread) - end - state.Stop = function() - --print("Stopping " .. state.Name) - state.isRunning = false - end - return state - end - - StateMachine.NewCondition = function() - local condition = {} - condition.Name = "" - condition.Evaluate = function() print("replace me") return false end - condition.TransitionState = {} - return condition - end - - return StateMachine -end - -return machine \ No newline at end of file diff --git a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_ZombieAI.lua b/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_ZombieAI.lua deleted file mode 100644 index e2a0780..0000000 --- a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/ModuleScripts/ROBLOX_ZombieAI.lua +++ /dev/null @@ -1,412 +0,0 @@ ---local PathLib = require(game.ServerStorage.PathfindingLibrary).new() -local HumanoidList = require(game.ServerStorage.ROBLOX_HumanoidList) -local AIUtilities = require(game.ServerStorage.ROBLOX_AIUtilities) - -local ZombieAI = {} - -function updateDisplay(display, state) - local thread = coroutine.create(function() - while true do - wait() - if state then - display.Text = state.Name - end - end - end) - coroutine.resume(thread) -end - -ZombieAI.new = function(model) - local zombie = {} - - -- CONFIGURATION VARIABLES --- local AttackRange, FieldOfView, AggroRange, ChanceOfBoredom, BoredomDuration, --- Damage, DamageCooldown - - local configTable = model.Configurations - local configs = {} - local function loadConfig(configName, defaultValue) - if configTable:FindFirstChild(configName) then - configs[configName] = configTable:FindFirstChild(configName).Value - else - configs[configName] = defaultValue - end - end - - loadConfig("AttackRange", 3) - loadConfig("FieldOfView", 180) - loadConfig("AggroRange", 200) - loadConfig("ChanceOfBoredom", .5) - loadConfig("BoredomDuration", 10) - loadConfig("Damage", 10) - loadConfig("DamageCooldown", 1) - - local StateMachine = require(game.ServerStorage.ROBLOX_StateMachine).new() - local PathLib = require(game.ServerStorage.ROBLOX_PathfindingLibrary).new() - local ZombieTarget = nil - local ZombieTargetLastLocation = nil - - local lastBored = os.time() - - -- STATE DEFINITIONS - - -- IdleState: NPC stays still. Refreshes bored timer when started to - -- allow for random state change - local IdleState = StateMachine.NewState() - IdleState.Name = "Idle" - IdleState.Action = function() - end - IdleState.Init = function() - lastBored = os.time() - end - - -- SearchState: NPC wanders randomly increasing chance of spotting - -- enemy. Refreshed bored timer when started to allow for random state - -- change - local SearchState = StateMachine.NewState() - SearchState.Name = "Search" - local lastmoved = os.time() - local searchTarget = nil - SearchState.Action = function() - -- move to random spot nearby - if model then - if model:FindFirstChild("HumanoidRootPart") then - local now = os.time() - if now - lastmoved > 2 then - lastmoved = now - local xoff = math.random(5, 10) - if math.random() > .5 then - xoff = xoff * -1 - end - local zoff = math.random(5, 10) - if math.random() > .5 then - zoff = zoff * -1 - end - - local testtarg = AIUtilities:FindCloseEmptySpace(model) - --if testtarg then print(testtarg) else print("could not find") end - searchTarget = Vector3.new(model.HumanoidRootPart.Position.X + xoff,model.HumanoidRootPart.Position.Y,model.HumanoidRootPart.Position.Z + zoff) - --local target = Vector3.new(model.HumanoidRootPart.Position.X + xoff,model.HumanoidRootPart.Position.Y,model.HumanoidRootPart.Position.Z + zoff) - --model.Humanoid:MoveTo(target) - searchTarget = testtarg - end - --PathLib:MoveToTarget(model, searchTarget) --Zombie will fall off path when searching - end - end - end - SearchState.Init = function() - lastBored = os.time() - end - - -- PursueState: Enemy has been spotted, need to give chase. - local PursueState = StateMachine.NewState() - PursueState.Name = "Pursue" - PursueState.Action = function() - -- Double check we still have target - if ZombieTarget then - if model:FindFirstChild("HumanoidRootPart") then - if ZombieTarget:FindFirstChild("HumanoidRootPart") then - -- Get distance to target - local distance = (model.HumanoidRootPart.Position - ZombieTarget.HumanoidRootPart.Position).magnitude - -- If we're far from target use pathfinding to move. Otherwise just MoveTo - if distance > configs["AttackRange"] + 5 then - PathLib:MoveToTarget(model, ZombieTarget.HumanoidRootPart.Position) - else - model.Humanoid:MoveTo(ZombieTarget.HumanoidRootPart.Position) - -- if ZombieTarget.HumanoidRootPart.Position.Y > model.HumanoidRootPart.Position.Y + 2 then - -- model.Humanoid.Jump = true - -- end - end - end - end - end - end - PursueState.Init = function() - end - - -- AttackState: Keep moving towards target and play attack animation. - local AttackState = StateMachine.NewState() - AttackState.Name = "Attack" - local lastAttack = os.time() - local attackTrack = model.Humanoid:LoadAnimation(model.Animations.Attack) - AttackState.Action = function() - model.Humanoid:MoveTo(ZombieTarget.HumanoidRootPart.Position) - local now = os.time() - if now - lastAttack > 3 then - lastAttack = now - attackTrack:Play() - end - end - - -- HuntState: Can't see target but NPC will move to target's last known location. - -- Will eventually get bored and switch state. - local HuntState = StateMachine.NewState() - HuntState.Name = "Hunt" - HuntState.Action = function() - if ZombieTargetLastLocation then - PathLib:MoveToTarget(model, ZombieTargetLastLocation) - end - end - HuntState.Init = function() - lastBored = os.time() + configs["BoredomDuration"] / 2 - end - - -- CONDITION DEFINITIONS - - -- CanSeeTarget: Determines if a target is visible. Returns true if target is visible and - -- sets current target. A target is valid if it is nearby, visible, has a HumanoidRootPart and WalkSpeed - -- greater than 0 (this is to ignore inanimate objects that happen to use humanoids) - local CanSeeTarget = StateMachine.NewCondition() - CanSeeTarget.Name = "CanSeeTarget" - CanSeeTarget.Evaluate = function() - if model then - -- Get list of all nearby Zombies and non-Zombie humanoids - -- Zombie list is used to ignore zombies during later raycast - local humanoids = HumanoidList:GetCurrent() - local zombies = {} - local characters = {} - for _, object in pairs(humanoids) do - if object and object.Parent and object.Parent:FindFirstChild("HumanoidRootPart") and object.Health > 0 and object.WalkSpeed > 0 then - local HumanoidRootPart = object.Parent:FindFirstChild("HumanoidRootPart") - if HumanoidRootPart and model:FindFirstChild("HumanoidRootPart") then - local distance = (model.HumanoidRootPart.Position - HumanoidRootPart.Position).magnitude - if distance <= configs["AggroRange"] then - if object.Parent.Name == "Zombie" then - table.insert(zombies, object.Parent) - else - table.insert(characters, object.Parent) - end - end - end - end - end - - local target = AIUtilities:GetClosestVisibleTarget(model, characters, zombies, configs["FieldOfView"]) - if target then - ZombieTarget = target - return true - end - --- -- Go through each valid target to see if within field of view and if there is --- -- clear line of sight. Field of view treated as wedge in front of character. --- for _, character in pairs(characters) do --- local toTarget = (character.HumanoidRootPart.Position - model.HumanoidRootPart.Position) --- toTarget = Vector3.new(toTarget.X, 0, toTarget.Z) --- local angle = math.acos(toTarget:Dot(model.HumanoidRootPart.CFrame.lookVector)/toTarget.magnitude) --- if math.deg(angle) < configs["FieldOfView"]/2 then --- ZombieTarget = character --- -- raycast to see if target is actually visible --- local toTarget = Ray.new(model.HumanoidRootPart.Position, (ZombieTarget.HumanoidRootPart.Position - model.HumanoidRootPart.Position)) --- local part, position = game.Workspace:FindPartOnRayWithIgnoreList(toTarget, zombies) --- if part and part.Parent == ZombieTarget then --- return true --- end --- ZombieTarget = nil --- end --- end - end - return false - end - CanSeeTarget.TransitionState = PursueState - - -- TargetDead: Check if target is dead. - local TargetDead = StateMachine.NewCondition() - TargetDead.Name = "TargetDead" - TargetDead.Evaluate = function() - if ZombieTarget and ZombieTarget.Humanoid then - return ZombieTarget.Humanoid.Health <= 0 - end - return true - end - TargetDead.TransitionState = IdleState - - -- GotDamaged: Check if NPC has taken damage - local lastHealth = model.Humanoid.Health - local GotDamaged = StateMachine.NewCondition() - GotDamaged.Name = "GotDamaged" - GotDamaged.Evaluate = function() - if model then - if lastHealth > model.Humanoid.Health then - return true - end - end - return false - end - GotDamaged.TransitionState = SearchState - - -- GotBored: Used to provide random state change. - local GotBored = StateMachine.NewCondition() - GotBored.Name = "GotBored" - GotBored.Evaluate = function() - local now = os.time() - if now - lastBored > configs["BoredomDuration"] then - local roll = math.random() - if roll < configs["ChanceOfBoredom"] then - lastBored = now - if GotBored.TransitionState == SearchState then - GotBored.TransitionState = IdleState - else - GotBored.TransitionState = SearchState - end - return true - end - end - return false - end - GotBored.TransitionState = IdleState - - -- LostTarget: Checks clear line of sight - local LostTarget = StateMachine.NewCondition() - LostTarget.Name = "LostTarget" - LostTarget.Evaluate = function() - if true then return false end - if ZombieTarget then - if (ZombieTarget.HumanoidRootPart.Position - model.HumanoidRootPart.Position).magnitude > 10 then - local toTarget = Ray.new(model.HumanoidRootPart.Position, (ZombieTarget.HumanoidRootPart.Position - model.HumanoidRootPart.Position)) - local part, position = game.Workspace:FindPartOnRay(toTarget, model) - if not part or part.Parent ~= ZombieTarget then - --print("Lost target!") - ZombieTargetLastLocation = ZombieTarget.HumanoidRootPart.Position - ZombieTarget = nil - return true - end - end - end - return false - end - LostTarget.TransitionState = HuntState - - local WithinRange = StateMachine.NewCondition() - WithinRange.Name = "WithinRange" - WithinRange.Evaluate = function() - if ZombieTarget then - if model:FindFirstChild("HumanoidRootPart") then - local distance = (model.HumanoidRootPart.Position - ZombieTarget.HumanoidRootPart.Position).magnitude - if distance < configs["AttackRange"] then - --print("Within attack range!") - return true - end - end - end - return false - end - WithinRange.TransitionState = AttackState - - local OutsideRange = StateMachine.NewCondition() - OutsideRange.Name = "OutsideRange" - OutsideRange.Evaluate = function() - if ZombieTarget then - if model:FindFirstChild("HumanoidRootPart") and ZombieTarget:FindFirstChild("HumanoidRootPart") then - local distance = (model.HumanoidRootPart.Position - ZombieTarget.HumanoidRootPart.Position).magnitude - if distance > configs["AttackRange"] then - --print("Outside attack range!") - return true - end - end - end - return false - end - OutsideRange.TransitionState = PursueState - - table.insert(IdleState.Conditions, CanSeeTarget) - table.insert(IdleState.Conditions, GotDamaged) - table.insert(IdleState.Conditions, GotBored) - - table.insert(SearchState.Conditions, GotBored) - table.insert(SearchState.Conditions, CanSeeTarget) - - table.insert(PursueState.Conditions, LostTarget) - table.insert(PursueState.Conditions, WithinRange) - table.insert(PursueState.Conditions, TargetDead) - - table.insert(AttackState.Conditions, OutsideRange) - table.insert(AttackState.Conditions, TargetDead) - - table.insert(HuntState.Conditions, GotBored) - table.insert(HuntState.Conditions, CanSeeTarget) - - -- Setup arms damage - local canHit = true - local lastHit = os.time() - local function handleHit(other, zombieArm) - if canHit then - if other and other.Parent and other.Parent.Name ~= "Zombie" and other.Parent:FindFirstChild("Humanoid") then - local enemy = other.Parent - if enemy.Humanoid.WalkSpeed > 0 then - local shield = enemy:FindFirstChild("Shield") - if shield then - model:BreakJoints() - end - local killBehaviour = require(game.ServerScriptService.Server_Main.Behaviours.Kill) - killBehaviour:ExecuteBehaviour(zombieArm, enemy) - end - end - else - local now = os.time() - if now - lastHit > configs["DamageCooldown"] then - lastHit = now - canHit = true - end - end - end - local leftHitConnect, rightHitConnect - leftHitConnect = model:FindFirstChild("Left Arm").Touched:connect(function(other) handleHit(other, model:FindFirstChild("Left Arm")) end) - rightHitConnect = model:FindFirstChild("Right Arm").Touched:connect(function(other) handleHit(other, model:FindFirstChild("Right Arm")) end) - - --ZombieAI.Animate(model) - --updateDisplay() - --updateDisplay(model.BillboardGui.TextLabel, StateMachine.CurrentState) - local thread = coroutine.create(function() - while true do - wait() - -- calculate repulsion force - if model == nil then - break - end - - if model:FindFirstChild("HumanoidRootPart") == nil then - break - end - - local humanoids = HumanoidList:GetCurrent() - local localZombies = {} - for _, humanoid in pairs(humanoids) do - if humanoid and humanoid ~= model.Humanoid and humanoid.Parent and humanoid.Parent:FindFirstChild("HumanoidRootPart") then - local HumanoidRootPart = humanoid.Parent:FindFirstChild("HumanoidRootPart") - if HumanoidRootPart ~= nil and model ~= nil then - if model:FindFirstChild("HumanoidRootPart") then - local distance = (model.HumanoidRootPart.Position - HumanoidRootPart.Position).magnitude - if distance <= 2.5 then - table.insert(localZombies, HumanoidRootPart.Position) - end - end - end - end - end - local repulsionDirection = AIUtilities:GetRepulsionVector(model.HumanoidRootPart.Position, localZombies) - if repulsionDirection.magnitude > 0 then - --print("replusion direction: " .. tostring(repulsionDirection)) - end - model.HumanoidRootPart.RepulsionForce.force = repulsionDirection - - if StateMachine.CurrentState and model.Configurations.Debug.Value then - model.BillboardGui.TextLabel.Visible = true - model.BillboardGui.TextLabel.Text = StateMachine.CurrentState.Name - end - if not model.Configurations.Debug.Value then - model.BillboardGui.TextLabel.Visible = false - end - end - end) - coroutine.resume(thread) - - StateMachine.SwitchState(IdleState) - - zombie.Stop = function() - StateMachine.SwitchState(nil) - end - - return zombie -end - -return ZombieAI \ No newline at end of file diff --git a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/Script.server.lua b/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/Script.server.lua deleted file mode 100644 index c80ca20..0000000 --- a/test-files/line-runner/filesystem/src/Workspace/Zombie/Parts/Zombie/Script.server.lua +++ /dev/null @@ -1,48 +0,0 @@ -local zombie = script.Parent - -for _, script in pairs(zombie.ModuleScripts:GetChildren()) do - if not game.ServerStorage:FindFirstChild(script.Name) then - script:Clone().Parent = game.ServerStorage - end -end - -local AI = require(game.ServerStorage.ROBLOX_ZombieAI).new(zombie) -local DestroyService = require(game.ServerStorage.ROBLOX_DestroyService) - - -local function clearParts(parent) - for _, part in pairs(parent:GetChildren()) do - clearParts(part) - end - local delay - if parent:IsA("Part") then - delay = math.random(5,10) - else - delay = 11 - end - DestroyService:AddItem(parent, delay) -end - -zombie.Humanoid.Died:connect(function() - AI.Stop() - math.randomseed(tick()) - clearParts(zombie) - script.Disabled = true -end) - -local lastMoan = os.time() -math.randomseed(os.time()) -while true do - local animationTrack = zombie.Humanoid:LoadAnimation(zombie.Animations.Arms) - animationTrack:Play() --- local now = os.time() --- if now - lastMoan > 5 then --- if math.random() > .3 then --- zombie.Moan:Play() ----- print("playing moan") --- lastMoan = now --- end --- end - wait(2) -end - diff --git a/test-files/line-runner/output.json b/test-files/line-runner/output.json index 49529ab..1733cee 100644 --- a/test-files/line-runner/output.json +++ b/test-files/line-runner/output.json @@ -12,12 +12,12 @@ "contents": { "Vfs": { "files": { - "PathPackager.lua": { + "PathPackager.luau": { "contents": { "Bytes": "-- Credit to Davidii for creating the orginal module which I slightly modified for my purposes\n\nlocal RoomPackager = {}\n\n--returns a table of vector3s that represent the corners of any given part\nfunction RoomPackager:CornersOfPart(part)\n\tlocal cframe = part.CFrame\n\tlocal halfSizeX = part.Size.X / 2\n\tlocal halfSizeY = part.Size.Y / 2\n\tlocal halfSizeZ = part.Size.Z / 2\n\n\tlocal corners = {\n\t\tRightTopBack =\t\tcframe:pointToWorldSpace(Vector3.new(halfSizeX, halfSizeY, halfSizeZ)),\n\t\tRightBottomBack =\tcframe:pointToWorldSpace(Vector3.new(halfSizeX, -halfSizeY, halfSizeZ)),\n\t\tRightTopFront =\t\tcframe:pointToWorldSpace(Vector3.new(halfSizeX, halfSizeY, -halfSizeZ)),\n\t\tRightBottomFront =\tcframe:pointToWorldSpace(Vector3.new(halfSizeX, -halfSizeY, -halfSizeZ)),\n\t\tLeftTopBack =\t\tcframe:pointToWorldSpace(Vector3.new(-halfSizeX, halfSizeY, halfSizeZ)),\n\t\tLeftBottomBack =\tcframe:pointToWorldSpace(Vector3.new(-halfSizeX, -halfSizeY, halfSizeZ)),\n\t\tLeftTopFront =\t\tcframe:pointToWorldSpace(Vector3.new(-halfSizeX, halfSizeY, -halfSizeZ)),\n\t\tLeftBottomFront =\tcframe:pointToWorldSpace(Vector3.new(-halfSizeX, -halfSizeY, -halfSizeZ)),\n\t}\n\n\treturn corners\nend\n\n--returns the four corners with the highest y components\n--this is to catch when a user has flipped the baseplate upside down\nfunction RoomPackager:TopCornersOfBasePlate(basePlate)\n\tlocal corners = self:CornersOfPart(basePlate)\n\tlocal centerY = basePlate.Position.Y\n\tlocal topCorners = {}\n\tfor _, corner in pairs(corners) do\n\t\t--if a corner is higher globally than the center of the part, then\n\t\t--it is along the top-facing surface of the part\n\t\tif corner.Y > centerY then\n\t\t\ttable.insert(topCorners, corner)\n\t\tend\n\tend\n\treturn topCorners\nend\n\n--this returns a region3 that lines up on top of the baseplate to capture\n--whatever room has been constructed on top of it, it is smart enough\n--to capture a room that has been less-than-ideally set up\nfunction RoomPackager:RegionsFromBasePlate(basePlate)\n\tlocal topCorners = self:TopCornersOfBasePlate(basePlate)\n\n\t--we farm the min and max x's and z's from the top corners\n\t--to get x and z coordinates for the region3 that will contain the room\n\t--we choose an arbitrary corner so that the initial values are in the data set\n\tlocal arbitraryCorner = topCorners[1]\n\tlocal minX = arbitraryCorner.X\n\tlocal minZ = arbitraryCorner.Z\n\tlocal maxX = arbitraryCorner.X\n\tlocal maxZ = arbitraryCorner.Z\n\tfor _, corner in pairs(topCorners) do\n\t\tminX = math.min(minX, corner.X)\n\t\tminZ = math.min(minZ, corner.Z)\n\t\tmaxX = math.max(maxX, corner.X)\n\t\tmaxZ = math.max(maxZ, corner.Z)\n\tend\n\n\t--construct the region using these new corners we have constructed\n\t--keeping in mind that all corners in topCorners *should* have the same y value\n\tlocal minY = topCorners[1].Y\n\tlocal lowerCorner = Vector3.new(minX, minY, minZ)\n\tlocal maxY = minY + 70\n\tlocal upperCorner = Vector3.new(maxX, maxY, maxZ)\n\n\tlocal segmentHeight = math.floor(100000/(math.abs(maxX-minX)*math.abs(maxZ-minZ)))\n\n\tlocal regions = {}\n\n\tlocal currentHeight = minY\n\twhile currentHeight - minY < 70 do\n\t\tcurrentHeight = currentHeight + segmentHeight\n\t\tlowerCorner = Vector3.new(lowerCorner.x, currentHeight - segmentHeight, lowerCorner.z)\n\t\tupperCorner = Vector3.new(upperCorner.x, currentHeight, upperCorner.z)\n\t\ttable.insert(regions, Region3.new(lowerCorner, upperCorner))\n\tend\n\n\treturn regions\nend\n\n--Finds the model the current part is in which is closest to workspace\n--Returns the part is the part is in Workspace\n--Returns nil if the object is already in the roomModel we are constructing\nlocal function closestParentToWorkspace(object, roomModel)\n\tif object.Parent == roomModel then\n\t\treturn nil\n\tend\n\tif object.Parent == game.Workspace then\n\t\treturn object\n\telse\n\t\treturn closestParentToWorkspace(object.Parent, roomModel)\n\tend\nend\n\n--Categorises a model based on the location of the start and end points of the path in the model\nfunction RoomPackager:CategoriseModel(pathModel)\n\tif pathModel:FindFirstChild(\"EndParts\") then\n\t\treturn game.ReplicatedStorage.PathModules.Branch\n\telseif pathModel.Start.Position.Y < pathModel.End.Position.Y - 5 then\n\t\treturn game.ReplicatedStorage.PathModules.GoingUp\n\telseif pathModel.Start.Position.Y > pathModel.End.Position.Y + 5 then\n\t\treturn game.ReplicatedStorage.PathModules.GoingDown\n\telse\n\t\treturn game.ReplicatedStorage.PathModules.SameHeight\n\tend\nend\n\nlocal function addBehavioursRecur(model, behaviourFolder)\n\tlocal children = model:GetChildren()\n\tfor i = 1, #children do\n\t\tif children[i]:isA(\"BasePart\") then\n\t\t\tbehaviourFolder:Clone().Parent = children[i]\n\t\telse\n\t\t\taddBehavioursRecur(children[i], behaviourFolder)\n\t\tend\n\tend\nend\n\nRoomPackager.setUpBehaviours = function(roomModel)\n\tif roomModel:FindFirstChild(\"Behaviours\") then\n\t\taddBehavioursRecur(roomModel, roomModel.Behaviours)\n\t\treturn\n\tend\n\tlocal children = roomModel:GetChildren()\n\tfor i = 1, #children do\n\t\tRoomPackager.setUpBehaviours(children[i])\n\tend\nend\n\nlocal function processPart(roomModel, part, parts)\n\tif part.Parent == roomModel then return end\n\tif part.Name == \"End\" and roomModel:FindFirstChild(\"End\") then\n\t\tlocal endsModel = Instance.new(\"Model\") --Used for branching the path\n\t\tendsModel.Name = \"EndParts\"\n\t\tendsModel.Parent = roomModel\n\t\tpart.Parent = endsModel\n\t\troomModel:FindFirstChild(\"End\").Parent = endsModel\n\telseif part.Name == \"End\" and roomModel:FindFirstChild(\"EndParts\") then\n\t\tpart.Parent = roomModel:FindFirstChild(\"EndParts\")\n\telseif part.Name == \"End\" then\n\t\tpart.Parent = roomModel\n\telse\n\t\tlocal topLevelParent = closestParentToWorkspace(part, roomModel)\n\t\tif topLevelParent ~= nil then\n\t\t\tif topLevelParent:isA(\"BasePart\") then\n\t\t\t\tlocal connectedParts = topLevelParent:GetConnectedParts(true)\n\t\t\t\tfor _, connectedPart in pairs(connectedParts) do\n\t\t\t\t\tif connectedPart.Name == \"End\" then\n\t\t\t\t\t\ttable.insert(parts, connectedPart)\n\t\t\t\t\telse\n\t\t\t\t\t\tlocal conTopLevelParent = closestParentToWorkspace(connectedPart, roomModel)\n\t\t\t\t\t\tif conTopLevelParent and conTopLevelParent ~= topLevelParent then\n\t\t\t\t\t\t\tconTopLevelParent.Parent = roomModel\n\t\t\t\t\t\tend\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\tend\n\t\t\ttopLevelParent.Parent = roomModel\n\t\tend\n\tend\nend\n\nfunction RoomPackager:PackageRoom(roomBasePlate)\n\tlocal roomModel = Instance.new(\"Model\")\n\troomModel.Name = \"Path\"\n\troomModel.Parent = game.ReplicatedStorage.PathModules\n\n\tlocal regions = self:RegionsFromBasePlate(roomBasePlate)\n\n\tfor i = 1, #regions do\n\t\t--Repeatedly finds 100 parts in the region until none are left\n\t\twhile true do\n\t\t\tlocal parts = game.Workspace:FindPartsInRegion3(regions[i], nil, 100)\n\t\t\tif #parts == 0 then\n\t\t\t\tbreak\n\t\t\tend\n\t\t\tfor _, part in pairs(parts) do\n\t\t\t\tprocessPart(roomModel, part, parts)\n\t\t\tend\n\t\tend\n\tend\n\n\t--Set-up model for use in the path (parts for locating the path are made transparent)\n\troomBasePlate.Transparency = 1\n\troomBasePlate.Parent = roomModel\n\troomModel:FindFirstChild(\"Start\", true).Parent = roomModel\n\troomModel:FindFirstChild(\"Start\", true).Transparency = 1\n\tif roomModel:FindFirstChild(\"EndParts\") then\n\t\tlocal ends = roomModel:FindFirstChild(\"EndParts\"):GetChildren()\n\t\tfor i = 1, #ends do\n\t\t\tends[i].Transparency = 1\n\t\tend\n\telse\n\t\troomModel.End.Transparency = 1\n\tend\n\troomModel.PrimaryPart = roomBasePlate\n\troomModel.Parent = self:CategoriseModel(roomModel)\n\tRoomPackager.setUpBehaviours(roomModel)\n\treturn roomModel\nend\n\nreturn RoomPackager" } }, - "init.server.lua": { + "init.server.luau": { "contents": { "Bytes": "-- Line Runner\n-- TheGamer101\n\nlocal path = nil\ncoroutine.wrap(function() path = require(script.PathCreator) end)()\n\n-- Handle remote functions/events\nfunction runStarting(player)\n\tif player.Character then\n\t\tif player.Character:FindFirstChild(\"FastStartScript\") then\n\t\t\tplayer.Character.FastStartScript.Disabled = false\n\t\tend\n\tend\nend\ngame.ReplicatedStorage.RemoteEvents.RunStarting.OnServerEvent:connect(runStarting)\n\nlocal behaviourModules = {}\n\ncoroutine.wrap(function()\n\tfor _, behaviourScript in ipairs(script.Behaviours:GetChildren()) do\n\t\tlocal success, errMessage = pcall(function()\n\t\t\tbehaviourModules[behaviourScript.Name] = require(behaviourScript)\n\t\tend)\n\t\tif not success then\n\t\t\twarn(\"Failed to load module\" ..behaviourScript.Name.. \".\\n\" ..errMessage)\n\t\tend\n\tend\nend)()\n\nfunction executeBehaviour(player, character, brickTouched, behaviourName)\n\tif behaviourModules[behaviourName] ~= nil then\n\t\tbehaviourModules[behaviourName]:ExecuteBehaviour(brickTouched, character)\n\tend\nend\ngame.ReplicatedStorage.RemoteEvents.ExecuteBehaviour.OnServerEvent:connect(executeBehaviour)\n\n-- Initialization\nlocal lastActivePath = {}\n\nif game.Workspace:FindFirstChild(\"BasePlate\") then\n\tgame.Workspace.BasePlate:Destroy()\nend\n\nlocal tracksModel = Instance.new(\"Model\")\ntracksModel.Name = \"Tracks\"\ntracksModel.Parent = game.Workspace\n\nfunction packagePathModels()\n\tlocal pathPackager = require(script.PathPackager)\n\twhile true do\n\t\tlocal pathBase = game.Workspace:FindFirstChild(\"PathBase\", true)\n\t\tif pathBase then\n\t\t\tpathPackager:PackageRoom(pathBase)\n\t\telse\n\t\t\tbreak\n\t\tend\n\tend\nend\n\ncoroutine.wrap(function() packagePathModels() end)()\n\n-- Leaderboard\nfunction updateHighScorePlayerPoints(newValue, player)\n\tlocal pointsService = game:GetService(\"PointsService\")\n\tlocal currentBalance = pointsService:GetGamePointBalance(player.userId)\n\tlocal amountToAward = newValue - currentBalance\n\tpcall(function() pointsService:AwardPoints(player.userId, amountToAward) end)\nend\n\nfunction checkNewHighScore(player)\n\tif player:FindFirstChild(\"leaderstats\") then\n\t\tif player.userId > 0 then\n\t\t\tlocal storedScore = 0\n\t\t\tpcall(function() storedScore = game:GetService(\"PointsService\"):GetGamePointBalance(player.userId) end)\n\t\t\tif storedScore < player.leaderstats[\"High Score\"].Value then\n\t\t\t\tupdateHighScorePlayerPoints(player.leaderstats[\"High Score\"].Value, player)\n\t\t\tend\n\t\tend\n\tend\nend\n\nfunction loadLeaderstats(player)\n\tlocal stats = Instance.new(\"IntValue\")\n\tstats.Name = \"leaderstats\"\n\n\tlocal highScore = Instance.new(\"IntValue\")\n\thighScore.Name = \"High Score\"\n\thighScore.Parent = stats\n\thighScore.Value = 0\n\n\tcoroutine.wrap(function()\n\t\tpcall(function()\n\t\t\thighScore.Value = game:GetService(\"PointsService\"):GetGamePointBalance(player.userId)\n\t\tend)\n\tend)()\n\n\tlocal currentScore = Instance.new(\"IntValue\")\n\tcurrentScore.Name = \"Score\"\n\tcurrentScore.Parent = stats\n\n\tstats.Parent = player\nend\n\nfunction initialiseRunStats(player)\n\tif player:FindFirstChild(\"RunStats\") then\n\t\tplayer.RunStats.Distance.Value = 0\n\t\tplayer.RunStats.CoinsCollected.Value = 0\n\tend\nend\n\nfunction showResults(player)\n\tlocal resultsGUI = game.ServerStorage.GUIs.PostRunGUI:Clone()\n\tresultsGUI.Frame.DistanceValue.Text = player.RunStats.Distance.Value\n\tresultsGUI.Frame.CoinsValue.Text = player.RunStats.CoinsCollected.Value\n\tresultsGUI.Frame.ScoreValue.Text = player.leaderstats.Score.Value\n\n\tresultsGUI.Parent = player.PlayerGui\n\treturn resultsGUI\nend\n\nfunction initialiseNewRun(player, delayTime, charExpected, showLastResults)\n\tif not path then\n\t\twhile not path do\n\t\t\twait()\n\t\tend\n\tend\n\n\tlocal lastResultsGUI = nil\n\tif showLastResults then\n\t\tlastResultsGUI = showResults(player)\n\tend\n\n\tif delayTime ~= 0 then\n\t\twait(delayTime)\n\tend\n\n\tif lastResultsGUI ~= nil then\n\t\tlastResultsGUI:Destroy()\n\tend\n\n\tif player and player.Parent then\n\t\t-- charExpected is needed to avoid calling LoadCharacter on players leaving the game\n\t\tif player.Character or charExpected == false then\n\t\t\tplayer:LoadCharacter()\n\n\t\t\tinitialiseRunStats(player)\n\n\t\t\tlocal playersPath = path()\n\t\t\tlastActivePath[player.Name] = playersPath\n\t\t\tplayersPath:init(player.Name)\n\t\tend\n\tend\nend\n\nfunction setUpPostRunStats(player)\n\tlocal folder = Instance.new(\"Folder\")\n\tfolder.Name = \"RunStats\"\n\tfolder.Parent = player\n\tlocal currentDistance = Instance.new(\"IntValue\")\n\tcurrentDistance.Name = \"Distance\"\n\tcurrentDistance.Value = 0\n\tcurrentDistance.Parent = folder\n\tlocal coinsCollected = Instance.new(\"IntValue\")\n\tcoinsCollected.Name = \"CoinsCollected\"\n\tcoinsCollected.Value = 0\n\tcoinsCollected.Parent = folder\nend\n\nfunction onPlayerEntered(player)\n\tplayer.CharacterAdded:connect(function(character)\n\t\tlocal humanoid = character:WaitForChild(\"Humanoid\")\n\t\tif humanoid then\n\t\t\thumanoid.Died:connect(function()\n\t\t\t\tinitialiseNewRun(player, 4, true, true)\n\t\t\t\tcheckNewHighScore(player)\n\t\t\tend)\n\t\tend\n\tend)\n\n\t-- Initial loading\n\tloadLeaderstats(player)\n\tsetUpPostRunStats(player)\n\n\t-- Start game\n\tinitialiseNewRun(player, 0, false, false)\nend\ngame.Players.PlayerAdded:connect(onPlayerEntered)\n\nfunction onPlayerRemoving(player)\n\tlocal track = game.Workspace.Tracks:FindFirstChild(player.Name)\n\tif track ~= nil then\n\t\ttrack:Destroy()\n\tend\nend\ngame.Players.PlayerRemoving:connect(onPlayerRemoving)\n\nfor _, player in pairs(game.Players:GetChildren()) do\n\tonPlayerEntered(player)\nend\n\n\n" } @@ -31,37 +31,37 @@ "contents": { "Vfs": { "files": { - "Boost.lua": { + "Boost.luau": { "contents": { "Bytes": "local module = {}\n\nlocal equalizingForce = 236 / 1.2 -- amount of force required to levitate a mass\nlocal gravity = .90 -- things float at > 1\n\nfunction recursiveGetLift(node)\n\tlocal m = 0\n\tlocal c = node:GetChildren()\n\tfor i=1,#c do\n\t\tif c[i]:IsA(\"BasePart\") then\n\t\t\tif c[i].Name == \"Handle\" then\n\t\t\t\tm = m + (c[i]:GetMass() * equalizingForce * 1) -- makes hats weightless, so different hats don't change your jump height\n\t\t\telse\n\t\t\t\tm = m + (c[i]:GetMass() * equalizingForce * gravity)\n\t\t\tend\n\t\tend\n\t\tm = m + recursiveGetLift(c[i])\n\tend\n\treturn m\nend\n\nfunction module:ExecuteBehaviour(brickTouched, character)\n\tif character:FindFirstChild(\"HumanoidRootPart\") ~= nil then\n\t\tif character.Humanoid.Health > 0 then\n\t\t\tif character.HumanoidRootPart:FindFirstChild(\"BoostEffect\") == nil then\n\t\t\t\tlocal boostEffect = Instance.new(\"BodyForce\")\n\t\t\t\tboostEffect.Name = \"BoostEffect\"\n\t\t\t\tboostEffect.force = Vector3.new(0, recursiveGetLift(character) ,0)\n\t\t\t\tboostEffect.Parent = character.HumanoidRootPart\n\t\t\t\tgame:GetService(\"Debris\"):AddItem(boostEffect, .8)\n\t\t\t\twait(.5)\n\t\t\t\tboostEffect.Name = \"OldBoostEffect\"\n\t\t\tend\n\t\tend\n\tend\nend\n\nreturn module\n" } }, - "CoinCollected.lua": { + "CoinCollected.luau": { "contents": { "Bytes": "local module = {}\n\nfunction module:ExecuteBehaviour(brickTouched, character)\n\tif character:FindFirstChild(\"Humanoid\") ~= nil then\n\t\tif character.Humanoid.Health > 0 then\n\t\t\tif brickTouched ~= nil then\n\t\t\t\tif brickTouched.Parent ~= nil then\n\t\t\t\t\tlocal player = game.Players:GetPlayerFromCharacter(character)\n\t\t\t\t\tif player ~= nil then\n\t\t\t\t\t\tif brickTouched.Parent:FindFirstChild(\"Coin\") then\n\t\t\t\t\t\t\tif brickTouched.Parent.Coin:FindFirstChild(\"Sound\") then\n\t\t\t\t\t\t\t\tlocal sound = brickTouched.Parent.Coin.Sound:Clone()\n\t\t\t\t\t\t\t\tsound.Parent = player.PlayerGui\n\t\t\t\t\t\t\t\tsound:Play()\n\t\t\t\t\t\t\t\tgame:GetService(\"Debris\"):AddItem(sound, 1)\n\t\t\t\t\t\t\tend\n\t\t\t\t\t\tend\n\t\t\t\t\t\tbrickTouched.Parent:Destroy()\n\t\t\t\t\t\tplayer.RunStats.CoinsCollected.Value = player.RunStats.CoinsCollected.Value + 1\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\tend\nend\n\nreturn module\n\n" } }, - "Explode.lua": { + "Explode.luau": { "contents": { "Bytes": "local module = {}\n\nfunction module:ExecuteBehaviour(brickTouched, character)\n\tif character:FindFirstChild(\"HumanoidRootPart\") ~= nil then\n\t\tif character.HumanoidRootPart:FindFirstChild(\"Explosion\") == nil then\n\t\t\tlocal explosion = Instance.new(\"Explosion\")\n\t\t\texplosion.Name = \"Explosion\"\n\t\t\texplosion.BlastRadius = 10\n\t\t\texplosion.BlastPressure = 0\n\t\t\texplosion.Position = character.HumanoidRootPart.Position\n\t\t\texplosion.Parent = character.HumanoidRootPart\n\t\tend\n\tend\nend\n\nreturn module\n\n" } }, - "Kill.lua": { + "Kill.luau": { "contents": { "Bytes": "local module = {}\n\nfunction module:ExecuteBehaviour(brickTouched, character)\n\tif character:FindFirstChild(\"Humanoid\") ~= nil then\n\t\tlocal shield = character:FindFirstChild(\"Shield\")\n\t\tif shield == nil then\n\t\t\tif character.Humanoid.Health > 0 then\n\t\t\t\tcharacter.Humanoid.Health = 0\n\t\t\t\tcharacter:BreakJoints()\n\t\t\tend\n\t\telse\n\t\t\tif shield:isA(\"ForceField\") then\n\t\t\t\tlocal tempShield = Instance.new(\"BoolValue\")\n\t\t\t\ttempShield.Name = \"Shield\"\n\t\t\t\ttempShield.Parent = character\n\t\t\t\tgame:GetService(\"Debris\"):AddItem(tempShield, 1)\n\t\t\t\tshield:Destroy()\n\t\t\tend\n\t\tend\n\tend\nend\n\nreturn module\n" } }, - "KillWithShield.lua": { + "KillWithShield.luau": { "contents": { "Bytes": "local module = {}\n\n--Kills users even if they have a shield\n\nfunction module:ExecuteBehaviour(brickTouched, character)\n\tif character:FindFirstChild(\"Humanoid\") ~= nil then\n\t\tif character.Humanoid.Health > 0 then\n\t\t\tcharacter.Humanoid.Health = 0\n\t\tend\n\tend\nend\n\nreturn module\n" } }, - "LadderBoost.lua": { + "LadderBoost.luau": { "contents": { "Bytes": "local module = {}\n\nlocal equalizingForce = 236 / 1.2 -- amount of force required to levitate a mass\nlocal gravity = .90 -- things float at > 1\n\nfunction recursiveGetLift(node)\n\tlocal m = 0\n\tlocal c = node:GetChildren()\n\tfor i=1,#c do\n\t\tif c[i]:IsA(\"BasePart\") then\n\t\t\tif c[i].Name == \"Handle\" then\n\t\t\t\tm = m + (c[i]:GetMass() * equalizingForce * 1) -- makes hats weightless, so different hats don't change your jump height\n\t\t\telse\n\t\t\t\tm = m + (c[i]:GetMass() * equalizingForce * gravity)\n\t\t\tend\n\t\tend\n\t\tm = m + recursiveGetLift(c[i])\n\tend\n\treturn m\nend\n\nfunction module:ExecuteBehaviour(brickTouched, character)\n\tif character:FindFirstChild(\"HumanoidRootPart\") ~= nil then\n\t\tif character.Humanoid.Health > 0 then\n\t\t\tif character.HumanoidRootPart:FindFirstChild(\"LadderBoostEffect\") == nil then\n\t\t\t\tlocal boostEffectDebounce = Instance.new(\"IntValue\")\n\t\t\t\tboostEffectDebounce.Name = \"LadderBoostEffect\"\n\t\t\t\tboostEffectDebounce.Parent = character.HumanoidRootPart\n\t\t\t\tgame:GetService(\"Debris\"):AddItem(boostEffectDebounce, 2)\n\t\t\t\tlocal boostEffect = Instance.new(\"BodyForce\")\n\t\t\t\tboostEffect.force = Vector3.new(0, recursiveGetLift(character) ,0)\n\t\t\t\tboostEffect.Parent = character.HumanoidRootPart\n\t\t\t\tgame:GetService(\"Debris\"):AddItem(boostEffect, .2)\n\t\t\tend\n\t\tend\n\tend\nend\n\nreturn module\n" } }, - "Trapdoor.lua": { + "Trapdoor.luau": { "contents": { "Bytes": "local module = {}\n\nfunction module:ExecuteBehaviour(brickTouched, character)\n\tfor _, part in pairs(brickTouched.Parent:GetChildren()) do\n\t\tif part:isA(\"BasePart\") then\n\t\t\tpart.Anchored = false\n\t\tend\n\tend\n\twait(.3)\n\tif brickTouched ~= nil and brickTouched.Parent ~= nil then\n\t\tfor _, part in pairs(brickTouched.Parent:GetChildren()) do\n\t\t\tif part:isA(\"BasePart\") then\n\t\t\t\tpart.CanCollide = false\n\t\t\tend\n\t\tend\n\tend\nend\n\nreturn module\n" } @@ -80,12 +80,12 @@ "contents": { "Vfs": { "files": { - "CharacterHandler.lua": { + "CharacterHandler.luau": { "contents": { "Bytes": "function makeCharacterHandler()\n\tlocal characterHandler = {}\n\n\tcharacterHandler.SpawnPoint\t= nil\n\n\tcharacterHandler.newHighScore = false\n\t--characterHandler.newHighScore = characterHandler.player.leaderstats[\"High Score\"].Value > 0\n\tcharacterHandler.player = nil\n\tcharacterHandler.character = nil\n\n\t--Updates the score based on how far from the SpawnPoint the character is\n\tfunction characterHandler:UpdateScore()\n\t\tlocal player = characterHandler.player\n\t\tlocal character = characterHandler.character\n\t\tlocal leaderstats = player and player:FindFirstChild(\"leaderstats\") or nil\n\t\tif player and character and leaderstats then\n\t\t\tlocal humanoid = character:FindFirstChildOfClass(\"Humanoid\")\n\t\t\tif not humanoid or not (humanoid.Health > 0) then\n\t\t\t\treturn\n\t\t\tend\n\n\t\t\tlocal torso = character:FindFirstChild(\"HumanoidRootPart\")\n\n\t\t\tif not torso then\n\t\t\t\treturn\n\t\t\tend\n\n\t\t\t-- Sanity check for large score increases\n\t\t\tif characterHandler.SpawnPoint.Z - torso.Position.Z > leaderstats.Score.Value + 100 then\n\t\t\t\treturn\n\t\t\tend\n\n\t\t\t-- Update Score\n\t\t\tplayer.RunStats.Distance.Value = characterHandler.SpawnPoint.Z - torso.Position.Z\n\t\t\tleaderstats.Score.Value = player.RunStats.Distance.Value + player.RunStats.CoinsCollected.Value * 50\n\n\t\t\t-- Update High Score\n\t\t\tif leaderstats.Score.Value > leaderstats[\"High Score\"].Value then\n\t\t\t\t-- First time player, don't show New High Score GUI\n\t\t\t\tif characterHandler.player.leaderstats[\"High Score\"].Value == 0 then\n\t\t\t\t\tcharacterHandler.newHighScore = true\n\t\t\t\tend\n\n\t\t\t\tleaderstats[\"High Score\"].Value = leaderstats.Score.Value\n\n\t\t\t\t-- Show New High Score GUI if they beat their High Score for the first time in this run\n\t\t\t\tif characterHandler.newHighScore == false then\n\t\t\t\t\tcharacterHandler.newHighScore = true\n\t\t\t\t\tgame.ServerStorage.GUIs.HighScore:Clone().Parent = characterHandler.player.PlayerGui\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\tend\n\n\tcharacterHandler.BodyPartPositions = {\n\t\t[\"Head\"] = {},\n\t\t[\"Torso\"] = {},\n\t\t[\"Right Arm\"] = {},\n\t\t[\"Left Arm\"] = {},\n\t\t[\"Right Leg\"] = {},\n\t\t[\"Left Leg\"] = {},\n\t\t[\"HumanoidRootPart\"] = {}\n\t}\n\n\n\tfunction characterHandler:UpdateBodyPartPositions()\n\t\tif characterHandler.character then\n\t\t\tfor _, part in pairs(characterHandler.character:GetChildren()) do\n\t\t\t\tif part:isA(\"BasePart\") then\n\t\t\t\t\tif characterHandler.BodyPartPositions[part.Name] == nil then\n\t\t\t\t\t\tcharacterHandler.BodyPartPositions[part.Name] = {}\n\t\t\t\t\tend\n\t\t\t\t\ttable.insert(characterHandler.BodyPartPositions[part.Name], 1, part.CFrame)\n\t\t\t\t\tif #characterHandler.BodyPartPositions[part.Name] > 120 then\n\t\t\t\t\t\ttable.remove(characterHandler.BodyPartPositions[part.Name], 121)\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\tend\n\n\t--Can collide is false for the previously cloned handles of the hats\n\tlocal function canCollideParts(character)\n\t\tlocal parts = character:GetChildren()\n\t\tfor i = 1, #parts do\n\t\t\tif parts[i]:isA(\"BasePart\") then\n\t\t\t\tif parts[i].CanCollide == false then\n\t\t\t\t\tparts[i].CanCollide = true\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\tend\n\n\tfunction characterHandler:init(startPathModel, playerName)\n\t\tcharacterHandler.player = game.Players:FindFirstChild(playerName)\n\t\tif characterHandler.player ~= nil then\n\t\t\tcharacterHandler.character = characterHandler.player.Character\n\n\t\t\tif not characterHandler.character then\n\t\t\t\tcharacterHandler.player.CharacterAdded:wait()\n\t\t\t\tcharacterHandler.character = characterHandler.player.Character\n\t\t\tend\n\n\t\t\tcharacterHandler.newHighScore = characterHandler.player.leaderstats[\"High Score\"].Value > 0\n\t\t\tcharacterHandler.SpawnPoint = startPathModel.Start.Position + Vector3.new(0, 4, -3)\n\t\t\tcharacterHandler.character:MoveTo(characterHandler.SpawnPoint)\n\t\t\tlocal updateScoreConnection = game:GetService(\"RunService\").Heartbeat:connect(function() self:UpdateScore() end)\n\t\t\tcharacterHandler.updatePositionsConnection = game:GetService(\"RunService\").Heartbeat:connect(function() self:UpdateBodyPartPositions() end)\n\t\t\tcharacterHandler.character.Humanoid.Died:connect(function()\n\t\t\t\tupdateScoreConnection:disconnect()\n\t\t\t\tcanCollideParts(characterHandler.character)\n\t\t\tend)\n\t\t\tcharacterHandler.player.CharacterRemoving:connect(function() characterHandler.updatePositionsConnection:disconnect() end)\n\t\tend\n\tend\n\n\treturn characterHandler\nend\n\nreturn makeCharacterHandler" } }, - "init.lua": { + "init.luau": { "contents": { "Bytes": "local function makePathObject()\n\tlocal Path = {}\n\n\tlocal pathModels = nil\n\n\tlocal MODELS_AHEAD = 5\n\n\tPath.LastAdded = {}\n\tPath.pathModels = {}\n\n\tPath.Branches = {}\n\n\tPath.multipleBranches = false\n\tPath.BranchAt = nil\n\tPath.LastBranch = nil\n\n\tPath.AvailableModules = {}\n\n\tPath.CharacterHandler = require(script.CharacterHandler)()\n\n\t--Set up AvailableModules so all modules can be accessed easily\n\tfor _, pathCategory in pairs(game.ReplicatedStorage.PathModules:GetChildren()) do\n\t\tfor _, pathModule in pairs(pathCategory:GetChildren()) do\n\t\t\ttable.insert(Path.AvailableModules, pathModule)\n\t\tend\n\tend\n\n\t--Takes the given Vector3 value away from the position value of every part in a given model\n\tlocal function moveOffset(model, vector)\n\t\tif model:isA(\"Model\") or model:isA(\"Folder\") then\n\t\t\tfor _, object in pairs(model:GetChildren()) do\n\t\t\t\tmoveOffset(object, vector)\n\t\t\tend\n\t\telseif model:isA(\"BasePart\") then\n\t\t\tmodel.Position = model.Position - vector\n\t\tend\n\tend\n\n\t--Adds a new branch to the path, adds multiple path models at all the possible EndParts of the model\n\tfunction Path:AddNewBranch(lastPathModel, playerName, pathType)\n\t\tPath.Branches = {}\n\t\tlocal endParts = lastPathModel:FindFirstChild(\"EndParts\")\n\t\tendParts = endParts:GetChildren()\n\t\tif #endParts == 2 then\n\t\t\t--Special case for 2 endParts, 1 endPart should go up and the other should go down\n\t\t\t--even if one end part continues at the same height as the Start part of the model\n\t\t\tlocal top = nil\n\t\t\tlocal bottom = nil\n\t\t\tif endParts[1].Position.Y > endParts[2].Position.Y then\n\t\t\t\ttop = endParts[1]\n\t\t\t\tbottom = endParts[2]\n\t\t\telse\n\t\t\t\ttop = endParts[2]\n\t\t\t\tbottom = endParts[1]\n\t\t\tend\n\t\t\ttop.Parent = lastPathModel\n\t\t\tlocal newBranch = self:addNewPathModel(lastPathModel, playerName, \"GoingUp\")\n\t\t\tnewBranch.CurrentBranchValue.Value = newBranch.CurrentBranchValue.Value + 1\n\t\t\tPath.Branches[newBranch.CurrentBranchValue.Value] = top.Position\n\t\t\ttop.Parent = lastPathModel.EndParts\n\t\t\tbottom.Parent = lastPathModel\n\t\t\tlocal newBranch = self:addNewPathModel(lastPathModel, playerName, \"GoingDown\")\n\t\t\tnewBranch.CurrentBranchValue.Value = newBranch.CurrentBranchValue.Value + 2\n\t\t\tPath.Branches[newBranch.CurrentBranchValue.Value] = bottom.Position\n\t\telse\n\t\t\t--Continues the path up, down or straight depending on where the End part is relative to the middle endPart of the branch\n\t\t\ttable.sort(endParts,function(a, b) return a.Position.Y < b.Position.Y end)\n\t\t\tfor i = 1, #endParts do\n\t\t\t\tendParts[i].Parent = lastPathModel\n\t\t\t\tif endParts[i].Position.Y > endParts[math.floor((#endParts + 1)/2)].Position.Y then\n\t\t\t\t\tlocal newBranch = self:addNewPathModel(lastPathModel, playerName, \"GoingUp\")\n\t\t\t\t\tnewBranch.CurrentBranchValue.Value = newBranch.CurrentBranchValue.Value + i\n\t\t\t\t\tPath.Branches[newBranch.CurrentBranchValue.Value] = endParts[i].Position\n\t\t\t\telseif endParts[i].Position.Y < endParts[math.floor((#endParts + 1)/2)].Position.Y then\n\t\t\t\t\tlocal newBranch = self:addNewPathModel(lastPathModel, playerName, \"GoingDown\")\n\t\t\t\t\tnewBranch.CurrentBranchValue.Value = newBranch.CurrentBranchValue.Value + i\n\t\t\t\t\tPath.Branches[newBranch.CurrentBranchValue.Value] = endParts[i].Position\n\t\t\t\telse\n\t\t\t\t\tlocal newBranch = self:addNewPathModel(lastPathModel, playerName, \"SameHeight\")\n\t\t\t\t\tnewBranch.CurrentBranchValue.Value = newBranch.CurrentBranchValue.Value + i\n\t\t\t\t\tPath.Branches[newBranch.CurrentBranchValue.Value] = endParts[i].Position\n\t\t\t\tend\n\t\t\t\tif i ~= #endParts then\n\t\t\t\t\tendParts[i].Parent = lastPathModel.EndParts\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\tend\n\n\t--Adds a new model to the part, pathType is the folder in ReplicatedStorage.PathModules\n\t--from which to select a random path model. pathType \"random\" selects from all the available path models\n\tfunction Path:addNewPathModel(lastPathModel, playerName, pathType)\n\t\tif lastPathModel:FindFirstChild(\"End\") then\n\t\t\tlocal pathModelToAdd = nil\n\t\t\tif pathType == \"random\" then\n\t\t\t\t--if there are currently multiple branches we continue each branch at the height it's at until it can be closed\n\t\t\t\tif Path.multipleBranches == false then\n\t\t\t\t\tpathModelToAdd = Path.AvailableModules[math.random(1, #Path.AvailableModules)]:Clone()\n\t\t\t\telse\n\t\t\t\t\tlocal pathModelsSameHeight = game.ReplicatedStorage.PathModules.SameHeight:GetChildren()\n\t\t\t\t\tpathModelToAdd = pathModelsSameHeight[math.random(1, #pathModelsSameHeight)]:Clone()\n\t\t\t\tend\n\t\t\telse\n\t\t\t\tlocal availModules = game.ReplicatedStorage.PathModules[pathType]:GetChildren()\n\t\t\t\tpathModelToAdd = availModules[math.random(1, #availModules)]:Clone()\n\t\t\tend\n\t\t\tlocal positionDifference = pathModelToAdd.Start.Position - lastPathModel.End.Position + Vector3.new(0, 0, (pathModelToAdd.Start.Size.Z + lastPathModel.End.Size.Z)/2)\n\t\t\tlocal addedPath = pathModelToAdd:Clone()\n\t\t\tmoveOffset(addedPath, positionDifference)\n\t\t\t--The CurrentBranchValue IntValue is used for closing branches of the path once the player passes the decision point\n\t\t\tlastPathModel.CurrentBranchValue:Clone().Parent = addedPath\n\t\t\taddedPath.Parent = game.Workspace.Tracks[playerName]\n\t\t\ttable.insert(Path.pathModels, addedPath)\n\t\t\ttable.insert(Path.LastAdded, addedPath)\n\t\t\tif addedPath:FindFirstChild(\"EndParts\") then\n\t\t\t\tPath.multipleBranches = true\n\t\t\t\tPath.BranchAt = addedPath.EndParts:FindFirstChild(\"End\").Position.Z\n\t\t\tend\n\t\t\treturn addedPath\n\t\telse\n\t\t\tself:AddNewBranch(lastPathModel, playerName, pathType)\n\t\tend\n\tend\n\n\tlocal function removeFromTable(item, theTable)\n\t\tfor i = 1, #theTable do\n\t\t\tif theTable[i] == item then\n\t\t\t\ttable.remove(theTable, i)\n\t\t\t\tbreak\n\t\t\tend\n\t\tend\n\tend\n\n\t-- Checks if the player has made a decision on the currently open branch\n\t-- closes the branch if the player has already made a decision\n\tfunction Path:tryCloseBranches(playerName)\n\t\tlocal player = game.Players:FindFirstChild(playerName)\n\t\tif player.Character.HumanoidRootPart.Position.Z < Path.BranchAt then\n\t\t\tPath.multipleBranches = false\n\t\t\tPath.LastBranch = Path.BranchAt\n\t\t\tlocal closest = nil\n\t\t\tlocal closestValue = nil\n\t\t\t-- Check which branch the player selected based on the distance of the character from the End part of the branch\n\t\t\tfor i, v in pairs(Path.Branches) do\n\t\t\t\tif closest == nil then\n\t\t\t\t\tclosest = i\n\t\t\t\t\tclosestValue = (player.Character.HumanoidRootPart.Position - v).magnitude\n\t\t\t\telse\n\t\t\t\t\tif (player.Character.HumanoidRootPart.Position - v).magnitude < closestValue then\n\t\t\t\t\t\tclosest = i\n\t\t\t\t\t\tclosestValue = (player.Character.HumanoidRootPart.Position - v).magnitude\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\tend\n\t\t\t-- Remove all path models that have a different CurrentBranchValue than the path the player selected\n\t\t\tfor _, pathModel in pairs(game.Workspace.Tracks[player.Name]:GetChildren()) do\n\t\t\t\tif pathModel:isA(\"Model\") then\n\t\t\t\t\tif pathModel:FindFirstChild(\"CurrentBranchValue\") then\n\t\t\t\t\t\tif pathModel.CurrentBranchValue.Value ~= closest then\n\t\t\t\t\t\t\tgame:GetService(\"Debris\"):AddItem(pathModel, 3)\n\t\t\t\t\t\t\tremoveFromTable(pathModel, Path.pathModels)\n\t\t\t\t\t\t\tremoveFromTable(pathModel, Path.LastAdded)\n\t\t\t\t\t\tend\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\tend\n\n\t-- Check if the path needs to be extended based on the position of the player\n\tfunction Path:CheckExtendPath(playerName)\n\t\tlocal player = game.Players:FindFirstChild(playerName)\n\t\tif Path.LastAdded[1] then\n\t\t\tif player.Character.HumanoidRootPart.Position.Z < Path.LastAdded[1].Start.Position.Z + Path.LastAdded[1].PathBase.Size.Z*2 then\n\t\t\t\tself:addNewPathModel(Path.LastAdded[1], playerName, \"random\")\n\t\t\t\ttable.remove(Path.LastAdded, 1)\n\t\t\tend\n\t\telse\n\t\t\ttable.remove(Path.LastAdded, 1)\n\t\tend\n\tend\n\n\t-- Check if a path model is far enough of screen to be removed\n\tfunction Path:CheckRemovePart(playerName)\n\t\tlocal player = game.Players:FindFirstChild(playerName)\n\t\tif player.Character.HumanoidRootPart.Position.Z < Path.pathModels[1].End.Position.Z - Path.pathModels[1].PathBase.Size.Z*3 then\n\t\t\tPath.pathModels[1]:Destroy()\n\t\t\ttable.remove(Path.pathModels, 1)\n\t\tend\n\tend\n\n\t-- Extends the path as the player moves\n\tfunction Path:AddPathAsPlayerMoves(playerName)\n\t\tlocal player = game.Players:FindFirstChild(playerName)\n\t\tif player then\n\t\t\tif not player.Character then\n\t\t\t\tplayer.CharacterAdded:wait()\n\t\t\tend\n\n\t\t\tlocal extendPathConnection = game:GetService(\"RunService\").Heartbeat:connect(function()\n\t\t\t\tif player.Character:FindFirstChild(\"HumanoidRootPart\") then\n\t\t\t\t\tif Path.multipleBranches == true then\n\t\t\t\t\t\tself:tryCloseBranches(playerName)\n\t\t\t\t\tend\n\t\t\t\t\tself:CheckExtendPath(playerName)\n\t\t\t\t\tself:CheckRemovePart(playerName)\n\t\t\t\tend\n\t\t\tend)\n\n\t\t\tplayer.CharacterRemoving:connect(function() extendPathConnection:disconnect() end)\n\t\t\tplayer.Character.Humanoid.Died:connect(function() extendPathConnection:disconnect() end)\n\t\tend\n\tend\n\n\t-- Creates the initial path model for the path\n\tfunction Path:AddFirstPathModel(trackModel)\n\t\tlocal pathToAdd = nil\n\t\tif game.ReplicatedStorage.PathModules:FindFirstChild(\"StartModule\") ~= nil then\n\t\t\tpathToAdd = game.ReplicatedStorage.PathModules.StartModule:FindFirstChild(\"Start\")\n\t\telse\n\t\t\tpathToAdd = Path.AvailableModules[math.random(1, #Path.AvailableModules)]\n\t\tend\n\t\tpathToAdd = pathToAdd:Clone()\n\t\tpathToAdd.Parent = trackModel\n\t\tpathToAdd:MoveTo(trackModel.Location.Value)\n\n\t\tlocal branchModifier = Instance.new(\"IntValue\")\n\t\tbranchModifier.Name = \"CurrentBranchValue\"\n\t\tbranchModifier.Value = 0\n\t\tbranchModifier.Parent = pathToAdd\n\n\t\ttable.insert(Path.pathModels, pathToAdd)\n\t\ttable.insert(Path.LastAdded, pathToAdd)\n\t\treturn pathToAdd\n\tend\n\n\t-- Finds an open slot for the track, for possible multiplayer\n\tlocal function findOpenSlot()\n\t\tlocal takenLocations = {}\n\t\tlocal defaultLocation = Vector3.new(0, 100, 0)\n\t\tfor _, track in pairs(game.Workspace.Tracks:GetChildren()) do\n\t\t\ttable.insert(takenLocations, track.Location.Value)\n\t\tend\n\t\ttable.sort(takenLocations, function(a, b) return (a.X < b.X) end)\n\t\tfor i = 1, #takenLocations do\n\t\t\tif (takenLocations[i].X > defaultLocation.X) then\n\t\t\t\tbreak\n\t\t\telse\n\t\t\t\tdefaultLocation = Vector3.new(defaultLocation.X + 50, 100, 0)\n\t\t\tend\n\t\tend\n\t\treturn defaultLocation\n\tend\n\n\tfunction Path:init(playerName)\n\t\tlocal previousTrack = game.Workspace.Tracks:FindFirstChild(playerName)\n\t\tif (previousTrack) then\n\t\t\tpreviousTrack:Destroy()\n\t\tend\n\n\t\tlocal trackModel = Instance.new(\"Model\")\n\t\ttrackModel.Name = playerName\n\t\tlocal location = Instance.new(\"Vector3Value\")\n\t\tlocation.Name = \"Location\"\n\t\tlocation.Value = findOpenSlot()\n\t\tlocation.Parent = trackModel\n\t\ttrackModel.Parent = game.Workspace.Tracks\n\n\t\tlocal firstAddedPath = self:AddFirstPathModel(trackModel)\n\n\t\tfor i = 1, MODELS_AHEAD do\n\t\t\tself:addNewPathModel(Path.LastAdded[1], playerName, \"random\")\n\t\t\ttable.remove(Path.LastAdded, 1)\n\t\tend\n\n\t\twait()\n\t\tPath.CharacterHandler:init(firstAddedPath, playerName)\n\t\tself:AddPathAsPlayerMoves(playerName)\n\tend\n\n\treturn Path\nend\n\nreturn makePathObject\n\t" } @@ -121,7 +121,7 @@ "contents": { "Vfs": { "files": { - "GUITweenIn.client.lua": { + "GUITweenIn.client.luau": { "contents": { "Bytes": "local onScreenPosition = UDim2.new(0.5, -375, 0, 36)\nlocal offScreenPosition = UDim2.new(0.5, -375, 0, -140)\n\nscript.Parent.Frame:TweenPosition(onScreenPosition, \"Out\", \"Quad\", 1, true)\nwait(1.5)\nscript.Parent.Frame:TweenPosition(offScreenPosition, \"Out\", \"Quad\", 1, true)\nwait(1)\n\nscript.Parent:Destroy()\n" } @@ -140,7 +140,7 @@ "contents": { "Vfs": { "files": { - "GUITweenIn.client.lua": { + "GUITweenIn.client.luau": { "contents": { "Bytes": "local onScreenPosition = UDim2.new(0.5, -375, 0, 36)\nlocal offScreenPosition = UDim2.new(0.5, -375, 0, -140)\n\nscript.Parent.Frame:TweenPosition(onScreenPosition, \"Out\", \"Quad\", 1, true)\nwait(1.5)\nscript.Parent.Frame:TweenPosition(offScreenPosition, \"Out\", \"Quad\", 1.5, true)\nwait(1.5)\n\nscript.Parent:Destroy()\n" } @@ -159,17 +159,17 @@ "contents": { "Vfs": { "files": { - "CoinMagnet.server.lua": { + "CoinMagnet.server.luau": { "contents": { "Bytes": "local character = script.Parent\nlocal player = game.Players:GetPlayerFromCharacter(character)\nscript.Parent:WaitForChild(\"HumanoidRootPart\")\nlocal torso = script.Parent.HumanoidRootPart\n\ngame:GetService(\"RunService\").Heartbeat:connect(function()\n\tlocal playersTrack = game.Workspace.Tracks:FindFirstChild(player.Name)\n\tif playersTrack then\n\t\tif playersTrack:FindFirstChild(\"Coins\") then\n\t\t\tlocal coins = playersTrack.Coins:GetChildren()\n\t\t\tfor i = 1, #coins do\n\t\t\t\tif (coins[i].Coin.Position - torso.Position).magnitude < 50 then\n\t\t\t\t\tcoins[i].Coin.BodyPosition.maxForce = Vector3.new(500000000, 500000000, 500000000)\n\t\t\t\t\tif torso.Position.Z > coins[i].Coin.Position.Z then\n\t\t\t\t\t\tcoins[i].Coin.BodyPosition.position = torso.Position\n\t\t\t\t\t\tcoins[i].Coin.BodyPosition.P = 1500\n\t\t\t\t\telse\n\t\t\t\t\t\t--Needs to anticipate where the player is going\n\t\t\t\t\t\tcoins[i].Coin.BodyPosition.position = Vector3.new(torso.Position.X, torso.Position.Y, torso.Position.Z - 10)\n\t\t\t\t\t\tcoins[i].Coin.BodyPosition.P = 2500\n\t\t\t\t\tend\n\t\t\t\t\tcoins[i].CoinBoundingBox.Position = coins[i].Coin.Position\n\t\t\t\t\tif (coins[i].Coin.Position - torso.Position).magnitude < 5 then\n\t\t\t\t\t\tcoins[i].CoinBoundingBox.Position = Vector3.new(torso.Position.X, torso.Position.Y, torso.Position.Z - 3)\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\tend\nend)\n\n\n" } }, - "CoinScript.server.lua": { + "CoinScript.server.luau": { "contents": { "Bytes": "local coin = script.Parent\nlocal coinModel = coin.Parent\nlocal trackModel = coinModel.Parent\nlocal tracksModel = trackModel.Parent\n\ncoin.BodyPosition.position = script.Parent.Position\ncoin.BodyGyro.cframe = CFrame.new(\n\t0, 0, 0,\n\t0, -1, 0,\n\t0, 0, 0,\n\t0, 0, 0\n)\ncoin.RotVelocity = Vector3.new(0, 5, 0)\n\nif coinModel.Parent ~= game.Workspace then\n\tif game.Workspace:FindFirstChild(\"Tracks\") then\n\t\tif tracksModel:FindFirstChild(\"Coins\") == nil then\n\t\t\tlocal coinsModel = Instance.new(\"Model\")\n\t\t\tcoinsModel.Name = \"Coins\"\n\t\t\tcoinsModel.Parent = tracksModel\n\t\tend\n\n\t\ttracksModel.ChildRemoved:connect(function(child) if child == trackModel then coinModel:Destroy() end end)\n\t\tcoinModel.Parent = tracksModel:FindFirstChild(\"Coins\")\n\tend\nend\n\nwait(1)\ncoin.RotVelocity = Vector3.new(0, 5, 0)\n" } }, - "FastStartScript.server.lua": { + "FastStartScript.server.luau": { "contents": { "Bytes": "local character = script.Parent\nlocal humanoid = character.Humanoid\nlocal spawnLocation = character.HumanoidRootPart.Position\nlocal player = game.Players:GetPlayerFromCharacter(character)\n\nlocal started = false\n\n--Casts a ray to find the height for the character to hover at even if the path is going up or down\nfunction findHeight(distanceInFront)\n\tlocal torso = character.HumanoidRootPart\n\tlocal ray = Ray.new(\n Vector3.new(torso.Position.X, torso.Position.Y + 50, torso.Position.Z - distanceInFront), \t-- origin\n (Vector3.new(0, -1, 0)).unit * 300)\t \t\t\t\t\t\t\t\t\t\t\t\t\t\t-- direction\n\tlocal ignore = character\n\tlocal hit, position = game.Workspace:FindPartOnRay(ray, ignore)\n\treturn position.Y + 40\nend\n\nfunction highest(tableOfValues)\n\tlocal highestSoFar = tableOfValues[1]\n\tfor i = 2, #tableOfValues do\n\t\tif tableOfValues[i] > highestSoFar then\n\t\t\thighestSoFar = tableOfValues[i]\n\t\tend\n\tend\n\treturn highestSoFar\nend\n\nfunction fastStart()\n\tif started == false then\n\t\tstarted = true\n\t\tlocal fastStartPosition = Instance.new(\"BodyPosition\")\n\t\tfastStartPosition.Name = \"FastStart\"\n\t\tfastStartPosition.maxForce = Vector3.new(0, 15000, 0)\n\t\tfastStartPosition.Parent = character.HumanoidRootPart\n\t\tlocal fastStartVelocity = Instance.new(\"BodyVelocity\")\n\t\tfastStartVelocity.maxForce = Vector3.new(0, 0, 15000)\n\t\tfastStartVelocity.velocity = Vector3.new(0, 0, -150)\n\t\tfastStartVelocity.Parent = character.HumanoidRootPart\n\t\tfastStartPosition.position = Vector3.new(0, highest({findHeight(0), findHeight(10), findHeight(20), findHeight(30)}), 0)\n\t\twhile character.HumanoidRootPart.Position.Z > spawnLocation.Z - 1000 do\n\t\t\twait(1)\n\t\t\tif character:FindFirstChild(\"HumanoidRootPart\") == nil then\n\t\t\t\tbreak\n\t\t\tend\n\t\t\tfastStartPosition.position = Vector3.new(0, highest({findHeight(0), findHeight(10), findHeight(20), findHeight(30)}), 0)\n\t\tend\n\t\tfastStartVelocity.velocity = Vector3.new(0, 0, 0)\n\t\twait(2)\n\t\tif character:FindFirstChild(\"HumanoidRootPart\") then\n\t\t\tfastStartPosition:Destroy()\n\t\t\tfastStartVelocity:Destroy()\n\t\t\tlocal shield = Instance.new(\"ForceField\")\n\t\t\tshield.Name = \"Shield\"\n\t\t\tshield.Parent = character\n\t\t\tgame:GetService(\"Debris\"):AddItem(shield, 3)\n\t\tend\n\t\tfastStart:Destroy()\n\t\tscript:Destroy()\n\tend\nend\n\nfastStart() --Script starts disabled, only enabled when a player starts running\n\n\n" } @@ -196,12 +196,12 @@ "contents": { "Vfs": { "files": { - "CameraScript.client.lua": { + "CameraScript.client.luau": { "contents": { "Bytes": "local camera = game.Workspace.CurrentCamera\nlocal player = game.Players.LocalPlayer\n\ncamera.CameraType = Enum.CameraType.Scriptable\n\nlocal targetDistance = 30\nlocal cameraDistance = -30\nlocal cameraDirection = Vector3.new(-1,0,0)\n\nlocal currentTarget = cameraDirection*targetDistance\nlocal currentPosition = cameraDirection*cameraDistance\n\ngame:GetService(\"RunService\").RenderStepped:connect(function()\n\tlocal character = player.Character\n\tif character and character:FindFirstChild(\"Humanoid\") and character:FindFirstChild(\"HumanoidRootPart\") then\n\t\tlocal torso = character.HumanoidRootPart\n\t\tcamera.Focus = torso.CFrame\n\t\tif torso:FindFirstChild(\"FastStart\") == nil then\n\t\t\tcamera.CoordinateFrame = \tCFrame.new(Vector3.new(torso.Position.X, torso.Position.Y + 10, torso.Position.Z - 20) + currentPosition,\n\t\t\t\t\t\t\t\t\t\tVector3.new(torso.Position.X, torso.Position.Y, torso.Position.Z - 20) + currentTarget)\n\t\telse\n\t\t\t--Lower camera for fast start\n\t\t\tcamera.CoordinateFrame = CFrame.new(Vector3.new(torso.Position.X, torso.Position.Y - 15, torso.Position.Z - 20) + currentPosition,\n\t\t\t\t\t\t\t\t\t\t\t Vector3.new(torso.Position.X, torso.Position.Y - 15, torso.Position.Z - 20) + currentTarget)\n\t\tend\n\tend\nend)\n" } }, - "ControlScript.client.lua": { + "ControlScript.client.luau": { "contents": { "Bytes": "local player = game.Players.LocalPlayer\nlocal UserInputService = game:GetService(\"UserInputService\")\nlocal ContextActionService = game:GetService(\"ContextActionService\")\n\nlocal doJump = false\nlocal reviving = false\nlocal characterWalkSpeed = 40\n\ngame.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Chat, false)\ngame.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Health, false)\ngame.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)\n\nplayer:WaitForChild(\"PlayerGui\")\n\nlocal function jump()\n\tif player.Character ~= nil then\n\t\tif player.Character.Humanoid.WalkSpeed == 0 then\n\t\t\t-- Character is not yet moving, start screen was shown\n\t\t\tdoJump = false\n\t\t\tif player.PlayerGui.StartScreen.StartInstructions.Visible == true then\n\t\t\t\tplayer.PlayerGui.StartScreen:Destroy()\n\t\t\t\tplayer.Character.Humanoid.WalkSpeed = characterWalkSpeed\n\t\t\t\tgame.ReplicatedStorage.RemoteEvents.RunStarting:FireServer()\n\t\t\tend\n\t\telse\n\t\t\tplayer.Character.Humanoid.Jump = true\n\t\tend\n\tend\nend\n\n-- Handles behaviours\nlocal function characterTouchedBrick(partTouched)\n\tlocal behaviours = partTouched:FindFirstChild(\"Behaviours\")\n\tif behaviours ~= nil then\n\t\tbehaviours = behaviours:GetChildren()\n\t\tfor i = 1, #behaviours do\n\t\t\tif behaviours[i].Value == true then\n\t\t\t\tgame.ReplicatedStorage.RemoteEvents.ExecuteBehaviour:FireServer(player.Character, partTouched, behaviours[i].Name)\n\t\t\tend\n\t\tend\n\tend\nend\n\nfunction characterAdded(newCharacter)\n\tlocal humanoid = newCharacter:WaitForChild(\"Humanoid\")\n\thumanoid.WalkSpeed = 0\n\thumanoid.Touched:connect(characterTouchedBrick)\n\n\tlocal splashScreen = player.PlayerGui:WaitForChild(\"StartScreen\")\n\n\tif UserInputService.TouchEnabled == false then\n\t\tif UserInputService.GamepadEnabled then\n\t\t\tsplashScreen.StartInstructions.StartLabel.Text = \"Press Space or Gamepad A Button to Start\"\n\t\telse\n\t\t\tsplashScreen.StartInstructions.StartLabel.Text = \"Press Space to Start\"\n\t\tend\n\n\tend\n\tif reviving == true then\n\t\treviving = false\n\t\tsplashScreen:Destroy()\n\t\thumanoid.WalkSpeed = characterWalkSpeed\n\tend\n\n\thumanoid.WalkSpeed = 0\nend\nplayer.CharacterAdded:connect(characterAdded)\n\nif player.Character then\n\tcharacterAdded(player.Character)\nend\n\nfunction checkReviving(addedGui)\n\tif addedGui.Name == \"RevivingGUI\" then\n\t\treviving = true\n\tend\nend\nplayer.PlayerGui.ChildAdded:connect(checkReviving)\n\nif UserInputService.TouchEnabled then\n\tUserInputService.ModalEnabled = true\n\tUserInputService.TouchStarted:connect(function(inputObject, gameProcessedEvent) if gameProcessedEvent == false then doJump = true end end)\n\tUserInputService.TouchEnded:connect(function() doJump = false end)\nelse\n\tContextActionService:BindAction(\"Jump\", function(action, userInputState, inputObject) doJump = (userInputState == Enum.UserInputState.Begin) end, false, Enum.KeyCode.Space, Enum.KeyCode.ButtonA)\nend\n\ngame:GetService(\"RunService\").RenderStepped:connect(function()\n\tif player.Character ~= nil then\n\t\tif player.Character:FindFirstChild(\"Humanoid\") then\n\t\t\tif doJump == true then\n\t\t\t\tjump()\n\t\t\tend\n\t\t\tplayer.Character.Humanoid:Move(Vector3.new(0,0,-1), false)\n\t\tend\n\tend\nend)\n" } @@ -265,7 +265,7 @@ "contents": { "Vfs": { "files": { - "GetCoinScript.server.lua": { + "GetCoinScript.server.luau": { "contents": { "Bytes": "local newScript = game.ServerStorage.Scripts.CoinScript:Clone()\nnewScript.Parent = script.Parent\nnewScript.Disabled = false\n\nscript:Destroy()\n" } @@ -326,7 +326,7 @@ "contents": { "Vfs": { "files": { - "GetCoinScript.server.lua": { + "GetCoinScript.server.luau": { "contents": { "Bytes": "local newScript = game.ServerStorage.Scripts.CoinScript:Clone()\nnewScript.Parent = script.Parent\nnewScript.Disabled = false\n\nscript:Destroy()\n" } @@ -387,7 +387,7 @@ "contents": { "Vfs": { "files": { - "GetCoinScript.server.lua": { + "GetCoinScript.server.luau": { "contents": { "Bytes": "local newScript = game.ServerStorage.Scripts.CoinScript:Clone()\nnewScript.Parent = script.Parent\nnewScript.Disabled = false\n\nscript:Destroy()\n" } @@ -448,7 +448,7 @@ "contents": { "Vfs": { "files": { - "GetCoinScript.server.lua": { + "GetCoinScript.server.luau": { "contents": { "Bytes": "local newScript = game.ServerStorage.Scripts.CoinScript:Clone()\nnewScript.Parent = script.Parent\nnewScript.Disabled = false\n\nscript:Destroy()\n" } @@ -509,7 +509,7 @@ "contents": { "Vfs": { "files": { - "GetCoinScript.server.lua": { + "GetCoinScript.server.luau": { "contents": { "Bytes": "local newScript = game.ServerStorage.Scripts.CoinScript:Clone()\nnewScript.Parent = script.Parent\nnewScript.Disabled = false\n\nscript:Destroy()\n" } @@ -570,7 +570,7 @@ "contents": { "Vfs": { "files": { - "GetCoinScript.server.lua": { + "GetCoinScript.server.luau": { "contents": { "Bytes": "local newScript = game.ServerStorage.Scripts.CoinScript:Clone()\nnewScript.Parent = script.Parent\nnewScript.Disabled = false\n\nscript:Destroy()\n" } @@ -622,12 +622,12 @@ "Bytes": "{\n \"ignoreUnknownInstances\": true\n}" } }, - "Animate.server.lua": { + "Animate.server.luau": { "contents": { "Bytes": "function waitForChild(parent, childName)\n\tlocal child = parent:findFirstChild(childName)\n\tif child then return child end\n\twhile true do\n\t\tchild = parent.ChildAdded:wait()\n\t\tif child.Name==childName then return child end\n\tend\nend\n\nlocal Figure = script.Parent\nlocal Torso = waitForChild(Figure, \"Torso\")\nlocal RightShoulder = waitForChild(Torso, \"Right Shoulder\")\nlocal LeftShoulder = waitForChild(Torso, \"Left Shoulder\")\nlocal RightHip = waitForChild(Torso, \"Right Hip\")\nlocal LeftHip = waitForChild(Torso, \"Left Hip\")\nlocal Neck = waitForChild(Torso, \"Neck\")\nlocal Humanoid = waitForChild(Figure, \"Humanoid\")\nlocal pose = \"Standing\"\n\nlocal currentAnim = \"\"\nlocal currentAnimTrack = nil\nlocal currentAnimKeyframeHandler = nil\nlocal currentAnimSpeed = 1.0\nlocal animTable = {}\nlocal animNames = {\n\tidle = \t{\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=125750544\", weight = 9 },\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=125750618\", weight = 1 }\n\t\t\t},\n\twalk = \t{\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=125749145\", weight = 10 }\n\t\t\t},\n\trun = \t{\n\t\t\t\t{ id = \"run.xml\", weight = 10 }\n\t\t\t},\n\tjump = \t{\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=125750702\", weight = 10 }\n\t\t\t},\n\tfall = \t{\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=125750759\", weight = 10 }\n\t\t\t},\n\tclimb = {\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=125750800\", weight = 10 }\n\t\t\t},\n\ttoolnone = {\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=125750867\", weight = 10 }\n\t\t\t},\n\ttoolslash = {\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=129967390\", weight = 10 }\n--\t\t\t\t{ id = \"slash.xml\", weight = 10 }\n\t\t\t},\n\ttoollunge = {\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=129967478\", weight = 10 }\n\t\t\t},\n\twave = {\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=128777973\", weight = 10 }\n\t\t\t},\n\tpoint = {\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=128853357\", weight = 10 }\n\t\t\t},\n\tdance = {\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=130018893\", weight = 10 },\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=132546839\", weight = 10 },\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=132546884\", weight = 10 }\n\t\t\t},\n\tdance2 = {\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=160934142\", weight = 10 },\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=160934298\", weight = 10 },\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=160934376\", weight = 10 }\n\t\t\t},\n\tdance3 = {\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=160934458\", weight = 10 },\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=160934530\", weight = 10 },\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=160934593\", weight = 10 }\n\t\t\t},\n\tlaugh = {\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=129423131\", weight = 10 }\n\t\t\t},\n\tcheer = {\n\t\t\t\t{ id = \"http://www.roblox.com/asset/?id=129423030\", weight = 10 }\n\t\t\t},\n}\n\n-- Existance in this list signifies that it is an emote, the value indicates if it is a looping emote\nlocal emoteNames = { wave = false, point = false, dance = true, dance2 = true, dance3 = true, laugh = false, cheer = false}\n\nmath.randomseed(tick())\n\nfunction configureAnimationSet(name, fileList)\n\tif (animTable[name] ~= nil) then\n\t\tfor _, connection in pairs(animTable[name].connections) do\n\t\t\tconnection:disconnect()\n\t\tend\n\tend\n\tanimTable[name] = {}\n\tanimTable[name].count = 0\n\tanimTable[name].totalWeight = 0\n\tanimTable[name].connections = {}\n\n\t-- check for config values\n\tlocal config = script:FindFirstChild(name)\n\tif (config ~= nil) then\n--\t\tprint(\"Loading anims \" .. name)\n\t\ttable.insert(animTable[name].connections, config.ChildAdded:connect(function(child) configureAnimationSet(name, fileList) end))\n\t\ttable.insert(animTable[name].connections, config.ChildRemoved:connect(function(child) configureAnimationSet(name, fileList) end))\n\t\tlocal idx = 1\n\t\tfor _, childPart in pairs(config:GetChildren()) do\n\t\t\tif (childPart:IsA(\"Animation\")) then\n\t\t\t\ttable.insert(animTable[name].connections, childPart.Changed:connect(function(property) configureAnimationSet(name, fileList) end))\n\t\t\t\tanimTable[name][idx] = {}\n\t\t\t\tanimTable[name][idx].anim = childPart\n\t\t\t\tlocal weightObject = childPart:FindFirstChild(\"Weight\")\n\t\t\t\tif (weightObject == nil) then\n\t\t\t\t\tanimTable[name][idx].weight = 1\n\t\t\t\telse\n\t\t\t\t\tanimTable[name][idx].weight = weightObject.Value\n\t\t\t\tend\n\t\t\t\tanimTable[name].count = animTable[name].count + 1\n\t\t\t\tanimTable[name].totalWeight = animTable[name].totalWeight + animTable[name][idx].weight\n\t--\t\t\tprint(name .. \" [\" .. idx .. \"] \" .. animTable[name][idx].anim.AnimationId .. \" (\" .. animTable[name][idx].weight .. \")\")\n\t\t\t\tidx = idx + 1\n\t\t\tend\n\t\tend\n\tend\n\n\t-- fallback to defaults\n\tif (animTable[name].count <= 0) then\n\t\tfor idx, anim in pairs(fileList) do\n\t\t\tanimTable[name][idx] = {}\n\t\t\tanimTable[name][idx].anim = Instance.new(\"Animation\")\n\t\t\tanimTable[name][idx].anim.Name = name\n\t\t\tanimTable[name][idx].anim.AnimationId = anim.id\n\t\t\tanimTable[name][idx].weight = anim.weight\n\t\t\tanimTable[name].count = animTable[name].count + 1\n\t\t\tanimTable[name].totalWeight = animTable[name].totalWeight + anim.weight\n--\t\t\tprint(name .. \" [\" .. idx .. \"] \" .. anim.id .. \" (\" .. anim.weight .. \")\")\n\t\tend\n\tend\nend\n\n-- Setup animation objects\nfunction scriptChildModified(child)\n\tlocal fileList = animNames[child.Name]\n\tif (fileList ~= nil) then\n\t\tconfigureAnimationSet(child.Name, fileList)\n\tend\nend\n\nscript.ChildAdded:connect(scriptChildModified)\nscript.ChildRemoved:connect(scriptChildModified)\n\n\nfor name, fileList in pairs(animNames) do\n\tconfigureAnimationSet(name, fileList)\nend\n\n-- ANIMATION\n\n-- declarations\nlocal toolAnim = \"None\"\nlocal toolAnimTime = 0\n\nlocal jumpAnimTime = 0\nlocal jumpAnimDuration = 0.3\n\nlocal toolTransitionTime = 0.1\nlocal fallTransitionTime = 0.3\nlocal jumpMaxLimbVelocity = 0.75\n\n-- functions\n\nfunction stopAllAnimations()\n\tlocal oldAnim = currentAnim\n\n\t-- return to idle if finishing an emote\n\tif (emoteNames[oldAnim] ~= nil and emoteNames[oldAnim] == false) then\n\t\toldAnim = \"idle\"\n\tend\n\n\tcurrentAnim = \"\"\n\tif (currentAnimKeyframeHandler ~= nil) then\n\t\tcurrentAnimKeyframeHandler:disconnect()\n\tend\n\n\tif (currentAnimTrack ~= nil) then\n\t\tcurrentAnimTrack:Stop()\n\t\tcurrentAnimTrack:Destroy()\n\t\tcurrentAnimTrack = nil\n\tend\n\treturn oldAnim\nend\n\nfunction setAnimationSpeed(speed)\n\tif speed ~= currentAnimSpeed then\n\t\tcurrentAnimSpeed = speed\n\t\tcurrentAnimTrack:AdjustSpeed(currentAnimSpeed)\n\tend\nend\n\nfunction keyFrameReachedFunc(frameName)\n\tif (frameName == \"End\") then\n--\t\tprint(\"Keyframe : \".. frameName)\n\t\tlocal repeatAnim = stopAllAnimations()\n\t\tlocal animSpeed = currentAnimSpeed\n\t\tplayAnimation(repeatAnim, 0.0, Humanoid)\n\t\tsetAnimationSpeed(animSpeed)\n\tend\nend\n\n-- Preload animations\nfunction playAnimation(animName, transitionTime, humanoid)\n\tlocal idleFromEmote = (animName == \"idle\" and emoteNames[currentAnim] ~= nil)\n\tif (animName ~= currentAnim and not idleFromEmote) then\n\n\t\tif (currentAnimTrack ~= nil) then\n\t\t\tcurrentAnimTrack:Stop(transitionTime)\n\t\t\tcurrentAnimTrack:Destroy()\n\t\tend\n\n\t\tcurrentAnimSpeed = 1.0\n\t\tlocal roll = math.random(1, animTable[animName].totalWeight)\n\t\tlocal origRoll = roll\n\t\tlocal idx = 1\n\t\twhile (roll > animTable[animName][idx].weight) do\n\t\t\troll = roll - animTable[animName][idx].weight\n\t\t\tidx = idx + 1\n\t\tend\n--\t\tprint(animName .. \" \" .. idx .. \" [\" .. origRoll .. \"]\")\n\t\tlocal anim = animTable[animName][idx].anim\n\n\t\t-- load it to the humanoid; get AnimationTrack\n\t\tcurrentAnimTrack = humanoid:LoadAnimation(anim)\n\n\t\t-- play the animation\n\t\tcurrentAnimTrack:Play(transitionTime)\n\t\tcurrentAnim = animName\n\n\t\t-- set up keyframe name triggers\n\t\tif (currentAnimKeyframeHandler ~= nil) then\n\t\t\tcurrentAnimKeyframeHandler:disconnect()\n\t\tend\n\t\tcurrentAnimKeyframeHandler = currentAnimTrack.KeyframeReached:connect(keyFrameReachedFunc)\n\tend\nend\n\n-------------------------------------------------------------------------------------------\n-------------------------------------------------------------------------------------------\n\nlocal toolAnimName = \"\"\nlocal toolAnimTrack = nil\nlocal currentToolAnimKeyframeHandler = nil\n\nfunction toolKeyFrameReachedFunc(frameName)\n\tif (frameName == \"End\") then\n--\t\tprint(\"Keyframe : \".. frameName)\n\t\tlocal repeatAnim = stopToolAnimations()\n\t\tplayToolAnimation(repeatAnim, 0.0, Humanoid)\n\tend\nend\n\n\nfunction playToolAnimation(animName, transitionTime, humanoid)\n\tif (animName ~= toolAnimName) then\n\n\t\tif (toolAnimTrack ~= nil) then\n\t\t\ttoolAnimTrack:Stop()\n\t\t\ttoolAnimTrack:Destroy()\n\t\t\ttransitionTime = 0\n\t\tend\n\n\t\tlocal roll = math.random(1, animTable[animName].totalWeight)\n\t\tlocal origRoll = roll\n\t\tlocal idx = 1\n\t\twhile (roll > animTable[animName][idx].weight) do\n\t\t\troll = roll - animTable[animName][idx].weight\n\t\t\tidx = idx + 1\n\t\tend\n--\t\tprint(animName .. \" * \" .. idx .. \" [\" .. origRoll .. \"]\")\n\t\tlocal anim = animTable[animName][idx].anim\n\n\t\t-- load it to the humanoid; get AnimationTrack\n\t\ttoolAnimTrack = humanoid:LoadAnimation(anim)\n\n\t\t-- play the animation\n\t\ttoolAnimTrack:Play(transitionTime)\n\t\ttoolAnimName = animName\n\n\t\tcurrentToolAnimKeyframeHandler = toolAnimTrack.KeyframeReached:connect(toolKeyFrameReachedFunc)\n\tend\nend\n\nfunction stopToolAnimations()\n\tlocal oldAnim = toolAnimName\n\n\tif (currentToolAnimKeyframeHandler ~= nil) then\n\t\tcurrentToolAnimKeyframeHandler:disconnect()\n\tend\n\n\ttoolAnimName = \"\"\n\tif (toolAnimTrack ~= nil) then\n\t\ttoolAnimTrack:Stop()\n\t\ttoolAnimTrack:Destroy()\n\t\ttoolAnimTrack = nil\n\tend\n\n\n\treturn oldAnim\nend\n\n-------------------------------------------------------------------------------------------\n-------------------------------------------------------------------------------------------\n\n\nfunction onRunning(speed)\n\tif speed>0.01 then\n\t\tplayAnimation(\"walk\", 0.1, Humanoid)\n\t\tpose = \"Running\"\n\telse\n\t\tplayAnimation(\"idle\", 0.1, Humanoid)\n\t\tpose = \"Standing\"\n\tend\nend\n\nfunction onDied()\n\tpose = \"Dead\"\nend\n\nfunction onJumping()\n\tplayAnimation(\"jump\", 0.1, Humanoid)\n\tjumpAnimTime = jumpAnimDuration\n\tpose = \"Jumping\"\nend\n\nfunction onClimbing(speed)\n\tplayAnimation(\"climb\", 0.1, Humanoid)\n\tsetAnimationSpeed(speed / 12.0)\n\tpose = \"Climbing\"\nend\n\nfunction onGettingUp()\n\tpose = \"GettingUp\"\nend\n\nfunction onFreeFall()\n\tif (jumpAnimTime <= 0) then\n\t\tplayAnimation(\"fall\", fallTransitionTime, Humanoid)\n\tend\n\tpose = \"FreeFall\"\nend\n\nfunction onFallingDown()\n\tpose = \"FallingDown\"\nend\n\nfunction onSeated()\n\tpose = \"Seated\"\nend\n\nfunction onPlatformStanding()\n\tpose = \"PlatformStanding\"\nend\n\nfunction onSwimming(speed)\n\tif speed>0 then\n\t\tpose = \"Running\"\n\telse\n\t\tpose = \"Standing\"\n\tend\nend\n\nfunction getTool()\n\tfor _, kid in ipairs(Figure:GetChildren()) do\n\t\tif kid.className == \"Tool\" then return kid end\n\tend\n\treturn nil\nend\n\nfunction getToolAnim(tool)\n\tfor _, c in ipairs(tool:GetChildren()) do\n\t\tif c.Name == \"toolanim\" and c.className == \"StringValue\" then\n\t\t\treturn c\n\t\tend\n\tend\n\treturn nil\nend\n\nfunction animateTool()\n\n\tif (toolAnim == \"None\") then\n\t\tplayToolAnimation(\"toolnone\", toolTransitionTime, Humanoid)\n\t\treturn\n\tend\n\n\tif (toolAnim == \"Slash\") then\n\t\tplayToolAnimation(\"toolslash\", 0, Humanoid)\n\t\treturn\n\tend\n\n\tif (toolAnim == \"Lunge\") then\n\t\tplayToolAnimation(\"toollunge\", 0, Humanoid)\n\t\treturn\n\tend\nend\n\nfunction moveSit()\n\tRightShoulder.MaxVelocity = 0.15\n\tLeftShoulder.MaxVelocity = 0.15\n\tRightShoulder:SetDesiredAngle(3.14 /2)\n\tLeftShoulder:SetDesiredAngle(-3.14 /2)\n\tRightHip:SetDesiredAngle(3.14 /2)\n\tLeftHip:SetDesiredAngle(-3.14 /2)\nend\n\nlocal lastTick = 0\n\nfunction move(time)\n\tlocal amplitude = 1\n\tlocal frequency = 1\n \tlocal deltaTime = time - lastTick\n \tlastTick = time\n\n\tlocal climbFudge = 0\n\tlocal setAngles = false\n\n \tif (jumpAnimTime > 0) then\n \t\tjumpAnimTime = jumpAnimTime - deltaTime\n \tend\n\n\tif (pose == \"FreeFall\" and jumpAnimTime <= 0) then\n\t\tplayAnimation(\"fall\", fallTransitionTime, Humanoid)\n\telseif (pose == \"Seated\") then\n\t\tstopAllAnimations()\n\t\tmoveSit()\n\t\treturn\n\telseif (pose == \"Running\") then\n\t\tplayAnimation(\"walk\", 0.1, Humanoid)\n\telseif (pose == \"Dead\" or pose == \"GettingUp\" or pose == \"FallingDown\" or pose == \"Seated\" or pose == \"PlatformStanding\") then\n--\t\tprint(\"Wha \" .. pose)\n\t\tamplitude = 0.1\n\t\tfrequency = 1\n\t\tsetAngles = true\n\tend\n\n\tif (setAngles) then\n\t\tlocal desiredAngle = amplitude * math.sin(time * frequency)\n\n\t\tRightShoulder:SetDesiredAngle(desiredAngle + climbFudge)\n\t\tLeftShoulder:SetDesiredAngle(desiredAngle - climbFudge)\n\t\tRightHip:SetDesiredAngle(-desiredAngle)\n\t\tLeftHip:SetDesiredAngle(-desiredAngle)\n\tend\n\n\t-- Tool Animation handling\n\tlocal tool = getTool()\n\tif tool then\n\n\t\tlocal animStringValueObject = getToolAnim(tool)\n\n\t\tif animStringValueObject then\n\t\t\ttoolAnim = animStringValueObject.Value\n\t\t\t-- message recieved, delete StringValue\n\t\t\tanimStringValueObject.Parent = nil\n\t\t\ttoolAnimTime = time + .3\n\t\tend\n\n\t\tif time > toolAnimTime then\n\t\t\ttoolAnimTime = 0\n\t\t\ttoolAnim = \"None\"\n\t\tend\n\n\t\tanimateTool()\n\telse\n\t\tstopToolAnimations()\n\t\ttoolAnim = \"None\"\n\t\ttoolAnimTime = 0\n\tend\nend\n\n-- connect events\nHumanoid.Died:connect(onDied)\nHumanoid.Running:connect(onRunning)\nHumanoid.Jumping:connect(onJumping)\nHumanoid.Climbing:connect(onClimbing)\nHumanoid.GettingUp:connect(onGettingUp)\nHumanoid.FreeFalling:connect(onFreeFall)\nHumanoid.FallingDown:connect(onFallingDown)\nHumanoid.Seated:connect(onSeated)\nHumanoid.PlatformStanding:connect(onPlatformStanding)\nHumanoid.Swimming:connect(onSwimming)\n\n-- main program\n\nlocal runService = game:service(\"RunService\");\n\n-- initialize to idle\nplayAnimation(\"idle\", 0.1, Humanoid)\npose = \"Standing\"\n\nwhile Figure.Parent~=nil do\n\tlocal _, time = wait(0.1)\n\tmove(time)\nend\n\n\n" } }, - "Script.server.lua": { + "Script.server.luau": { "contents": { "Bytes": "local zombie = script.Parent\n\nfor _, script in pairs(zombie.ModuleScripts:GetChildren()) do\n\tif not game.ServerStorage:FindFirstChild(script.Name) then\n\t\tscript:Clone().Parent = game.ServerStorage\n\tend\nend\n\nlocal AI = require(game.ServerStorage.ROBLOX_ZombieAI).new(zombie)\nlocal DestroyService = require(game.ServerStorage.ROBLOX_DestroyService)\n\n\nlocal function clearParts(parent)\n\tfor _, part in pairs(parent:GetChildren()) do\n\t\tclearParts(part)\n\tend\n\tlocal delay\n\tif parent:IsA(\"Part\") then\n\t\tdelay = math.random(5,10)\n\telse\n\t\tdelay = 11\n\tend\n\tDestroyService:AddItem(parent, delay)\nend\n\nzombie.Humanoid.Died:connect(function()\n\tAI.Stop()\n\tmath.randomseed(tick())\n\tclearParts(zombie)\n\tscript.Disabled = true\nend)\n\nlocal lastMoan = os.time()\nmath.randomseed(os.time())\nwhile true do\n\tlocal animationTrack = zombie.Humanoid:LoadAnimation(zombie.Animations.Arms)\n\tanimationTrack:Play()\n--\tlocal now = os.time()\n--\tif now - lastMoan > 5 then\n--\t\tif math.random() > .3 then\n--\t\t\tzombie.Moan:Play()\n----\t\t\tprint(\"playing moan\")\n--\t\t\tlastMoan = now\n--\t\tend\n--\tend\n\twait(2)\nend\n\n" } @@ -646,32 +646,32 @@ "contents": { "Vfs": { "files": { - "ROBLOX_AIUtilities.lua": { + "ROBLOX_AIUtilities.luau": { "contents": { "Bytes": "local utility = {}\n\nfunction utility:WideRayCast(start, target, offset, ignoreList)\n\tlocal parts = {}\n\n\tlocal ray = Ray.new(start, target - start)\n\tlocal part, point = game.Workspace:FindPartOnRayWithIgnoreList(ray, ignoreList)\n\tif part then table.insert(parts, part) end\n\n\tlocal offsetVector = offset * (target - start):Cross(Vector3.FromNormalId(Enum.NormalId.Top)).unit\n\tlocal ray = Ray.new(start + offsetVector, target - start + offsetVector)\n\tlocal part, point = game.Workspace:FindPartOnRayWithIgnoreList(ray, ignoreList)\n\tif part then table.insert(parts, part) end\n\n\tlocal ray = Ray.new(start - offsetVector, target - start - offsetVector)\n\tlocal part, point = game.Workspace:FindPartOnRayWithIgnoreList(ray, ignoreList)\n\tif part then table.insert(parts, part) end\n\n\treturn parts\nend\n\nfunction utility:FindNearestPathPoint(path, point, start, target, ignoreList)\n\tlocal occludePoint = path:CheckOcclusionAsync(point)\n\tif occludePoint > 0 then\n\t\tutility:WideRayCast(start)\n\tend\nend\n\nlocal maxForce = 75\n\nfunction utility:GetRepulsionVector(unitPosition, otherUnitsPositions)\n\tlocal repulsionVector = Vector3.new(0,0,0)\n\tlocal count = 0\n\tfor _, other in pairs(otherUnitsPositions) do\n\t\tlocal fromOther = unitPosition - other\n\t\t--fromOther = fromOther.unit * ((-maxForce / 5) * math.pow(fromOther.magnitude,2) + maxForce)\n\t\tfromOther = fromOther.unit * 1000 / math.pow((fromOther.magnitude + 1), 2)\n\t\trepulsionVector = repulsionVector + fromOther\n\tend\n\treturn repulsionVector * maxForce\nend\n\nfunction utility:GetIdleState(StateMachine)\n\tlocal IdleState = StateMachine.NewState()\n\tIdleState.Name = \"Idle\"\n\tIdleState.Action = function() end\n\tIdleState.Init = function() end\n\treturn IdleState\nend\n\nfunction utility:GetClosestVisibleTarget(npcModel, characters, ignoreList, fieldOfView)\n\tlocal closestTarget = nil\n\tlocal closestDistance = math.huge\n\tfor _, character in pairs(characters) do\n\t\tlocal toTarget = character.HumanoidRootPart.Position - npcModel.HumanoidRootPart.Position\n\t\tlocal toTargetWedge = toTarget * Vector3.new(1,0,1)\n\t\tlocal angle = math.acos(toTargetWedge:Dot(npcModel.HumanoidRootPart.CFrame.lookVector)/toTargetWedge.magnitude)\n\t\tif math.deg(angle) < fieldOfView then\n\t\t\tlocal targetRay = Ray.new(npcModel.HumanoidRootPart.Position, toTarget)\n\t\t\tlocal part, position = game.Workspace:FindPartOnRayWithIgnoreList(targetRay, ignoreList)\n\t\t\tif part and part.Parent == character then\n\t\t\t\tif toTarget.magnitude < closestDistance then\n\t\t\t\t\tclosestTarget = character\n\t\t\t\t\tclosestDistance = toTarget.magnitude\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\tend\n\treturn closestTarget\nend\n\nlocal function isSpaceEmpty(position)\n\tlocal region = Region3.new(position - Vector3.new(2,2,2), position + Vector3.new(2,2,2))\n\treturn game.Workspace:IsRegion3Empty(region)\nend\n\nfunction utility:FindCloseEmptySpace(model)\n\tlocal targetPos = Vector3.new(0,0,0)\n\tlocal count = 0\n\tmath.randomseed(os.time())\n\trepeat\n\t\tlocal xoff = math.random(5,10)\n\t\tif math.random() > .5 then\n\t\t\txoff = xoff * -1\n\t\tend\n\t\tlocal zoff = math.random(5, 10)\n\t\tif math.random() > .5 then\n\t\t\tzoff = zoff * -1\n\t\tend\n\n\t\ttargetPos = Vector3.new(model.HumanoidRootPart.Position.X + xoff,model.HumanoidRootPart.Position.Y,model.HumanoidRootPart.Position.Z + zoff)\n\t\tif isSpaceEmpty(targetPos) then\n\t\t\treturn targetPos\n\t\telse\n\t\t\ttargetPos = targetPos + Vector3.new(0,4,0)\n\t\tend\n\n\t\tif isSpaceEmpty(targetPos) then\n\t\t\treturn targetPos\n\t\tend\n\t\tcount = count + 1\n\tuntil count > 10\n\treturn nil\nend\n\nreturn utility" } }, - "ROBLOX_DestroyService.lua": { + "ROBLOX_DestroyService.luau": { "contents": { "Bytes": "local destroyService = {}\n\nlocal destroyQueue = {}\n\nfunction destroyService:AddItem(theobject, delay)\n\tlocal now = os.time()\n\tlocal destroyObject = {object = theobject, destroyTime = delay + now}\n\tfor i, storedObject in pairs(destroyQueue) do\n\t\tif destroyQueue[i].destroyTime > destroyObject.destroyTime then\n\t\t\ttable.insert(destroyQueue, i, destroyObject)\n\t\t\treturn true\n\t\tend\n\tend\n\ttable.insert(destroyQueue, destroyObject)\n\treturn true\nend\n\nlocal updateThread = coroutine.create(function()\n\twhile true do\n\t\tlocal now = os.time()\n\t\tfor _, storedObject in pairs(destroyQueue) do\n\t\t\tif now >= storedObject.destroyTime then\n\t\t\t\ttable.remove(destroyQueue, 1)\n\t\t\t\tif storedObject.object then\n\t\t\t\t\tstoredObject.object:Destroy()\n\t\t\t\tend\n\t\t\telseif now >= storedObject.destroyTime - 1 then\n\n\t\t\t\tif storedObject.object and storedObject.object:IsA(\"Part\") then\n\t\t\t\t\tlocal trans = storedObject.object.Transparency + 1/30\n\t\t\t\t\tstoredObject.object.Transparency = trans\n\t\t\t\tend\n\t\t\telse\n\t\t\t\tbreak\n\t\t\tend\n\t\tend\n\t\twait()\n\tend\nend)\n\ncoroutine.resume(updateThread)\n\nreturn destroyService" } }, - "ROBLOX_HumanoidList.lua": { + "ROBLOX_HumanoidList.luau": { "contents": { "Bytes": "local humanoidList = {}\nlocal storage = {}\n\nfunction humanoidList:GetCurrent()\n\treturn storage\nend\n\nlocal function findHumanoids(object, list)\n\tif object then\n\t\tif object:IsA(\"Humanoid\") then\n\t\t\ttable.insert(list, object)\n\t\tend\n\n\t\tfor _, child in pairs(object:GetChildren()) do\n\t\t\tlocal childList = findHumanoids(child, list)\n\t\tend\n\tend\nend\n\nlocal updateThread = coroutine.create(function()\n\twhile true do\n\t\tstorage = {}\n\t\tfindHumanoids(game.Workspace, storage)\n\t\twait(3)\n\tend\nend)\n\ncoroutine.resume(updateThread)\n\nreturn humanoidList" } }, - "ROBLOX_PathfindingLibrary.lua": { + "ROBLOX_PathfindingLibrary.luau": { "contents": { "Bytes": "local PathfindingUtility = {}\nlocal TargetOffsetMax = 10--5\nlocal JumpThreshold = 1.5 --2.5\nlocal NextPointThreshold = 4\nlocal PathfindingService = game:GetService(\"PathfindingService\")\nPathfindingService.EmptyCutoff = .3\n\nfunction PathfindingUtility.new()\n\tlocal this = {}\n\n\tlocal currentTargetPos = nil\n\tlocal lastTargetPos = Vector3.new(math.huge, math.huge, math.huge)\n\tlocal path = nil\n\tlocal currentPointIndex = 1\n\n\tfunction this:MoveToTarget(character, target)\n\t\tlocal targetOffset = (lastTargetPos - target).magnitude\n--\n--\t\tlocal targetOffsetVector = (lastTargetPos - target)\n--\t\tif targetOffsetVector.magnitude < math.huge then\n--\t\t\ttargetOffsetVector = (lastTargetPos - target) * Vector3.new(1,0,1)\n--\t\tend\n\t\tif targetOffset > TargetOffsetMax then\n\t\t--if targetOffsetVector.magnitude > TargetOffsetMax then\n\t\t\t--print(\"moveto\")\n\t\t\tlocal startPoint = character.HumanoidRootPart.Position\n\t\t\tlocal humanoidState = character.Humanoid:GetState()\n\t\t\tif humanoidState == Enum.HumanoidStateType.Jumping or humanoidState == Enum.HumanoidStateType.Freefall then\n\t\t\t\t--print(\"this\")\n\t\t\t\tlocal ray = Ray.new(character.HumanoidRootPart.Position, Vector3.new(0, -100, 0))\n\t\t\t\tlocal hitPart, hitPoint = game.Workspace:FindPartOnRay(ray, character)\n\t\t\t\tif hitPart then\n\t\t\t\t\tstartPoint = hitPoint\n\t\t\t\tend\n\t\t\tend\n\t\t\t--print(\"making new path\")\n\t\t\tlocal newTarget = target\n\t\t\tlocal ray = Ray.new(target + Vector3.new(0,-3,0), Vector3.new(0, -100, 0))\n\t\t\tlocal hitPart, hitPoint = game.Workspace:FindPartOnRay(ray, character)\n\t\t\tif hitPoint then\n\t\t\t\tif (hitPoint - target).magnitude > 4 then\n\t\t\t\t\tnewTarget = newTarget * Vector3.new(1,0,1) + Vector3.new(0,3,0)\n\t\t\t\tend\n\t\t\tend\n\n\t\t\t--local newTarget = Vector3.new(1,0,1) * target + Vector3.new(0, 2, 0)\n\t\t\tpath = PathfindingService:ComputeSmoothPathAsync(startPoint, newTarget, 500)\n\t\t\tif path.Status ~= Enum.PathStatus.Success then\n\t\t\t\t--print(tostring(path.Status))\n\t\t\tend\n\t\t\t--path = PathfindingService:ComputeRawPathAsync(startPoint, target, 500)\n\n--\t\t\tgame.Workspace.Points:ClearAllChildren()\n--\t\t\tlocal ps = path:GetPointCoordinates()\n--\t\t\tfor _, point in pairs(ps) do\n--\t\t\t\tlocal part = Instance.new(\"Part\", game.Workspace.Points)\n--\t\t\t\tpart.CanCollide = false\n--\t\t\t\tpart.Anchored = true\n--\t\t\t\tpart.FormFactor = Enum.FormFactor.Custom\n--\t\t\t\tpart.Size = Vector3.new(1,1,1)\n--\t\t\t\tpart.Position = point\n--\t\t\tend\n\n\t\t\tcurrentPointIndex = 1\n\t\t\tlastTargetPos = target\n\t\tend\n\n\t\tif path then\n\t\t\tlocal points = path:GetPointCoordinates()\n\t\t\tif currentPointIndex < #points then\n\t\t\t\tlocal currentPoint = points[currentPointIndex]\n\t\t\t\tif character:FindFirstChild(\"HumanoidRootPart\") then\n\t\t\t\t\tlocal distance = (character.HumanoidRootPart.Position - currentPoint).magnitude\n\t\t\t\t\tif distance < NextPointThreshold then\n\t\t\t\t\t\tcurrentPointIndex = currentPointIndex + 1\n\t\t\t\t\tend\n\n\t\t\t\t\tcharacter.Humanoid:MoveTo(points[currentPointIndex])\n\t\t\t\t\tif points[currentPointIndex].Y - character.HumanoidRootPart.Position.Y > JumpThreshold then\n\t\t\t\t\t\tcharacter.Humanoid.Jump = true\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\telse\n\t\t\t\tif character:FindFirstChild(\"Humanoid\") then\n\t\t\t\t\tcharacter.Humanoid:MoveTo(target)\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\tend\n\n\treturn this\nend\nreturn PathfindingUtility " } }, - "ROBLOX_StateMachine.lua": { + "ROBLOX_StateMachine.luau": { "contents": { "Bytes": "local machine = {}\n\nmachine.new = function()\n\tlocal StateMachine = {}\n\n\tStateMachine.WaitTime = .2\n\tStateMachine.CurrentState = nil\n\tStateMachine.SwitchState = function(newState)\n\t\tif StateMachine.CurrentState then\n\t\t\tStateMachine.CurrentState.Stop()\n\t\tend\n\t\tStateMachine.CurrentState = newState\n\t\tif newState then\n\t\t\tnewState.Start()\n\t\tend\n\tend\n\n\tStateMachine.NewState = function()\n\t\tlocal state = {}\n\t\tstate.Name = \"\"\n\t\tstate.Conditions = {}\n\t\tstate.isRunning = false\n\t\tstate.Action = function() end\n\t\tstate.Run = function()\n\t\t\tstate.isRunning = true\n\t\t\twhile state.isRunning do\n\t\t\t\t--check conditions\n\t\t\t\t--print(\"checking conditions\")\n\t\t\t\tfor _, condition in pairs(state.Conditions) do\n\t\t\t\t\t--print(\"Checking \" .. condition.Name)\n\t\t\t\t\tif condition.Evaluate() then\n\t\t\t\t\t\t--print(condition.Name .. \" is true. Switching states\")\n\t\t\t\t\t\tStateMachine.SwitchState(condition.TransitionState)\n\t\t\t\t\t\treturn\n\t\t\t\t\tend\n\t\t\t\tend\n\n\t\t\t\t--if no conditions satisfied, perform action\n\t\t\t\tstate.Action()\n\t\t\t\twait(StateMachine.WaitTime)\n\t\t\tend\n\t\tend\n\t\tstate.Init = function()\n\n\t\tend\n\t\tstate.Start = function()\n\t\t\t--print(\"Starting \" .. state.Name)\n\t\t\tstate.Init()\n\t\t\tlocal thread = coroutine.create(state.Run)\n\t\t\tcoroutine.resume(thread)\n\t\tend\n\t\tstate.Stop = function()\n\t\t\t--print(\"Stopping \" .. state.Name)\n\t\t\tstate.isRunning = false\n\t\tend\n\t\treturn state\n\tend\n\n\tStateMachine.NewCondition = function()\n\t\tlocal condition = {}\n\t\tcondition.Name = \"\"\n\t\tcondition.Evaluate = function() print(\"replace me\") return false end\n\t\tcondition.TransitionState = {}\n\t\treturn condition\n\tend\n\n\treturn StateMachine\nend\n\nreturn machine" } }, - "ROBLOX_ZombieAI.lua": { + "ROBLOX_ZombieAI.luau": { "contents": { "Bytes": "--local PathLib = require(game.ServerStorage.PathfindingLibrary).new()\nlocal HumanoidList = require(game.ServerStorage.ROBLOX_HumanoidList)\nlocal AIUtilities = require(game.ServerStorage.ROBLOX_AIUtilities)\n\nlocal ZombieAI = {}\n\nfunction updateDisplay(display, state)\n\tlocal thread = coroutine.create(function()\n\t\twhile true do\n\t\t\twait()\n\t\t\tif state then\n\t\t\t\tdisplay.Text = state.Name\n\t\t\tend\n\t\tend\n\tend)\n\tcoroutine.resume(thread)\nend\n\nZombieAI.new = function(model)\n\tlocal zombie = {}\n\n\t-- CONFIGURATION VARIABLES\n--\tlocal AttackRange, FieldOfView, AggroRange, ChanceOfBoredom, BoredomDuration,\n--\t\tDamage, DamageCooldown\n\n\tlocal configTable = model.Configurations\n\tlocal configs = {}\n\tlocal function loadConfig(configName, defaultValue)\n\t\tif configTable:FindFirstChild(configName) then\n\t\t\tconfigs[configName] = configTable:FindFirstChild(configName).Value\n\t\telse\n\t\t\tconfigs[configName] = defaultValue\n\t\tend\n\tend\n\n\tloadConfig(\"AttackRange\", 3)\n\tloadConfig(\"FieldOfView\", 180)\n\tloadConfig(\"AggroRange\", 200)\n\tloadConfig(\"ChanceOfBoredom\", .5)\n\tloadConfig(\"BoredomDuration\", 10)\n\tloadConfig(\"Damage\", 10)\n\tloadConfig(\"DamageCooldown\", 1)\n\n\tlocal StateMachine = require(game.ServerStorage.ROBLOX_StateMachine).new()\n\tlocal PathLib = require(game.ServerStorage.ROBLOX_PathfindingLibrary).new()\n\tlocal ZombieTarget = nil\n\tlocal ZombieTargetLastLocation = nil\n\n\tlocal lastBored = os.time()\n\n\t-- STATE DEFINITIONS\n\n\t-- IdleState: NPC stays still. Refreshes bored timer when started to\n\t-- allow for random state change\n\tlocal IdleState = StateMachine.NewState()\n\tIdleState.Name = \"Idle\"\n\tIdleState.Action = function()\n\tend\n\tIdleState.Init = function()\n\t\tlastBored = os.time()\n\tend\n\n\t-- SearchState: NPC wanders randomly increasing chance of spotting\n\t-- enemy. Refreshed bored timer when started to allow for random state\n\t-- change\n\tlocal SearchState = StateMachine.NewState()\n\tSearchState.Name = \"Search\"\n\tlocal lastmoved = os.time()\n\tlocal searchTarget = nil\n\tSearchState.Action = function()\n\t\t-- move to random spot nearby\n\t\tif model then\n\t\t\tif model:FindFirstChild(\"HumanoidRootPart\") then\n\t\t\t\tlocal now = os.time()\n\t\t\t\tif now - lastmoved > 2 then\n\t\t\t\t\tlastmoved = now\n\t\t\t\t\tlocal xoff = math.random(5, 10)\n\t\t\t\t\tif math.random() > .5 then\n\t\t\t\t\t\txoff = xoff * -1\n\t\t\t\t\tend\n\t\t\t\t\tlocal zoff = math.random(5, 10)\n\t\t\t\t\tif math.random() > .5 then\n\t\t\t\t\t\tzoff = zoff * -1\n\t\t\t\t\tend\n\n\t\t\t\t\tlocal testtarg = AIUtilities:FindCloseEmptySpace(model)\n\t\t\t\t\t--if testtarg then print(testtarg) else print(\"could not find\") end\n\t\t\t\t\tsearchTarget = Vector3.new(model.HumanoidRootPart.Position.X + xoff,model.HumanoidRootPart.Position.Y,model.HumanoidRootPart.Position.Z + zoff)\n\t\t\t\t\t--local target = Vector3.new(model.HumanoidRootPart.Position.X + xoff,model.HumanoidRootPart.Position.Y,model.HumanoidRootPart.Position.Z + zoff)\n\t\t\t\t\t--model.Humanoid:MoveTo(target)\n\t\t\t\t\tsearchTarget = testtarg\n\t\t\t\tend\n\t\t\t\t--PathLib:MoveToTarget(model, searchTarget) --Zombie will fall off path when searching\n\t\t\tend\n\t\tend\n\tend\n\tSearchState.Init = function()\n\t\tlastBored = os.time()\n\tend\n\n\t-- PursueState: Enemy has been spotted, need to give chase.\n\tlocal PursueState = StateMachine.NewState()\n\tPursueState.Name = \"Pursue\"\n\tPursueState.Action = function()\n\t\t-- Double check we still have target\n\t\tif ZombieTarget then\n\t\t\tif model:FindFirstChild(\"HumanoidRootPart\") then\n\t\t\t\tif ZombieTarget:FindFirstChild(\"HumanoidRootPart\") then\n\t\t\t\t\t-- Get distance to target\n\t\t\t\t\tlocal distance = (model.HumanoidRootPart.Position - ZombieTarget.HumanoidRootPart.Position).magnitude\n\t\t\t\t\t-- If we're far from target use pathfinding to move. Otherwise just MoveTo\n\t\t\t\t\tif distance > configs[\"AttackRange\"] + 5 then\n\t\t\t\t\t\tPathLib:MoveToTarget(model, ZombieTarget.HumanoidRootPart.Position)\n\t\t\t\t\telse\n\t\t\t\t\t\tmodel.Humanoid:MoveTo(ZombieTarget.HumanoidRootPart.Position)\n\t\t--\t\t\t\tif ZombieTarget.HumanoidRootPart.Position.Y > model.HumanoidRootPart.Position.Y + 2 then\n\t\t--\t\t\t\t\tmodel.Humanoid.Jump = true\n\t\t--\t\t\t\tend\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\tend\n\tPursueState.Init = function()\n\tend\n\n\t-- AttackState: Keep moving towards target and play attack animation.\n\tlocal AttackState = StateMachine.NewState()\n\tAttackState.Name = \"Attack\"\n\tlocal lastAttack = os.time()\n\tlocal attackTrack = model.Humanoid:LoadAnimation(model.Animations.Attack)\n\tAttackState.Action = function()\n\t\tmodel.Humanoid:MoveTo(ZombieTarget.HumanoidRootPart.Position)\n\t\tlocal now = os.time()\n\t\tif now - lastAttack > 3 then\n\t\t\tlastAttack = now\n\t\t\tattackTrack:Play()\n\t\tend\n\tend\n\n\t-- HuntState: Can't see target but NPC will move to target's last known location.\n\t-- Will eventually get bored and switch state.\n\tlocal HuntState = StateMachine.NewState()\n\tHuntState.Name = \"Hunt\"\n\tHuntState.Action = function()\n\t\tif ZombieTargetLastLocation then\n\t\t\tPathLib:MoveToTarget(model, ZombieTargetLastLocation)\n\t\tend\n\tend\n\tHuntState.Init = function()\n\t\tlastBored = os.time() + configs[\"BoredomDuration\"] / 2\n\tend\n\n\t-- CONDITION DEFINITIONS\n\n\t-- CanSeeTarget: Determines if a target is visible. Returns true if target is visible and\n\t-- sets current target. A target is valid if it is nearby, visible, has a HumanoidRootPart and WalkSpeed\n\t-- greater than 0 (this is to ignore inanimate objects that happen to use humanoids)\n\tlocal CanSeeTarget = StateMachine.NewCondition()\n\tCanSeeTarget.Name = \"CanSeeTarget\"\n\tCanSeeTarget.Evaluate = function()\n\t\tif model then\n\t\t\t-- Get list of all nearby Zombies and non-Zombie humanoids\n\t\t\t-- Zombie list is used to ignore zombies during later raycast\n\t\t\tlocal humanoids = HumanoidList:GetCurrent()\n\t\t\tlocal zombies = {}\n\t\t\tlocal characters = {}\n\t\t\tfor _, object in pairs(humanoids) do\n\t\t\t\tif object and object.Parent and object.Parent:FindFirstChild(\"HumanoidRootPart\") and object.Health > 0 and object.WalkSpeed > 0 then\n\t\t\t\t\tlocal HumanoidRootPart = object.Parent:FindFirstChild(\"HumanoidRootPart\")\n\t\t\t\t\tif HumanoidRootPart and model:FindFirstChild(\"HumanoidRootPart\") then\n\t\t\t\t\t\tlocal distance = (model.HumanoidRootPart.Position - HumanoidRootPart.Position).magnitude\n\t\t\t\t\t\tif distance <= configs[\"AggroRange\"] then\n\t\t\t\t\t\t\tif object.Parent.Name == \"Zombie\" then\n\t\t\t\t\t\t\t\ttable.insert(zombies, object.Parent)\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\ttable.insert(characters, object.Parent)\n\t\t\t\t\t\t\tend\n\t\t\t\t\t\tend\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\tend\n\n\t\t\tlocal target = AIUtilities:GetClosestVisibleTarget(model, characters, zombies, configs[\"FieldOfView\"])\n\t\t\tif target then\n\t\t\t\tZombieTarget = target\n\t\t\t\treturn true\n\t\t\tend\n\n--\t\t\t-- Go through each valid target to see if within field of view and if there is\n--\t\t\t-- clear line of sight. Field of view treated as wedge in front of character.\n--\t\t\tfor _, character in pairs(characters) do\n--\t\t\t\tlocal toTarget = (character.HumanoidRootPart.Position - model.HumanoidRootPart.Position)\n--\t\t\t\ttoTarget = Vector3.new(toTarget.X, 0, toTarget.Z)\n--\t\t\t\tlocal angle = math.acos(toTarget:Dot(model.HumanoidRootPart.CFrame.lookVector)/toTarget.magnitude)\n--\t\t\t\tif math.deg(angle) < configs[\"FieldOfView\"]/2 then\n--\t\t\t\t\tZombieTarget = character\n--\t\t\t\t\t-- raycast to see if target is actually visible\n--\t\t\t\t\tlocal toTarget = Ray.new(model.HumanoidRootPart.Position, (ZombieTarget.HumanoidRootPart.Position - model.HumanoidRootPart.Position))\n--\t\t\t\t\tlocal part, position = game.Workspace:FindPartOnRayWithIgnoreList(toTarget, zombies)\n--\t\t\t\t\tif part and part.Parent == ZombieTarget then\n--\t\t\t\t\t\treturn true\n--\t\t\t\t\tend\n--\t\t\t\t\tZombieTarget = nil\n--\t\t\t\tend\n--\t\t\tend\n\t\tend\n\t\treturn false\n\tend\n\tCanSeeTarget.TransitionState = PursueState\n\n\t-- TargetDead: Check if target is dead.\n\tlocal TargetDead = StateMachine.NewCondition()\n\tTargetDead.Name = \"TargetDead\"\n\tTargetDead.Evaluate = function()\n\t\tif ZombieTarget and ZombieTarget.Humanoid then\n\t\t\treturn ZombieTarget.Humanoid.Health <= 0\n\t\tend\n\t\treturn true\n\tend\n\tTargetDead.TransitionState = IdleState\n\n\t-- GotDamaged: Check if NPC has taken damage\n\tlocal lastHealth = model.Humanoid.Health\n\tlocal GotDamaged = StateMachine.NewCondition()\n\tGotDamaged.Name = \"GotDamaged\"\n\tGotDamaged.Evaluate = function()\n\t\tif model then\n\t\t\tif lastHealth > model.Humanoid.Health then\n\t\t\t\treturn true\n\t\t\tend\n\t\tend\n\t\treturn false\n\tend\n\tGotDamaged.TransitionState = SearchState\n\n\t-- GotBored: Used to provide random state change.\n\tlocal GotBored = StateMachine.NewCondition()\n\tGotBored.Name = \"GotBored\"\n\tGotBored.Evaluate = function()\n\t\tlocal now = os.time()\n\t\tif now - lastBored > configs[\"BoredomDuration\"] then\n\t\t\tlocal roll = math.random()\n\t\t\tif roll < configs[\"ChanceOfBoredom\"] then\n\t\t\t\tlastBored = now\n\t\t\t\tif GotBored.TransitionState == SearchState then\n\t\t\t\t\tGotBored.TransitionState = IdleState\n\t\t\t\telse\n\t\t\t\t\tGotBored.TransitionState = SearchState\n\t\t\t\tend\n\t\t\t\treturn true\n\t\t\tend\n\t\tend\n\t\treturn false\n\tend\n\tGotBored.TransitionState = IdleState\n\n\t-- LostTarget: Checks clear line of sight\n\tlocal LostTarget = StateMachine.NewCondition()\n\tLostTarget.Name = \"LostTarget\"\n\tLostTarget.Evaluate = function()\n\t\tif true then return false end\n\t\tif ZombieTarget then\n\t\t\tif (ZombieTarget.HumanoidRootPart.Position - model.HumanoidRootPart.Position).magnitude > 10 then\n\t\t\t\tlocal toTarget = Ray.new(model.HumanoidRootPart.Position, (ZombieTarget.HumanoidRootPart.Position - model.HumanoidRootPart.Position))\n\t\t\t\tlocal part, position = game.Workspace:FindPartOnRay(toTarget, model)\n\t\t\t\tif not part or part.Parent ~= ZombieTarget then\n\t\t\t\t\t--print(\"Lost target!\")\n\t\t\t\t\tZombieTargetLastLocation = ZombieTarget.HumanoidRootPart.Position\n\t\t\t\t\tZombieTarget = nil\n\t\t\t\t\treturn true\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\t\treturn false\n\tend\n\tLostTarget.TransitionState = HuntState\n\n\tlocal WithinRange = StateMachine.NewCondition()\n\tWithinRange.Name = \"WithinRange\"\n\tWithinRange.Evaluate = function()\n\t\tif ZombieTarget then\n\t\t\tif model:FindFirstChild(\"HumanoidRootPart\") then\n\t\t\t\tlocal distance = (model.HumanoidRootPart.Position - ZombieTarget.HumanoidRootPart.Position).magnitude\n\t\t\t\tif distance < configs[\"AttackRange\"] then\n\t\t\t\t\t--print(\"Within attack range!\")\n\t\t\t\t\treturn true\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\t\treturn false\n\tend\n\tWithinRange.TransitionState = AttackState\n\n\tlocal OutsideRange = StateMachine.NewCondition()\n\tOutsideRange.Name = \"OutsideRange\"\n\tOutsideRange.Evaluate = function()\n\t\tif ZombieTarget then\n\t\t\tif model:FindFirstChild(\"HumanoidRootPart\") and ZombieTarget:FindFirstChild(\"HumanoidRootPart\") then\n\t\t\t\tlocal distance = (model.HumanoidRootPart.Position - ZombieTarget.HumanoidRootPart.Position).magnitude\n\t\t\t\tif distance > configs[\"AttackRange\"] then\n\t\t\t\t\t--print(\"Outside attack range!\")\n\t\t\t\t\treturn true\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\t\treturn false\n\tend\n\tOutsideRange.TransitionState = PursueState\n\n\ttable.insert(IdleState.Conditions, CanSeeTarget)\n\ttable.insert(IdleState.Conditions, GotDamaged)\n\ttable.insert(IdleState.Conditions, GotBored)\n\n\ttable.insert(SearchState.Conditions, GotBored)\n\ttable.insert(SearchState.Conditions, CanSeeTarget)\n\n\ttable.insert(PursueState.Conditions, LostTarget)\n\ttable.insert(PursueState.Conditions, WithinRange)\n\ttable.insert(PursueState.Conditions, TargetDead)\n\n\ttable.insert(AttackState.Conditions, OutsideRange)\n\ttable.insert(AttackState.Conditions, TargetDead)\n\n\ttable.insert(HuntState.Conditions, GotBored)\n\ttable.insert(HuntState.Conditions, CanSeeTarget)\n\n\t-- Setup arms damage\n\tlocal canHit = true\n\tlocal lastHit = os.time()\n\tlocal function handleHit(other, zombieArm)\n\t\tif canHit then\n\t\t\tif other and other.Parent and other.Parent.Name ~= \"Zombie\" and other.Parent:FindFirstChild(\"Humanoid\") then\n\t\t\t\tlocal enemy = other.Parent\n\t\t\t\tif enemy.Humanoid.WalkSpeed > 0 then\n\t\t\t\t\tlocal shield = enemy:FindFirstChild(\"Shield\")\n\t\t\t\t\tif shield then\n\t\t\t\t\t\tmodel:BreakJoints()\n\t\t\t\t\tend\n\t\t\t\t\tlocal killBehaviour = require(game.ServerScriptService.Server_Main.Behaviours.Kill)\n\t\t\t\t\tkillBehaviour:ExecuteBehaviour(zombieArm, enemy)\n\t\t\t\tend\n\t\t\tend\n\t\telse\n\t\t\tlocal now = os.time()\n\t\t\tif now - lastHit > configs[\"DamageCooldown\"] then\n\t\t\t\tlastHit = now\n\t\t\t\tcanHit = true\n\t\t\tend\n\t\tend\n\tend\n\tlocal leftHitConnect, rightHitConnect\n\tleftHitConnect = model:FindFirstChild(\"Left Arm\").Touched:connect(function(other) handleHit(other, model:FindFirstChild(\"Left Arm\")) end)\n\trightHitConnect = model:FindFirstChild(\"Right Arm\").Touched:connect(function(other) handleHit(other, model:FindFirstChild(\"Right Arm\")) end)\n\n\t--ZombieAI.Animate(model)\n\t--updateDisplay()\n\t--updateDisplay(model.BillboardGui.TextLabel, StateMachine.CurrentState)\n\tlocal thread = coroutine.create(function()\n\t\twhile true do\n\t\t\twait()\n\t\t\t-- calculate repulsion force\n\t\t\tif model == nil then\n\t\t\t\tbreak\n\t\t\tend\n\n\t\t\tif model:FindFirstChild(\"HumanoidRootPart\") == nil then\n\t\t\t\tbreak\n\t\t\tend\n\n\t\t\tlocal humanoids = HumanoidList:GetCurrent()\n\t\t\tlocal localZombies = {}\n\t\t\tfor _, humanoid in pairs(humanoids) do\n\t\t\t\tif humanoid and humanoid ~= model.Humanoid and humanoid.Parent and humanoid.Parent:FindFirstChild(\"HumanoidRootPart\") then\n\t\t\t\t\tlocal HumanoidRootPart = humanoid.Parent:FindFirstChild(\"HumanoidRootPart\")\n\t\t\t\t\tif HumanoidRootPart ~= nil and model ~= nil then\n\t\t\t\t\t\tif model:FindFirstChild(\"HumanoidRootPart\") then\n\t\t\t\t\t\t\tlocal distance = (model.HumanoidRootPart.Position - HumanoidRootPart.Position).magnitude\n\t\t\t\t\t\t\tif distance <= 2.5 then\n\t\t\t\t\t\t\t\ttable.insert(localZombies, HumanoidRootPart.Position)\n\t\t\t\t\t\t\tend\n\t\t\t\t\t\tend\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\tend\n\t\t\tlocal repulsionDirection = AIUtilities:GetRepulsionVector(model.HumanoidRootPart.Position, localZombies)\n\t\t\tif repulsionDirection.magnitude > 0 then\n\t\t\t\t--print(\"replusion direction: \" .. tostring(repulsionDirection))\n\t\t\tend\n\t\t\tmodel.HumanoidRootPart.RepulsionForce.force = repulsionDirection\n\n\t\t\tif StateMachine.CurrentState and model.Configurations.Debug.Value then\n\t\t\t\tmodel.BillboardGui.TextLabel.Visible = true\n\t\t\t\tmodel.BillboardGui.TextLabel.Text = StateMachine.CurrentState.Name\n\t\t\tend\n\t\t\tif not model.Configurations.Debug.Value then\n\t\t\t\tmodel.BillboardGui.TextLabel.Visible = false\n\t\t\tend\n\t\tend\n\tend)\n\tcoroutine.resume(thread)\n\n\tStateMachine.SwitchState(IdleState)\n\n\tzombie.Stop = function()\n\t\tStateMachine.SwitchState(nil)\n\tend\n\n\treturn zombie\nend\n\nreturn ZombieAI" } diff --git a/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithJustScriptsInside/LocalScript.client.lua b/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithJustScriptsInside/LocalScript.client.lua deleted file mode 100644 index f1a1813..0000000 --- a/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithJustScriptsInside/LocalScript.client.lua +++ /dev/null @@ -1 +0,0 @@ -print("Hello world!") diff --git a/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithJustScriptsInside/ModuleScript.lua b/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithJustScriptsInside/ModuleScript.lua deleted file mode 100644 index f4098ad..0000000 --- a/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithJustScriptsInside/ModuleScript.lua +++ /dev/null @@ -1,3 +0,0 @@ -local module = {} - -return module diff --git a/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithJustScriptsInside/Script.server.lua b/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithJustScriptsInside/Script.server.lua deleted file mode 100644 index f1a1813..0000000 --- a/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithJustScriptsInside/Script.server.lua +++ /dev/null @@ -1 +0,0 @@ -print("Hello world!") diff --git a/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithJustScriptsInside/init.server.lua b/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithJustScriptsInside/init.server.lua deleted file mode 100644 index e69de29..0000000 diff --git a/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithNoScriptsInside.server.lua b/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithNoScriptsInside.server.lua deleted file mode 100644 index f1a1813..0000000 --- a/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithNoScriptsInside.server.lua +++ /dev/null @@ -1 +0,0 @@ -print("Hello world!") diff --git a/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithNothingInside.server.lua b/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithNothingInside.server.lua deleted file mode 100644 index e69de29..0000000 diff --git a/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithScriptDescendant/Function/LocalScript.client.lua b/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithScriptDescendant/Function/LocalScript.client.lua deleted file mode 100644 index f1a1813..0000000 --- a/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithScriptDescendant/Function/LocalScript.client.lua +++ /dev/null @@ -1 +0,0 @@ -print("Hello world!") diff --git a/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithScriptDescendant/init.server.lua b/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithScriptDescendant/init.server.lua deleted file mode 100644 index f1a1813..0000000 --- a/test-files/script-descendant-tests/filesystem/src/Folder/ScriptWithScriptDescendant/init.server.lua +++ /dev/null @@ -1 +0,0 @@ -print("Hello world!") diff --git a/test-files/script-descendant-tests/output.json b/test-files/script-descendant-tests/output.json index 719cc28..16fb30c 100644 --- a/test-files/script-descendant-tests/output.json +++ b/test-files/script-descendant-tests/output.json @@ -9,12 +9,12 @@ "Bytes": "{\n \"ignoreUnknownInstances\": true\n}" } }, - "ScriptWithNoScriptsInside.server.lua": { + "ScriptWithNoScriptsInside.server.luau": { "contents": { "Bytes": "print(\"Hello world!\")\n" } }, - "ScriptWithNothingInside.server.lua": { + "ScriptWithNothingInside.server.luau": { "contents": { "Bytes": "" } @@ -33,22 +33,22 @@ "contents": { "Vfs": { "files": { - "LocalScript.client.lua": { + "LocalScript.client.luau": { "contents": { "Bytes": "print(\"Hello world!\")\n" } }, - "ModuleScript.lua": { + "ModuleScript.luau": { "contents": { "Bytes": "local module = {}\n\nreturn module\n" } }, - "Script.server.lua": { + "Script.server.luau": { "contents": { "Bytes": "print(\"Hello world!\")\n" } }, - "init.server.lua": { + "init.server.luau": { "contents": { "Bytes": "" } @@ -67,7 +67,7 @@ "Bytes": "{\n \"ignoreUnknownInstances\": true\n}" } }, - "init.server.lua": { + "init.server.luau": { "contents": { "Bytes": "print(\"Hello world!\")\n" } @@ -81,7 +81,7 @@ "contents": { "Vfs": { "files": { - "LocalScript.client.lua": { + "LocalScript.client.luau": { "contents": { "Bytes": "print(\"Hello world!\")\n" } diff --git a/test-files/script-with-character-inside/filesystem/src/ModuleScript.lua b/test-files/script-with-character-inside/filesystem/src/ModuleScript.lua deleted file mode 100644 index a564707..0000000 --- a/test-files/script-with-character-inside/filesystem/src/ModuleScript.lua +++ /dev/null @@ -1 +0,0 @@ -return {} diff --git a/test-files/script-with-character-inside/output.json b/test-files/script-with-character-inside/output.json index 8c4cf7a..61f6dc3 100644 --- a/test-files/script-with-character-inside/output.json +++ b/test-files/script-with-character-inside/output.json @@ -1,6 +1,6 @@ { "files": { - "ModuleScript.lua": { + "ModuleScript.luau": { "contents": { "Bytes": "return {}\n" } diff --git a/test-files/scripts-with-scripts/filesystem/src/Folder/LocalScript/ModuleScript.lua b/test-files/scripts-with-scripts/filesystem/src/Folder/LocalScript/ModuleScript.lua deleted file mode 100644 index f4098ad..0000000 --- a/test-files/scripts-with-scripts/filesystem/src/Folder/LocalScript/ModuleScript.lua +++ /dev/null @@ -1,3 +0,0 @@ -local module = {} - -return module diff --git a/test-files/scripts-with-scripts/filesystem/src/Folder/LocalScript/init.client.lua b/test-files/scripts-with-scripts/filesystem/src/Folder/LocalScript/init.client.lua deleted file mode 100644 index f1a1813..0000000 --- a/test-files/scripts-with-scripts/filesystem/src/Folder/LocalScript/init.client.lua +++ /dev/null @@ -1 +0,0 @@ -print("Hello world!") diff --git a/test-files/scripts-with-scripts/filesystem/src/Folder/ModuleScript/ModuleScript.lua b/test-files/scripts-with-scripts/filesystem/src/Folder/ModuleScript/ModuleScript.lua deleted file mode 100644 index f4098ad..0000000 --- a/test-files/scripts-with-scripts/filesystem/src/Folder/ModuleScript/ModuleScript.lua +++ /dev/null @@ -1,3 +0,0 @@ -local module = {} - -return module diff --git a/test-files/scripts-with-scripts/filesystem/src/Folder/ModuleScript/init.lua b/test-files/scripts-with-scripts/filesystem/src/Folder/ModuleScript/init.lua deleted file mode 100644 index f4098ad..0000000 --- a/test-files/scripts-with-scripts/filesystem/src/Folder/ModuleScript/init.lua +++ /dev/null @@ -1,3 +0,0 @@ -local module = {} - -return module diff --git a/test-files/scripts-with-scripts/filesystem/src/Folder/Script/ModuleScript.lua b/test-files/scripts-with-scripts/filesystem/src/Folder/Script/ModuleScript.lua deleted file mode 100644 index f4098ad..0000000 --- a/test-files/scripts-with-scripts/filesystem/src/Folder/Script/ModuleScript.lua +++ /dev/null @@ -1,3 +0,0 @@ -local module = {} - -return module diff --git a/test-files/scripts-with-scripts/filesystem/src/Folder/Script/init.server.lua b/test-files/scripts-with-scripts/filesystem/src/Folder/Script/init.server.lua deleted file mode 100644 index f1a1813..0000000 --- a/test-files/scripts-with-scripts/filesystem/src/Folder/Script/init.server.lua +++ /dev/null @@ -1 +0,0 @@ -print("Hello world!") diff --git a/test-files/scripts-with-scripts/output.json b/test-files/scripts-with-scripts/output.json index b9f64a3..34b5c01 100644 --- a/test-files/scripts-with-scripts/output.json +++ b/test-files/scripts-with-scripts/output.json @@ -18,12 +18,12 @@ "contents": { "Vfs": { "files": { - "ModuleScript.lua": { + "ModuleScript.luau": { "contents": { "Bytes": "local module = {}\n\nreturn module\n" } }, - "init.client.lua": { + "init.client.luau": { "contents": { "Bytes": "print(\"Hello world!\")\n" } @@ -37,12 +37,12 @@ "contents": { "Vfs": { "files": { - "ModuleScript.lua": { + "ModuleScript.luau": { "contents": { "Bytes": "local module = {}\n\nreturn module\n" } }, - "init.lua": { + "init.luau": { "contents": { "Bytes": "local module = {}\n\nreturn module\n" } @@ -56,12 +56,12 @@ "contents": { "Vfs": { "files": { - "ModuleScript.lua": { + "ModuleScript.luau": { "contents": { "Bytes": "local module = {}\n\nreturn module\n" } }, - "init.server.lua": { + "init.server.luau": { "contents": { "Bytes": "print(\"Hello world!\")\n" } diff --git a/test-files/sword/filesystem/src/ClassicSword/MouseIcon.client.lua b/test-files/sword/filesystem/src/ClassicSword/MouseIcon.client.lua deleted file mode 100644 index 8b5d1c1..0000000 --- a/test-files/sword/filesystem/src/ClassicSword/MouseIcon.client.lua +++ /dev/null @@ -1,28 +0,0 @@ ---Made by Luckymaxer - -Mouse_Icon = "rbxasset://textures/GunCursor.png" -Reloading_Icon = "rbxasset://textures/GunWaitCursor.png" - -Tool = script.Parent - -Mouse = nil - -function UpdateIcon() - if Mouse then - Mouse.Icon = Tool.Enabled and Mouse_Icon or Reloading_Icon - end -end - -function OnEquipped(ToolMouse) - Mouse = ToolMouse - UpdateIcon() -end - -function OnChanged(Property) - if Property == "Enabled" then - UpdateIcon() - end -end - -Tool.Equipped:Connect(OnEquipped) -Tool.Changed:Connect(OnChanged) diff --git a/test-files/sword/filesystem/src/ClassicSword/SwordScript.server.lua b/test-files/sword/filesystem/src/ClassicSword/SwordScript.server.lua deleted file mode 100644 index f66f9d6..0000000 --- a/test-files/sword/filesystem/src/ClassicSword/SwordScript.server.lua +++ /dev/null @@ -1,229 +0,0 @@ ---Rescripted by Luckymaxer ---EUROCOW WAS HERE BECAUSE I MADE THE PARTICLES AND THEREFORE THIS ENTIRE SWORD PRETTY AND LOOK PRETTY WORDS AND I'D LIKE TO DEDICATE THIS TO MY FRIENDS AND HI LUCKYMAXER PLS FIX SFOTH SWORDS TY LOVE Y'ALl ---Updated for R15 avatars by StarWars ---Re-updated by TakeoHonorable - -Tool = script.Parent -Handle = Tool:WaitForChild("Handle") - -function Create(ty) - return function(data) - local obj = Instance.new(ty) - for k, v in pairs(data) do - if type(k) == 'number' then - v.Parent = obj - else - obj[k] = v - end - end - return obj - end -end - -local BaseUrl = "rbxassetid://" - -Players = game:GetService("Players") -Debris = game:GetService("Debris") -RunService = game:GetService("RunService") - -DamageValues = { - BaseDamage = 5, - SlashDamage = 10, - LungeDamage = 30 -} - ---For R15 avatars -Animations = { - R15Slash = 522635514, - R15Lunge = 522638767 -} - -Damage = DamageValues.BaseDamage - -Grips = { - Up = CFrame.new(0, 0, -1.70000005, 0, 0, 1, 1, 0, 0, 0, 1, 0), - Out = CFrame.new(0, 0, -1.70000005, 0, 1, 0, 1, -0, 0, 0, 0, -1) -} - -Sounds = { - Slash = Handle:WaitForChild("SwordSlash"), - Lunge = Handle:WaitForChild("SwordLunge"), - Unsheath = Handle:WaitForChild("Unsheath") -} - -ToolEquipped = false - ---For Omega Rainbow Katana thumbnail to display a lot of particles. -for i, v in pairs(Handle:GetChildren()) do - if v:IsA("ParticleEmitter") then - v.Rate = 20 - end -end - -Tool.Grip = Grips.Up -Tool.Enabled = true - -function IsTeamMate(Player1, Player2) - return (Player1 and Player2 and not Player1.Neutral and not Player2.Neutral and Player1.TeamColor == Player2.TeamColor) -end - -function TagHumanoid(humanoid, player) - local Creator_Tag = Instance.new("ObjectValue") - Creator_Tag.Name = "creator" - Creator_Tag.Value = player - Debris:AddItem(Creator_Tag, 2) - Creator_Tag.Parent = humanoid -end - -function UntagHumanoid(humanoid) - for i, v in pairs(humanoid:GetChildren()) do - if v:IsA("ObjectValue") and v.Name == "creator" then - v:Destroy() - end - end -end - -function Blow(Hit) - if not Hit or not Hit.Parent or not CheckIfAlive() or not ToolEquipped then - return - end - local RightArm = Character:FindFirstChild("Right Arm") or Character:FindFirstChild("RightHand") - if not RightArm then - return - end - local RightGrip = RightArm:FindFirstChild("RightGrip") - if not RightGrip or (RightGrip.Part0 ~= Handle and RightGrip.Part1 ~= Handle) then - return - end - local character = Hit.Parent - if character == Character then - return - end - local humanoid = character:FindFirstChildOfClass("Humanoid") - if not humanoid or humanoid.Health == 0 then - return - end - local player = Players:GetPlayerFromCharacter(character) - if player and (player == Player or IsTeamMate(Player, player)) then - return - end - UntagHumanoid(humanoid) - TagHumanoid(humanoid, Player) - humanoid:TakeDamage(Damage) -end - - -function Attack() - Damage = DamageValues.SlashDamage - Sounds.Slash:Play() - - if Humanoid then - if Humanoid.RigType == Enum.HumanoidRigType.R6 then - local Anim = Instance.new("StringValue") - Anim.Name = "toolanim" - Anim.Value = "Slash" - Anim.Parent = Tool - elseif Humanoid.RigType == Enum.HumanoidRigType.R15 then - local Anim = Tool:FindFirstChild("R15Slash") - if Anim then - local Track = Humanoid:LoadAnimation(Anim) - Track:Play(0) - end - end - end -end - -function Lunge() - Damage = DamageValues.LungeDamage - - Sounds.Lunge:Play() - - if Humanoid then - if Humanoid.RigType == Enum.HumanoidRigType.R6 then - local Anim = Instance.new("StringValue") - Anim.Name = "toolanim" - Anim.Value = "Lunge" - Anim.Parent = Tool - elseif Humanoid.RigType == Enum.HumanoidRigType.R15 then - local Anim = Tool:FindFirstChild("R15Lunge") - if Anim then - local Track = Humanoid:LoadAnimation(Anim) - Track:Play(0) - end - end - end - --[[ - if CheckIfAlive() then - local Force = Instance.new("BodyVelocity") - Force.velocity = Vector3.new(0, 10, 0) - Force.maxForce = Vector3.new(0, 4000, 0) - Debris:AddItem(Force, 0.4) - Force.Parent = Torso - end - ]] - - wait(0.2) - Tool.Grip = Grips.Out - wait(0.6) - Tool.Grip = Grips.Up - - Damage = DamageValues.SlashDamage -end - -Tool.Enabled = true -LastAttack = 0 - -function Activated() - if not Tool.Enabled or not ToolEquipped or not CheckIfAlive() then - return - end - Tool.Enabled = false - local Tick = RunService.Stepped:wait() - if (Tick - LastAttack < 0.2) then - Lunge() - else - Attack() - end - LastAttack = Tick - --wait(0.5) - Damage = DamageValues.BaseDamage - local SlashAnim = (Tool:FindFirstChild("R15Slash") or Create("Animation"){ - Name = "R15Slash", - AnimationId = BaseUrl .. Animations.R15Slash, - Parent = Tool - }) - - local LungeAnim = (Tool:FindFirstChild("R15Lunge") or Create("Animation"){ - Name = "R15Lunge", - AnimationId = BaseUrl .. Animations.R15Lunge, - Parent = Tool - }) - Tool.Enabled = true -end - -function CheckIfAlive() - return (((Player and Player.Parent and Character and Character.Parent and Humanoid and Humanoid.Parent and Humanoid.Health > 0 and Torso and Torso.Parent) and true) or false) -end - -function Equipped() - Character = Tool.Parent - Player = Players:GetPlayerFromCharacter(Character) - Humanoid = Character:FindFirstChildOfClass("Humanoid") - Torso = Character:FindFirstChild("Torso") or Character:FindFirstChild("HumanoidRootPart") - if not CheckIfAlive() then - return - end - ToolEquipped = true - Sounds.Unsheath:Play() -end - -function Unequipped() - Tool.Grip = Grips.Up - ToolEquipped = false -end - -Tool.Activated:Connect(Activated) -Tool.Equipped:Connect(Equipped) -Tool.Unequipped:Connect(Unequipped) - -Connection = Handle.Touched:Connect(Blow) \ No newline at end of file diff --git a/test-files/sword/output.json b/test-files/sword/output.json index 8794fd0..5fa6ebc 100644 --- a/test-files/sword/output.json +++ b/test-files/sword/output.json @@ -4,12 +4,12 @@ "contents": { "Vfs": { "files": { - "MouseIcon.client.lua": { + "MouseIcon.client.luau": { "contents": { "Bytes": "--Made by Luckymaxer\n\nMouse_Icon = \"rbxasset://textures/GunCursor.png\"\nReloading_Icon = \"rbxasset://textures/GunWaitCursor.png\"\n\nTool = script.Parent\n\nMouse = nil\n\nfunction UpdateIcon()\n\tif Mouse then\n\t\tMouse.Icon = Tool.Enabled and Mouse_Icon or Reloading_Icon\n\tend\nend\n\nfunction OnEquipped(ToolMouse)\n\tMouse = ToolMouse\n\tUpdateIcon()\nend\n\nfunction OnChanged(Property)\n\tif Property == \"Enabled\" then\n\t\tUpdateIcon()\n\tend\nend\n\nTool.Equipped:Connect(OnEquipped)\nTool.Changed:Connect(OnChanged)\n" } }, - "SwordScript.server.lua": { + "SwordScript.server.luau": { "contents": { "Bytes": "--Rescripted by Luckymaxer\n--EUROCOW WAS HERE BECAUSE I MADE THE PARTICLES AND THEREFORE THIS ENTIRE SWORD PRETTY AND LOOK PRETTY WORDS AND I'D LIKE TO DEDICATE THIS TO MY FRIENDS AND HI LUCKYMAXER PLS FIX SFOTH SWORDS TY LOVE Y'ALl\n--Updated for R15 avatars by StarWars\n--Re-updated by TakeoHonorable\n\nTool = script.Parent\nHandle = Tool:WaitForChild(\"Handle\")\n\nfunction Create(ty)\n\treturn function(data)\n\t\tlocal obj = Instance.new(ty)\n\t\tfor k, v in pairs(data) do\n\t\t\tif type(k) == 'number' then\n\t\t\t\tv.Parent = obj\n\t\t\telse\n\t\t\t\tobj[k] = v\n\t\t\tend\n\t\tend\n\t\treturn obj\n\tend\nend\n\nlocal BaseUrl = \"rbxassetid://\"\n\nPlayers = game:GetService(\"Players\")\nDebris = game:GetService(\"Debris\")\nRunService = game:GetService(\"RunService\")\n\nDamageValues = {\n\tBaseDamage = 5,\n\tSlashDamage = 10,\n\tLungeDamage = 30\n}\n\n--For R15 avatars\nAnimations = {\n\tR15Slash = 522635514,\n\tR15Lunge = 522638767\n}\n\nDamage = DamageValues.BaseDamage\n\nGrips = {\n\tUp = CFrame.new(0, 0, -1.70000005, 0, 0, 1, 1, 0, 0, 0, 1, 0),\n\tOut = CFrame.new(0, 0, -1.70000005, 0, 1, 0, 1, -0, 0, 0, 0, -1)\n}\n\nSounds = {\n\tSlash = Handle:WaitForChild(\"SwordSlash\"),\n\tLunge = Handle:WaitForChild(\"SwordLunge\"),\n\tUnsheath = Handle:WaitForChild(\"Unsheath\")\n}\n\nToolEquipped = false\n\n--For Omega Rainbow Katana thumbnail to display a lot of particles.\nfor i, v in pairs(Handle:GetChildren()) do\n\tif v:IsA(\"ParticleEmitter\") then\n\t\tv.Rate = 20\n\tend\nend\n\nTool.Grip = Grips.Up\nTool.Enabled = true\n\nfunction IsTeamMate(Player1, Player2)\n\treturn (Player1 and Player2 and not Player1.Neutral and not Player2.Neutral and Player1.TeamColor == Player2.TeamColor)\nend\n\nfunction TagHumanoid(humanoid, player)\n\tlocal Creator_Tag = Instance.new(\"ObjectValue\")\n\tCreator_Tag.Name = \"creator\"\n\tCreator_Tag.Value = player\n\tDebris:AddItem(Creator_Tag, 2)\n\tCreator_Tag.Parent = humanoid\nend\n\nfunction UntagHumanoid(humanoid)\n\tfor i, v in pairs(humanoid:GetChildren()) do\n\t\tif v:IsA(\"ObjectValue\") and v.Name == \"creator\" then\n\t\t\tv:Destroy()\n\t\tend\n\tend\nend\n\nfunction Blow(Hit)\n\tif not Hit or not Hit.Parent or not CheckIfAlive() or not ToolEquipped then\n\t\treturn\n\tend\n\tlocal RightArm = Character:FindFirstChild(\"Right Arm\") or Character:FindFirstChild(\"RightHand\")\n\tif not RightArm then\n\t\treturn\n\tend\n\tlocal RightGrip = RightArm:FindFirstChild(\"RightGrip\")\n\tif not RightGrip or (RightGrip.Part0 ~= Handle and RightGrip.Part1 ~= Handle) then\n\t\treturn\n\tend\n\tlocal character = Hit.Parent\n\tif character == Character then\n\t\treturn\n\tend\n\tlocal humanoid = character:FindFirstChildOfClass(\"Humanoid\")\n\tif not humanoid or humanoid.Health == 0 then\n\t\treturn\n\tend\n\tlocal player = Players:GetPlayerFromCharacter(character)\n\tif player and (player == Player or IsTeamMate(Player, player)) then\n\t\treturn\n\tend\n\tUntagHumanoid(humanoid)\n\tTagHumanoid(humanoid, Player)\n\thumanoid:TakeDamage(Damage)\t\nend\n\n\nfunction Attack()\n\tDamage = DamageValues.SlashDamage\n\tSounds.Slash:Play()\n\n\tif Humanoid then\n\t\tif Humanoid.RigType == Enum.HumanoidRigType.R6 then\n\t\t\tlocal Anim = Instance.new(\"StringValue\")\n\t\t\tAnim.Name = \"toolanim\"\n\t\t\tAnim.Value = \"Slash\"\n\t\t\tAnim.Parent = Tool\n\t\telseif Humanoid.RigType == Enum.HumanoidRigType.R15 then\n\t\t\tlocal Anim = Tool:FindFirstChild(\"R15Slash\")\n\t\t\tif Anim then\n\t\t\t\tlocal Track = Humanoid:LoadAnimation(Anim)\n\t\t\t\tTrack:Play(0)\n\t\t\tend\n\t\tend\n\tend\t\nend\n\nfunction Lunge()\n\tDamage = DamageValues.LungeDamage\n\n\tSounds.Lunge:Play()\n\t\n\tif Humanoid then\n\t\tif Humanoid.RigType == Enum.HumanoidRigType.R6 then\n\t\t\tlocal Anim = Instance.new(\"StringValue\")\n\t\t\tAnim.Name = \"toolanim\"\n\t\t\tAnim.Value = \"Lunge\"\n\t\t\tAnim.Parent = Tool\n\t\telseif Humanoid.RigType == Enum.HumanoidRigType.R15 then\n\t\t\tlocal Anim = Tool:FindFirstChild(\"R15Lunge\")\n\t\t\tif Anim then\n\t\t\t\tlocal Track = Humanoid:LoadAnimation(Anim)\n\t\t\t\tTrack:Play(0)\n\t\t\tend\n\t\tend\n\tend\t\n\t--[[\n\tif CheckIfAlive() then\n\t\tlocal Force = Instance.new(\"BodyVelocity\")\n\t\tForce.velocity = Vector3.new(0, 10, 0) \n\t\tForce.maxForce = Vector3.new(0, 4000, 0)\n\t\tDebris:AddItem(Force, 0.4)\n\t\tForce.Parent = Torso\n\tend\n\t]]\n\t\n\twait(0.2)\n\tTool.Grip = Grips.Out\n\twait(0.6)\n\tTool.Grip = Grips.Up\n\n\tDamage = DamageValues.SlashDamage\nend\n\nTool.Enabled = true\nLastAttack = 0\n\nfunction Activated()\n\tif not Tool.Enabled or not ToolEquipped or not CheckIfAlive() then\n\t\treturn\n\tend\n\tTool.Enabled = false\n\tlocal Tick = RunService.Stepped:wait()\n\tif (Tick - LastAttack < 0.2) then\n\t\tLunge()\n\telse\n\t\tAttack()\n\tend\n\tLastAttack = Tick\n\t--wait(0.5)\n\tDamage = DamageValues.BaseDamage\n\tlocal SlashAnim = (Tool:FindFirstChild(\"R15Slash\") or Create(\"Animation\"){\n\t\tName = \"R15Slash\",\n\t\tAnimationId = BaseUrl .. Animations.R15Slash,\n\t\tParent = Tool\n\t})\n\t\n\tlocal LungeAnim = (Tool:FindFirstChild(\"R15Lunge\") or Create(\"Animation\"){\n\t\tName = \"R15Lunge\",\n\t\tAnimationId = BaseUrl .. Animations.R15Lunge,\n\t\tParent = Tool\n\t})\n\tTool.Enabled = true\nend\n\nfunction CheckIfAlive()\n\treturn (((Player and Player.Parent and Character and Character.Parent and Humanoid and Humanoid.Parent and Humanoid.Health > 0 and Torso and Torso.Parent) and true) or false)\nend\n\nfunction Equipped()\n\tCharacter = Tool.Parent\n\tPlayer = Players:GetPlayerFromCharacter(Character)\n\tHumanoid = Character:FindFirstChildOfClass(\"Humanoid\")\n\tTorso = Character:FindFirstChild(\"Torso\") or Character:FindFirstChild(\"HumanoidRootPart\")\n\tif not CheckIfAlive() then\n\t\treturn\n\tend\n\tToolEquipped = true\n\tSounds.Unsheath:Play()\nend\n\nfunction Unequipped()\n\tTool.Grip = Grips.Up\n\tToolEquipped = false\nend\n\nTool.Activated:Connect(Activated)\nTool.Equipped:Connect(Equipped)\nTool.Unequipped:Connect(Unequipped)\n\nConnection = Handle.Touched:Connect(Blow)" }