From 8541916f42082d4d21ef2072eddc0b73dff855eb Mon Sep 17 00:00:00 2001 From: activejoey60 Date: Mon, 30 Oct 2023 20:06:33 -0400 Subject: [PATCH] rbxlx-to-rojo --- .gitignore | 8 + rojo/MainMenu/default.project.json | 40 + .../ReplicatedStorage/Classes/DataHandler.lua | 253 +++ .../Classes/TeleportHandler.lua | 45 + .../Classes/UIFramework/Button.lua | 3 + .../Classes/UIFramework/Camera.lua | 3 + .../Classes/UIFramework/Game.lua | 3 + .../Classes/UIFramework/init.lua | 3 + .../ReplicatedStorage/Classes/init.meta.json | 3 + .../Modules/Menu/Blog/100,000 visits.lua | 39 + .../Modules/Menu/Blog/Building Contest | 0 .../Menu/Blog/FWM Guide - BrickBattle.lua | 40 + .../Modules/Menu/Blog/Welcome!.lua | 25 + .../Modules/Menu/Blog/init.lua | 7 + .../ReplicatedStorage/Modules/Menu/Games.lua | 977 +++++++++++ .../Modules/Menu/GrabStuff.lua | 241 +++ .../Modules/Menu/HelpPages.lua | 13 + .../Modules/Menu/TweenWrapper.lua | 30 + .../Modules/Menu/UILibrary.lua | 80 + .../Modules/Menu/VpfRayCast/GJK.lua | 259 +++ .../Modules/Menu/VpfRayCast/init.lua | 246 +++ .../Modules/Menu/init.meta.json | 3 + .../ReplicatedStorage/Modules/init.meta.json | 3 + .../ViewportFrame/Preview/Animate.client.lua | 260 +++ .../ViewportFrame/Preview/Animate.meta.json | 3 + .../ViewportFrame/Preview/init.meta.json | 4 + .../FriendAvatar/ViewportFrame/init.meta.json | 4 + .../Guis/Friend/FriendAvatar/init.meta.json | 4 + .../Templates/Guis/Friend/init.meta.json | 4 + .../PlayButton/Button/Main.client.lua | 19 + .../PlayButton/Button/init.meta.json | 4 + .../GameContainer/PlayButton/init.meta.json | 4 + .../PlaySoloButton/Button/Main.client.lua | 19 + .../PlaySoloButton/Button/init.meta.json | 4 + .../PlaySoloButton/init.meta.json | 4 + .../Guis/GameContainer/init.meta.json | 4 + .../Templates/Guis/init.meta.json | 3 + .../Templates/init.meta.json | 3 + .../BanScreen/OminousMusic.client.lua | 6 + .../BackendMain/BanScreen/init.meta.json | 4 + .../BackendMain/init.server.lua | 1059 +++++++++++ .../src/ServerScriptService/Musik.server.lua | 141 ++ .../src/ServerScriptService/Script.server.lua | 7 + .../Subscription.server.lua | 38 + .../ServerScriptService/UIProvider.server.lua | 32 + .../Archive/UnfinishedAssets/Profiles.lua | 34 + .../Archive/UnfinishedAssets/init.meta.json | 3 + .../src/ServerStorage/Archive/init.meta.json | 3 + .../Smooth Block Model/Script.server.lua | 4 + .../Smooth Block Model/init.meta.json | 4 + .../ServerStorage/Crossroads/init.meta.json | 4 + .../WitchRoom/Cauldron/WitchBrew.server.lua | 29 + .../WitchRoom/Cauldron/init.meta.json | 4 + .../RegenFurniture/WitchRoom/init.meta.json | 4 + .../RegenFurniture/init.meta.json | 4 + .../Home/haunted house/init.meta.json | 4 + .../src/ServerStorage/Home/init.meta.json | 4 + .../Settings/Light/Script.server.lua | 5 + .../Settings/Light/init.meta.json | 4 + .../Smooth Block Model/Script.server.lua | 4 + .../Smooth Block Model/init.meta.json | 4 + .../src/ServerStorage/Settings/init.meta.json | 4 + .../Preview/Animate.client.lua | 269 +++ .../Preview/Animate.meta.json | 3 + .../Preview/init.meta.json | 4 + .../AvatarPreviewShadow/init.meta.json | 4 + .../AvatarPreview/Preview/Animate.client.lua | 268 +++ .../AvatarPreview/Preview/Animate.meta.json | 3 + .../AvatarPreview/Preview/init.meta.json | 4 + .../AvatarPreview/init.meta.json | 4 + .../AvatarPreviewContainer/init.meta.json | 4 + .../MainUI/Content/AvatarPage/init.meta.json | 4 + .../ViewportFrame/Preview/Animate.client.lua | 260 +++ .../ViewportFrame/Preview/Animate.meta.json | 3 + .../ViewportFrame/Preview/init.meta.json | 4 + .../ViewportFrame/init.meta.json | 4 + .../Profile/AvatarPreview/init.meta.json | 4 + .../Container/Profile/init.meta.json | 4 + .../ProfileContainer/Container/init.meta.json | 4 + .../ProfileContainer/init.meta.json | 4 + .../HomePage/HomePageContainer/init.meta.json | 4 + .../MainUI/Content/HomePage/init.meta.json | 4 + .../ViewportFrame/Preview/Animate.client.lua | 260 +++ .../ViewportFrame/Preview/Animate.meta.json | 3 + .../ViewportFrame/Preview/init.meta.json | 4 + .../ViewportFrame/init.meta.json | 4 + .../Profile/AvatarPreview/init.meta.json | 4 + .../Container/Profile/init.meta.json | 4 + .../ProfileContainer/Container/init.meta.json | 4 + .../ProfileContainer/init.meta.json | 4 + .../PlayButton/Button/Main.client.lua | 19 + .../PlayButton/Button/init.meta.json | 4 + .../JoinOptions/PlayButton/init.meta.json | 4 + .../PlaySoloButton/Button/Main.client.lua | 19 + .../PlaySoloButton/Button/init.meta.json | 4 + .../JoinOptions/PlaySoloButton/init.meta.json | 4 + .../PlaceContainer/JoinOptions/init.meta.json | 4 + .../PlaceContainer/init.meta.json | 4 + .../StatisticContainer/init.meta.json | 4 + .../ProfilesPage/UserProfile/init.meta.json | 4 + .../Content/ProfilesPage/init.meta.json | 4 + .../StarterGui/MainUI/Content/init.meta.json | 4 + .../MainUI/NewGuiHandler.client.lua | 1020 +++++++++++ .../StarterGui/MainUI/UIHandler.client.lua | 1340 ++++++++++++++ .../src/StarterGui/MainUI/init.meta.json | 4 + .../RocketLauncher/Client.client.lua | 9 + .../RocketLauncher/MouseIcon.client.lua | 26 + .../RocketLauncher/Server/Rocket.server.lua | 154 ++ .../RocketLauncher/Server/init.meta.json | 3 + .../RocketLauncher/Server/init.server.lua | 112 ++ .../StarterPack/RocketLauncher/init.meta.json | 4 + .../CameraHandler.client.lua | 30 + .../LegacyVisualsClient.client.lua | 400 +++++ rojo/MainModule/default.project.json | 6 + .../ReplicatedStorage/Modules/BreakJoints.lua | 24 + .../Modules/BrickBattleToolsHandler.lua | 4 + .../ReplicatedStorage/Modules/BrickColor.lua | 67 + .../Modules/CustomCamera.lua | 61 + .../ReplicatedStorage/Modules/CustomFont.lua | 349 ++++ .../Modules/CustomMouseFunctions.lua | 197 +++ .../ReplicatedStorage/Modules/Diogenes.lua | 7 + .../Modules/DraggableObject.lua | 120 ++ .../ReplicatedStorage/Modules/MakeJoints.lua | 104 ++ .../ReplicatedStorage/Modules/MouseIcon.lua | 61 + .../ReplicatedStorage/Modules/StockSound.lua | 27 + .../Modules/SuperSafeChat.lua | 773 ++++++++ .../Modules/TextureGroups.lua | 308 ++++ .../ReplicatedStorage/Modules/TimePeriods.lua | 12 + .../src/ReplicatedStorage/Modules/Toolbox.lua | 61 + .../ReplicatedStorage/Modules/init.meta.json | 3 + .../src/ReplicatedStorage/init.meta.json | 3 + .../AdminServer/KillAura.server.lua | 57 + .../AdminServer/init.server.lua | 391 +++++ .../ServerScriptService/Chat/MuteSystem.lua | 39 + .../ServerScriptService/Chat/init.server.lua | 154 ++ .../ServerScriptService/GameCount.server.lua | 46 + .../LegacyVisualsServer.server.lua | 173 ++ .../PlayerHandler.server.lua | 427 +++++ .../ToolboxServer.server.lua | 42 + .../src/ServerScriptService/init.meta.json | 3 + .../Accessories/Gloves/Script.server.lua | 17 + .../Accessories/Gloves/init.meta.json | 4 + .../ServerStorage/Accessories/init.meta.json | 3 + .../ServerStorage/Dependencies/Explosion.lua | 73 + .../ServerStorage/Dependencies/init.meta.json | 3 + .../HopperBins/Clone/Client.client.lua | 146 ++ .../HopperBins/Clone/Server.server.lua | 71 + .../HopperBins/Clone/init.meta.json | 4 + .../GameTool/GameToolLocal.client.lua | 170 ++ .../GameTool/GameToolScript.server.lua | 61 + .../HopperBins/GameTool/init.meta.json | 4 + .../HopperBins/Grab/GrabToolLocal.client.lua | 212 +++ .../HopperBins/Grab/GrabToolScript.server.lua | 63 + .../HopperBins/Grab/init.meta.json | 4 + .../HopperBins/Hammer/HammerLocal.client.lua | 101 ++ .../HopperBins/Hammer/HammerScript.server.lua | 45 + .../HopperBins/Hammer/init.meta.json | 4 + .../HopperBins/Laser/Client.client.lua | 40 + .../HopperBins/Laser/Server.server.lua | 44 + .../HopperBins/Laser/init.meta.json | 4 + .../HopperBins/Rocket/Client.client.lua | 36 + .../HopperBins/Rocket/Launcher.server.lua | 64 + .../HopperBins/Rocket/RocketScript.server.lua | 71 + .../HopperBins/Rocket/init.meta.json | 4 + .../HopperBins/Slingshot/Client.client.lua | 58 + .../Slingshot/PelletScript.server.lua | 50 + .../HopperBins/Slingshot/Slingshot.server.lua | 115 ++ .../HopperBins/Slingshot/init.meta.json | 4 + .../ServerStorage/HopperBins/init.meta.json | 3 + .../src/ServerStorage/ToolHandlers/Rocket.lua | 13 + .../ServerStorage/ToolHandlers/init.meta.json | 3 + .../UI/AdminGuis/Admi/AdminClient.client.lua | 575 ++++++ .../UI/AdminGuis/Admi/AdminClient.meta.json | 3 + .../UI/AdminGuis/Admi/init.meta.json | 4 + .../ESP/ESP/fartware/display/bounding.lua | 58 + .../ESP/ESP/fartware/display/cull.lua | 53 + .../ESP/ESP/fartware/display/init.lua | 145 ++ .../ESP/ESP/fartware/display/init.meta.json | 3 + .../ESP/ESP/fartware/display/skeleton.lua | 122 ++ .../ESP/ESP/fartware/init.client.lua | 94 + .../UI/AdminGuis/ESP/ESP/init.meta.json | 4 + .../UI/AdminGuis/ESP/init.meta.json | 4 + .../ServerStorage/UI/AdminGuis/init.meta.json | 3 + .../ClientLocalPlayerScripts.client.lua | 112 ++ .../Loading/LoadingHandler.client.lua | 161 ++ .../UI/StarterGui/Loading/init.meta.json | 4 + .../MainGui/MainGuiHandler.client.lua | 1344 ++++++++++++++ .../MainGui/MainGuiOffset.client.lua | 53 + .../ToolboxHandler/ScrollbarXP/Util.lua | 89 + .../ToolboxHandler/ScrollbarXP/init.lua | 249 +++ .../ToolboxHandler/ScrollbarXP/init.meta.json | 3 + .../ToolboxHandler/init.client.lua | 40 + .../MainGui/ToolboxWindow/init.meta.json | 4 + .../UI/StarterGui/MainGui/init.meta.json | 4 + .../MainResetGuiHandler.client.lua | 616 +++++++ .../UI/StarterGui/MainResetGui/init.meta.json | 4 + .../UI/StarterGui/init.meta.json | 3 + .../src/ServerStorage/UI/init.meta.json | 3 + .../src/ServerStorage/init.meta.json | 3 + .../CharacterMainReRewrite.client.lua | 629 +++++++ .../RobloxTeam.server.lua | 55 + .../StarterCharacterScripts/init.meta.json | 3 + .../ControllerFlagHandler.client.lua | 196 +++ .../MainGui/MainGuiHandler.client.lua | 1344 ++++++++++++++ .../MainGui/MainGuiOffset.client.lua | 53 + .../ToolboxHandler/ScrollbarXP/Util.lua | 89 + .../ToolboxHandler/ScrollbarXP/init.lua | 249 +++ .../ToolboxHandler/ScrollbarXP/init.meta.json | 3 + .../ToolboxHandler/init.client.lua | 40 + .../MainGui/ToolboxWindow/init.meta.json | 4 + .../src/StarterGui/MainGui/init.meta.json | 4 + .../MainResetGuiHandler.client.lua | 616 +++++++ .../StarterGui/MainResetGui/init.meta.json | 4 + rojo/MainModule/src/StarterGui/init.meta.json | 3 + .../CameraScript/Invisicam.lua | 584 ++++++ .../CameraScript/PopperCam.lua | 243 +++ .../CameraScript/RootCamera/AttachCamera.lua | 75 + .../CameraScript/RootCamera/ClassicCamera.lua | 261 +++ .../CameraScript/RootCamera/FixedCamera.lua | 48 + .../CameraScript/RootCamera/FollowCamera.lua | 230 +++ .../CameraScript/RootCamera/OrbitalCamera.lua | 450 +++++ .../RootCamera/ScriptableCamera.lua | 12 + .../CameraScript/RootCamera/TrackCamera.lua | 54 + .../CameraScript/RootCamera/VRCamera.lua | 0 .../CameraScript/RootCamera/WatchCamera.lua | 63 + .../CameraScript/RootCamera/init.lua | 1558 +++++++++++++++++ .../CameraScript/ShiftLockController.lua | 206 +++ .../CameraScript/init.client.lua | 324 ++++ .../ControlScript/MasterControl/DPad.lua | 170 ++ .../MasterControl/DynamicThumbstick.lua | 559 ++++++ .../ControlScript/MasterControl/Gamepad.lua | 198 +++ .../MasterControl/KeyboardMovement.lua | 176 ++ .../ControlScript/MasterControl/Thumbpad.lua | 228 +++ .../MasterControl/Thumbstick.lua | 178 ++ .../ControlScript/MasterControl/TouchJump.lua | 172 ++ .../MasterControl/VRNavigation.lua | 433 +++++ .../MasterControl/VRNavigation.meta.json | 3 + .../MasterControl/VehicleController.lua | 180 ++ .../ControlScript/MasterControl/init.lua | 181 ++ .../ControlScript/PathDisplay.lua | 131 ++ .../ControlScript/init.client.lua | 450 +++++ .../StarterPlayerScripts/DevInfo.client.lua | 16 + .../StarterPlayerScripts/FPSCap.client.lua | 12 + .../GraphicsPipeline/Explosions.lua | 31 + .../GraphicsPipeline/Humanoid.lua | 185 ++ .../GraphicsPipeline/Humanoid.meta.json | 3 + .../GraphicsPipeline/Replacements.lua | 107 ++ .../GraphicsPipeline/SkyElements.lua | 538 ++++++ .../GraphicsPipeline/SkyElements.meta.json | 3 + .../GraphicsPipeline/Surfaces.lua | 341 ++++ .../GraphicsPipeline/Surfaces.meta.json | 3 + .../GraphicsPipeline/init.client.lua | 47 + .../GraphicsPipelineNEW.client.lua | 112 ++ .../RbxCharacterAnimations/Character.lua | 185 ++ .../States/Climbing.lua | 12 + .../States/Freefall.lua | 10 + .../RbxCharacterAnimations/States/Jumping.lua | 10 + .../RbxCharacterAnimations/States/Running.lua | 46 + .../RbxCharacterAnimations/States/Seated.lua | 10 + .../States/init.meta.json | 3 + .../RbxCharacterAnimations/init.client.lua | 59 + .../RbxCharacterSounds.client.lua | 296 ++++ .../src/StarterPlayerScripts/init.meta.json | 3 + rojo/MainModule/src/init.lua | 96 + rojo/MainModule/src/init.meta.json | 3 + 265 files changed, 29768 insertions(+) create mode 100644 .gitignore create mode 100644 rojo/MainMenu/default.project.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Classes/DataHandler.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Classes/TeleportHandler.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/Button.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/Camera.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/Game.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/init.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Classes/init.meta.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/100,000 visits.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/Building Contest create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/FWM Guide - BrickBattle.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/Welcome!.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/init.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Games.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/GrabStuff.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/HelpPages.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/TweenWrapper.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/UILibrary.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/VpfRayCast/GJK.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/VpfRayCast/init.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/init.meta.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Modules/init.meta.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/Preview/Animate.client.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/Preview/Animate.meta.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/Preview/init.meta.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/init.meta.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/init.meta.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/init.meta.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlayButton/Button/Main.client.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlayButton/Button/init.meta.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlayButton/init.meta.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlaySoloButton/Button/Main.client.lua create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlaySoloButton/Button/init.meta.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlaySoloButton/init.meta.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/init.meta.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/init.meta.json create mode 100644 rojo/MainMenu/src/ReplicatedStorage/Templates/init.meta.json create mode 100644 rojo/MainMenu/src/ServerScriptService/BackendMain/BanScreen/OminousMusic.client.lua create mode 100644 rojo/MainMenu/src/ServerScriptService/BackendMain/BanScreen/init.meta.json create mode 100644 rojo/MainMenu/src/ServerScriptService/BackendMain/init.server.lua create mode 100644 rojo/MainMenu/src/ServerScriptService/Musik.server.lua create mode 100644 rojo/MainMenu/src/ServerScriptService/Script.server.lua create mode 100644 rojo/MainMenu/src/ServerScriptService/Subscription.server.lua create mode 100644 rojo/MainMenu/src/ServerScriptService/UIProvider.server.lua create mode 100644 rojo/MainMenu/src/ServerStorage/Archive/UnfinishedAssets/Profiles.lua create mode 100644 rojo/MainMenu/src/ServerStorage/Archive/UnfinishedAssets/init.meta.json create mode 100644 rojo/MainMenu/src/ServerStorage/Archive/init.meta.json create mode 100644 rojo/MainMenu/src/ServerStorage/Crossroads/Smooth Block Model/Script.server.lua create mode 100644 rojo/MainMenu/src/ServerStorage/Crossroads/Smooth Block Model/init.meta.json create mode 100644 rojo/MainMenu/src/ServerStorage/Crossroads/init.meta.json create mode 100644 rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/WitchRoom/Cauldron/WitchBrew.server.lua create mode 100644 rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/WitchRoom/Cauldron/init.meta.json create mode 100644 rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/WitchRoom/init.meta.json create mode 100644 rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/init.meta.json create mode 100644 rojo/MainMenu/src/ServerStorage/Home/haunted house/init.meta.json create mode 100644 rojo/MainMenu/src/ServerStorage/Home/init.meta.json create mode 100644 rojo/MainMenu/src/ServerStorage/Settings/Light/Script.server.lua create mode 100644 rojo/MainMenu/src/ServerStorage/Settings/Light/init.meta.json create mode 100644 rojo/MainMenu/src/ServerStorage/Settings/Smooth Block Model/Script.server.lua create mode 100644 rojo/MainMenu/src/ServerStorage/Settings/Smooth Block Model/init.meta.json create mode 100644 rojo/MainMenu/src/ServerStorage/Settings/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/Preview/Animate.client.lua create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/Preview/Animate.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/Preview/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/Preview/Animate.client.lua create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/Preview/Animate.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/Preview/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.client.lua create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.client.lua create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlayButton/Button/Main.client.lua create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlayButton/Button/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlayButton/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlaySoloButton/Button/Main.client.lua create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlaySoloButton/Button/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlaySoloButton/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/Content/init.meta.json create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/NewGuiHandler.client.lua create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/UIHandler.client.lua create mode 100644 rojo/MainMenu/src/StarterGui/MainUI/init.meta.json create mode 100644 rojo/MainMenu/src/StarterPack/RocketLauncher/Client.client.lua create mode 100644 rojo/MainMenu/src/StarterPack/RocketLauncher/MouseIcon.client.lua create mode 100644 rojo/MainMenu/src/StarterPack/RocketLauncher/Server/Rocket.server.lua create mode 100644 rojo/MainMenu/src/StarterPack/RocketLauncher/Server/init.meta.json create mode 100644 rojo/MainMenu/src/StarterPack/RocketLauncher/Server/init.server.lua create mode 100644 rojo/MainMenu/src/StarterPack/RocketLauncher/init.meta.json create mode 100644 rojo/MainMenu/src/StarterPlayer/StarterPlayerScripts/CameraHandler.client.lua create mode 100644 rojo/MainMenu/src/StarterPlayer/StarterPlayerScripts/LegacyVisualsClient.client.lua create mode 100644 rojo/MainModule/default.project.json create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/BreakJoints.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/BrickBattleToolsHandler.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/BrickColor.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/CustomCamera.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/CustomFont.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/CustomMouseFunctions.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/Diogenes.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/DraggableObject.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/MakeJoints.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/MouseIcon.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/StockSound.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/SuperSafeChat.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/TextureGroups.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/TimePeriods.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/Toolbox.lua create mode 100644 rojo/MainModule/src/ReplicatedStorage/Modules/init.meta.json create mode 100644 rojo/MainModule/src/ReplicatedStorage/init.meta.json create mode 100644 rojo/MainModule/src/ServerScriptService/AdminServer/KillAura.server.lua create mode 100644 rojo/MainModule/src/ServerScriptService/AdminServer/init.server.lua create mode 100644 rojo/MainModule/src/ServerScriptService/Chat/MuteSystem.lua create mode 100644 rojo/MainModule/src/ServerScriptService/Chat/init.server.lua create mode 100644 rojo/MainModule/src/ServerScriptService/GameCount.server.lua create mode 100644 rojo/MainModule/src/ServerScriptService/LegacyVisualsServer.server.lua create mode 100644 rojo/MainModule/src/ServerScriptService/PlayerHandler.server.lua create mode 100644 rojo/MainModule/src/ServerScriptService/ToolboxServer.server.lua create mode 100644 rojo/MainModule/src/ServerScriptService/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/Accessories/Gloves/Script.server.lua create mode 100644 rojo/MainModule/src/ServerStorage/Accessories/Gloves/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/Accessories/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/Dependencies/Explosion.lua create mode 100644 rojo/MainModule/src/ServerStorage/Dependencies/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Clone/Client.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Clone/Server.server.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Clone/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/GameTool/GameToolLocal.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/GameTool/GameToolScript.server.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/GameTool/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Grab/GrabToolLocal.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Grab/GrabToolScript.server.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Grab/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Hammer/HammerLocal.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Hammer/HammerScript.server.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Hammer/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Laser/Client.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Laser/Server.server.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Laser/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Rocket/Client.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Rocket/Launcher.server.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Rocket/RocketScript.server.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Rocket/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/Client.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/PelletScript.server.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/Slingshot.server.lua create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/HopperBins/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/ToolHandlers/Rocket.lua create mode 100644 rojo/MainModule/src/ServerStorage/ToolHandlers/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/UI/AdminGuis/Admi/AdminClient.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/UI/AdminGuis/Admi/AdminClient.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/UI/AdminGuis/Admi/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/bounding.lua create mode 100644 rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/cull.lua create mode 100644 rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/init.lua create mode 100644 rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/skeleton.lua create mode 100644 rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/init.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/UI/AdminGuis/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/UI/StarterGui/ClientLocalPlayerScripts.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/UI/StarterGui/Loading/LoadingHandler.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/UI/StarterGui/Loading/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/MainGuiHandler.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/MainGuiOffset.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/Util.lua create mode 100644 rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.lua create mode 100644 rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/init.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/UI/StarterGui/MainResetGui/MainResetGuiHandler.client.lua create mode 100644 rojo/MainModule/src/ServerStorage/UI/StarterGui/MainResetGui/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/UI/StarterGui/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/UI/init.meta.json create mode 100644 rojo/MainModule/src/ServerStorage/init.meta.json create mode 100644 rojo/MainModule/src/StarterCharacterScripts/CharacterMainReRewrite.client.lua create mode 100644 rojo/MainModule/src/StarterCharacterScripts/RobloxTeam.server.lua create mode 100644 rojo/MainModule/src/StarterCharacterScripts/init.meta.json create mode 100644 rojo/MainModule/src/StarterGui/ControllerFlagHandler.client.lua create mode 100644 rojo/MainModule/src/StarterGui/MainGui/MainGuiHandler.client.lua create mode 100644 rojo/MainModule/src/StarterGui/MainGui/MainGuiOffset.client.lua create mode 100644 rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/Util.lua create mode 100644 rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.lua create mode 100644 rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.meta.json create mode 100644 rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/init.client.lua create mode 100644 rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/init.meta.json create mode 100644 rojo/MainModule/src/StarterGui/MainGui/init.meta.json create mode 100644 rojo/MainModule/src/StarterGui/MainResetGui/MainResetGuiHandler.client.lua create mode 100644 rojo/MainModule/src/StarterGui/MainResetGui/init.meta.json create mode 100644 rojo/MainModule/src/StarterGui/init.meta.json create mode 100644 rojo/MainModule/src/StarterPlayerScripts/CameraScript/Invisicam.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/CameraScript/PopperCam.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/AttachCamera.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/ClassicCamera.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/FixedCamera.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/FollowCamera.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/OrbitalCamera.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/ScriptableCamera.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/TrackCamera.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/VRCamera.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/WatchCamera.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/init.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/CameraScript/ShiftLockController.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/CameraScript/init.client.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/DPad.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/DynamicThumbstick.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/Gamepad.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/KeyboardMovement.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/Thumbpad.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/Thumbstick.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/TouchJump.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/VRNavigation.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/VRNavigation.meta.json create mode 100644 rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/VehicleController.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/init.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/ControlScript/PathDisplay.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/ControlScript/init.client.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/DevInfo.client.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/FPSCap.client.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Explosions.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Humanoid.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Humanoid.meta.json create mode 100644 rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Replacements.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/SkyElements.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/SkyElements.meta.json create mode 100644 rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Surfaces.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Surfaces.meta.json create mode 100644 rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/init.client.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/GraphicsPipelineNEW.client.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/RbxCharacterAnimations/Character.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/RbxCharacterAnimations/States/Climbing.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/RbxCharacterAnimations/States/Freefall.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/RbxCharacterAnimations/States/Jumping.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/RbxCharacterAnimations/States/Running.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/RbxCharacterAnimations/States/Seated.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/RbxCharacterAnimations/States/init.meta.json create mode 100644 rojo/MainModule/src/StarterPlayerScripts/RbxCharacterAnimations/init.client.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/RbxCharacterSounds.client.lua create mode 100644 rojo/MainModule/src/StarterPlayerScripts/init.meta.json create mode 100644 rojo/MainModule/src/init.lua create mode 100644 rojo/MainModule/src/init.meta.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6ce7abd --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.vscode + +*.rbxl.lock +*.rbxlx.lock + +.DS_Store + +rbxlx-to-rojo.log \ No newline at end of file diff --git a/rojo/MainMenu/default.project.json b/rojo/MainMenu/default.project.json new file mode 100644 index 0000000..6367296 --- /dev/null +++ b/rojo/MainMenu/default.project.json @@ -0,0 +1,40 @@ +{ + "name": "project", + "tree": { + "$className": "DataModel", + "ReplicatedStorage": { + "$className": "ReplicatedStorage", + "$ignoreUnknownInstances": true, + "$path": "src/ReplicatedStorage" + }, + "ServerScriptService": { + "$className": "ServerScriptService", + "$ignoreUnknownInstances": true, + "$path": "src/ServerScriptService" + }, + "ServerStorage": { + "$className": "ServerStorage", + "$ignoreUnknownInstances": true, + "$path": "src/ServerStorage" + }, + "StarterGui": { + "$className": "StarterGui", + "$ignoreUnknownInstances": true, + "$path": "src/StarterGui" + }, + "StarterPack": { + "$className": "StarterPack", + "$ignoreUnknownInstances": true, + "$path": "src/StarterPack" + }, + "StarterPlayer": { + "$className": "StarterPlayer", + "StarterPlayerScripts": { + "$className": "StarterPlayerScripts", + "$ignoreUnknownInstances": true, + "$path": "src/StarterPlayer/StarterPlayerScripts" + }, + "$ignoreUnknownInstances": true + } + } +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Classes/DataHandler.lua b/rojo/MainMenu/src/ReplicatedStorage/Classes/DataHandler.lua new file mode 100644 index 0000000..c389385 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Classes/DataHandler.lua @@ -0,0 +1,253 @@ +-- i am still learning this "oop" thing, god i hate the abbreviation +-- also feel free to tell me whether this oop code sucks or not PLZ +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local GrabbedStuff = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("Menu"):WaitForChild("GrabStuff")) + +DataHandler = {} +DataHandler.__index = DataHandler + +function DataHandler.New(newdata, plruserid) + if newdata then + local NewTab = {} + NewTab.data = newdata + NewTab.userdata = newdata["FWM_USER_DATA_"..tostring(plruserid)] or nil + + setmetatable(NewTab, DataHandler) + + return NewTab + else + return nil + end +end + +function DataHandler:changeSetting(changing, newval) + --local userData = self.userdata + + --if userData then + -- local playerData = self.userdata["PlayerData"] + + -- if playerData then + -- local otherUserData = playerData["UserData"] + -- local userSettings = otherUserData["Settings"] + + -- local foundSetting = userSettings[changing] + + -- if foundSetting ~= nil then + -- userSettings[changing] = newval + -- end + -- end + --end + + if self.userdata and self.userdata["PlayerData"]["UserData"]["Settings"][changing] ~= nil then + self.userdata["PlayerData"]["UserData"]["Settings"][changing] = newval + end +end + +function DataHandler:changeAvatar(newfull, part, color) + local userData = self.userdata + + if userData then + local playerData = self.userdata["PlayerData"] + + if playerData then + local get2007Avatar = playerData["Avatar"] + local get2006Avatar = playerData["Avatar2006"] + + if get2006Avatar and get2007Avatar then + if newfull then + playerData["Avatar"] = table.clone(newfull) + playerData["Avatar2006"] = table.clone(newfull) + elseif (part and color) and get2007Avatar[part] ~= nil then + --local Color = color[1] + --local Transparency = color[2] + --local Reflectance = color[3] + + playerData["Avatar"][part] = color + end + end + end + end + + --if self.userdata and self.userdata["PlayerData"]["Avatar"] ~= nil and self.userdata["PlayerData"]["Avatar2006"] ~= nil then + -- if (part and color) and self.userdata["PlayerData"]["Avatar"][part] ~= nil then + -- self.userdata["PlayerData"]["Avatar"][part] = color + -- else + -- self.userdata["PlayerData"]["Avatar"] = newfull or self.userdata["PlayerData"]["Avatar"] + -- end + --end +end + +function DataHandler:getData() + return self.data +end + +function DataHandler:getUserData() + return self.userdata +end + +function DataHandler:getSetting() + if self.userdata and self.userdata["PlayerData"]["UserData"]["Settings"] ~= nil then + return self.userdata["PlayerData"]["UserData"]["Settings"] + end +end + +function DataHandler:getAvatar(avatarType) + local userData = self.userdata + + if userData then + local playerData = self.userdata["PlayerData"] + + if playerData then + local get2007Avatar = playerData["Avatar"] + local get2006Avatar = playerData["Avatar2006"] + + if get2006Avatar and get2007Avatar then + + if avatarType == 2006 then + return get2006Avatar + else + return get2007Avatar + end + end + end + end + + --if self.userdata and self.userdata["PlayerData"]["Avatar"] ~= nil and self.userdata["PlayerData"]["Avatar2006"] ~= nil then + -- return (avatarType == 2006 and self.userdata["PlayerData"]["Avatar2006"]) or self.userdata["PlayerData"]["Avatar"] + --end +end + + + +function DataHandler:getStats() + if self.userdata and self.userdata["PlayerData"]["UserData"]["BrickBattleData"] ~= nil then + return self.userdata["PlayerData"]["UserData"]["BrickBattleData"] + end +end + +-- THIS FUNCTION IS HORRIBLY CODED, DO NOT SCREAM AT ME I AM AWARE!!!! +--function DataHandler:OldFixData() +-- if self.userdata["PlayerData"]["Avatar"]["Face"] == 7601602741 then +-- self.userdata["PlayerData"]["Avatar"]["Face"] = 11403137139 +-- print("Updating outdated face texture") +-- end + +-- if self.userdata["PlayerData"]["UserData"]["Settings"]["ErrorsInChat"] == nil then +-- self.userdata["PlayerData"]["UserData"]["Settings"]["ErrorsInChat"] = false + +-- print("Adding ErrorsInChat to Settings") +-- end + +-- if self.userdata["PlayerData"]["UserData"]["Settings"]["DisplayNames"] == nil then +-- self.userdata["PlayerData"]["UserData"]["Settings"]["DisplayNames"] = false + +-- print("Adding DisplayNames to Settings") +-- end + +-- if self.userdata["PlayerData"]["UserData"]["Settings"]["CameraLerp"] == nil then +-- self.userdata["PlayerData"]["UserData"]["Settings"]["CameraLerp"] = 0.9 + +-- print("Adding DisplayNames to Settings") +-- end +--end + +local function CountTable(Table) + local Count = 0 + + for i, v in pairs(Table) do + if typeof(v) == "table" then + Count += CountTable(Table[i]) + else + Count += 1 + end + end + + return Count +end + +local function findViaInformation(fullTable: {any}, value): any + for ind, information in pairs(fullTable) do + if information[1] == value then + return ind + end + end + + return nil +end + +local function fixNewData(FixedTable, Table) + local FixedTableAmount = CountTable(FixedTable) + local TableAmount = CountTable(Table) + local Pairing = nil + + if FixedTableAmount > TableAmount then + Pairing = FixedTable + else + Pairing = Table + end + + + for i, v in pairs(Pairing) do + if typeof(v) == "table" then + if FixedTable[i] ~= nil and Table[i] == nil then + print("Adding table: "..i) + Table[i] = table.clone(FixedTable[i]) + elseif FixedTable[i] ~= nil and Table[i] ~= nil then + print("Searching through table: "..i) + fixNewData(FixedTable[i], Table[i]) + elseif FixedTable[i] == nil and Table[i] ~= nil then + print("Removing table: "..i) + Table[i] = nil + end + else + if FixedTable[i] ~= nil and Table[i] == nil then + print("Adding "..i.." with a value of: "..tostring(v)) + Table[i] = v + elseif FixedTable[i] == nil and Table[i] ~= nil then + print("Removing value: "..i) + Table[i] = nil + end + end + end +end + +--[[ +function DataHandler:fixData() + +end + + +]]-- + +function DataHandler:fixData(FixedData) + if self.userdata and FixedData then + local CurrentDataPlayerData = self.userdata["PlayerData"] + local FixingDataPlayerData = FixedData["PlayerData"] + + fixNewData(FixingDataPlayerData, CurrentDataPlayerData) + + local fixedPlayerData = self.userdata["PlayerData"] + + local get2007Avatar = fixedPlayerData["Avatar"] + local get2006Avatar = fixedPlayerData["Avatar2006"] + + if get2006Avatar and get2007Avatar then + --local faceValid2006 = table.find(GrabbedStuff.Faces, get2006Avatar.Face) + --local faceValid2007 = table.find(GrabbedStuff.Faces, get2007Avatar.Face) + local faceValid2006 = findViaInformation(GrabbedStuff.Faces, get2006Avatar.Face) + local faceValid2007 = findViaInformation(GrabbedStuff.Faces, get2007Avatar.Face) + + if not faceValid2006 then + get2006Avatar.Face = 11945029012 + print("Fixing Face for 2006 Avatar...") + end + + if not faceValid2007 then + get2007Avatar.Face = 11945029012 + print("Fixing Face for 2007 Avatar...") + end + end + end +end + +return DataHandler diff --git a/rojo/MainMenu/src/ReplicatedStorage/Classes/TeleportHandler.lua b/rojo/MainMenu/src/ReplicatedStorage/Classes/TeleportHandler.lua new file mode 100644 index 0000000..2d59341 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Classes/TeleportHandler.lua @@ -0,0 +1,45 @@ +--!strict +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local TeleportService: TeleportService = game:GetService("TeleportService") + +local DataHandler = require(ReplicatedStorage:WaitForChild("DataHandler", nil)) + +local protocols = ReplicatedStorage:WaitForChild("Protocols", nil) +local templates = ReplicatedStorage:WaitForChild("Templates", nil) + +local function grabUserData(player: Player) + -- put code here + return {} -- placeholder +end + +local TeleportHandler = {} + +function TeleportHandler.teleportEvent(player: Player, placeId: number, placeName: string, teleportType: string): () + local userData = grabUserData(player) + + if userData then + local teleportData = userData["PlayerData"] + + if teleportType == "play" then + TeleportService:Teleport(placeId , player, teleportData, templates.Guis.LoadingGui) + + local returnPlace = protocols:FindFirstChild("ReturnPlace", false) + + if returnPlace and returnPlace:IsA("RemoteEvent") then + returnPlace:FireClient(player, tostring(placeName)) + end + elseif teleportType == "solo" then + local reservedServerAccessCode, privateServerId = TeleportService:ReserveServer(placeId) + + TeleportService:TeleportToPrivateServer(placeId, reservedServerAccessCode, {player}, nil, teleportData) + + local returnPlace = protocols:FindFirstChild("ReturnPlace", false) + + if returnPlace and returnPlace:IsA("RemoteEvent") then + returnPlace:FireClient(player, tostring(placeName)) + end + end + end +end + +return TeleportHandler diff --git a/rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/Button.lua b/rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/Button.lua new file mode 100644 index 0000000..f4098ad --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/Button.lua @@ -0,0 +1,3 @@ +local module = {} + +return module diff --git a/rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/Camera.lua b/rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/Camera.lua new file mode 100644 index 0000000..f4098ad --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/Camera.lua @@ -0,0 +1,3 @@ +local module = {} + +return module diff --git a/rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/Game.lua b/rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/Game.lua new file mode 100644 index 0000000..f4098ad --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/Game.lua @@ -0,0 +1,3 @@ +local module = {} + +return module diff --git a/rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/init.lua b/rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/init.lua new file mode 100644 index 0000000..f4098ad --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Classes/UIFramework/init.lua @@ -0,0 +1,3 @@ +local module = {} + +return module diff --git a/rojo/MainMenu/src/ReplicatedStorage/Classes/init.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Classes/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Classes/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/100,000 visits.lua b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/100,000 visits.lua new file mode 100644 index 0000000..dfbee24 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/100,000 visits.lua @@ -0,0 +1,39 @@ +local post = { + ["Title"] = "100,000 visits", + ["Date"] = 1686697690, + ["HeaderImage"] = "rbxassetid://13728452653", + + ["Content"] = [[ +We have finally done it, 100,000 visits have been achieved on FWM! That is like one followed by five zeros, think about it. This achievement is not new, as we had actually achieved it prior to the original game getting deleted off of ROBLOX. FWM's goal has been to show people what ROBLOX really looked like in 2006 and early 2007. With the help of footage and resources from that era, FWM's goal has been able to be nearly perfected. + +This blog post will talk about some up-and-coming features, along with some statistical things. Note that none of these features have any ETA for release. + + +Features Coming Soon... + +Controllers - Ever since September 2022, when we re-opened this game, people had noticed one major missing detail about FWM: Controllers. Well fear not, as this summer the development team will be heavily focused on a Controller system for FWM. It will work exactly like how controllers worked in 2006 (and on the March 2007 client). We will (probably) include functionality for "Chase" and "Flee" controllers, though no games in 2006 really utilized those, so that might just be a waste of development resources. + +People - FWM had always been sort of a "yourself" thing when it came to menu functionality, but we have decided to expand past the yourself idea and go with a "Peoples" section. This also means major quality of life and social updates are coming on the way (like bios, friends, etc)! Be on the lookout for that! + +Menu Updates - We have gradually been rolling out new menu designs lately, and that's really for a good reason. When FWM was being developed in its early days, the menu design was very clunky. But as of recently, we have decided to give more improvements towards the menu. One major thing we plan on starting soon is the 2006 site, stay tuned for that! + +Moderators - Yep, moderators. Since FWM has been growing, the developers have decided that sooner or later we would start needing to get moderators together. These moderators will enforce FWM, making sure everybody is following ROBLOX Terms of Service and having a good time. + + +Statistical Things (as of 6/13/2023): + +The top 3 players with most points of all time are: Sir_Thomas1IsBack (2742 Points), NetteJr (2155 Points), JohnsPuzzleGame (1894 Points) + +The most visited FWM game is: Robloxopolis + +Amount of Players with Bloxxer badge: 20 + + +We want to thank everyone who has stuck around since the start of FWM's journey in August 2020. Whether you have played since Pre-Alpha, or recently joined a few weeks ago, you are all a part of history one way or another. + +- Roblox_Gamer2030 + + ]] +} + +return post \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/Building Contest b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/Building Contest new file mode 100644 index 0000000..e69de29 diff --git a/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/FWM Guide - BrickBattle.lua b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/FWM Guide - BrickBattle.lua new file mode 100644 index 0000000..3d662a5 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/FWM Guide - BrickBattle.lua @@ -0,0 +1,40 @@ +local post = { + ["Title"] = "FWM Guide - BrickBattle", + ["Date"] = 1683526812, + ["HeaderImage"] = "rbxassetid://13383290282", + + ["Content"] = [[ +BrickBattling is an amazing core feature of FWM. It is one of the biggest aspects of FWM. Many of you guys on FWM are already experienced with these tools. But this guide is here for all the new players who seem to have a little bit of trouble with BrickBattling. This guide will hopefully answer a few questions a new player might ask about BrickBattling. + +So, why is BrickBattling important? + +It is a heavily contribution to your FWM player stats. Killing a player using the brick battle items will grant you a "Knockout" point, but getting killed or having your own weapon kill you will grant you a "Wipeout" point. These two points apply heavily towards your KDR, or Kill/Death ratio. In fact, your ratio is responsible for achieving the "Combat Initiation", "Warrior", and "Bloxxer" badge. Badges which help increase your status here on FWM. The better, or higher your KDR is, the more dangerous you are. Okay that's a little bit exaggerated, but you kind of get the point. Having a high KDR is a huge deal, and heavily looked up upon. + +What are the basic BrickBattle tools? + +There are many different types of BrickBattle tools used throughout FWM. But I really want to showcase 5 tools that I think are heavily contributions in the BrickBattling scene: + +Rocket - The Rocket Launcher is commonly seen as a Rocket icon on your StarterHopper. It is, in my opinion, the most important item in BrickBattle. By clicking/tapping a point on the screen, it will shoot out a Rocket bullet (commonly seen as a Blue 4x1x1 Brick). The bullet will fly towards the direction your mouse pointed. Once the bullet hits an object, it'll cause an explosion, exploding any bricks in its radius. You can kill other players with the bullet directly or indirectly from its explosion to gain a Knockout. Be careful though, if you aim it way too close, it might explode on you! + +SuperBall - The Superball is commonly seen as a collection of Dodgeballs on your StarterHopper. It is a heavy contributor in BrickBattling. By clicking/tapping a point on the screen, you are able to throw a shiny dodgeball which'll be thrown in the direction of your mouse, usually under a random color. The dodgeball will bounce around damaging players it hits, be careful as it can also damage you! This item is very important for finishing off players who are low on health. The damage a superball does depends on where you hit them from, so head shots are bound to really do a lot! A tip I have is to aim higher as the higher your aim, the further it can get across. + +SlingShot - The Slingshot is commonly seen as a yellow Slingshot icon on your StarterHopper. It may look small, but if used right, it can really deal some damage! There are 2 different variations of the slingshot. The first and commonly used variation is the scripted version. By clicking/tapping a point on the screen, a small (usually a grey 1x1x1 ball) pellet will be thrown at the direction of your cursor. The second version is the HopperBin version, which instead of clicking/tapping a point, you can hold to unleash a load of slingshot pellets at the direction your aiming. The slingshot is a very difficult item to use as the pellets despawn really fast and don't go as far as the superball does. However, each pellet can pack a serious punch if used correctly, and yes it also can deal heavy damage to you. + +Bomb - The Bomb is commonly seen as a black Bomb icon on your StarterHopper. It is a very easy item to use. By clicking your left mouse or tapping your screen, it'll spawn a bomb above your head. Each ticking sound represents time before the bomb explodes. The faster the ticking sound is, the less time the bomb has before it explodes. So make sure to get out of its range before it explodes! Once the bomb does explode, it'll usually release a very big explosion, exploding any bricks and killing any players in its radius. The bomb is both very simple and very destructive to use. So make sure you be careful with how you use them! Bombs can be really good for killing a group of players who just so happen to get in its radius when it explodes. It can also be used to knock down buildings very quickly. + +Trowel - The Trowel is commonly seen as a Wall icon on your StarterHopper. Just like the bomb, it is also pretty simple to use. By clicking/tapping a point on the screen, you are able to spawn a Wall. The wall is a straight to the point item which is very helpful in many situations. It can be used to protect you from rocket launcher or superball shots, or be used to traverse areas with dangerous ground. Be careful, a wall will despawn after a little bit so its best to time your wall placement and make sure it was used in the right situation. It doesn't deal any damage to players at all, but it is a core element that is very helpful. + +How can I BrickBattle? + +It's very simple if you want to get started with BrickBattling. Most of FWM's featured games are BrickBattle games, so that is a good place to start. As well as that, many games on FWM are also BrickBattle places. For example: SharkRock Island, Sunset Plain, Lava Rush, and Roblox Coliseum! These aren't the only BrickBattle games on FWM as there is way more. Most BrickBattle games use a completely different map, which grants as a different environment for BrickBattling. + +Final Note + +I hope this guide was able to at least give you some sort of knowledge on how BrickBattling works. Got any questions? Make sure to say so on the "FWM Official" group wall. Now get out there and score some KOs! + +- Roblox_Gamer2030 + + ]] +} + +return post \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/Welcome!.lua b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/Welcome!.lua new file mode 100644 index 0000000..28b4c5e --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/Welcome!.lua @@ -0,0 +1,25 @@ +local post = { + ["Title"] = "Welcome!", + ["Date"] = 1682206693, + ["HeaderImage"] = "rbxassetid://7419508424", + + ["Content"] = [[ +In the beginning there was an empty darkness.. The only thing in this void was a black brick, Two-By-Two. Two-By-Two was the Alpha Brick, the First. Copied, pasted, and recolored a million times, Robloxia was built out of nothing from the images of Two-By-Two. These were the early days… +- The Chronicles of Roblox, VI.203 + +Welcome one and all to the FWM Developer’s Journal. Like everything in FWM, this journal is an experiment. The idea is that members of the FWM team will post here to share their thoughts about different aspects of the game, give hints, answer questions, and occasionally post some sneak-previews of what is in the works. Nobonet wanted to write the first post to the blog, but unfortunately he is buried under a mountain of RBX.Lua shenanigans and its unyielding logic. We all hope that he recovers soon. + +One thing we at FWM have been thinking hard about is user interaction and input. We really want to host events more frequently and improve the game. Everybody loves it when their favorite game is updated, and at least some kind of contest, right? We want ideas, feedback, and level submissions from the community! Have any of these? Make sure to comment on the FWM Official group wall. User interaction is what makes FWM fun! + +In the meantime, I have pulled out some of my old favorites that new players may not have seen. So if you are looking for something fun to play, check them out. + +Sites to See +Train Depot v.3.0 - A train-reliant dystopia from RobloxPolice +TeamGameBuildBattle's Place - An action-packed team-based battle royale +Fantasy Kingdom - A forest map with boat-building and a magical waterfall by Miked +Overflow - A classic FWM flood escape map by the FWM Team +santa's village - A fun, holiday-themed map from santaclau5e + ]] +} + +return post diff --git a/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/init.lua b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/init.lua new file mode 100644 index 0000000..3bfc58e --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Blog/init.lua @@ -0,0 +1,7 @@ +local module = {} + +for _, v in pairs(script:GetChildren()) do + table.insert(module, require(v)) +end + +return module diff --git a/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Games.lua b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Games.lua new file mode 100644 index 0000000..525518d --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/Games.lua @@ -0,0 +1,977 @@ +--[[ + Game Types: "ROBLOX Game", "Event Game", "Game" (Case sensitive) + + FORMAT: + ["GAME NAME"] = { + TeleportID = GAME ID, + GameIcon = "rbxassetid://GAMEIMAGEID" or nil (if no thumbnail is known/made for the game), + Description = "GAME DESCRIPTION", + Creator = "GAME CREATOR NAME", + Type = "GAME TYPE (refer to the list above FORMAT)", + Period = "TIME PERIOD" ex. (March 2007, November 2006, etc.) + }, + + +]]-- + +return{ + ["Brick Battle: Crossroads"] = { + TeleportID = 10797053041, + GameIcon = "rbxassetid://13725032206", --rbxassetid://11637360237 + Description = "Battle your way through the secret hideout, storm the castle, invade the underground ruins, and capture the lookout tower. But be wary: there's always a showdown at The Crossroads.", + Creator = "ROBLOX", + Type = "ROBLOX Game", + Period = "November 2006", + }, + + ["Brick Battle: Chaos Canyon"] = { + TeleportID = 10797053416, + GameIcon = "rbxassetid://11637360391", + Description = "Experience Chaos Canyon - Escape from Desolation Valley, explore the ruins on the cliffs, walk on the Sky Bridge and hold the Battle Cube from invaders! This map features models created by the community, including: PilotLuke, tingc222, and Yahoo.", + Creator = "ROBLOX", + Type = "ROBLOX Game", + Period = "October 2006", + }, + + ["Community Construction Site"] = { + TeleportID = 10797053600, + GameIcon = "rbxassetid://11637359306", + Description = "Prefer to create rather than destroy, or just want to experiment? Try the Community Construction Site where you and your friends can build together.", + Creator = "ROBLOX", + Type = "ROBLOX Game", + Period = "September 2006", + }, + + ["Santa's Winter Stronghold"] = { + TeleportID = 11301126695, + GameIcon = "rbxassetid://13473158129", + Description = "Deep in the arctic wastes lies Santa's Workshop, where his elves work to make toys for children 364 days a year. Well, the elves have had enough! They are revolting! Play as an elf and collect as many presents as you can find. Play as Santa and use your special powers to hunt down those elves and teach them a lesson before they ruin Christmas for everyone! Who will prevail?", + Creator = "ROBLOX", + Type = "ROBLOX Game", + Period = "December 2006", + }, + + ["Brick Battle: Glass Houses"] = { + TeleportID = 12780541449, + GameIcon = "rbxassetid://12787180180", + Description = "Take sides in the epic struggle of Red vs. Blue in this futuristic map. Man the gun emplacements and rain fiery destruction on your enemies below. Find the Battle Armor to protect yourself and then escape from invaders using the anti-grav elevator tube. Finally, summon the dread mechanized Spheres of Doom to pelt the opposing team with rockets from above. Those who live in glass houses should hit the deck!", + Creator = "ROBLOX", + Type = "ROBLOX Game", + Period = "February 2007", + }, + + ["Brick Battle: Rocket Arena"] = { + TeleportID = 12178799427, + GameIcon = "rbxassetid://7347176266", + Description = "This map goes back to basics: rockets, jetboots, and blowing up bridges. Out-maneuver your foes using your jetboots, cut off their escape by nuking the bridges, and rain doom down upon them using a rapid-fire rocket launcher. But don't fall in the lava - ouch!", + Creator = "RocketArena", + Type = "ROBLOX Game", + Period = "January 2007", + }, + + ["Brick Battle: Haunted Mansion"] = { + TeleportID = 12110909938, + GameIcon = "rbxassetid://7353931449", + Description = "There is an abandoned house on a cliff that some say is haunted. And it is. You should know, because the ghost who haunts this house ... is you! During stormy weather, passersby often think to stop at the house for shelter. Use your eerie powers to frighten them and run them out of your home!", + Creator = "arena2", + Type = "ROBLOX Game", + Period = "October 2006", + }, + + ["Advanced Building"] = { + TeleportID = 10797053779, + GameIcon = "rbxassetid://11637359697", + Description = "Want to build with more tools? Check out the Advanced Building area today! Features anti grief, property changing, and more colors to choose from.", + Creator = "ROBLOX", + Type = "Game", + Period = "April 2007", + }, + + ["Z-BLOX"] = { + TeleportID = 11301118664, + GameIcon = "rbxassetid://11637359036", + Description = "Face off against endless waves of the undead. At the end of every wave, boxes containing ammo clips will be air-dropped. The last survivor of each round wins and is awarded points. How many waves can you survive?", + Creator = "fwmcontests2", + Type = "Game", + Period = "November 2006", + }, + + ["SharkRock Island"] = { + TeleportID = 11542218240, + GameIcon = "rbxassetid://11637359878", + Description = "SharkRock Island. Hey this is my place i have made other places, i am actually koopa and his accounts so yes this would be a Schwaabo production! Hope you have fun looking around and battling here. Remember to check out my other places.", + Creator = "goomba", + Type = "Game", + Period = "November 2006", + }, + + ["RobloxPolices Vehicle Labs"] = { + TeleportID = 11301129119, + GameIcon = "rbxassetid://11637360035", + Description = "This is RobloxPolice here, and this is where I'll be building some cool new vehicles to drive! So far featured is a truck, airplane (and one large detailed one) and a helicopter. Soon to be built, rocket ship, UFO, submarine, etc. THIS IS A PRIVATE ZONE AND KNOW COPIERS WILL NOT BE ADMITED IN! ANY ONE WHO USES THIS MAP OR IT'S MODELS WILL BE BANNED FROM ALL POLICE MAPS (ALL!)", + Creator = "PoliceLabs", + Type = "Game", + Period = "January 2007", + }, + + ["LukeJacobuilder 's Place"] = { + TeleportID = 11560456038, + GameIcon = "rbxassetid://11637359471", + Description = "", + Creator = "LukeJacobuilder", + Type = "Game", + Period = "October 2006", + }, + + ["The Big Slide's Place"] = { + TeleportID = 11637171049, -- + GameIcon = nil, + Description = "BIG SLIDES!!!!!!", + Creator = "The Big Slide", + Type = "Game", + Period = "November 2006", + }, + + ["santa's village"] = { + TeleportID = 11561129788, + GameIcon = "rbxassetid://7463135939", + Description = "come visit my village and ride a sleigh thru the snow or iceskate.", + Creator = "santaclau5e", + Type = "Game", + Period = "December 2006", + }, + + ["Robloxopolis"] = { + TeleportID = 11876778708, + GameIcon = "rbxassetid://7330384761", + Description = "The public city-building project. Read more at...", + Creator = "Robloxopolis", + Type = "Game", + Period = "E. March 2007", + }, + + ["TeamGameBuildBattle's Place"] = { + TeleportID = 11914340287, + GameIcon = "rbxassetid://7360262299", + Description = "BRICK BUILD AND BATTLE: A You are put on a random team and on 2 minutes the gates to the building area will open! When they do they will stay open for 1 minute and then close. Then if you got in the arena you build a fort and after 10 min's you battle others! (you only have 1 life) If you die you just have to watch the game...", + Creator = "TeamGameBuildBattle", + Type = "Game", + Period = "November 2006", + }, + + ["Nuke the Whales EXTREME!!!"] = { + TeleportID = 11914693526, + GameIcon = "rbxassetid://8028365699", + Description = "If he had the chance, he would nuke you.", + Creator = "NukeTheWhales", + Type = "Game", + Period = "November 2006", + }, + + ["Katalyst's Place"] = { + TeleportID = 11922918912, + GameIcon = "rbxassetid://7081948716", + Description = "Yea... that's a giant kitty, no? Or how about that gigantic pyramid?", + Creator = "Katalyst", + Type = "Game", + Period = "August 2006", + }, + + ["Stairway to Heaven"] = { + TeleportID = 11917400393, + GameIcon = "rbxassetid://7091140671", + Description = "Condo building top unit floorplan revised. Larger floor space now available. Will add more later.", + Creator = "tingc222", + Type = "Game", + Period = "September 2006", + }, + + ["★ Minigame World"] = { + TeleportID = 11957266580, + GameIcon = "rbxassetid://11979784398", + Description = "------- [Minigame World] ------- [4] minigames. [?] more started... {Last Updates}-> Added the Giant and Zombie minigames. Working on bug fixes.", + Creator = "miked", + Type = "Game", + Period = "E. March 2007", + }, + + ["FANTASY KINGDOM"] = { + TeleportID = 11957280861, + GameIcon = "rbxassetid://7681415797", + Description = "This map was made public 26th November, and still gets updates. It was the first i know of that used brick velocity. Many people have copied it, which I dont mind so much now, as long as you dont claim you made it. A lot of the models used I have made public, so look out for them.", + Creator = "miked", + Type = "Game", + Period = "November 2006", + }, + + ["L&L APT"] = { + TeleportID = 12087424578, + GameIcon = "rbxassetid://7355558376", + Description = "", + Creator = "Leeav", + Type = "Game", + Period = "November 2006", + }, + + ["Mustafar"] = { + TeleportID = 12087787363, + GameIcon = "rbxassetid://7330524040", + Description = "Mustafar, a small, but dangerous, moon. A moon that's totally volcanic, This moon contains absolutely no water, but 99% molten hot rock. This moon is also the fateful location of a battle between a Jedi and a new Sith lord. Explore all you want, but beware of the lava stream and pools.", + Creator = "Indiana Jones", + Type = "Game", + Period = "September 2006", + }, + + ["ROBLOX World Headquarters"] = { + TeleportID = 12088094879, + GameIcon = "rbxassetid://7346811121", + Description = 'Welcome to ROBLOX World Headquarters. We have intentionally hidden a few of the components necessary to implement the "fly bug". Come and visit the ROBLOX team! Builderman', + Creator = "Builderman", + Type = "Game", + Period = "November 2006", + }, + + ["Lawrence Yamut's Place"] = { + TeleportID = 12102911836, + GameIcon = "rbxassetid://7692197753", + Description = "", + Creator = "Lawrence Yamut", + Type = "Game", + Period = "October 2006", + }, + + ["PFCity"] = { + TeleportID = 12110553230, + GameIcon = "rbxassetid://7463135826", + Description = "A city with a population of many PFains... If you'd like to move in please send me a freind's request! Today's wether: Rainy with no lighting", + Creator = "PFCity", + Type = "Game", + Period = "November 2006", + }, + + ["Phenix Fire Testing Zone"] = { + TeleportID = 12118559005, + GameIcon = "rbxassetid://7712992882", + Description = "come to my battle ground! Hears my funny little saying: The demon that lies within shal consume yo ####! >:)", + Creator = "ryanfire94", + Type = "Game", + Period = "December 2006", + }, + + ["Grey City"] = { + TeleportID = 12155429467, + GameIcon = "rbxassetid://5429412019", + Description = "Run through this beautiful city planting time bombs! I would be curious to know how well this level runs on your machine. Leave me a message in the forums that says what kind of computer you have and how well it ran this level. Is a bigger city possible?", + Creator = "EarlGrey", + Type = "Game", + Period = "September 2006", + }, + + ["Forest of Desolation"] = { + TeleportID = 13232543257, + GameIcon = "http://www.roblox.com/asset/?id=13232661194", + Description = "Anyone want to help me make a forest-themed Brick Battle level? My idea is to have a dark forest peppered with interesting buildings and ruins.", + Creator = "Abyss", + Type = "Game", + Period = "September 2006", + }, + + ["Christmas .vs. holloween!"] = { + TeleportID = 12159308694, + GameIcon = "rbxassetid://7506033577", + Description = "the battle of Christmas .vs. holloween!!!", + Creator = "SniperofDoom", + Type = "Game", + Period = "November 2006", + }, + + ["Sunset Plain"] = { + TeleportID = 12167804773, + GameIcon = "rbxassetid://7330548765", + Description = "Have fun at Sunset Plain! unfortunatly i could not get the regenerate scripts to work in this map so nothing regenerates obviosly. You might have already seen some of this map from the adventure awaits movie on the homepage of roblox. So have fun here! P.S check out the waterfall!", + Creator = "Schwaabo", + Type = "Game", + Period = "November 2006", + }, + + ["Volcanic Island"] = { + TeleportID = 12172248326, + GameIcon = "rbxassetid://7790873728", + Description = "Welcome to the tropical Volcanic Island. It's not very big, because I didn't work too much on it. But I hope you enjoy it.", + Creator = "Pheonix", + Type = "Game", + Period = "November 2006", + }, + + ["MegaBuilder's Place"] = { + TeleportID = 12178265112, + GameIcon = "rbxassetid://7463135944", + Description = "A work in progress", + Creator = "MegaBuilder", + Type = "Game", + Period = "November 2006", + }, + + ["Bowling Ally"] = { + TeleportID = 12312517015, + GameIcon = "rbxassetid://8028365678", + Description = "RobloxPolice, I'm working on a Bowling Ally here.", + Creator = "PoliceLabs2", + Type = "Game", + Period = "January 2007", + }, + + ["Yan's Place"] = { + TeleportID = 12181177828, + GameIcon = "rbxassetid://7467421507", + Description = "UNDER CONSTRUCTION FOR AN UNDERTERMINED PERIOD", + Creator = "Yannik11", + Type = "Game", + Period = "December 2006", + }, + + ["Escape"] = { + TeleportID = 12324137955, + GameIcon = "rbxassetid://12324964166", + Description = "Escape the building to win! Features the creepy styles of Jack and RobloxPolice!", + Creator = "JackRackam", + Type = "Game", + Period = "January 2007", + }, + + ["Lava Rush"] = { + TeleportID = 12333733213, + GameIcon = nil, + Description = "This is a very cool game.", + Creator = "test888", + Type = "Game", + Period = "November 2006", -- change lighting in rbxl + }, + + ["Phionx Fire Hangers"] = { + TeleportID = 12343615080, + GameIcon = "rbxassetid://12382071600", + Description = "", + Creator = "Jacobxxduel", + Type = "Game", + Period = "September 2006", + }, + + ["trem's City (unfinished)"] = { + TeleportID = 12382877608, + GameIcon = "rbxassetid://12382898576", + Description = "", + Creator = "Trem", + Type = "Game", + Period = "December 2006", + }, + + ["DracoTrainingMaster's Place"] = { + TeleportID = 12384983232, + GameIcon = "rbxassetid://7505574358", + Description = "", + Creator = "DracoTrainingMaster", + Type = "Game", + Period = "October 2006", + }, + + ["Roblox Coliseum"] = { + TeleportID = 12396285203, + GameIcon = "rbxassetid://13391311737", + Description = "Have you ever seen the movie Gladiator? This map is a work in progress... will make public when completed and debugged. Don't copy the scripts, they won't work in the next release :-/", + Creator = "Telamon", + Type = "Game", + Period = "November 2006", + }, + + ["Trouble in the Killbot Factory Level 2"] = { + TeleportID = 12396864362, + GameIcon = "rbxassetid://13727533132", + Description = "As an experiment, I have created some simple bots for Roblox. They are hovering spheres that will kind of chase you around and shoot rockets at you. Probably pretty good training for BrickBattles.", + Creator = "Telamon", + Type = "Game", + Period = "January 2007", + }, + + ["Angel of Truth"] = { + TeleportID = 12405951700, + GameIcon = "rbxassetid://7415452933", + Description = "I saw the angel in the plastic and I kept working until she was free. Open my place if you want to find out how good your computer is. lol.", + Creator = "DigitalMessiah", + Type = "Game", + Period = "September 2006", + }, + + ["TrainCrasher's Place"] = { + TeleportID = 12467186972, + GameIcon = "rbxassetid://7508260132", + Description = "", + Creator = "TrainCrasher", + Type = "Game", + Period = "January 2007", + }, + + ["SwordFights's Place"] = { + TeleportID = 12472967362, + GameIcon = "rbxassetid://12472975958", + Description = "The ultmate sword fighting map!! (Real working light-sabrs comeing this month!)", + Creator = "SwordFights", + Type = "Game", + Period = "February 2007", + }, + + ["Pirate-ville"] = { + TeleportID = 12481916621, + GameIcon = "rbxassetid://13391309943", + Description = "The city of Pirate's! Come all! Property is available to Pirate Army members. Just send me the model and I'll put it in. PF Army has an embacy located across the twin-pirate towers. Land plots come in different sizes: small = 32x32, medium 48x48, large 64x64, XL 96x96", + Creator = "JackRackam", + Type = "Game", + Period = "November 2006", + }, + + ["Castle Destruction"] = { + TeleportID = 12560666914, + GameIcon = "rbxassetid://12560594679", + Description = "There's a bouncing ball that gobbles up bricks. After a while the castle comes crashing down.", + Creator = "Crazy Eddie", + Type = "Game", + Period = "August 2006", + }, + + ["room_environment"] = { + TeleportID = 12590827747, + GameIcon = "rbxassetid://12590877149", + Description = "Play around with the furniture!", + Creator = "David.Baszucki", + Type = "Game", + Period = "August 2006", + }, + + ["Happy Home in ROBLOXia"] = { + TeleportID = 12590516933, + GameIcon = "rbxassetid://12590893956", + Description = "A nice peaceful starting place with a house and some bricks to build with.", + Creator = "Telamon", + Type = "Game", + Period = "January 2007", + }, + + ["Pirate Ship"] = { + TeleportID = 12600432050, + GameIcon = "rbxassetid://12600566352", + Description = "", + Creator = "Brickmason", + Type = "Game", + Period = "September 2006", + }, + + ["The Doom Spire"] = { + TeleportID = 12614607156, + GameIcon = "rbxassetid://12614734944", + Description = "From the top of the tower, Teferi watched over the once green land. His minions had carved a path through the trees that had once covered Keld, a sinuous scar that spidered out from his shimering Doom Spire. 'Soon...' He thought to himself, fingering the bright panels on the console in front of him.", + Creator = "leeor_net", + Type = "Game", + Period = "December 2006", + }, + + ["Rocketjeep Rally!"] = { + TeleportID = 12686988267, + GameIcon = "rbxassetid://12687014097", + Description = "Just a little project of mine. Press the green cube to regen the level. I'm sure you can think of 100 cool things to add to this map - copy it and give it a whirl!", + Creator = "Telamon", + Type = "Game", + Period = "E. March 2007", + }, + + ["Brick Battle: Classic Crossroads"] = { + TeleportID = 12758551659, + GameIcon = "rbxassetid://7704541260", + Description = "Brick battle old skool!", + Creator = "Bspurrell", + Type = "Game", + Period = "November 2006", + }, + + ["Thunderbirds and the Red raiders!"] = { + TeleportID = 12779277535, + GameIcon = nil, + Description = "A B C D E F G Gummy bears are mean to me 1 is red 1 is dead 1 its biting off my head A B C D E F G it ate me and now i have to PEE", + Creator = "freddy", + Type = "Game", + Period = "October 2006", + }, + + ["Demons Lair"] = { + TeleportID = 12779884863, + GameIcon = "rbxassetid://13391310605", + Description = "100% Done", + Creator = "DemonBrother", + Type = "Game", + Period = "January 2007", + }, + + ["Area 51"] = { + TeleportID = 12828122182, + GameIcon = "rbxassetid://13650921905", + Description = "", + Creator = "Telamon", + Type = "Game", + Period = "April 2007", + }, + + ["BridgeCrossingDemo"] = { + TeleportID = 12828865592, + GameIcon = nil, + Description = "Bridge crossing, Ultamte bridge map! Map rules: Do not use foul, or abuseive words- Do not disobay admin (me, and koopa LISTEN TO HIM!!) rules- I build, my rules, my things, I do what I want- Don't beg for any thing to add to the map, or a reset, Just ask---- > BREAK ANY OF THESE RULES AND I WILL KICK or BAND YOU FROM THE MAP <", + Creator = "Jacobxxduel", + Type = "Game", + Period = "April 2007", + }, + + ["Overflow"] = { + TeleportID = 12118678013, + GameIcon = nil, + Description = "Fixed the game (OOPS!) Who clogged the toilet? Be the first to collect the coin before everyone else does, use the tools you have to defeat other potential winners. Current map count: 8", + Creator = "FWM", + Type = "Game", + Period = "December 2006" + }, + + ["Grenades and Oranges"] = { + TeleportID = 12972506084, + GameIcon = "rbxassetid://12972793193", + Description = "Grenades and Oranges!!!! Here it is people! It is a load of fruity fun with big explosions! Choose your team and pick up your Telanade (sticky grenade) and other grendae weapons and go on a rampage! Hope you all enjoy, please message me if there are any problems or any ideas. Have fun!", + Creator = "Koopa", + Type = "Game", + Period = "February 2007" + }, + + ["The Deadly Ice Sheet of Frostmoor"] = { + TeleportID = 12983413992, + GameIcon = "rbxassetid://13391314997", + Description = "Do battle on this frozen sheet of ice, but watch out for the Deadly Ice Spikes of Doom!", + Creator = "SonOfSevenless", + Type = "Game", + Period = "L. March 2007" + }, + + ["Mausoleum at Halicarnassus [WWC]"] = { + TeleportID = 13037426388, + GameIcon = nil, + Description = "i would not recommend to join this place if your computer is bad.", + Creator = "FWM", + Type = "Game", + Period = "L. March 2007" + }, + + ["Powerhouse Paintball(70%)"] = { + TeleportID = 13073256753, + GameIcon = "rbxassetid://13086510944", + Description = 'Hio! I had a big change of well... ideas lets say. So here is the new Powerhouse Paintball. The name will be changing sometime... lol have fun! At the moment i am busy adding typing commands here. If you dont like the time of day, simply type any of these to change it to that time of day "day", "night", "morning", "evening". If you have any ideas message me!', + Creator = "Koopa", + Type = "Game", + Period = "April 2007" -- add daylight cycle chat cmds to this rbxl + }, + + ["DoomSpire Wars"] = { + TeleportID = 13120333001, + GameIcon = nil, + Description = "A fun team battle game. Destroy the other teams' towers before they destroy yours to win!", + Creator = "JohnsPuzzleGame", + Type = "Game", + Period = "February 2007" + }, + + ["Train Depot v3.0"] = { + TeleportID = 12463040186, + GameIcon = "rbxassetid://13391313254", + Description = "", + Creator = "RobloxPolice", + Type = "Game", + Period = "December 2006" + }, + + ["Wizard Wars"] = { + TeleportID = 12981564265, + GameIcon = "rbxassetid://13693934987", + Description = "", + Creator = "SonOfSevenless", + Type = "Game", + Period = "February 2007" + }, + + ["Traveler's Tale"] = { + TeleportID = 13176588674, + GameIcon = nil, + Description = "Have fun at Traveler's Tale, the weapons made by me hope you like em. Script for the vine cart donated by Robloxpolice. Lots of huge trees here, boats, secrets, and other stuff. Enjoy and have fun!", + Creator = "Bowser", + Type = "Game", + Period = "February 2007" + }, + + ["Super Wfmp Bros World 1"] = { + TeleportID = 13187932647, + GameIcon = "rbxassetid://13692051579", + Description = "!No copyright fringe intended! Super Wfmp bros.beat the levels.Wfmp:Its a me a Wfmp! Woo hoo!World 1 is now complete,come in and watch out for bowser fire and the koopa kids,go and save Toad now!lol.there is now 2 up to 4 players to do a level,race and the first 1 who touch the flag wins.if u want a figure of urself here,tell me in the fourms of the off topic.lets a go*cya*.", + Creator = "wfmp", + Type = "Game", + Period = "April 2007" + }, + + ["maze of DOOM!!!!!!!!!!!!!!"] = { + TeleportID = 12381844004, + GameIcon = "rbxassetid://13217304805", + Description = "its back!!!!!!!!!!!", + Creator = "kit403 2", + Type = "Game", + Period = "October 2006" + }, + + ["PilotLuke's Cloud City"] = { + TeleportID = 12343628825, + GameIcon = "rbxassetid://13222165009", + Description = "This is my virtual Roblox world. In the sky.", + Creator = "PilotLuke", + Type = "Game", + Period = "October 2006" + }, + + ["CTF Demo Version: Navial Battle!"] = { + TeleportID = 12343640424, + GameIcon = "rbxassetid://13231578137", + Description = "Race to the ships! All hands on deck! Theres a CTF Battle a-brewin! Defend the base and capture the enemy flag! Or just explore the island! Just make sure you don't fall off da boats! Youll drown! (we think it's cuz of our none bendable, brick arms...)", + Creator = "PoliceLabs5real", + Type = "Game", + Period = "January 2007" + }, + + ["SilentAssassin's Place"] = { + TeleportID = 12155381562, + GameIcon = "http://www.roblox.com/asset/?id=13233027368", + Description = "", + Creator = "SilentAssassin", + Type = "Game", + Period = "December 2006" + }, + + ["Roblox Museum©®™"] = { + TeleportID = 13245230718, + GameIcon = "http://www.roblox.com/asset/?id=13254094151", + Description = "here are the Roblox Museum©®™ were all of the best model will be and all of the most famus player and contest winner.The museum is not complet yet!!!!Please dont copy the idea!!!", + Creator = "robloxmuseum", + Type = "Game", + Period = "April 2007" + }, + + ["▒▓█ Team Battle: Behind Enemy Lines █▓▒"] = { + TeleportID = 13292389793, + GameIcon = "http://www.roblox.com/asset/?id=13292629113", + Description = "Destroy the opposite team! Use your cannons to blast away the wall seperating you from your foes. Hide in the caves, but beware you will find that you only have one way out. Go into the towers and rain fire among the people below. Try to survive and have fun.", + Creator = "Leeav", + Type = "Game", + Period = "April 2007" + }, + + ["City Wall"] = { + TeleportID = 12851101854, + GameIcon = "http://www.roblox.com/asset/?id=13293095354", + Description = "Welcome to the Great City! Take hold and defend the city from the enemy! Slay your foes with your mighty sword and rain arrows upon them! (Arrows coming soon) UPDATE--Now you can climb the wall to get in, but first you'll have to find the area, and it'll require climbing skill! UPDATE--Now the doors open and close on their own, so you don't have to! Now you can just push the button and watch! No hastle! (Still needs some fixing)", + Creator = "Anaminus", + Type = "Game", + Period = "April 2007" + }, + + ["Sword Fights on the Heights!"] = { + TeleportID = 13293878655, + GameIcon = "http://www.roblox.com/asset/?id=13293948299", + Description = "The first sword fight level evar.", + Creator = "Telamon", + Type = "Game", + Period = "April 2007" + }, + + ["Eliet-Sniper Clan's Base And Sniping pit!"] = { + TeleportID = 13305738206, + GameIcon = "rbxassetid://13306323328", + Description = "See if YOU can beat the eliet snipers! :-P", + Creator = "TringForAllTheBadges", + Type = "Game", + Period = "January 2007" + }, + + + ["Experimental jet pack"] = { + TeleportID = 13306736065, + GameIcon = "rbxassetid://13306815999", + Description = "This is a work in progress", + Creator = "erik.cassel", + Type = "Game", + Period = "September 2006" + }, + + ["Air Base Sector 128A"] = { + TeleportID = 13308114418, + GameIcon = "rbxassetid://13308485288", + Description = 'The rebel alliance rushed to finish the construction of the new air base. A large swarm flashed across the radar screen. "The Emporer has sent a fleet," the Cammander said, "We shall be ready for them." "The Main laser beam is in place, Sir," said the construction supervisor. "Good," smiled the Cammander. "Airplane parts shipped" "Side tower 1 in place" "Get to work ont he soldiers quaters," boomed the Cammander. "But don`t you think the design is too luxurious" "NO, GET TO WORK"', + Creator = "tie it up", + Type = "Game", + Period = "November 2006" + }, + + ["ROBLOX Hat Demo"] = { + TeleportID = 13308769036, + GameIcon = "rbxassetid://13727428778", + Description = "ROBLOX hat testing began in the last week of April 2007", + Creator = "Telamon", + Type = "Game", + Period = "April 2007" + }, + + ["Death Valley"] = { + TeleportID = 13380394269, + GameIcon = "rbxassetid://13380572949", + Description = "Fight in the valleys! They hide secrets.", + Creator = "Rombom", + Type = "Game", + Period = "April 2007" + }, + + ["Skyscraper"] = { + TeleportID = 13381689455, + GameIcon = "rbxassetid://13381730226", + Description = "", + Creator = "Matt Dusek", + Type = "Game", + Period = "September 2006" + }, + + ["Racetrack +Jetpacks+plane?"] = { + TeleportID = 13398522682, + GameIcon = "rbxassetid://13398649872", + Description = "*incomplete*, ladder big thx to are14 for car models and drive script, also thx to chrisd for plane", + Creator = "Smooshface", + Type = "Game", + Period = "February 2007" + }, + + ["A Pirates Life"] = { + TeleportID = 13399172156, + GameIcon = nil, + Description = "Yarghhhh, join forces wit yer heartys and go send da other team ta davey jones's locker matey! Har is some stuff ye should know about ma place mateys. 1. To start yer boat press ta blue button, ten proceed to press the green. 2. Ta turn, i am using reverse controls so it be more like a real wheel. So if ye click and hold on ta yellow button on the left, it will make ye turn hard to tha right, and same fer da opposite. 3. Ta stop yer boat press and hold da red. 4. To start yer boat for tha second time just press ta green, not the green then ta blue. Tata about most o the stuff ye need ta know. If ye want to go into ta tower, well then just walk into the larg room, with the big underwater window in it. Ta yer left and right are grey pads, use tem to to go into ta towers. Ye want ta join a team, well then in ta main lobby room, just go left or right to ta red or black pads. Try going underneath tha rocks on both sides of yer dock and see where they lead.", + Creator = "CaptinSilver", + Type = "Game", + Period = "E. March 2007" + }, + + ["Areplanes"] = { + TeleportID = 13406955536, + GameIcon = nil, + Description = "", + Creator = "are72", + Type = "Game", + Period = "February 2007" + }, + + ["driversED's Place"] = { + TeleportID = 13407824043, + GameIcon = "rbxassetid://13407920593", + Description = "", + Creator = "driversED", + Type = "Game", + Period = "February 2007" + }, + + ["Pirate Army HQ"] = { + TeleportID = 13436777321, + GameIcon = "rbxassetid://13436839359", + Description = "Welcome to the Pirate Army Headquarters. This map was made entirely by jackrackam with NO outside models (none!). The castle is unfurnished. Watch out for land mines, and try to find the healing pads.", + Creator = "Pirate Army", + Type = "Game", + Period = "December 2006" + }, + + ["Bumbper Cars!!!!!!!!!!!!!!!!!!!!"] = { + TeleportID = 13436470382, + GameIcon = nil, + Description = "This will be awsome!", + Creator = "PoliceLabs4", + Type = "Game", + Period = "January 2007" + }, + + ["Rocks25's huge slide!"] = { + TeleportID = 13455742036, + GameIcon = "rbxassetid://13727323985", + Description = "this slide is gigantic its hard to stay on though!", + Creator = "Rocks25", + Type = "Game", + Period = "November 2006" + }, + + + ["Ball Roll"] = { + TeleportID = 13482112951, + GameIcon = nil, + Description = "It's back, and its better than ever! Survive the incoming balls and climb the mountain!", + Creator = "FWM", + Type = "Game", + Period = "December 2006" + }, + + + ["Frontline II: Urban Warfare"] = { + TeleportID = 13540920198, + GameIcon = nil, + Description = "You are a soldier of a once-powerful robloxian empire. Your superiors have stationed you at a base in the West Robloxia region. You and your comrades must retake the region quickly before the battle falls into a stalemate, or worse, the region is lost!", + Creator = "FWM", + Type = "Game", + Period = "E. March 2007" + }, + + ["DROME RACERS"] = { + TeleportID = 13540640835, + GameIcon = "rbxassetid://13725216889", + Description = "Sory this place is under construktion but it gone be the drome race arena. Than it is complet will it be public for evereone . P:S: dont copy", + Creator = "ARE92", + Type = "Game", + Period = "February 2007" + }, + + ["DoomSpire and Towers"] = { + TeleportID = 13578750494, + GameIcon = "rbxassetid://13727230133", + Description = 'Possibly the Halloween version of "The Doom Spire"?', + Creator = "leeor_net", + Type = "Game", + Period = "November 2006" + }, + + ["The Divide"] = { + TeleportID = 13583080985, + GameIcon = nil, + Description = "A long time ago... There was a battle between the Dark and Light. Now you must pick sides and fight, for better...or worse.", + Creator = "Trampoline", + Type = "Game", + Period = "November 2006" + }, + + + ["Sword Fight Testing"] = { + TeleportID = 12840714756, + GameIcon = "rbxassetid://13692126422", + Description = "", + Creator = "Telamon", + Type = "Game", + Period = "L. March 2007" + }, + + ["FoxPolicesBlackHole's Place"] = { + TeleportID = 13541788234, + GameIcon = nil, + Description = "", + Creator = "FoxPolicesBlackHole", + Type = "Game", + Period = "February 2007" + }, + + ["the titanic"] = { + TeleportID = 13602124817, + GameIcon = "rbxassetid://13602204397", + Description = "", + Creator = "chrisd", + Type = "Game", + Period = "January 2007" + }, + + + ["Building Room"] = { + TeleportID = 13683087365, + GameIcon = "rbxassetid://13684933658", + Description = "This is a room with a bunch of bricks to get you started.", + Creator = "David.Baszucki", + Type = "Game", + Period = "August 2006", + }, + + ["Canonical Roblox Weapons - Linked"] = { + TeleportID = 13831468318, + GameIcon = "rbxassetid://13832392409", + Description = "", + Creator = "Telamon", + Type = "Game", + Period = "April 2007", + }, + + ["City Under Fire Ltd. Server Network"] = { + TeleportID = 13832790391, + GameIcon = nil, + Description = "This Server Network/Corporate Office stores the data for the Monster Web Hosting network.", + Creator = "City Under Fire", + Type = "Game", + Period = "January 2007", + }, + + ["Spring and Fall"] = { + TeleportID = 13833432103, + GameIcon = nil, + Description = "I steal other people's models without remorse. They are mine now ;-)", + Creator = "WorldsOfWanwood", + Type = "Game", + Period = "October 2006", + }, + + ["Blox Battle Arena"] = { + TeleportID = 13884578100, + GameIcon = nil, + Description = "", + Creator = "FWM", + Type = "Game", + Period = "April 2007", + }, + + ["my flipsydoodah placeV2.5"] = { + TeleportID = 13938939357, + GameIcon = nil, + Description = "now whith more fliping action! still in beta testing.", + Creator = "stang90", + Type = "Game", + Period = "E. March 2007" + }, + + ["HoverTank Arena Version 2.0"] = { + TeleportID = 13948489988, + GameIcon = "rbxassetid://13948645320", + Description = "Welcome to the HoverTank Arena! I have made a whole new version of the map! Tired of just driving the Tanks all the time? Then duke it out on the platforms above the arena, or sneak along through the labyrinth! Or just sit back and enjoy the new and improved spectator's area, where you can watch the battle from any angle! I have also added the Wall weapon. Enjoy!", + Creator = "ThunderStealth", + Type = "Game", + Period = "April 2007" + }, + + ["brutus's town"] = { + TeleportID = 13956603289, + GameIcon = "rbxassetid://13956801977", + Description = "", + Creator = "brutus", + Type = "Game", + Period = "December 2006" + }, + + ["PONG (2 Players)"] = { + TeleportID = 13968260883, + GameIcon = "rbxassetid://13968548520", + Description = "This is RobloxPolice's personal and private Labratory. Featuring PONG! Grab your friend and play pong! Controls are easy. Press and hold the blue button to go up and the yellow to go down. Green button pauses the game.", + Creator = "RPAdvancedLabs", + Type = "Game", + Period = "January 2007" + }, + + ["Arena Test"] = { + TeleportID = 14066099466, + GameIcon = "rbxassetid://14207380680", + Description = "", + Creator = "Joe Mama", + Type = "Game", + Period = "L. August 2006" -- real? + }, + +} diff --git a/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/GrabStuff.lua b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/GrabStuff.lua new file mode 100644 index 0000000..e079e3d --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/GrabStuff.lua @@ -0,0 +1,241 @@ +--[[ + + FORMAT: + {ID OF SHIRT OR FACE, (DETERMINES WHETHER TO BE OBTAINABLE BY DEFAULT OR NOT), {KEYWORDS HERE (SEPERATE THEM BY COMMAS)}} + + EXAMPLE: + {0, true, {"blank", "shirt", "flex please work on fwm more"}} + + NOTE: IF THE SECOND PARAMETER IS FALSE AND OBTAINABLE THROUGH SOME WAY, YOU MUST EDIT THE + "Requirements" TABLE IN BackendMain, ASK Vibin FOR ASSISTANCE ON THAT +]]-- + +return{ + ["BrickColors"] = { + 1, + 208, + 194, + 199, + 26, + 21, + 24, + 226, + 23, + 107, + 102, + 11, + 45, + 135, + 106, + 105, + 141, + 28, + 37, + 119, + 29, + 151, + 38, + 192, + 104, + 9, + 101, + 5, + 153, + 217, + 18, + 125 + }, + + ["TShirts"] = { -- to search how many shirts there are in total, ctrl + f the following without the x: "}x, + {7601978013, true, "roblox 2006 logo beta default base64"}, + {7225890697, false, "roblox 2006 logo beta modified veteran"}, + {0, true, "blank nothing empty transparent none"}, + + {1015070, false, "administrator gear cog moderator badge 75x75"}, + {1014399, false, "combat initiation badge star medal 75x75"}, + {1005130, false, "warrior badge star medal 75x75"}, + {1000004, false, "bloxxer badge 75x75 bricks explosion"}, + + {5886805736, true, "pf phoenix fire army flames jacobxxduel flag base64 2006"}, + {6084538010, true, "roblox police badge army jackrackam 2006 2007"}, + {7121346966, true, "rocket boots jet tool fly bug fire 2006"}, + {7121344440, true, "halloween skull black skeleton telamon haunted 2006"}, + {7076185913, true, "smiley flower matt dusek white drawing 2007"}, + {7121398759, true, "snowflake santa winter stronghold telamon 2006"}, + {6084691100, true, "sunset windows xp background wallpaper pink 2007"}, + {7076165986, true, "jacbob super pea vegetable funny 2007"}, + {6205718408, true, "superman katalyst hero base64 2006"}, + {6084461592, true, "tuxedo suit katalyst james bond base64 2006"}, + {1000362, true, "drome racers red dragon are92 base64 2007"}, -- 6084696684 + {6084673680, true, "radioactive green glow uranium nuke nuclear 2007"}, + {7121404744, true, "halloween pumpkin telamon jack-o-lantern 2006"}, + {6084541916, true, "pokeball pokemon pokemon97 base64 2006 2007"}, + {6328909100, true, "pirate ship brickmason jacbob 2006 2007"}, + {6251339984, true, "pirate mike brickmason base64 2006"}, + {7076153627, true, "fleskhjerta mushroom mario bloopers 2007"}, + {7121411249, true, "multirocket tool 2006 rocket arena"}, + {6084671744, true, "miked logo emblem super 2007"}, + {6436742908, true, "lightning purple black jacbob gooblox 2007"}, + {6205722211, true, "im with stupid arrow pointing meme 2007"}, + {6084526821, true, "gravitation 2007 space purple mysterious hole"}, + {5921249189, true, "god of night and day 2007 base64 telamon homestead shield"}, + {7121345101, true, "haunted mansion ghost tool spooky halloween telamon 2006"}, + {6084695263, true, "fish aquatic ocean animal 2007"}, + {7121381586, true, "face meme dank base64 2006"}, -- may remove + {7061990017, true, "dragon shield emblem telamon 2007"}, + {7076184240, true, "telamon jacbob dead head2 2006 2007"}, + {6205702463, true, "mrdoombringer doom homestead base64 2007"}, + {6084709412, true, "arrow cursor erik.cassel mouse 2007"}, + {7121381584, true, "controller flag uhjk 2005 beta dynablocks"}, + {7121352095, true, "character 2005 beta blue figure teal dynablocks"}, + {6084545449, true, "character 2005 beta blue figure teal dynablocks"}, + {6084565594, true, "bspurrell kirigi army blood hawk pf base64 2006"}, + {13337268453, true, "drome racers are92 logo 2007"}, + {6084698101, true, "american flag usa united states flag july fireworks 2007"}, + {6427376160, true, "adventure awaits roblox - game trailer crossroads telamon 2006"}, + {6084667475, true, "black ace of clubs card casino poker solitaire gambling 2007"}, + {7618927381, true, "homestead mrwaffles orange waffle butter 2007"}, + + + {13337078578, true, "roblox r logo badge default 2007"}, + {13337503926, true, "nuke nuclear explosion castle bravo 2007"}, + {1015429, true, "spongebob squarepants spunch cartoon 2007"}, + {1000024, true, "builderman wrench buildermanShirt.png 2007"}, + {13337858984, true, "aol aim running man stickman mascot logo"}, + + {1000554, true, "baseball sports 2007"}, + {1016496, true, "ussr communism soviet union flag 2007"}, + {13245205113, true, "anaminus homestead question mark base64 2007"}, + {1000740, true, "gamer3d shirt split red black transparent joker jester clown base64 2007"}, + {13187758818, true, "wfmp super mario bros overalls base64 2007"}, + + {1017060, true, "telamon mog fleskhjerta animal character transparent 2007"}, + {1003384, true, "death star wars space sci fi 2007"}, + {1018460, true, "bloxxer plus parody red grey fake 2007"}, + {13143788393, true, "jackrackam pirate army base64 flag 2006"}, + {7678853935, true, "are92 blood paintball logo studio are 2007"}, + + {1018182, true, "scarface movie mafia gun shoot 2007"}, + {1011512, true, "dark green suit tuxedo blue tie 2007"}, + {1011508, true, "dark black suit tuxedo blue tie 2007"}, + {1011796, true, "brown beige tan suit tuxedo coat black tie 2007"}, + {1001808, true, "eight 8 ball luck bowling gambling casino 2007"}, + + {1017918, true, "kop k white shirt blood shot bullet logo 2007"}, + {1013879, true, "im with stupider arrow pointer meme 2007"}, + {1000926, true, "sonic the hedgehog game character 2007"}, + {1014529, true, "pepsi cola drink soda logo blue 2007"}, + {13187755263, true, "super mario bros luigi overalls base64 wfmp 2007"}, + + {7679375110, true, "barraki rocks25 bionicles base64 homestead 2007"}, + {1010976, true, "lamborghini car fast speed yellow 2007"}, + {1012476, true, "food muffin cupcake yummy 2007"}, + {6084565594, true, "black hole space dark swirl gravity 2007"}, + {1008012, true, "red black x cross sign flag 2007"}, + + {1002268, true, "gamestop logo company videogames shop 2007"}, + {1011304, true, "halo master chief character 2007"}, + {1012929, true, "skull and crossbones death halloween spooky 2007"}, + {1009609, true, "smiley glaggleland happy face 2007"}, + {1003356, true, "roblox r logo red large full transparent icon 2007"}, + + {1029239, true, "cruss kilderstrohe stylish 3-piece tuxedo transparent suit 2007"}, + {1017832, true, "draco's shirt dracoaxemaster dracoswordmaster dracolabs knight jester 2007"}, + {1008721, true, "ziigy.jpg bomb cartoon omb mario cartoon 2007"}, + {1008078, true, "c chrisd titanic logo rainbow 2007"}, + {13187860604, true, "shirt4.png base64 transparent builderman screwdriver wrench tools 2007"}, + + {1013723, true, "binary hacker green black hax h4x l33t 9001 exploit 2007"}, + {1005242, true, "lego star wars desert jawa 2007"}, + {10858686890, true, "i am not think as you dumb i am meme 2007"}, + {13337117323, true, "purple robot 57 metal tron base64 2007"}, + {1015000, true, "internet explorer ie6 ie7 ring e icon logo blue 2007"}, + + {1005908, true, "robloxmuseum map egypt desert treasure museum pirate paper 2007"}, + {13337200441, true, "lego metal armor bullet vest base64 2007"}, + {13337691566, true, "cadi employee white pocket shirt base64 2007"}, + {1015611, true, "chocolate cake brown meme food yum 2007"}, + {1005186, true, "red striped shirt skater 2007"}, + + {13337566022, true, "windows xp background desktop wallpaper hill defaultfield"}, + {1005378, true, "chainmail armor metal knight fight viking medieval 2007"}, + {1004108, true, "space cool water neptune moon solar system wallpaper blue 2007"}, + {1006624, true, "helicopter flight military war middle east oil 2007"}, + {1037394, true, "jj5x5 elder scrolls morrowind meme 2007"}, + + {13644881970, true, "kirby super smash bros brawl mario ssbb"}, + {1007234, true, "target practice landing red white circle loop 2007"}, + {1010061, true, "sprite soda cola soft drink bubble green lemon lime 2007"}, + {1011254, true, "im no noob telamon shedletsky roblox 2007"}, + {13253939211, true, "pilot luke stealh pilot cloud city black blue jacket base64 2007"}, + + {1008468, true, "wikipedia logo icon globe world puzzle nerd 2007"}, + {1000976, true, "this is my son tustin cheese mario 3d 2007"}, + {1000356, true, "studioare are92 drome racers green uten navnx base64 2007"}, + {1000358, true, "studioare are92 drome racers nitro team metal base64 2007"}, + {1000372, true, "studioare are92 drome racers hot team orange base64 2007"}, + + {1000366, true, "studioare are92 drome racers blue zero team base64 2007"}, + {1008717, true, "void star black text contest telamon shedletsky * coding lua l33t 2007"}, + {1006026, true, "got root white text meme clone trooper telamon shedletsky l33t 2007"}, + {13253888384, true, "red black robloxmuseum base64 2007"}, + {12547933456, true, "toazuku armor blue white homestead contest base64 2007"}, + + {12638216701, true, "roblox police badge army jackrackam 2006 2007"}, + {1004184, true, "coca cola soda soft drink 2007"}, + {1016804, true, "fleskhjerta roblox bloopers sm64 mario 2007"}, + {1000038, true, "halo warthog vehicle future sci fi gaming 2007"}, + {1000532, true, "sun star solar system fireball orange hot 2007"}, + + {1010207, true, "blue suit coat red tie 2007"}, + {1028592, true, "i heart builderman love bm <3 telamon shedletsky 2007"}, + {1007862, true, "cartoon skull skeleton black white 2007"}, + {1003402, true, "i went to glass houses and all i got was this stupid tshirt 2007"}, + {1004052, true, "portal blue black video game vortex gun 2007"}, + + + {1006600, true, "fusion planet jpg space solar system hot cold black galaxy 2007"}, + {1029132, true, "are92 blood paintball logo studio are white 2007"}, + {1004172, true, "dr pepper soda cola soft drink 2007"}, + {1006858, true, "halo hello kitty meme 2007"}, + {10630575224, true, "nik1995 dragon backpack base64 2006"}, + + {1012724, true, "pie red meme food yum 2007"}, + {1009175, true, "orange half life logo icon 2007"}, + {1008987, true, "super mario 64 sm64 game bowser tail windows xp 2007"}, + {1000010, true, "world of warcraft logo black 2007"}, + {1009647, true, "old google logo browser web icon white transparent 2007"}, + + {1011830, true, "griffin red green gold yellow dragon shield medieval knight 2007"}, + {1003322, true, "meta avatar in an avatar loop render black shirt 2007"}, + {1003642, true, "Error loading 3d avatar press Alt + F4 to continue 2007"}, + {1015022, true, "red white pattern trippy colors tie dye 2007"}, + {1008651, true, "mrdoombringer doom 2 ii logo icon 2007"}, + + {1002860, true, "star wars jengo fett boba clone wars trooper 2007"}, + {13253896450, true, "roblox museum sonofsevenless cell green base64 2007"}, + {1008617, true, "cat arms out pool meme kitty 2007"}, + {1003448, true, "naruto orange anime 2007"}, + {1008388, true, "bionicles abcdefghijklmnopqrstuvwxyz 2007"}, + + {1002542, true, "transparent jacket shirt suit 2007"}, + {1005746, true, "blue cold winter.jpg ice 2007"}, + {1017522, true, "green day american idiot album song red grenade 2007"}, + {1000790, true, "green military camo 2007"}, + {1002864, true, "biohazard caution radioactive waste yellow black icon logo warning danger 2007"}, + {90991452, false, "riolu"} + }, + + ["Faces"] = { + {11945029012, true}, + {12393448905, true}, + {12393532118, true}, + {13145259803, true}, + {7679385451, true}, + {13621473345, true}, + {7678855713, true}, + {13621498989, true}, + {13621616396, true}, + {5577595083, false} -- ekosi's face + }, +} diff --git a/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/HelpPages.lua b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/HelpPages.lua new file mode 100644 index 0000000..777fd05 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/HelpPages.lua @@ -0,0 +1,13 @@ +local module = { + ["InitPage"] = [===[Welcome to FWM! + +To get started, simply choose a character and visit somebody's Place. When you visit your own place, changes that you make are permanent. Changes to someone else's place are not permanent. + +Consult the developer section in the coming days to learn how to create complex Places, how to create and publish Things, and how to work offline. + +Please enter feedback and bugs in the group wall. Thank you from the FWM team. + + ]===], +} + +return module diff --git a/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/TweenWrapper.lua b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/TweenWrapper.lua new file mode 100644 index 0000000..0b7192f --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/TweenWrapper.lua @@ -0,0 +1,30 @@ +--TweenService Wrapper +--Andrew Bereza +local TweenService = game:GetService("TweenService") +return function (object, properties, value, duration, style, direction, repeatCount, reverses) + style = style or Enum.EasingStyle.Quad + direction = direction or Enum.EasingDirection.Out + reverses = reverses or false + repeatCount = repeatCount or 0 + + duration = duration or 0.5 + + local propertyGoals = {} + + local isTable = type(value) == "table" + + for i,property in pairs(properties) do + propertyGoals[property] = isTable and value[i] or value + end + local tweenInfo = TweenInfo.new( + duration, + style, + direction, + repeatCount, + reverses + ) + local tween = TweenService:Create(object,tweenInfo,propertyGoals) + tween:Play() + + return tween +end \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/UILibrary.lua b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/UILibrary.lua new file mode 100644 index 0000000..02c4c0c --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/UILibrary.lua @@ -0,0 +1,80 @@ +local module = {} + +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local Modules = ReplicatedStorage:WaitForChild("Modules") + +local TweenWrapper = require(Modules:WaitForChild("Menu"):WaitForChild("TweenWrapper")) + +function module:SetupButtonFeedback(Button, Config) + --Cache the initial stuff so we dont need an extra dumb parameter just for that: + local NormalSize: UDim2 = Button.Size + local NormalRotation: number = Button.Rotation + local NormalBackgroundTransparency: number = Button.BackgroundTransparency + + --Config stuff into vars for safe keeping: + local HoverSize = Config["HoverSize"] or NormalSize + local DownSize = Config["DownSize"] or NormalSize + local BackgroundTransparency = Config["BackgroundTransparency"] or NormalBackgroundTransparency + local BackgroundTransparencyDown = Config["BackgroundTransparencyDown"] or NormalBackgroundTransparency + local HoverRotation = Config["HoverRotation"] or Button.Rotation + local Style = Config["Style"] or Enum.EasingStyle.Elastic + + if Config["FrameStyled"] ~= nil and Config["FrameStyled"] == true then --Some buttons use different methods of styling, such as the "JoinButton" having styling and resizing in the TextButton itself + local TextButton: Instance? = Button:FindFirstChildOfClass("TextButton") + + if TextButton and TextButton:IsA("TextButton") then + + --Hookup everything: + TextButton.MouseEnter:Connect(function() + TweenWrapper(Button, {"Size"}, {HoverSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {HoverRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {BackgroundTransparency}, .5, Style, Enum.EasingDirection.Out) + end) + + TextButton.MouseLeave:Connect(function() + TweenWrapper(Button, {"Size"}, {NormalSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {NormalRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {NormalBackgroundTransparency}, .5, Style, Enum.EasingDirection.Out) + end) + + TextButton.MouseButton1Down:Connect(function() + TweenWrapper(Button, {"Size"}, {DownSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {NormalRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {BackgroundTransparencyDown}, .5, Style, Enum.EasingDirection.Out) + end) + + TextButton.MouseButton1Up:Connect(function() + TweenWrapper(Button, {"Size"}, {NormalSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {NormalRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {NormalBackgroundTransparency}, .5, Style, Enum.EasingDirection.Out) + end) + end + elseif Config["FrameStyled"] ~= nil and Config["FrameStyled"] == false then --Just use the button instance directly + --Hookup everything: + Button.MouseEnter:Connect(function() + TweenWrapper(Button, {"Size"}, {HoverSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {HoverRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {BackgroundTransparency}, .5, Style, Enum.EasingDirection.Out) + end) + + Button.MouseLeave:Connect(function() + TweenWrapper(Button, {"Size"}, {NormalSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {NormalRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {NormalBackgroundTransparency}, .5, Style, Enum.EasingDirection.Out) + end) + + Button.MouseButton1Down:Connect(function() + TweenWrapper(Button, {"Size"}, {DownSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {NormalRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {BackgroundTransparencyDown}, .5, Style, Enum.EasingDirection.Out) + end) + + Button.MouseButton1Up:Connect(function() + TweenWrapper(Button, {"Size"}, {NormalSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {NormalRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {NormalBackgroundTransparency}, .5, Style, Enum.EasingDirection.Out) + end) + end +end + +return module diff --git a/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/VpfRayCast/GJK.lua b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/VpfRayCast/GJK.lua new file mode 100644 index 0000000..cb57bd0 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/VpfRayCast/GJK.lua @@ -0,0 +1,259 @@ +--!nolint +--Gilbert-Johnson-Keerthi distance and intersection tests +--Tyler R. Hoyer +--11/20/2014 + +--May return early if no intersection if found. If it is primed, it will run in amortized constant time (untested). + +--If the distance function is used between colliding objects, the program +--may loop a hundred times without finding a result. If this is the case, +--it will throw an error. The check is omited for speed. If the objects +--might intersect eachother, call the intersection method first. + +--Objects must implement the :getFarthestPoint(dir) function which returns the +--farthest point in a given direction. + +--Used Roblox's Vector3 userdata. Outside implementations will require a implementation of the methods of +--the Vector3's. :Dot, :Cross, .new, and .magnitude must be defined. + +local abs = math.abs +local min = math.min +local huge = math.huge +local origin = Vector3.new() + +local function loopRemoved(data, step) + --We're on the next step + step = step + 1 + + --If we have completed the last cycle, stop + if step > #data then + return nil + end + + --To be the combination without the value + local copy = {} + + --Copy the data up to the missing value + for i = 1, step - 1 do + copy[i] = data[i] + end + + --Copy the data on the other side of the missing value + for i = step, #data - 1 do + copy[i] = data[i + 1] + end + + --return the step, combination, and missing value + return step, copy, data[step] +end + +--Finds the vector direction to search for the next point +--in the simplex. +local function getDir(points, to) + --Single point, return vector + if #points == 1 then + return to - points[1] + + --Line, return orthogonal line + elseif #points == 2 then + local v1 = points[2] - points[1] + local v2 = to - points[1] + return v1:Cross(v2):Cross(v1) + + --Triangle, return normal + else + local v1 = points[3] - points[1] + local v2 = points[2] - points[1] + local v3 = to - points[1] + local n = v1:Cross(v2) + return n:Dot(v3) < 0 and -n or n + end +end + +--The function that finds the intersection between two sets +--of points, s1 and s2. s1 and s2 must return the point in +--the set that is furthest in a given direction when called. +--If the start direction sV is specified as the seperation +--vector, the program runs in constant time. (excluding the +--user implemented functions for finding the furthest point). +function intersection(s1, s2, sV) + local points = {} + + -- find point + local function support(dir) + local a = s1(dir) + local b = s2(-dir) + points[#points + 1] = a - b + return dir:Dot(a) < dir:Dot(b) + end + + -- find all points forming a simplex + if support(sV) + or support(getDir(points, origin)) + or support(getDir(points, origin)) + or support(getDir(points, origin)) + then + return false + end + + local step, others, removed = 0, nil,nil + repeat + step, others, removed = loopRemoved(points, step) + local dir = getDir(others, removed) + if others[1]:Dot(dir) > 0 then + points = others + if support(-dir) then + return false + end + step = 0 + end + until step == 4 + + return true +end + +--Checks if two vectors are equal +local function equals(p1, p2) + return p1.x == p2.x and p1.y == p2.y and p1.z == p2.z +end + +--Gets the mathematical scalar t of the parametrc line defined by +--o + t * v of a point p on the line (the magnitude of the projection). +local function getT(o, v, p) + return (p - o):Dot(v) / v:Dot(v) +end + +--Returns the scalar of the closest point on a line to +--the origin. Note that if the vector is a zero vector then +--it treats it as a point offset instead of a line. +local function lineToOrigin(o, v) + if equals(v, origin) then + return o + end + local t = getT(o, v, origin) + if t < 0 then + t = 0 + elseif t > 1 then + t = 1 + end + return o + v*t +end + +--Convoluted to deal with cases like points in the same place +local function closestPoint(a, b, c) + --if abc is a line + if c == nil then + --get the scalar of the closest point + local dir = b - a + local t = getT(a, dir, origin) + if t < 0 then t = 0 + elseif t > 1 then t = 1 + end + --and return the point + return a + dir * t + end + + --Otherwise it is a triangle. + --Define all the lines of the triangle and the normal + local vAB, vBC, vCA = b - a, c - b, a - c + local normal = vAB:Cross(vBC) + + --If two points are in the same place then + if normal.magnitude == 0 then + + --Find the closest line between ab and bc to the origin (it cannot be ac) + local ab = lineToOrigin(a, vAB) + local bc = lineToOrigin(b, vBC) + if ab.magnitude < bc.magnitude then + return ab + else + return bc + end + + --The following statements find the line which is closest to the origin + --by using voroni regions. If it is inside the triangle, it returns the + --normal of the triangle. + elseif a:Dot(a + vAB * getT(a, vAB, c) - c) <= 0 then + return lineToOrigin(a, vAB) + elseif b:Dot(b + vBC * getT(b, vBC, a) - a) <= 0 then + return lineToOrigin(b, vBC) + elseif c:Dot(c + vCA * getT(c, vCA, b) - b) <= 0 then + return lineToOrigin(c, vCA) + else + return -normal * getT(a, normal, origin) + end +end + +--The distance function. Works like the intersect function above. Returns +--the translation vector between the two closest points. +function distance(s1, s2, sV) + local function support (dir) + return s1(dir) - s2(-dir) + end + + --Find the initial three points in the search direction, opposite of the + --search direction, and in the orthoginal direction between those two + --points to the origin. + local a = support(sV) + local b = support(-a) + local c = support(-closestPoint(a, b)) + + --Setup maximum loops + local i = 1 + while i < 100 do + i = i + 1 + + --Get the closest point on the triangle + local p = closestPoint(a, b, c) + + --If it is the origin, the objects are just touching, + --return a zero vector. + if equals(p, origin) then + return origin + end + + --Search in the direction from the closest point + --to the origin for a point. + local dir = p.unit + local d = support(dir) + local dd = d:Dot(dir) + local dm = math.min( + a:Dot(dir), + b:Dot(dir), + c:Dot(dir) + ) + + --If the new point is farther or equal to the closest + --point on the triangle, then we have found the closest + --point. + if dd >= dm then + --return the point on the minkowski difference as the + --translation vector between the two closest point. + return -p + end + + --Otherwise replace the point on the triangle furthest + --from the origin with the new point + local ma, mb, mc = a:Dot(dir), b:Dot(dir), c:Dot(dir) + if ma > mb then + if ma > mc then + a = d + else + c = d + end + elseif mb > mc then + b = d + else + c = d + end + end + + --Return an error if no point was found in the maximum + --number of iterations + error 'Unable to find distance, are they intersecting?' +end + +return { + intersection = intersection; + distance = distance; +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/VpfRayCast/init.lua b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/VpfRayCast/init.lua new file mode 100644 index 0000000..5a48bb6 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/VpfRayCast/init.lua @@ -0,0 +1,246 @@ +local VpfRayCast = {} + +local Runservice = game:GetService("RunService") +local GJK = require(script.GJK) +local FRONT = Vector3.new(0, 0, -1) +local AllParts = {} + VpfRayCast.__index = VpfRayCast + + +local function LocalPos(Pos,Viewport) + local X = Pos.X - Viewport.AbsolutePosition.X + local Y = Pos.Y - Viewport.AbsolutePosition.Y + return Vector2.new(X, Y) +end + + +local function ToVec2(Vector) + return Vector2.new(Vector.x, Vector.y) +end + + +local function ScreenTo3DPlane(Pos, viewport, camera,Depth, Normal, Gui_Inset) + Pos = LocalPos(Vector2.new(Pos.X, Pos.Y ), viewport) + local Cam_Size = Vector2.new(viewport.AbsoluteSize.X , viewport.AbsoluteSize.Y - (Gui_Inset or 0)) + local Height = Cam_Size.Y + local Width = Cam_Size.X + local AspectRatio = (Cam_Size.X/Cam_Size.Y) + local Cam_Pos = camera.CFrame.Position + local Scale =(Depth or 1) + local yfov =math.rad(camera.FieldOfView) +local Tangent = math.tan((yfov/2)); + local fx = ((2 * Scale) * (Pos.x /(Width-1)) -(Scale*1)) + local fy = ((2 * Scale) * (Pos.y/(Height-1)) -(Scale*1)) + local NX = ((AspectRatio * Tangent * fx )) + local NY = (-Tangent * fy) +local NZ = -Scale +local Translatedcf = (camera.CFrame) * CFrame.new(Vector3.new(NX, NY, NZ)) -- rotate rel to camera + return CFrame.new( Translatedcf.p , camera.CFrame.p ) -- rotate to face camera +end + + + +local pPos, pI, pJ, pK +local function supportPart(dir) + return pPos + + (pI:Dot(dir) > 0 and pI or -pI) + + (pJ:Dot(dir) > 0 and pJ or -pJ) + + (pK:Dot(dir) > 0 and pK or -pK) +end + + +local min = math.min +local max = math.max + +local function rejectionVector(point, start, dir) + local vStartToPoint = point - start + return vStartToPoint - vStartToPoint:Dot(dir) * dir +end + +local function rejectionMagnitudeSquared(point, start, dir) + local vStartToPoint = point - start + local projectionMagnitude = vStartToPoint:Dot(dir) + return vStartToPoint:Dot(vStartToPoint) - projectionMagnitude * projectionMagnitude +end + + + +local rayStart, rayFinish +local function supportRay(dir) + if rayStart:Dot(dir) > rayFinish:Dot(dir) then + return rayStart + else + return rayFinish + end +end + + +local vertices + local function SupportPolygon(dir) + local furthestDistance = -math.huge + local furthestVertex = nil + for i =1, #vertices do + local distance = vertices[i].p:Dot(dir); + if (distance > furthestDistance) then + furthestDistance = distance; + furthestVertex = vertices[i].p + end + end + return furthestVertex; +end + + + +local function CloneTable(Table) +local Newtable = {} + for _, v in ipairs(Table) do + table.insert(Newtable,v) + end + return Newtable +end + + +local function GetWedgeCorners(part) +local T = {} +local S = part.size * .5 +local cf = part.CFrame +table.insert(T, cf * CFrame.new(-S.x,-S.y,-S.z)) +table.insert(T,cf * CFrame.new(S.x,-S.y,-S.z)) +table.insert(T, cf * CFrame.new(-S.x,S.y,S.z)) +table.insert(T,cf * CFrame.new(S.x,S.y,S.z)) +table.insert(T, cf * CFrame.new(-S.x,-S.y,S.z)) +table.insert(T,cf *CFrame.new(S.x,-S.y,S.z)) + return T +end + + + +local pos, s, radius +local function SupportSphere(dir) + return pos + dir.Unit * radius +end + + +local function ClosetPoint(Part, vec) + local Transform = Part.CFrame:pointToObjectSpace(vec) + local HalfSize = Part.Size * 0.5 + return Part.CFrame * Vector3.new( + math.clamp(Transform.x, -HalfSize.x, HalfSize.x), + math.clamp(Transform.y, -HalfSize.y, HalfSize.y), + math.clamp(Transform.z, -HalfSize.z, HalfSize.z) + ) +end + + + +local function ClosetPart(RayOrigin,Parts) + local BestScore = -math.huge +local BestPick +local OverallClosetPoint + for i, Part in ipairs(Parts) do + local ClosetPoint = ClosetPoint(Part, rayStart) + local Mag = (ClosetPoint- RayOrigin).Magnitude + if BestScore > Mag or i == 1 then + BestScore = Mag + BestPick = Part + OverallClosetPoint = ClosetPoint + end + end + return BestPick, OverallClosetPoint +end + + +local function findPartsOnRay(start, dir, parts,maxDist, ReturnAll ) +local finish = start + dir * (maxDist or 500) +rayStart = start +rayFinish = finish +local Foundparts = {} +for i, part in next, parts do + local Mag = rejectionMagnitudeSquared(part.Position, start, dir) + if Mag < part.Size:Dot(part.Size) then + local SupportFunc + pPos = part.Position + if part:IsA("WedgePart") then + SupportFunc = SupportPolygon + vertices = GetWedgeCorners(part) + elseif part:IsA("Part") and part.Shape == Enum.PartType.Ball then ---Check if part is a Sphere + pos = part.Position + s = part.Size * 0.5 + radius = math.min(s.X, s.Y, s.Z) + SupportFunc = SupportSphere + else ---if part is not sphere or wedge then... + SupportFunc = supportPart + local cf = part.CFrame + cf = cf - cf.p + local s = part.Size * 0.5 + pI = cf.RightVector * s.X + pJ = cf.UpVector * s.Y + pK = cf.LookVector * s.Z + end + if SupportFunc then + local vec =rejectionVector(pPos, start, dir) + if GJK.intersection(SupportFunc,supportRay,vec) then + table.insert(Foundparts, part ) + end + end + end + end + if ReturnAll then + return Foundparts, rayFinish + else + return ClosetPart(rayStart,Foundparts) + end +end + + + + + + + +local function GetAllDecendents(Table, handler, Filter) + if not Table[handler] then + Table[handler] ={} + end + Filter = Filter or {} +local ModelTargetFilters = {} + for _, part in pairs(handler:GetDescendants()) do + if not table.find(Filter, part) and not table.find(ModelTargetFilters,part) then + if part:IsA("MeshPart") or part:IsA("BasePart") then + if not table.find(Table[handler] , part) then + table.insert(Table[handler] , part) + end + end + elseif part:IsA("Model") then + for _, p in pairs(part:GetDescendants()) do + table.insert(ModelTargetFilters, p) + end + end + end + return Table[handler] +end + + +local function MouseHitFunc(Mouse,Viewport, Handler, cam, TargetFilter,All,Dist) +if typeof(TargetFilter) ~= "table" then TargetFilter = {TargetFilter} end + local Parts = GetAllDecendents(AllParts, Handler or Viewport, TargetFilter) -----This Can Be Removed as to not check constantly for parts + local cf, rot = ScreenTo3DPlane(Vector2.new(Mouse.X, Mouse.Y) , Viewport, cam) + local FowardDir = cf:VectorToWorldSpace(-FRONT) + local Parts, Pos = findPartsOnRay(cf.p, FowardDir,Parts, Dist, All) + return Parts, Pos +end + + + +function VpfRayCast.NewMouse(Mouse,vpf,camera, Handler, maxDist ) + local Functions = { + MouseHit = function(Targetfilter, All) + return MouseHitFunc(Mouse,vpf, Handler, camera,Targetfilter, All, maxDist) + end} + return Functions, setmetatable(VpfRayCast,Functions) +end + +VpfRayCast.new = VpfRayCast.NewMouse +VpfRayCast.RayCast = findPartsOnRay + +return VpfRayCast diff --git a/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/init.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Modules/Menu/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Modules/init.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Modules/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Modules/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/Preview/Animate.client.lua b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/Preview/Animate.client.lua new file mode 100644 index 0000000..ca62ad0 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/Preview/Animate.client.lua @@ -0,0 +1,260 @@ +-- declarations +local Players = game:GetService("Players") +local self = Players.LocalPlayer +local Figure = script.Parent +local Torso = Figure:WaitForChild("Torso") +local RightShoulder = Torso:WaitForChild("Right Shoulder") +local LeftShoulder = Torso:WaitForChild("Left Shoulder") +local RightHip = Torso:WaitForChild("Right Hip") +local LeftHip = Torso:WaitForChild("Left Hip") +local Neck = Torso:WaitForChild("Neck") +local Humanoid = Figure:WaitForChild("Humanoid") + +local pose = "Standing" +local jumped = false + +local TablePoseList = { +-- [Enum.HumanoidStateType.FallingDown] = "FallingDown", +-- [Enum.HumanoidStateType.Freefall] = "FreeFall", + [Enum.HumanoidStateType.Climbing] = "Climbing", + [Enum.HumanoidStateType.Jumping] = "Jumping", + [Enum.HumanoidStateType.Seated] = "Seated", + [Enum.HumanoidStateType.Dead] = "Dead", +} + +local params = OverlapParams.new() +local ignore = {Figure, workspace.CurrentCamera} +params.FilterDescendantsInstances = ignore +params.FilterType = Enum.RaycastFilterType.Blacklist + +local legObjects = {} + +local toolAnim = "None" +local toolAnimTime = 0 + +-- functions + +local speed : number = 0 +function onRunning(spd : number) + speed = spd + if speed >= 0.6 or Humanoid.MoveDirection.Magnitude > 0.1 then + pose = "Running" + else + pose = "Standing" + end +end + +local sillyPoses = {"Jumping", "Freefall"} +function StateChanged(old : Enum.HumanoidStateType, new : Enum.HumanoidStateType) + if not new.Name:match("Running") then + local poseFound = TablePoseList[new] + + if poseFound then + pose = poseFound + end + end + + if not table.find(sillyPoses, new.Name) and jumped == true then + jumped = false + end +end + +function moveJump() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = 3.14 + LeftShoulder.DesiredAngle = -3.14 + RightHip.DesiredAngle = 0 + LeftHip.DesiredAngle = 0 +end + +function moveSeated() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = 3.14/2 + LeftShoulder.DesiredAngle = -3.14/2 + RightHip.DesiredAngle = 3.14/2 + LeftHip.DesiredAngle = -3.14/2 +end + +function moveClimb() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = -3.14 + LeftShoulder.DesiredAngle = 3.14 + RightHip.DesiredAngle = 0 + LeftHip.DesiredAngle = 0 +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" and pose ~= "Climbing") then + RightShoulder.DesiredAngle = 1.57 + RightShoulder.MaxVelocity = 0.175/2 + -- LeftShoulder.MaxVelocity = 0.175 + return + end + + if (toolAnim == "Slash") then + RightShoulder.MaxVelocity = 0.35/2 + RightShoulder.DesiredAngle = 0 + return + end + + if (toolAnim == "Lunge") then + RightShoulder.MaxVelocity = 0.35/2 + LeftShoulder.MaxVelocity = 0.35/2 + RightHip.MaxVelocity = 0.35/2 + LeftHip.MaxVelocity = 0.35/2 + RightShoulder.DesiredAngle = 1.57 + LeftShoulder.DesiredAngle = 1.0 + RightHip.DesiredAngle = 1.57 + LeftHip.DesiredAngle = 1.0 + return + end +end + +function getTool() + for _, v : Instance in pairs(Figure:GetChildren()) do + if v:IsA("Tool") then + if not v:FindFirstChild("FakeHopperbin") then + return v + end + end + end + + return false +end + +function move(time) + local state = Humanoid:GetState().Name + local amplitude + local frequency + + if pose == "Seated" or state == "Seated" then + moveSeated() + return + end + + if (pose == "FreeFall" or pose == "Jumping") and jumped == true then + moveJump() + return + end + + if pose == "Climbing" or #legObjects > 0 then + moveClimb() + return + end + + RightShoulder.MaxVelocity = 0.15/2 + LeftShoulder.MaxVelocity = 0.15/2 + if pose == "Running" then + amplitude = 1 + frequency = 9 + else + amplitude = 0.1 + frequency = 1 + end + + local desiredAngle = amplitude * math.sin(time*frequency) + + RightShoulder.DesiredAngle = desiredAngle + LeftShoulder.DesiredAngle = desiredAngle + RightHip.DesiredAngle = -desiredAngle + LeftHip.DesiredAngle = -desiredAngle + + 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 + toolAnim = "None" + toolAnimTime = 0 + end +end + + +-- Connect events + +Humanoid.Running:Connect(onRunning) +Humanoid.StateChanged:Connect(StateChanged) + +script:WaitForChild("ForcePose").Event:Connect(function(newPose : string) + if typeof(newPose) == "string" then + pose = newPose + if newPose == "Jumping" then + jumped = true + moveJump() + end + end +end) + +Humanoid.Jumping:Connect(function(state) + if state == true then + jumped = true + pose = "Jumping" + moveJump() + end +end) + +-- main program + +local nextTime = 0 +local runService = game:GetService("RunService"); + +while Figure.Parent ~= nil do + local CurrentState = Humanoid:GetState().Name + local time = runService.Stepped:Wait() + if time > nextTime then + local VerticalVelocity = Torso.AssemblyLinearVelocity.Y + local HorizontalVelocity = Torso.AssemblyLinearVelocity * Vector3.new(1, 0, 1) + local requestMoveMagnitude = (Humanoid.MoveDirection.Magnitude > 0 and Humanoid.MoveDirection.Magnitude or CFrame.lookAt(Torso.Position * Vector3.new(1, 0, 1), Humanoid.WalkToPoint * Vector3.new(1, 0, 1)).LookVector.Magnitude) + + if math.abs(VerticalVelocity) > 0.025 and CurrentState:match("Running") then + local overlap = workspace:GetPartBoundsInBox((Torso.CFrame * CFrame.new(0, -1.75, 0)) * CFrame.new(Torso.AssemblyLinearVelocity.Unit * Vector3.new(1, 0, 1)), Vector3.new(2, 2, 1) / 1.5, params) + for _, v : BasePart? in pairs(overlap) do + if v and v.CanCollide == false then + table.insert(ignore, v) + params.FilterDescendantsInstances = ignore + + table.remove(overlap, table.find(overlap, v)) + end + end + legObjects = overlap + else + table.clear(legObjects) + if jumped == false and CurrentState ~= "Climbing" and CurrentState ~= "FallingDown" then + onRunning(HorizontalVelocity.Magnitude * requestMoveMagnitude) + end + end + + move(time) + nextTime = time + 0.1 + end +end diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/Preview/Animate.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/Preview/Animate.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/Preview/Animate.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/Preview/init.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/Preview/init.meta.json new file mode 100644 index 0000000..ed9b9af --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/Preview/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "WorldModel", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/init.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/init.meta.json new file mode 100644 index 0000000..a31ba2a --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/ViewportFrame/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ViewportFrame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/init.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/FriendAvatar/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/init.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/Friend/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlayButton/Button/Main.client.lua b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlayButton/Button/Main.client.lua new file mode 100644 index 0000000..2b186a3 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlayButton/Button/Main.client.lua @@ -0,0 +1,19 @@ +--!strict + +local TeleportService : TeleportService = game:GetService("TeleportService") +local ReplicatedStorage : ReplicatedStorage = game:GetService("ReplicatedStorage") + +local Protocols : Instance = ReplicatedStorage:WaitForChild("Protocols") +local TeleportPlayer : Instance = Protocols:WaitForChild("TeleportPlayer") + + +local function Clicked(): () + local Container = script.Parent.Parent.Parent + local GameID = Container.GameId + + if TeleportPlayer:IsA("RemoteEvent") then + TeleportPlayer:FireServer(GameID.Value, Container.GameName.Text, "play") + end +end + +script.Parent.MouseButton1Click:Connect(Clicked) \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlayButton/Button/init.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlayButton/Button/init.meta.json new file mode 100644 index 0000000..8ed9503 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlayButton/Button/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "TextButton", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlayButton/init.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlayButton/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlayButton/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlaySoloButton/Button/Main.client.lua b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlaySoloButton/Button/Main.client.lua new file mode 100644 index 0000000..bab5aef --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlaySoloButton/Button/Main.client.lua @@ -0,0 +1,19 @@ +--!strict + +local TeleportService : TeleportService = game:GetService("TeleportService") +local ReplicatedStorage : ReplicatedStorage = game:GetService("ReplicatedStorage") + +local Protocols : Instance = ReplicatedStorage:WaitForChild("Protocols") +local TeleportPlayer : Instance = Protocols:WaitForChild("TeleportPlayer") + + +local function Clicked(): () + local Container = script.Parent.Parent.Parent + local GameID = Container.GameId + + if TeleportPlayer:IsA("RemoteEvent") then + TeleportPlayer:FireServer(GameID.Value, Container.GameName.Text, "solo") + end +end + +script.Parent.MouseButton1Click:Connect(Clicked) \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlaySoloButton/Button/init.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlaySoloButton/Button/init.meta.json new file mode 100644 index 0000000..8ed9503 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlaySoloButton/Button/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "TextButton", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlaySoloButton/init.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlaySoloButton/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/PlaySoloButton/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/init.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/GameContainer/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/init.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/Guis/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ReplicatedStorage/Templates/init.meta.json b/rojo/MainMenu/src/ReplicatedStorage/Templates/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainMenu/src/ReplicatedStorage/Templates/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerScriptService/BackendMain/BanScreen/OminousMusic.client.lua b/rojo/MainMenu/src/ServerScriptService/BackendMain/BanScreen/OminousMusic.client.lua new file mode 100644 index 0000000..4e5ac0e --- /dev/null +++ b/rojo/MainMenu/src/ServerScriptService/BackendMain/BanScreen/OminousMusic.client.lua @@ -0,0 +1,6 @@ +workspace.Music.Volume = 0 + +local newMusic = Instance.new("Sound") +newMusic.SoundId = "rbxasset://0" +newMusic.Volume = 1 +newMusic.Parent = workspace \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerScriptService/BackendMain/BanScreen/init.meta.json b/rojo/MainMenu/src/ServerScriptService/BackendMain/BanScreen/init.meta.json new file mode 100644 index 0000000..118e2ca --- /dev/null +++ b/rojo/MainMenu/src/ServerScriptService/BackendMain/BanScreen/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ScreenGui", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerScriptService/BackendMain/init.server.lua b/rojo/MainMenu/src/ServerScriptService/BackendMain/init.server.lua new file mode 100644 index 0000000..8c30897 --- /dev/null +++ b/rojo/MainMenu/src/ServerScriptService/BackendMain/init.server.lua @@ -0,0 +1,1059 @@ +local DataStoreService: DataStoreService = game:GetService("DataStoreService") +local MessagingService: MessagingService = game:GetService("MessagingService") +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local RunService: RunService = game:GetService("RunService") +local TeleportService: TeleportService = game:GetService("TeleportService") +local BadgeService: BadgeService = game:GetService("BadgeService") +local ChatService: Chat = game:GetService("TextService") +local MarketPlaceService = game:GetService("MarketplaceService") + +--------------------------------------------------------------------------------------------------------------- +local Main: GlobalDataStore = DataStoreService:GetDataStore("FWM_MAIN_DATA") +local Messages: GlobalDataStore = DataStoreService:GetDataStore("FWM_MAIN_DATA", "Messages") +local BannedPeople: GlobalDataStore = DataStoreService:GetDataStore("FWM_MAIN_DATA", "Banned") +--------------------------------------------------------------------------------------------------------------- +local OnlineStatus: OrderedDataStore = DataStoreService:GetOrderedDataStore("FWM_ACTIVITY") +local Points: OrderedDataStore = DataStoreService:GetOrderedDataStore("FWM_POINTS_BOARD") +-- The KOs - WOs system is referred to as "Points" + +local Protocols: Instance = ReplicatedStorage:FindFirstChild("Protocols") +local TeleportPlayer = Protocols:FindFirstChild("TeleportPlayer") +local AvatarChange = Protocols:FindFirstChild("ChangeAvatar") +local SettingsChange = Protocols:FindFirstChild("ChangeSettings") +local ReturnBadgeInfo = Protocols:FindFirstChild("ReturnBadgeInfo") +local GetAvatarRemote = Protocols:FindFirstChild("GetLocalPlayerAvatar") +local AwardItem = Protocols:FindFirstChild("AwardItem") +local UpdatePointsLeaderboard = Protocols:FindFirstChild("UpdatePointsLeaderboard") +--local BanScreen = script.BanScreen + +local UpdateAvatar: Instance | RemoteEvent = Protocols:FindFirstChild("V2ChangeAvatar") +local ChangeSetting: Instance | RemoteEvent = Protocols:FindFirstChild("V2ChangeSetting") + +local GetAvatar: Instance | RemoteEvent = Protocols:FindFirstChild("V2GetAvatar") + +local ReturnAvatar: Instance | RemoteEvent = Protocols:FindFirstChild("V2ReturnAvatar") +local ReturnStats: Instance | RemoteEvent = Protocols:FindFirstChild("V2ReturnStats") +local ReturnSettings: Instance | RemoteEvent = Protocols:FindFirstChild("V2ReturnSetting") +local ReturnBadges: Instance | RemoteEvent = Protocols:FindFirstChild("V2ReturnBadges") + +local DataHandler = require(ReplicatedStorage:WaitForChild("Classes"):WaitForChild("DataHandler")) +local GrabStuff = require(ReplicatedStorage:FindFirstChild("Modules"):FindFirstChild("Menu"):FindFirstChild("GrabStuff")) + + +local PlayerDatas: any = {} + +--[[ + + Badges = { + [UID] = { + Badge = false, + } + }, + + IsAdmin = { + [UID] = boolean + } + +]]-- +local TestingPlayerDatas: any = {} + +local TestingPlayerCaches = { + Badges = {}, + IsAdmin = {}, + Gamepasses = {}, + Avatars = {}, + Ids = {}, + Names = {} +} + +local TestingCooldown = { + Messenging = {}, + Profiles = {} +} + +local TestingRescript = false +local Testers = { + [385867863] = true, + [151461991] = true +} + + +local AdditionalPlayerDatas: any = {} +local GrabbedAvs = {} +local DataStoreFailedMessage = "DataStore failed to load. Please try again later!" + +local Avatars: {{ [string] : number }} = { + [1] = { + Head = 24, + Torso = 194, + LeftArm = 24, + RightArm = 24, + LeftLeg = 119, + RightLeg = 119, + TShirt = 7601978013, + Face = 11945029012 + }, + [2] = { + Head = 24, + Torso = 101, + LeftArm = 24, + RightArm = 24, + LeftLeg = 9, + RightLeg = 9, + TShirt = 7601978013, + Face = 11945029012 + }, + [3] = { + Head = 24, + Torso = 23, + LeftArm = 24, + RightArm = 24, + LeftLeg = 119, + RightLeg = 119, + TShirt = 7601978013, + Face = 11945029012 + }, + [4] = { + Head = 24, + Torso = 101, + LeftArm = 24, + RightArm = 24, + LeftLeg = 119, + RightLeg = 119, + TShirt = 7601978013, + Face = 11945029012 + }, + [5] = { + Head = 24, + Torso = 11, + LeftArm = 24, + RightArm = 24, + LeftLeg = 119, + RightLeg = 119, + TShirt = 7601978013, + Face = 11945029012 + }, + [6] = { + Head = 12, + Torso = 194, + LeftArm = 12, + RightArm = 12, + LeftLeg = 119, + RightLeg = 119, + TShirt = 7601978013, + Face = 11945029012 + }, + [7] = { + Head = 18, + Torso = 119, + LeftArm = 18, + RightArm = 18, + LeftLeg = 119, + RightLeg = 119, + TShirt = 7601978013, + Face = 11945029012 + }, + [8] = { + Head = 9, + Torso = 194, + LeftArm = 9, + RightArm = 9, + LeftLeg = 119, + RightLeg = 119, + TShirt = 7601978013, + Face = 11945029012 + } +} + +local MessageFormat = { + UserId = 0, + SentTime = 0, + + MessageTitle = "", + MessageBody = "", + + MessageOpened = false +} + +local DefaultFace = 11945029012 +local FWMVIPGamepass = 10762139 + +--[[ + + FORMAT FOR TSHIRTS/FACE: + TShirt = { + [TSHIRTID] = function(Player: Player) + + end, + } + + Face = { + [FACEID] = function(Player: Player) + + end, + } + +]]-- +local Requirements = { + TShirt = { + [1015070] = function(Player: Player) -- Admin T-Shirt + local IsDevAttribute = Player:GetAttribute("IsDev") + return IsDevAttribute + end, + + [1014399] = function(Player: Player) -- Combat Initiation T-Shirt + local IsRegisteredExtra = AdditionalPlayerDatas[Player] + + if IsRegisteredExtra then + return IsRegisteredExtra.BadgeInfo.CombatInitiation + end + + return false + end, + + [1005130] = function(Player: Player) -- Warrior T-Shirt + local IsRegisteredExtra = AdditionalPlayerDatas[Player] + + if IsRegisteredExtra then + return IsRegisteredExtra.BadgeInfo.Warrior + end + + return false + end, + + [1000004] = function(Player: Player) -- Bloxxer T-Shirt + local IsRegisteredExtra = AdditionalPlayerDatas[Player] + + if IsRegisteredExtra then + return IsRegisteredExtra.BadgeInfo.Bloxxer + end + + return false + end, + + [7225890697] = function(Player: Player) + local IsRegisteredExtra = AdditionalPlayerDatas[Player] + + if IsRegisteredExtra then + return IsRegisteredExtra.BadgeInfo.Veteran + end + + return false + end, + + -- I will murder you no matter what. + [90991452] = function(Player: Player) + local IsMax = (Player.UserId == 45507514) + return IsMax + end, + }, + + Face = { + [5577595083] = function(Player: Player) + local IsEkosi = (Player.UserId == 13972952) + return IsEkosi + end, + } +} + +local BodyParts: { [string] : boolean } = { + ["Head"] = true, + ["Torso"] = true, + ["LeftArm"] = true, + ["RightArm"] = true, + ["LeftLeg"] = true, + ["RightLeg"] = true, + ["TShirt"] = true, + ["Face"] = true +} + +local Badges = { + ["CombatInitiation"] = 2141034357, + ["Warrior"] = 2141034375, + ["Bloxxer"] = 2141034376, + ["Veteran"] = 2124574679 +} + +-- Format: +-- SettingVariable = {"Setting Type", Default Value, Minimum [for numbers, optional], Maximum [for numbers, optional]} + +-- NOTE that the setting type must work with "typeof" +local Settings: {[string]: {any}} = { + FPS = {"boolean", false}, + ErrorsInChat = {"boolean", false}, + DisplayNames = {"boolean", false}, + CameraLerp = {"number", 0.9, 0.1, 1}, + LobbyMusic = {"boolean", true} +} + +local function findViaInformation(fullTable: {any}, value: any): any + for ind, information in pairs(fullTable) do + if information[1] == value then + return ind + end + end + + return nil +end + +local ExtraChecks = { + ["TShirt"] = function(Value) + local InfoSearch = findViaInformation(GrabStuff.TShirts, Value) + + return InfoSearch and GrabStuff.TShirts[InfoSearch][2] or false + end, + + ["Face"] = function(Value, Player) + local InfoSearch = findViaInformation(GrabStuff.Faces, Value) + local HasAdvanced = TestingPlayerCaches.HasGamepass[Player].Advanced + + return (InfoSearch and HasAdvanced == true) and GrabStuff.Faces[InfoSearch][2] or false + end, +} + +local function NewData(UserID : number) + local NewAvatar = Avatars[math.random(1, 8)] + return{ + ["FWM_USER_DATA_"..UserID] = { + ["PlayerData"] = { + Avatar = table.clone(NewAvatar), + Avatar2006 = table.clone(NewAvatar), + + UserData = { + Settings = { + BloomAndDoF = false, + Animations = false, + FPS = true, + LobbyMusic = true, + ErrorsInChat = false, + DisplayNames = false, + CameraLerp = 0.9, + }, + + BrickBattleData = { + KOs = 0, + WOs = 0, + }, + }, + }, + }, + } +end + +local function returnNewDataTable() + local randomAvatar = math.random(1, #Avatars) + local cloned2007Avatar = table.clone(Avatars[randomAvatar]) + + return{ + Avatars = { + Avatar2007 = cloned2007Avatar, + Avatar2006 = randomAvatar + }, + + Settings = { + FPS = false, + ErrorsInChat = false, + DisplayNames = false, + CameraLerp = 0.9, + LobbyMusic = true + }, + + BrickBattleData = { + KOs = 0, + WOs = 0 + }, + + Profile = { + ProfileStatus = "", + RecentlyPlayed = {} + } + } +end + +-- An automatic DataStore updater, used to sync old data and turn it into a new format, or 2.0 format as I like to call it +-- by I, I mean Vibin lol +local function updateDataTable(dataTable, userId) + local outdatedDataTable = dataTable["FWM_USER_DATA_"..userId] + local finishedDataStore: any = dataTable + + -- UH OH! OUTDATED! lets convert to new datastores + if outdatedDataTable ~= nil then + print("DataStore outdated... converting into 2.0 data...") + local newDataTable = returnNewDataTable() + + local playerDataOutdated = outdatedDataTable["PlayerData"] + local userdataOutdated = playerDataOutdated["UserData"] + + newDataTable.Avatars.Avatar2007 = table.clone(playerDataOutdated.Avatar) + + for settingName, settingValue in pairs(userdataOutdated.Settings) do + local isValidSetting = Settings[settingName] + + if isValidSetting == nil then + print("Destroying outdated setting: "..settingName) + continue + end + + newDataTable.Settings[settingName] = settingValue + end + + if userdataOutdated.BrickBattleData then + newDataTable.BrickBattleData.KOs = userdataOutdated.BrickBattleData.KOs + newDataTable.BrickBattleData.WOs = userdataOutdated.BrickBattleData.WOs + end + + finishedDataStore = newDataTable + end + + return finishedDataStore +end + +local function FilterString(Player, StringFiltering) + local IsMultiple = typeof(StringFiltering) == "table" + + if IsMultiple then + local ReturningTable = {} + + for Index, Text in IsMultiple do + local Filtered, Final = pcall(function() + return ChatService:FilterStringForBroadcast(Text, Player) + end) + + if (not Filtered) then + return nil + end + + ReturningTable[Index] = Final + end + + return ReturningTable + else + local Filtered, Final = pcall(function() + return ChatService:FilterStringForBroadcast(StringFiltering, Player) + end) + + return Filtered and Final or nil + end +end + +local function GrabBadgeStatus(Player, BadgeVariable, BadgeId) + local AlreadyCached = TestingPlayerCaches.Badges[Player.UserId][BadgeVariable] ~= nil + + if AlreadyCached then + return TestingPlayerCaches.Badges[Player.UserId][BadgeVariable] + end + + local BadgeStatusGrabbed, BadgeStatus = pcall(function() + return BadgeService:UserHasBadgeAsync(Player.UserId, BadgeId) + end) + + TestingPlayerCaches.Badges[Player.UserId][BadgeVariable] = BadgeStatus or false +end + +local function GrabGamepassStatus(Player, GamepassVariable, GamepassId) + local AlreadyCached = TestingPlayerCaches.Gamepasses[Player.UserId][GamepassVariable] ~= nil + + if AlreadyCached then + return TestingPlayerCaches.Gamepasses[Player.UserId][GamepassVariable] + end + + local GamepassStatusGrabbed, GamepassStatus = pcall(function() + return MarketPlaceService:UserOwnsGamePassAsync(Player.UserId, GamepassId) + end) + + TestingPlayerCaches.Gamepasses[Player.UserId][GamepassVariable] = GamepassStatus +end + +local function GrabAdminStatus(Player) + local AlreadyCached = TestingPlayerCaches.IsAdmin[Player.UserId] ~= nil + + if AlreadyCached then + return TestingPlayerCaches.IsAdmin[Player.UserId] + end + + local AdminStatusSuccess, AdminStatus = pcall(function() + return Player:GetRankInGroup(15820336) > 251 + end) + + TestingPlayerCaches.IsAdmin[Player.UserId] = AdminStatus +end + +local function GrabProfile(Player, NameSearching) + +end + +local function SendMessage(Player, SendingName, Title, Body) + +end + +-- Rewrite ban section +local function CoolerPlayerAdded(Player: Player): () + if (not TestingRescript) then + return + end + + if (not Testers[Player.UserId]) then + return + end + + local StringedID = tostring(Player.UserId) + local DataTable + + local BanStatusSuccess, BanStatusGrabbed = pcall(function() + return BannedPeople:GetAsync(StringedID) + end) + + if (not BanStatusSuccess) then + Player:Kick(DataStoreFailedMessage) + + return + end + + if BanStatusGrabbed then + local Terminated = not tonumber(BanStatusGrabbed.UnbanTime) + + local PlayerGui = Player:WaitForChild("PlayerGui") + local MainGui = PlayerGui:WaitForChild("MainUI") + + task.defer(MainGui.Destroy) + + if Terminated or BanStatusGrabbed.UnbanTime > os.time() then + local BanScreen = script.BanScreen:Clone() + local BanInformation = BanScreen.Information.TimeToCryKiddos + + BanInformation.BanNote.Text = "Banned for: "..BanStatusGrabbed.Reason + BanInformation.UnbanTime.Text = Terminated and "Your FWM account has been terminated." or `Unbanned on: {os.date("%B %d, %Y @ %I:%M %p", BanStatusGrabbed.UnbanTime)}` + + BanScreen.Parent = PlayerGui + + return + end + + BannedPeople:RemoveAsync(StringedID) + end + + local StandardDataSuccess, StandardDataGrabbed = pcall(function() + return Main:GetAsync("FWM_TESTING_DATA_"..Player.UserId) + end) + + if StandardDataSuccess then + DataTable = StandardDataGrabbed and updateDataTable(StandardDataGrabbed, StringedID) or returnNewDataTable() + else + Player:Kick(DataStoreFailedMessage) + + return + end + + ReturnSettings:FireClient(Player, DataTable.Settings) + + ReturnAvatar:FireClient(Player, DataTable.Avatars.Avatar2007, "Home") + ReturnAvatar:FireClient(Player, Avatars[DataTable.Avatars.Avatar2006], "Avatar") + + ReturnStats:FireClient(Player, DataTable.BrickBattleData) + + TestingPlayerDatas[Player] = DataTable + + for Name, List in pairs(TestingPlayerCaches) do + TestingPlayerCaches[Name][Player.UserId] = {} + end + + -- Lets grab all information + GrabGamepassStatus(Player, "Advanced", FWMVIPGamepass) + GrabAdminStatus(Player) + + for BadgeVariable, BadgeId in pairs(Badges) do + GrabBadgeStatus(Player, BadgeVariable, BadgeId) + end + + -- IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE + if DataTable.BrickBattleData.KOs >= 10 and (not TestingPlayerCaches.Badges[Player.UserId].CombatInitiation) then + TestingPlayerCaches.Badges[Player.UserId].CombatInitiation = true + BadgeService:AwardBadge(Player.UserId, Badges.CombatInitiation) + end + + if DataTable.BrickBattleData.KOs >= 100 and (not TestingPlayerCaches.Badges[Player.UserId].Warrior) then + TestingPlayerCaches.Badges[Player.UserId].Warrior = true + BadgeService:AwardBadge(Player.UserId, Badges.Warrior) + end + + if (DataTable.BrickBattleData.KOs >= 250 and DataTable.BrickBattleData.KOs > DataTable.BrickBattleData.WOs) and (not TestingPlayerCaches.Badges[Player].Bloxxer) then + TestingPlayerCaches.Badges[Player.UserId].Bloxxer = true + BadgeService:AwardBadge(Player.UserId, Badges.Bloxxer) + end + -- IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE + + ReturnBadges:FireClient(Player, TestingPlayerCaches.Badges[Player]) + -- oh so thats how you're going to be? + --PlayerDatas[Player] = DataTable +end + +local function V2ChangeAvatar(Player, Figure, Changing, Value, Time) + local UserData = TestingPlayerDatas[Player] + + if (not UserData) then + return + end + + Time = Time ~= nil and Time or 2006 + + if Time == 2006 and Figure and Avatars[Figure] then + UserData.Avatars.Avatar2006 = Figure + ReturnAvatar:FireClient(Player, Avatars[UserData.Avatars.Avatar2006], "Avatar") + elseif Time == 2007 and (not Figure) and (Changing and Value) and BodyParts[Changing] then + local IsValidForChange = false + local Requirement = Requirements[Changing] + + local IsRegisteredColor = table.find(GrabStuff.BrickColors, Value) + IsValidForChange = (not ExtraChecks[Changing]) and IsRegisteredColor ~= nil or ExtraChecks[Changing](Value, Player) + + if Requirement and IsValidForChange then + local ItemRequirement = Requirement[Value] + + if ItemRequirement then + IsValidForChange = ItemRequirement(Player) or false + end + end + + if IsValidForChange then + UserData.Avatars.Avatar2007[Changing] = Value + ReturnAvatar:FireClient(Player, UserData.Avatars.Avatar2007) + end + end +end + +local function V2GetAvatar(Player, Time) + local UserData = TestingPlayerDatas[Player] + + if (not UserData) then + return + end + + if Time == 2006 then + ReturnAvatar:FireClient(Player, Avatars[UserData.Avatars.Avatar2006], "Avatar") + return + end + + ReturnAvatar:FireClient(Player, UserData.Avatars.Avatar2007, "Avatar") +end + +local function V2ChangeSetting(Player, Setting, Value) + local UserData = TestingPlayerDatas[Player] + + if (not UserData) then + return + end + + if Settings[Setting] then + local SettingInformation = Settings[Setting] + + local ValueType = typeof(Value) + local IsValid = SettingInformation[1] == ValueType + + if IsValid then + local IsClamp = ValueType == "number" and math.clamp(Value, SettingInformation[3] or Value, SettingInformation[4] or Value) or false + + UserData.Settings[Setting] = IsClamp or Value + end + end +end + +local function PlayerAdded(Player: Player): () + if TestingRescript and Testers[Player.UserId] then + return + end + --if Player.UserId == 385867863 then + -- return + --end + + local PlayerData + local Inserting + + local IsBanned + local GrabbedBan, Failed = pcall(function() + IsBanned = BannedPeople:GetAsync(tostring(Player.UserId)) + end) + + if (not Failed) and IsBanned then + local NotTerminated = IsBanned.UnbanTime ~= "Never" and tonumber(IsBanned.UnbanTime) + local WaitForPlayerGui = Player:WaitForChild("PlayerGui") + + if (NotTerminated and IsBanned.UnbanTime > os.time()) or (not NotTerminated) then + if WaitForPlayerGui then + local MainUI = WaitForPlayerGui:FindFirstChild("MainUI") + + if MainUI and MainUI:IsA("ScreenGui") then + local BanScreen = script.BanScreen:Clone() + local BanInformation = BanScreen.Information.TimeToCryKiddos + + BanInformation.BanNote.Text = "Banned for: "..IsBanned.Reason + BanInformation.UnbanTime.Text = NotTerminated and `Unbanned on: {os.date("%B", IsBanned.UnbanTime)} {os.date("%d", IsBanned.UnbanTime)}, {os.date("%Y", IsBanned.UnbanTime)} @ {os.date("%I", IsBanned.UnbanTime)}:{os.date("%M", IsBanned.UnbanTime)} {string.upper(os.date("%p", IsBanned.UnbanTime))}` or "Your FWM account has been terminated." + + BanScreen.Parent = WaitForPlayerGui + MainUI.Enabled = false + end + end + + return + end + + local Unbanned, FailedToUnban = pcall(function() + return BannedPeople:RemoveAsync(tostring(Player.UserId)) + end) + end + + local GrabbedData, FailedToGrab = pcall(function() + PlayerData = Main:GetAsync("FWM_TESTING_DATA_" .. Player.UserId) + end) + + if not FailedToGrab then + if PlayerData then + Inserting = PlayerData + else + Inserting = NewData(Player.UserId) + end + end + + if Inserting then + PlayerDatas[Player] = Inserting + AdditionalPlayerDatas[Player] = {} + + print("Loaded data of "..tostring(Player.Name)) + + local Find = DataHandler.New(PlayerDatas[Player], Player.UserId) + + if Find then + local NewFixing = NewData(0) + local NewFixingData = NewFixing["FWM_USER_DATA_0"] + + Find:fixData(NewFixingData) + + local grabbedAvatar = Find:getAvatar() + local grabbedSetting = Find:getSetting() + local grabbedStats = Find:getStats() + + local Return = Protocols:FindFirstChild("ReturnAvatar") + local ReturnSet = Protocols:FindFirstChild("ReturnSettings") + local ReturnStats = Protocols:FindFirstChild("ReturnStats") + + if Return:IsA("RemoteEvent") and ReturnSet:IsA("RemoteEvent") and ReturnStats:IsA("RemoteEvent") and grabbedAvatar and grabbedSetting and grabbedStats then + Return:FireClient(Player, grabbedAvatar, "All") + ReturnSet:FireClient(Player, grabbedSetting) + ReturnStats:FireClient(Player, grabbedStats) + end + end + end + + local HasCombat + local HasWarrior + local HasBloxxer + local HasVeteran + + local BadgeSuccess, BadgeFailed = nil, true + + while BadgeFailed do + task.wait(1) + + BadgeSuccess, BadgeFailed = pcall(function() + HasCombat = BadgeService:UserHasBadgeAsync(Player.UserId, 2141034357) + HasWarrior = BadgeService:UserHasBadgeAsync(Player.UserId, 2141034375) + HasBloxxer = BadgeService:UserHasBadgeAsync(Player.UserId, 2141034376) + HasVeteran = BadgeService:UserHasBadgeAsync(Player.UserId, 2124574679) + end) + end + + local ReturningBadgeInfo = { + CombatInitiation = false, + Warrior = false, + Bloxxer = false, + Veteran = false + } + + local Data = DataHandler.New(PlayerDatas[Player], Player.UserId) + + if Data and (not BadgeFailed) and ((HasCombat and HasWarrior and HasBloxxer and HasVeteran) ~= nil) then + local playerstats = Data:getStats() + + if playerstats["KOs"] >= 10 then + if (not HasCombat) then + BadgeService:AwardBadge(Player.UserId, 2141034357) + end + + ReturningBadgeInfo.CombatInitiation = true + end + + if playerstats["KOs"] >= 100 then + if (not HasWarrior) then + BadgeService:AwardBadge(Player.UserId, 2141034375) + end + + ReturningBadgeInfo.Warrior = true + end + + if (playerstats["KOs"] >= 250 and playerstats["KOs"] > playerstats["WOs"]) then + if (not HasBloxxer) then + BadgeService:AwardBadge(Player.UserId, 2141034376) + end + + ReturningBadgeInfo.Bloxxer = true + end + + ReturningBadgeInfo.Veteran = HasVeteran + + if ReturnBadgeInfo:IsA("RemoteEvent") then + ReturnBadgeInfo:FireClient(Player, ReturningBadgeInfo) + end + end + AdditionalPlayerDatas[Player].BadgeInfo = table.clone(ReturningBadgeInfo) + + local IsDev = false + local DevSuccess, DevFailed = pcall(function() + IsDev = Player:GetRankInGroup(15820336) > 251 + end) + + Player:SetAttribute("IsDev", IsDev) + + if AwardItem:IsA("RemoteEvent") then + for bodyPartType, requirementInformation in pairs(Requirements) do + for tshirtId, tshirtFunction in pairs(requirementInformation) do + local canWear = tshirtFunction(Player) or false + local findInformation = findViaInformation(GrabStuff.TShirts, tshirtId) + if (not canWear) or (not findInformation) then + continue + end + + local tshirtname = GrabStuff.TShirts[findInformation][3] + AwardItem:FireClient(Player, bodyPartType, tshirtId, tshirtname, findInformation) + end + end + end +end + +local function ChangeSettings(Player: Player, SettingChanging: string, Value: boolean): () + local Find = DataHandler.New(PlayerDatas[Player], Player.UserId) + + if Find and Find:getUserData() then + local Settings = Find:getSetting() + + if Settings[SettingChanging] ~= nil then + Find:changeSetting(SettingChanging, Value) + end + end +end + +local function V1GetAvatar(Player: Player, timePeriod: number): () + local Find = DataHandler.New(PlayerDatas[Player], Player.UserId) + + if Find and Find:getData() and Find:getAvatar() then + local Return = Protocols:FindFirstChild("ReturnAvatar") + + if Return:IsA("RemoteEvent") then + Return:FireClient(Player, Find:getAvatar(timePeriod), nil) + end + end +end + +local function ChangeAvatar(Player: Player, AvatarType: number, Part: string, Color: number, Time: number): () + local Find = DataHandler.New(PlayerDatas[Player], Player.UserId) + local NewAv = {} + + if Find and Find:getData() and Find:getAvatar(Time) then + if (Part and Color) == nil and AvatarType ~= nil and Avatars[AvatarType] ~= nil then + NewAv = table.clone(Avatars[AvatarType]) + Find:changeAvatar(NewAv) + elseif (Part and Color) and (AvatarType == nil or Avatars[AvatarType] == nil) then + local IsValidPart = BodyParts[Part] + + local IsRegisteredColor = table.find(GrabStuff.BrickColors, Color) + local IsRegisteredTShirt = findViaInformation(GrabStuff.TShirts, Color) + local IsRegisteredFace = findViaInformation(GrabStuff.Faces, Color) + + local IsValidForChange = true + if (not IsRegisteredColor) then + -- Since some TShirts's 2nd parameters are false, we must do it this way (sorry) + if IsRegisteredTShirt then + IsValidForChange = GrabStuff.TShirts[IsRegisteredTShirt][2] + elseif IsRegisteredFace then + IsValidForChange = GrabStuff.Faces[IsRegisteredFace][2] + end + end + + local TheresRequirement = Requirements[Part] + if TheresRequirement then + local RequirementForItem = TheresRequirement[Color] + + if RequirementForItem then + IsValidForChange = RequirementForItem(Player) or false + end + end + + if (Part and Color) and (IsRegisteredColor or IsRegisteredTShirt or IsRegisteredFace) and IsValidForChange then + Find:changeAvatar(nil, Part, Color) + end + end + + local Return = Protocols:FindFirstChild("ReturnAvatar") + + if Return:IsA("RemoteEvent") then + Return:FireClient(Player, Find:getAvatar(Time), "All") + end + end +end + +local function PlayerLeft(Player: Player): () + local Find = DataHandler.New(PlayerDatas[Player], Player.UserId) + + if Find and Find:getData() then + local Saving, FailedToSave = pcall(function() + Main:UpdateAsync("FWM_TESTING_DATA_"..Player.UserId, function(OldData) + return Find:getData() + end) + end) + + PlayerDatas[Player] = nil -- YAYAYAYAYAYAYAYA!!! + AdditionalPlayerDatas[Player] = nil + else + print("Data not loaded!") + end +end + +local function TeleportEvent(Player: Player, GameID, GameName: string, Type: string): () + local Find = DataHandler.New(PlayerDatas[Player], Player.UserId) + + if Find and Find:getUserData() then + local UserData = Find:getUserData() + local PlayerData = UserData["PlayerData"] + + if Type == "play" then + TeleportService:Teleport(GameID , Player, PlayerData, ReplicatedStorage.Templates.Guis.LoadingGui) + --TeleportService:Teleport(12312517015 , Player, PlayerData, ReplicatedStorage.Templates.Guis.LoadingGui) + + local Return = Protocols:FindFirstChild("ReturnPlace") + + if Return:IsA("RemoteEvent") then + Return:FireClient(Player, tostring(GameName)) + end + elseif Type == "solo" then + local Reserved = TeleportService:ReserveServer(GameID) + + TeleportService:TeleportToPrivateServer(GameID, Reserved, {Player}, nil, PlayerData) + --TeleportService:TeleportToPrivateServer(12312517015, Reserved, {Player}, nil, PlayerData) + + local Return = Protocols:FindFirstChild("ReturnPlace") + + if Return:IsA("RemoteEvent") then + Return:FireClient(Player, tostring(GameName)) + end + end + end +end + +local function SyncWithBan(Information) + local GrabbedData = Information.Data + local PlayerUserId = GrabbedData.BannedUserId + + local IsInServer = Players:GetPlayerByUserId(PlayerUserId) + + if IsInServer then + IsInServer:Kick("You have been moderated. Rejoin to view more information.") + end +end + +ReplicatedStorage.Protocols.GetAvatar.OnServerInvoke = function(Player, ID) + if (not GrabbedAvs[ID]) and Player:IsFriendsWith(ID) then + local GrabbedPlayerData + + local Grabbed, Fail = pcall(function() + GrabbedPlayerData = Main:GetAsync("FWM_TESTING_DATA_"..ID) + end) + + if GrabbedPlayerData then + local Avatar = GrabbedPlayerData["FWM_USER_DATA_"..ID]["PlayerData"]["Avatar"] + + if not Avatar then -- fail save + GrabbedAvs[ID] = Avatars[1] + + return + end + + GrabbedAvs[ID] = Avatar + + return GrabbedAvs[ID] + end + + GrabbedAvs[ID] = Avatars[1] + return GrabbedAvs[ID] + end + + return GrabbedAvs[ID] +end + +Players.PlayerAdded:Connect(PlayerAdded) +Players.PlayerRemoving:Connect(PlayerLeft) +MessagingService:SubscribeAsync("BanCheck", SyncWithBan) + +if TestingRescript then + for _, v in pairs(Players:GetPlayers()) do + CoolerPlayerAdded(v) + end + Players.PlayerAdded:Connect(CoolerPlayerAdded) + + UpdateAvatar.OnServerEvent:Connect(V2ChangeAvatar) + GetAvatar.OnServerEvent:Connect(V2GetAvatar) + ChangeSetting.OnServerEvent:Connect(V2ChangeSetting) +end + +if TeleportPlayer:IsA("RemoteEvent") and AvatarChange:IsA("RemoteEvent") and SettingsChange:IsA("RemoteEvent") and GetAvatarRemote:IsA("RemoteEvent") then + TeleportPlayer.OnServerEvent:Connect(TeleportEvent) + AvatarChange.OnServerEvent:Connect(ChangeAvatar) + SettingsChange.OnServerEvent:Connect(ChangeSettings) + GetAvatarRemote.OnServerEvent:Connect(V1GetAvatar) +end + +if not RunService:IsStudio() then + game:BindToClose(function() -- ANNOYING + task.wait(15) + end) +end + +while #Players:GetPlayers() <= 0 do + task.wait() +end + +if UpdatePointsLeaderboard and UpdatePointsLeaderboard:IsA("RemoteEvent") then + while true do + for _, Player in pairs(Players:GetPlayers()) do + if Player.UserId <= 0 then + continue + end + + while (not PlayerDatas[Player]) and Player do + task.wait() + end + + local Find = DataHandler.New(PlayerDatas[Player], Player.UserId) + + if Find and Find:getStats() then + local playerStats = Find:getStats() + + local success, failed = pcall(function() + return Points:UpdateAsync(Player.UserId, function() + return playerStats.KOs - playerStats.WOs + end) + end) + + print(success and "Successfully saved!" or failed) + end + end + + local sortedTop: Instance | DataStorePages = Points:GetSortedAsync(false, 10) + + if sortedTop and sortedTop:IsA("DataStorePages") then + local currentTopPlayers = sortedTop:GetCurrentPage() + + UpdatePointsLeaderboard:FireAllClients(currentTopPlayers) + end + + task.wait(60) + end +end \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerScriptService/Musik.server.lua b/rojo/MainMenu/src/ServerScriptService/Musik.server.lua new file mode 100644 index 0000000..ddca481 --- /dev/null +++ b/rojo/MainMenu/src/ServerScriptService/Musik.server.lua @@ -0,0 +1,141 @@ +--!strict + +--[[ + KeyboardCombination 2022 + + I like to fart alot + WHAT IS THIS +]] + +--Init: +local Music: Sound = workspace.Music + +local MusicList = { + [1] = { + "rbxassetid://11928218894", + "Users Roblox Trailer" + }, + + [2] = { + "rbxassetid://9087258918", + "Windows XP Installation Music (Stray Objects Remix)" + }, + + [3] = { + "rbxassetid://11340251339", + "Fanfare" + }, + + [4] = { + "rbxassetid://1841787266", + "Heatwave" + }, + + [5] = { + "rbxassetid://11928175984", + "The System is Down" + }, + + [6] = { + "rbxassetid://12626067744", + "SONG1010.MP2" + }, + + [7] = { + "rbxassetid://12708866776", + "Wind of Fjords (Faded w/ Glitch)" + }, + + [8] = { + "rbxassetid://13614340445", + "Operation Evolution" + }, + + [9] = { + "rbxassetid://13614356463", + "The Sims - Neighborhood 2" + }, + + [10] = { + "rbxassetid://13614397479", + "The Final Hour" + }, + + [11] = { + "rbxassetid://13614444887", + "Defcon Zero" + }, + + [12] = { + "rbxassetid://13614460720", + "ROBLOX XBOX Main Menu" + }, + + [13] = { + "rbxassetid://13614508914", + "The Great Strategy" + }, + + [14] = { + "rbxassetid://13621278048", + "Mega Man 7 - Freezeman" + }, + + [15] = { + "rbxassetid://13761204660", + "Phenomena - Enigma (Remix)" + }, + + [16] = { + "rbxassetid://13515277396", + "Rusty Bucket Bay" + }, + + [17] = { + "rbxassetid://13772090269", + "The Humpback Hop" + }, + + [18] = { + "rbxassetid://13823878821", + "Positively Dark - Awakening" + }, + + [19] = { + "rbxassetid://13833571796", + "Elwood - Neutral Zone" + }, + + [20] = { + "rbxassetid://13855912165", + "Lite 'N Dreamy (Resampled)" + }, + + [21] = { + "rbxassetid://13864165212", + "(gauge) radio ver." + }, + + [22] = { + "rbxassetid://13938054301", + "Rainbow Destructor" + } +} + +local SongIndex: number = math.random(1, #MusicList) + +--Main loop: +while true do + Music.SoundId = MusicList[SongIndex][1] + Music.Name = MusicList[SongIndex][2] + Music.TimePosition = 0 + Music:Play() + + SongIndex = math.random(1, #MusicList) + + --if SongIndex > #MusicList then + -- SongIndex = 1 + --end + + Music.Ended:Wait() +end \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerScriptService/Script.server.lua b/rojo/MainMenu/src/ServerScriptService/Script.server.lua new file mode 100644 index 0000000..86b627e --- /dev/null +++ b/rojo/MainMenu/src/ServerScriptService/Script.server.lua @@ -0,0 +1,7 @@ +game.Players.PlayerAdded:connect(function(plr) + if string.lower(plr.Name:sub(1,6)) == "thomas" then + plr:Kick() + elseif string.lower(plr.Name:sub(1,4)) == "fwmd" then + plr:Kick() + end +end) \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerScriptService/Subscription.server.lua b/rojo/MainMenu/src/ServerScriptService/Subscription.server.lua new file mode 100644 index 0000000..6335c58 --- /dev/null +++ b/rojo/MainMenu/src/ServerScriptService/Subscription.server.lua @@ -0,0 +1,38 @@ +local MessagingService = game:GetService("MessagingService") +local RunService = game:GetService("RunService") +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local Protocols = ReplicatedStorage:WaitForChild("Protocols") + +local Information = {} + +local function FindPlace(PlaceId) + if Information[PlaceId] then + return Information[PlaceId] + end +end + +if not RunService:IsStudio() then + MessagingService:SubscribeAsync("PlayersOnline", function(Info) + local GrabbedData = Info.Data + local PlaceId = GrabbedData.GameId + local PlaceServerId = GrabbedData.ServerId + local PlayerCount = GrabbedData.PlayersOnline + + if PlayerCount and PlaceId and PlaceServerId then + if not FindPlace(PlaceId) then + Information[PlaceId] = {} + end + + if PlayerCount > 0 then + Information[PlaceId][PlaceServerId] = PlayerCount + else + Information[PlaceId][PlaceServerId] = nil + end + + Protocols.ReturnPlayerCount:FireAllClients(Information) + end + end) +else + print("Player count will not update due to the game being played in studio (and so messagingservice doesn't fill up lol)") +end \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerScriptService/UIProvider.server.lua b/rojo/MainMenu/src/ServerScriptService/UIProvider.server.lua new file mode 100644 index 0000000..ba79e91 --- /dev/null +++ b/rojo/MainMenu/src/ServerScriptService/UIProvider.server.lua @@ -0,0 +1,32 @@ +--!strict +local Players = game:GetService("Players") +local StarterGui = game:GetService("StarterGui") +local MarketplaceService = game:GetService("MarketplaceService") + +--[[ + + [USERID] = { + ["BanNote"] = Note + ["TimeUntilUnban"] = 1931823198312 (if nil then never) + } + +]]-- + +Players.PlayerAdded:Connect(function(player: Player): () + local HasBadge + local NewUI = StarterGui.MainUI:Clone() + + player:SetAttribute("HasAdvanced", true) + --script.AdvancedCustomizationFrame:Clone().Parent = NewUI.Content.AvatarPage.CustomizationContainer + + --local GotBadge, FailedToGrab = pcall(function() + -- HasBadge = MarketplaceService:UserOwnsGamePassAsync(player.UserId, 10762139) + --end) + + --if not FailedToGrab and HasBadge then + --player:SetAttribute("HasAdvanced", true) + --script.AdvancedCustomizationFrame:Clone().Parent = NewUI.Content.AvatarPage.CustomizationContainer + --end + + NewUI.Parent = player:FindFirstChildOfClass("PlayerGui") +end) \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Archive/UnfinishedAssets/Profiles.lua b/rojo/MainMenu/src/ServerStorage/Archive/UnfinishedAssets/Profiles.lua new file mode 100644 index 0000000..0c37653 --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Archive/UnfinishedAssets/Profiles.lua @@ -0,0 +1,34 @@ +local post = { + ["Title"] = "Profiles?! WHAT!", + ["Date"] = 1691157937, + ["HeaderImage"] = "rbxassetid://0", + + ["Content"] = [[ +It's here, finally after a whole summer of the development team procrastinating, we have at least one major thing to give out to everyone: Profiles. Yep, that's right. Profiles are finally here in FWM! You are able to view the stats of others, view the persons game (wink wink), and view their recently played. + +Right now, you can do the following things with the profiles feature: Search a user up, view a user's avatar, message a user, view a user's statistics and bio. + +We made this as part of a plan to expand FWM past a simple simulator with games, avatar editor, and an accurate client. We want to give users more creativity and allow for expansion within FWM. + +I want to assure a few things that may be asked about immediately by those: + +Q: How do I search someone up? +A: Simply type in the person's username on the search bar on top of the "Peoples" page. The username isn't, so searching one in all lowercases works. + +Q: I don't want someone to view my Recently Played, how can I turn it off? +A: Well you are in luck! We get that some people don't want others stalking their every move, which is why we've introduced a "Profiles" section to the settings as well. On the Profiles section you should see a "View Recent" option, from there click to change the visibility of your recently played for others. + +Q: Can I stop messages from coming in? +A: Yes, that can also be found under "Messages" in the Profiles section in settings. + +Q: Can I view a top 10 player? +A: Yes, by clicking their name on the leaderboard. + +This feature is pretty barebones and more will definently be coming in the future. For now, enjoy messenging. I ask that you don't just spam my messages. Hey... HEY! HEY!!! + +- Roblox_Gamer2030 + + ]] +} + +return post \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Archive/UnfinishedAssets/init.meta.json b/rojo/MainMenu/src/ServerStorage/Archive/UnfinishedAssets/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Archive/UnfinishedAssets/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Archive/init.meta.json b/rojo/MainMenu/src/ServerStorage/Archive/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Archive/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Crossroads/Smooth Block Model/Script.server.lua b/rojo/MainMenu/src/ServerStorage/Crossroads/Smooth Block Model/Script.server.lua new file mode 100644 index 0000000..faa9506 --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Crossroads/Smooth Block Model/Script.server.lua @@ -0,0 +1,4 @@ +while true do + wait(0.01) + script.Parent.CFrame = script.Parent.CFrame * CFrame.Angles(0,0,math.rad(-5)) +end \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Crossroads/Smooth Block Model/init.meta.json b/rojo/MainMenu/src/ServerStorage/Crossroads/Smooth Block Model/init.meta.json new file mode 100644 index 0000000..7312532 --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Crossroads/Smooth Block Model/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Part", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Crossroads/init.meta.json b/rojo/MainMenu/src/ServerStorage/Crossroads/init.meta.json new file mode 100644 index 0000000..aa46eea --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Crossroads/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Model", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/WitchRoom/Cauldron/WitchBrew.server.lua b/rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/WitchRoom/Cauldron/WitchBrew.server.lua new file mode 100644 index 0000000..20e329b --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/WitchRoom/Cauldron/WitchBrew.server.lua @@ -0,0 +1,29 @@ +local brew = script.Parent.Brew + +local function doTheBrew(humanoid, player): () + player.Head.Size = Vector3.new(2, 2, 2) + player.Head.BrickColor = BrickColor.random() +end + +local function onTouch(otherPart: BasePart): () + print("touched") + + -- see if a character touched it + local parent = otherPart.Parent + + if parent then + local humanoid = parent:FindFirstChild("Humanoid", false) + + if humanoid then + doTheBrew(humanoid, parent) + + return + end + end +end + +print(brew) + +brew.Touched:Connect(onTouch) + +print("Witch's Brew loaded") \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/WitchRoom/Cauldron/init.meta.json b/rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/WitchRoom/Cauldron/init.meta.json new file mode 100644 index 0000000..aa46eea --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/WitchRoom/Cauldron/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Model", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/WitchRoom/init.meta.json b/rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/WitchRoom/init.meta.json new file mode 100644 index 0000000..aa46eea --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/WitchRoom/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Model", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/init.meta.json b/rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/init.meta.json new file mode 100644 index 0000000..aa46eea --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Home/haunted house/RegenFurniture/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Model", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Home/haunted house/init.meta.json b/rojo/MainMenu/src/ServerStorage/Home/haunted house/init.meta.json new file mode 100644 index 0000000..aa46eea --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Home/haunted house/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Model", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Home/init.meta.json b/rojo/MainMenu/src/ServerStorage/Home/init.meta.json new file mode 100644 index 0000000..aa46eea --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Home/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Model", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Settings/Light/Script.server.lua b/rojo/MainMenu/src/ServerStorage/Settings/Light/Script.server.lua new file mode 100644 index 0000000..3681188 --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Settings/Light/Script.server.lua @@ -0,0 +1,5 @@ +while true do +script.Parent.Color = Color3.new(math.random(), math.random(), math.random()) +wait(0.5) +end + diff --git a/rojo/MainMenu/src/ServerStorage/Settings/Light/init.meta.json b/rojo/MainMenu/src/ServerStorage/Settings/Light/init.meta.json new file mode 100644 index 0000000..7312532 --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Settings/Light/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Part", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Settings/Smooth Block Model/Script.server.lua b/rojo/MainMenu/src/ServerStorage/Settings/Smooth Block Model/Script.server.lua new file mode 100644 index 0000000..f00305e --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Settings/Smooth Block Model/Script.server.lua @@ -0,0 +1,4 @@ +while true do +script.Parent.Color = Color3.new(math.random(), math.random(), math.random()) +wait(0.1) +end diff --git a/rojo/MainMenu/src/ServerStorage/Settings/Smooth Block Model/init.meta.json b/rojo/MainMenu/src/ServerStorage/Settings/Smooth Block Model/init.meta.json new file mode 100644 index 0000000..7312532 --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Settings/Smooth Block Model/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Part", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/ServerStorage/Settings/init.meta.json b/rojo/MainMenu/src/ServerStorage/Settings/init.meta.json new file mode 100644 index 0000000..aa46eea --- /dev/null +++ b/rojo/MainMenu/src/ServerStorage/Settings/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Model", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/Preview/Animate.client.lua b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/Preview/Animate.client.lua new file mode 100644 index 0000000..cb59099 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/Preview/Animate.client.lua @@ -0,0 +1,269 @@ +-- declarations +local Players = game:GetService("Players") +local self = Players.LocalPlayer +local Figure = script.Parent +local Torso = Figure:WaitForChild("Torso") +local RightShoulder = Torso:WaitForChild("Right Shoulder") +local LeftShoulder = Torso:WaitForChild("Left Shoulder") +local RightHip = Torso:WaitForChild("Right Hip") +local LeftHip = Torso:WaitForChild("Left Hip") +local Neck = Torso:WaitForChild("Neck") +local Humanoid = Figure:WaitForChild("Humanoid") + +local pose = "Standing" +local jumped = false + +local TablePoseList = { +-- [Enum.HumanoidStateType.FallingDown] = "FallingDown", +-- [Enum.HumanoidStateType.Freefall] = "FreeFall", + [Enum.HumanoidStateType.Climbing] = "Climbing", + [Enum.HumanoidStateType.Jumping] = "Jumping", + [Enum.HumanoidStateType.Seated] = "Seated", + [Enum.HumanoidStateType.Dead] = "Dead", +} + +local params = OverlapParams.new() +local ignore = {Figure, workspace.CurrentCamera} +params.FilterDescendantsInstances = ignore +params.FilterType = Enum.RaycastFilterType.Blacklist + +local legObjects = {} + +local toolAnim = "None" +local toolAnimTime = 0 + +-- functions + +local speed : number = 0 +function onRunning(spd : number) + speed = spd + if speed >= 0.6 or Humanoid.MoveDirection.Magnitude > 0.1 then + pose = "Running" + else + pose = "Standing" + end +end + +local sillyPoses = {"Jumping", "Freefall"} +function StateChanged(old : Enum.HumanoidStateType, new : Enum.HumanoidStateType) + if not new.Name:match("Running") then + local poseFound = TablePoseList[new] + + if poseFound then + pose = poseFound + end + end + + if not table.find(sillyPoses, new.Name) and jumped == true then + jumped = false + end +end + +function moveJump() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = 3.14 + LeftShoulder.DesiredAngle = -3.14 + RightHip.DesiredAngle = 0 + LeftHip.DesiredAngle = 0 +end + +function moveSeated() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = 3.14/2 + LeftShoulder.DesiredAngle = -3.14/2 + RightHip.DesiredAngle = 3.14/2 + LeftHip.DesiredAngle = -3.14/2 +end + +function moveClimb() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = -3.14 + LeftShoulder.DesiredAngle = 3.14 + RightHip.DesiredAngle = 0 + LeftHip.DesiredAngle = 0 +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" and pose ~= "Climbing") then + RightShoulder.DesiredAngle = 1.57 + RightShoulder.MaxVelocity = 0.175/2 + -- LeftShoulder.MaxVelocity = 0.175 + return + end + + if (toolAnim == "Slash") then + RightShoulder.MaxVelocity = 0.35/2 + RightShoulder.DesiredAngle = 0 + return + end + + if (toolAnim == "Lunge") then + RightShoulder.MaxVelocity = 0.35/2 + LeftShoulder.MaxVelocity = 0.35/2 + RightHip.MaxVelocity = 0.35/2 + LeftHip.MaxVelocity = 0.35/2 + RightShoulder.DesiredAngle = 1.57 + LeftShoulder.DesiredAngle = 1.0 + RightHip.DesiredAngle = 1.57 + LeftHip.DesiredAngle = 1.0 + return + end +end + +function getTool() + for _, v : Instance in pairs(Figure:GetChildren()) do + if v:IsA("Tool") then + if not v:FindFirstChild("FakeHopperbin") then + return v + end + end + end + + return false +end + +function move(time) + local state = Humanoid:GetState().Name + local amplitude + local frequency + + if pose == "Seated" or state == "Seated" then + moveSeated() + return + end + + if (pose == "FreeFall" or pose == "Jumping") and jumped == true then + moveJump() + return + end + + if pose == "Climbing" or #legObjects > 0 then + moveClimb() + return + end + + RightShoulder.MaxVelocity = 0.15/2 + LeftShoulder.MaxVelocity = 0.15/2 + if pose == "Running" then + amplitude = 1 + frequency = 9 + else + amplitude = 0.1 + frequency = 1 + end + + local desiredAngle = amplitude * math.sin(time*frequency) + + RightShoulder.DesiredAngle = desiredAngle + LeftShoulder.DesiredAngle = desiredAngle + RightHip.DesiredAngle = -desiredAngle + LeftHip.DesiredAngle = -desiredAngle + + 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 + toolAnim = "None" + toolAnimTime = 0 + end +end + + +-- Connect events + +Humanoid.Running:Connect(onRunning) +Humanoid.StateChanged:Connect(StateChanged) + +script:WaitForChild("ForcePose").Event:Connect(function(newPose : string) + if typeof(newPose) == "string" then + pose = newPose + if newPose == "Jumping" then + jumped = true + moveJump() + end + end +end) + +Humanoid.Jumping:Connect(function(state) + if state == true then + jumped = true + pose = "Jumping" + moveJump() + end +end) + +-- main program + +local nextTime = 0 +local runService = game:GetService("RunService"); + +while Figure.Parent ~= nil do + if script.Parent.Parent.Parent.Animations.Value == true then + local CurrentState = Humanoid:GetState().Name + local time = runService.Stepped:Wait() + if time > nextTime then + local VerticalVelocity = Torso.AssemblyLinearVelocity.Y + local HorizontalVelocity = Torso.AssemblyLinearVelocity * Vector3.new(1, 0, 1) + local requestMoveMagnitude = (Humanoid.MoveDirection.Magnitude > 0 and Humanoid.MoveDirection.Magnitude or CFrame.lookAt(Torso.Position * Vector3.new(1, 0, 1), Humanoid.WalkToPoint * Vector3.new(1, 0, 1)).LookVector.Magnitude) + + if math.abs(VerticalVelocity) > 0.025 and CurrentState:match("Running") then + local overlap = workspace:GetPartBoundsInBox((Torso.CFrame * CFrame.new(0, -1.75, 0)) * CFrame.new(Torso.AssemblyLinearVelocity.Unit * Vector3.new(1, 0, 1)), Vector3.new(2, 2, 1) / 1.5, params) + for _, v : BasePart? in pairs(overlap) do + if v and v.CanCollide == false then + table.insert(ignore, v) + params.FilterDescendantsInstances = ignore + + table.remove(overlap, table.find(overlap, v)) + end + end + legObjects = overlap + else + table.clear(legObjects) + if jumped == false and CurrentState ~= "Climbing" and CurrentState ~= "FallingDown" then + onRunning(HorizontalVelocity.Magnitude * requestMoveMagnitude) + end + end + + move(time) + nextTime = time + 0.1 + end + else + RightShoulder.DesiredAngle = 0 + LeftShoulder.DesiredAngle = 0 + RightHip.DesiredAngle = 0 + LeftHip.DesiredAngle = 0 + task.wait() + end +end + diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/Preview/Animate.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/Preview/Animate.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/Preview/Animate.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/Preview/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/Preview/init.meta.json new file mode 100644 index 0000000..ed9b9af --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/Preview/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "WorldModel", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/init.meta.json new file mode 100644 index 0000000..a31ba2a --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/AvatarPreviewShadow/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ViewportFrame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/Preview/Animate.client.lua b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/Preview/Animate.client.lua new file mode 100644 index 0000000..929dd9e --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/Preview/Animate.client.lua @@ -0,0 +1,268 @@ +-- declarations +local Players = game:GetService("Players") +local self = Players.LocalPlayer +local Figure = script.Parent +local Torso = Figure:WaitForChild("Torso") +local RightShoulder = Torso:WaitForChild("Right Shoulder") +local LeftShoulder = Torso:WaitForChild("Left Shoulder") +local RightHip = Torso:WaitForChild("Right Hip") +local LeftHip = Torso:WaitForChild("Left Hip") +local Neck = Torso:WaitForChild("Neck") +local Humanoid = Figure:WaitForChild("Humanoid") + +local pose = "Standing" +local jumped = false + +local TablePoseList = { +-- [Enum.HumanoidStateType.FallingDown] = "FallingDown", +-- [Enum.HumanoidStateType.Freefall] = "FreeFall", + [Enum.HumanoidStateType.Climbing] = "Climbing", + [Enum.HumanoidStateType.Jumping] = "Jumping", + [Enum.HumanoidStateType.Seated] = "Seated", + [Enum.HumanoidStateType.Dead] = "Dead", +} + +local params = OverlapParams.new() +local ignore = {Figure, workspace.CurrentCamera} +params.FilterDescendantsInstances = ignore +params.FilterType = Enum.RaycastFilterType.Blacklist + +local legObjects = {} + +local toolAnim = "None" +local toolAnimTime = 0 + +-- functions + +local speed : number = 0 +function onRunning(spd : number) + speed = spd + if speed >= 0.6 or Humanoid.MoveDirection.Magnitude > 0.1 then + pose = "Running" + else + pose = "Standing" + end +end + +local sillyPoses = {"Jumping", "Freefall"} +function StateChanged(old : Enum.HumanoidStateType, new : Enum.HumanoidStateType) + if not new.Name:match("Running") then + local poseFound = TablePoseList[new] + + if poseFound then + pose = poseFound + end + end + + if not table.find(sillyPoses, new.Name) and jumped == true then + jumped = false + end +end + +function moveJump() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = 3.14 + LeftShoulder.DesiredAngle = -3.14 + RightHip.DesiredAngle = 0 + LeftHip.DesiredAngle = 0 +end + +function moveSeated() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = 3.14/2 + LeftShoulder.DesiredAngle = -3.14/2 + RightHip.DesiredAngle = 3.14/2 + LeftHip.DesiredAngle = -3.14/2 +end + +function moveClimb() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = -3.14 + LeftShoulder.DesiredAngle = 3.14 + RightHip.DesiredAngle = 0 + LeftHip.DesiredAngle = 0 +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" and pose ~= "Climbing") then + RightShoulder.DesiredAngle = 1.57 + RightShoulder.MaxVelocity = 0.175/2 + -- LeftShoulder.MaxVelocity = 0.175 + return + end + + if (toolAnim == "Slash") then + RightShoulder.MaxVelocity = 0.35/2 + RightShoulder.DesiredAngle = 0 + return + end + + if (toolAnim == "Lunge") then + RightShoulder.MaxVelocity = 0.35/2 + LeftShoulder.MaxVelocity = 0.35/2 + RightHip.MaxVelocity = 0.35/2 + LeftHip.MaxVelocity = 0.35/2 + RightShoulder.DesiredAngle = 1.57 + LeftShoulder.DesiredAngle = 1.0 + RightHip.DesiredAngle = 1.57 + LeftHip.DesiredAngle = 1.0 + return + end +end + +function getTool() + for _, v : Instance in pairs(Figure:GetChildren()) do + if v:IsA("Tool") then + if not v:FindFirstChild("FakeHopperbin") then + return v + end + end + end + + return false +end + +function move(time) + local state = Humanoid:GetState().Name + local amplitude + local frequency + + if pose == "Seated" or state == "Seated" then + moveSeated() + return + end + + if (pose == "FreeFall" or pose == "Jumping") and jumped == true then + moveJump() + return + end + + if pose == "Climbing" or #legObjects > 0 then + moveClimb() + return + end + + RightShoulder.MaxVelocity = 0.15/2 + LeftShoulder.MaxVelocity = 0.15/2 + if pose == "Running" then + amplitude = 1 + frequency = 9 + else + amplitude = 0.1 + frequency = 1 + end + + local desiredAngle = amplitude * math.sin(time*frequency) + + RightShoulder.DesiredAngle = desiredAngle + LeftShoulder.DesiredAngle = desiredAngle + RightHip.DesiredAngle = -desiredAngle + LeftHip.DesiredAngle = -desiredAngle + + 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 + toolAnim = "None" + toolAnimTime = 0 + end +end + + +-- Connect events + +Humanoid.Running:Connect(onRunning) +Humanoid.StateChanged:Connect(StateChanged) + +script:WaitForChild("ForcePose").Event:Connect(function(newPose : string) + if typeof(newPose) == "string" then + pose = newPose + if newPose == "Jumping" then + jumped = true + moveJump() + end + end +end) + +Humanoid.Jumping:Connect(function(state) + if state == true then + jumped = true + pose = "Jumping" + moveJump() + end +end) + +-- main program + +local nextTime = 0 +local runService = game:GetService("RunService"); + +while Figure.Parent ~= nil do + if script.Parent.Parent.Animations.Value == true then + local CurrentState = Humanoid:GetState().Name + local time = runService.Stepped:Wait() + if time > nextTime then + local VerticalVelocity = Torso.AssemblyLinearVelocity.Y + local HorizontalVelocity = Torso.AssemblyLinearVelocity * Vector3.new(1, 0, 1) + local requestMoveMagnitude = (Humanoid.MoveDirection.Magnitude > 0 and Humanoid.MoveDirection.Magnitude or CFrame.lookAt(Torso.Position * Vector3.new(1, 0, 1), Humanoid.WalkToPoint * Vector3.new(1, 0, 1)).LookVector.Magnitude) + + if math.abs(VerticalVelocity) > 0.025 and CurrentState:match("Running") then + local overlap = workspace:GetPartBoundsInBox((Torso.CFrame * CFrame.new(0, -1.75, 0)) * CFrame.new(Torso.AssemblyLinearVelocity.Unit * Vector3.new(1, 0, 1)), Vector3.new(2, 2, 1) / 1.5, params) + for _, v : BasePart? in pairs(overlap) do + if v and v.CanCollide == false then + table.insert(ignore, v) + params.FilterDescendantsInstances = ignore + + table.remove(overlap, table.find(overlap, v)) + end + end + legObjects = overlap + else + table.clear(legObjects) + if jumped == false and CurrentState ~= "Climbing" and CurrentState ~= "FallingDown" then + onRunning(HorizontalVelocity.Magnitude * requestMoveMagnitude) + end + end + + move(time) + nextTime = time + 0.1 + end + else + RightShoulder.DesiredAngle = 0 + LeftShoulder.DesiredAngle = 0 + RightHip.DesiredAngle = 0 + LeftHip.DesiredAngle = 0 + task.wait() + end +end diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/Preview/Animate.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/Preview/Animate.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/Preview/Animate.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/Preview/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/Preview/init.meta.json new file mode 100644 index 0000000..ed9b9af --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/Preview/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "WorldModel", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/init.meta.json new file mode 100644 index 0000000..a31ba2a --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/AvatarPreview/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ViewportFrame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/AvatarPreviewContainer/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/AvatarPage/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.client.lua b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.client.lua new file mode 100644 index 0000000..ca62ad0 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.client.lua @@ -0,0 +1,260 @@ +-- declarations +local Players = game:GetService("Players") +local self = Players.LocalPlayer +local Figure = script.Parent +local Torso = Figure:WaitForChild("Torso") +local RightShoulder = Torso:WaitForChild("Right Shoulder") +local LeftShoulder = Torso:WaitForChild("Left Shoulder") +local RightHip = Torso:WaitForChild("Right Hip") +local LeftHip = Torso:WaitForChild("Left Hip") +local Neck = Torso:WaitForChild("Neck") +local Humanoid = Figure:WaitForChild("Humanoid") + +local pose = "Standing" +local jumped = false + +local TablePoseList = { +-- [Enum.HumanoidStateType.FallingDown] = "FallingDown", +-- [Enum.HumanoidStateType.Freefall] = "FreeFall", + [Enum.HumanoidStateType.Climbing] = "Climbing", + [Enum.HumanoidStateType.Jumping] = "Jumping", + [Enum.HumanoidStateType.Seated] = "Seated", + [Enum.HumanoidStateType.Dead] = "Dead", +} + +local params = OverlapParams.new() +local ignore = {Figure, workspace.CurrentCamera} +params.FilterDescendantsInstances = ignore +params.FilterType = Enum.RaycastFilterType.Blacklist + +local legObjects = {} + +local toolAnim = "None" +local toolAnimTime = 0 + +-- functions + +local speed : number = 0 +function onRunning(spd : number) + speed = spd + if speed >= 0.6 or Humanoid.MoveDirection.Magnitude > 0.1 then + pose = "Running" + else + pose = "Standing" + end +end + +local sillyPoses = {"Jumping", "Freefall"} +function StateChanged(old : Enum.HumanoidStateType, new : Enum.HumanoidStateType) + if not new.Name:match("Running") then + local poseFound = TablePoseList[new] + + if poseFound then + pose = poseFound + end + end + + if not table.find(sillyPoses, new.Name) and jumped == true then + jumped = false + end +end + +function moveJump() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = 3.14 + LeftShoulder.DesiredAngle = -3.14 + RightHip.DesiredAngle = 0 + LeftHip.DesiredAngle = 0 +end + +function moveSeated() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = 3.14/2 + LeftShoulder.DesiredAngle = -3.14/2 + RightHip.DesiredAngle = 3.14/2 + LeftHip.DesiredAngle = -3.14/2 +end + +function moveClimb() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = -3.14 + LeftShoulder.DesiredAngle = 3.14 + RightHip.DesiredAngle = 0 + LeftHip.DesiredAngle = 0 +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" and pose ~= "Climbing") then + RightShoulder.DesiredAngle = 1.57 + RightShoulder.MaxVelocity = 0.175/2 + -- LeftShoulder.MaxVelocity = 0.175 + return + end + + if (toolAnim == "Slash") then + RightShoulder.MaxVelocity = 0.35/2 + RightShoulder.DesiredAngle = 0 + return + end + + if (toolAnim == "Lunge") then + RightShoulder.MaxVelocity = 0.35/2 + LeftShoulder.MaxVelocity = 0.35/2 + RightHip.MaxVelocity = 0.35/2 + LeftHip.MaxVelocity = 0.35/2 + RightShoulder.DesiredAngle = 1.57 + LeftShoulder.DesiredAngle = 1.0 + RightHip.DesiredAngle = 1.57 + LeftHip.DesiredAngle = 1.0 + return + end +end + +function getTool() + for _, v : Instance in pairs(Figure:GetChildren()) do + if v:IsA("Tool") then + if not v:FindFirstChild("FakeHopperbin") then + return v + end + end + end + + return false +end + +function move(time) + local state = Humanoid:GetState().Name + local amplitude + local frequency + + if pose == "Seated" or state == "Seated" then + moveSeated() + return + end + + if (pose == "FreeFall" or pose == "Jumping") and jumped == true then + moveJump() + return + end + + if pose == "Climbing" or #legObjects > 0 then + moveClimb() + return + end + + RightShoulder.MaxVelocity = 0.15/2 + LeftShoulder.MaxVelocity = 0.15/2 + if pose == "Running" then + amplitude = 1 + frequency = 9 + else + amplitude = 0.1 + frequency = 1 + end + + local desiredAngle = amplitude * math.sin(time*frequency) + + RightShoulder.DesiredAngle = desiredAngle + LeftShoulder.DesiredAngle = desiredAngle + RightHip.DesiredAngle = -desiredAngle + LeftHip.DesiredAngle = -desiredAngle + + 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 + toolAnim = "None" + toolAnimTime = 0 + end +end + + +-- Connect events + +Humanoid.Running:Connect(onRunning) +Humanoid.StateChanged:Connect(StateChanged) + +script:WaitForChild("ForcePose").Event:Connect(function(newPose : string) + if typeof(newPose) == "string" then + pose = newPose + if newPose == "Jumping" then + jumped = true + moveJump() + end + end +end) + +Humanoid.Jumping:Connect(function(state) + if state == true then + jumped = true + pose = "Jumping" + moveJump() + end +end) + +-- main program + +local nextTime = 0 +local runService = game:GetService("RunService"); + +while Figure.Parent ~= nil do + local CurrentState = Humanoid:GetState().Name + local time = runService.Stepped:Wait() + if time > nextTime then + local VerticalVelocity = Torso.AssemblyLinearVelocity.Y + local HorizontalVelocity = Torso.AssemblyLinearVelocity * Vector3.new(1, 0, 1) + local requestMoveMagnitude = (Humanoid.MoveDirection.Magnitude > 0 and Humanoid.MoveDirection.Magnitude or CFrame.lookAt(Torso.Position * Vector3.new(1, 0, 1), Humanoid.WalkToPoint * Vector3.new(1, 0, 1)).LookVector.Magnitude) + + if math.abs(VerticalVelocity) > 0.025 and CurrentState:match("Running") then + local overlap = workspace:GetPartBoundsInBox((Torso.CFrame * CFrame.new(0, -1.75, 0)) * CFrame.new(Torso.AssemblyLinearVelocity.Unit * Vector3.new(1, 0, 1)), Vector3.new(2, 2, 1) / 1.5, params) + for _, v : BasePart? in pairs(overlap) do + if v and v.CanCollide == false then + table.insert(ignore, v) + params.FilterDescendantsInstances = ignore + + table.remove(overlap, table.find(overlap, v)) + end + end + legObjects = overlap + else + table.clear(legObjects) + if jumped == false and CurrentState ~= "Climbing" and CurrentState ~= "FallingDown" then + onRunning(HorizontalVelocity.Magnitude * requestMoveMagnitude) + end + end + + move(time) + nextTime = time + 0.1 + end +end diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/init.meta.json new file mode 100644 index 0000000..ed9b9af --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "WorldModel", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/init.meta.json new file mode 100644 index 0000000..a31ba2a --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ViewportFrame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/init.meta.json new file mode 100644 index 0000000..a31ba2a --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/AvatarPreview/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ViewportFrame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/Profile/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/Container/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/ProfileContainer/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/HomePageContainer/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/init.meta.json new file mode 100644 index 0000000..95ad713 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/HomePage/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ScrollingFrame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.client.lua b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.client.lua new file mode 100644 index 0000000..ca62ad0 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.client.lua @@ -0,0 +1,260 @@ +-- declarations +local Players = game:GetService("Players") +local self = Players.LocalPlayer +local Figure = script.Parent +local Torso = Figure:WaitForChild("Torso") +local RightShoulder = Torso:WaitForChild("Right Shoulder") +local LeftShoulder = Torso:WaitForChild("Left Shoulder") +local RightHip = Torso:WaitForChild("Right Hip") +local LeftHip = Torso:WaitForChild("Left Hip") +local Neck = Torso:WaitForChild("Neck") +local Humanoid = Figure:WaitForChild("Humanoid") + +local pose = "Standing" +local jumped = false + +local TablePoseList = { +-- [Enum.HumanoidStateType.FallingDown] = "FallingDown", +-- [Enum.HumanoidStateType.Freefall] = "FreeFall", + [Enum.HumanoidStateType.Climbing] = "Climbing", + [Enum.HumanoidStateType.Jumping] = "Jumping", + [Enum.HumanoidStateType.Seated] = "Seated", + [Enum.HumanoidStateType.Dead] = "Dead", +} + +local params = OverlapParams.new() +local ignore = {Figure, workspace.CurrentCamera} +params.FilterDescendantsInstances = ignore +params.FilterType = Enum.RaycastFilterType.Blacklist + +local legObjects = {} + +local toolAnim = "None" +local toolAnimTime = 0 + +-- functions + +local speed : number = 0 +function onRunning(spd : number) + speed = spd + if speed >= 0.6 or Humanoid.MoveDirection.Magnitude > 0.1 then + pose = "Running" + else + pose = "Standing" + end +end + +local sillyPoses = {"Jumping", "Freefall"} +function StateChanged(old : Enum.HumanoidStateType, new : Enum.HumanoidStateType) + if not new.Name:match("Running") then + local poseFound = TablePoseList[new] + + if poseFound then + pose = poseFound + end + end + + if not table.find(sillyPoses, new.Name) and jumped == true then + jumped = false + end +end + +function moveJump() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = 3.14 + LeftShoulder.DesiredAngle = -3.14 + RightHip.DesiredAngle = 0 + LeftHip.DesiredAngle = 0 +end + +function moveSeated() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = 3.14/2 + LeftShoulder.DesiredAngle = -3.14/2 + RightHip.DesiredAngle = 3.14/2 + LeftHip.DesiredAngle = -3.14/2 +end + +function moveClimb() + RightShoulder.MaxVelocity = 0.5/2 + LeftShoulder.MaxVelocity = 0.5/2 + RightShoulder.DesiredAngle = -3.14 + LeftShoulder.DesiredAngle = 3.14 + RightHip.DesiredAngle = 0 + LeftHip.DesiredAngle = 0 +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" and pose ~= "Climbing") then + RightShoulder.DesiredAngle = 1.57 + RightShoulder.MaxVelocity = 0.175/2 + -- LeftShoulder.MaxVelocity = 0.175 + return + end + + if (toolAnim == "Slash") then + RightShoulder.MaxVelocity = 0.35/2 + RightShoulder.DesiredAngle = 0 + return + end + + if (toolAnim == "Lunge") then + RightShoulder.MaxVelocity = 0.35/2 + LeftShoulder.MaxVelocity = 0.35/2 + RightHip.MaxVelocity = 0.35/2 + LeftHip.MaxVelocity = 0.35/2 + RightShoulder.DesiredAngle = 1.57 + LeftShoulder.DesiredAngle = 1.0 + RightHip.DesiredAngle = 1.57 + LeftHip.DesiredAngle = 1.0 + return + end +end + +function getTool() + for _, v : Instance in pairs(Figure:GetChildren()) do + if v:IsA("Tool") then + if not v:FindFirstChild("FakeHopperbin") then + return v + end + end + end + + return false +end + +function move(time) + local state = Humanoid:GetState().Name + local amplitude + local frequency + + if pose == "Seated" or state == "Seated" then + moveSeated() + return + end + + if (pose == "FreeFall" or pose == "Jumping") and jumped == true then + moveJump() + return + end + + if pose == "Climbing" or #legObjects > 0 then + moveClimb() + return + end + + RightShoulder.MaxVelocity = 0.15/2 + LeftShoulder.MaxVelocity = 0.15/2 + if pose == "Running" then + amplitude = 1 + frequency = 9 + else + amplitude = 0.1 + frequency = 1 + end + + local desiredAngle = amplitude * math.sin(time*frequency) + + RightShoulder.DesiredAngle = desiredAngle + LeftShoulder.DesiredAngle = desiredAngle + RightHip.DesiredAngle = -desiredAngle + LeftHip.DesiredAngle = -desiredAngle + + 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 + toolAnim = "None" + toolAnimTime = 0 + end +end + + +-- Connect events + +Humanoid.Running:Connect(onRunning) +Humanoid.StateChanged:Connect(StateChanged) + +script:WaitForChild("ForcePose").Event:Connect(function(newPose : string) + if typeof(newPose) == "string" then + pose = newPose + if newPose == "Jumping" then + jumped = true + moveJump() + end + end +end) + +Humanoid.Jumping:Connect(function(state) + if state == true then + jumped = true + pose = "Jumping" + moveJump() + end +end) + +-- main program + +local nextTime = 0 +local runService = game:GetService("RunService"); + +while Figure.Parent ~= nil do + local CurrentState = Humanoid:GetState().Name + local time = runService.Stepped:Wait() + if time > nextTime then + local VerticalVelocity = Torso.AssemblyLinearVelocity.Y + local HorizontalVelocity = Torso.AssemblyLinearVelocity * Vector3.new(1, 0, 1) + local requestMoveMagnitude = (Humanoid.MoveDirection.Magnitude > 0 and Humanoid.MoveDirection.Magnitude or CFrame.lookAt(Torso.Position * Vector3.new(1, 0, 1), Humanoid.WalkToPoint * Vector3.new(1, 0, 1)).LookVector.Magnitude) + + if math.abs(VerticalVelocity) > 0.025 and CurrentState:match("Running") then + local overlap = workspace:GetPartBoundsInBox((Torso.CFrame * CFrame.new(0, -1.75, 0)) * CFrame.new(Torso.AssemblyLinearVelocity.Unit * Vector3.new(1, 0, 1)), Vector3.new(2, 2, 1) / 1.5, params) + for _, v : BasePart? in pairs(overlap) do + if v and v.CanCollide == false then + table.insert(ignore, v) + params.FilterDescendantsInstances = ignore + + table.remove(overlap, table.find(overlap, v)) + end + end + legObjects = overlap + else + table.clear(legObjects) + if jumped == false and CurrentState ~= "Climbing" and CurrentState ~= "FallingDown" then + onRunning(HorizontalVelocity.Magnitude * requestMoveMagnitude) + end + end + + move(time) + nextTime = time + 0.1 + end +end diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/Animate.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/init.meta.json new file mode 100644 index 0000000..ed9b9af --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/Preview/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "WorldModel", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/init.meta.json new file mode 100644 index 0000000..a31ba2a --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/ViewportFrame/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ViewportFrame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/init.meta.json new file mode 100644 index 0000000..a31ba2a --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/AvatarPreview/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ViewportFrame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/Profile/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/Container/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/ProfileContainer/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlayButton/Button/Main.client.lua b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlayButton/Button/Main.client.lua new file mode 100644 index 0000000..2b186a3 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlayButton/Button/Main.client.lua @@ -0,0 +1,19 @@ +--!strict + +local TeleportService : TeleportService = game:GetService("TeleportService") +local ReplicatedStorage : ReplicatedStorage = game:GetService("ReplicatedStorage") + +local Protocols : Instance = ReplicatedStorage:WaitForChild("Protocols") +local TeleportPlayer : Instance = Protocols:WaitForChild("TeleportPlayer") + + +local function Clicked(): () + local Container = script.Parent.Parent.Parent + local GameID = Container.GameId + + if TeleportPlayer:IsA("RemoteEvent") then + TeleportPlayer:FireServer(GameID.Value, Container.GameName.Text, "play") + end +end + +script.Parent.MouseButton1Click:Connect(Clicked) \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlayButton/Button/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlayButton/Button/init.meta.json new file mode 100644 index 0000000..8ed9503 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlayButton/Button/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "TextButton", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlayButton/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlayButton/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlayButton/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlaySoloButton/Button/Main.client.lua b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlaySoloButton/Button/Main.client.lua new file mode 100644 index 0000000..bab5aef --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlaySoloButton/Button/Main.client.lua @@ -0,0 +1,19 @@ +--!strict + +local TeleportService : TeleportService = game:GetService("TeleportService") +local ReplicatedStorage : ReplicatedStorage = game:GetService("ReplicatedStorage") + +local Protocols : Instance = ReplicatedStorage:WaitForChild("Protocols") +local TeleportPlayer : Instance = Protocols:WaitForChild("TeleportPlayer") + + +local function Clicked(): () + local Container = script.Parent.Parent.Parent + local GameID = Container.GameId + + if TeleportPlayer:IsA("RemoteEvent") then + TeleportPlayer:FireServer(GameID.Value, Container.GameName.Text, "solo") + end +end + +script.Parent.MouseButton1Click:Connect(Clicked) \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlaySoloButton/Button/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlaySoloButton/Button/init.meta.json new file mode 100644 index 0000000..8ed9503 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlaySoloButton/Button/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "TextButton", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlaySoloButton/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlaySoloButton/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/PlaySoloButton/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/JoinOptions/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/PlaceContainer/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/StatisticContainer/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/UserProfile/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/ProfilesPage/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/Content/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/Content/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/Content/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/NewGuiHandler.client.lua b/rojo/MainMenu/src/StarterGui/MainUI/NewGuiHandler.client.lua new file mode 100644 index 0000000..fa41735 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/NewGuiHandler.client.lua @@ -0,0 +1,1020 @@ +--[[ + FWM Official 2023 + + Handle UI, but better. +]] + +--Init: +local Lighting = game:GetService("Lighting") +local MarketplaceService = game:GetService("MarketplaceService") +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local SoundService = game:GetService("SoundService") +local StarterGui = game:GetService("StarterGui") +local UserInputService = game:GetService("UserInputService") + +local Sound = workspace:FindFirstChildOfClass("Sound") + +local Protocols = ReplicatedStorage:WaitForChild("Protocols") +local Modules = ReplicatedStorage:WaitForChild("Modules") +local Templates = ReplicatedStorage:WaitForChild("Templates") + +local TeleportPlayer = Protocols:FindFirstChild("TeleportPlayer") + +local GetAvatar = Protocols:FindFirstChild("V2GetAvatar") + +local ChangeAvatar = Protocols:FindFirstChild("V2ChangeAvatar") +local ChangeSetting = Protocols:FindFirstChild("V2ChangeSetting") + +local ReturnAvatar = Protocols:FindFirstChild("V2ReturnAvatar") +local ReturnStats = Protocols:FindFirstChild("V2ReturnStats") +local ReturnSettings = Protocols:FindFirstChild("V2ReturnSetting") +local ReturnBadges = Protocols:FindFirstChild("V2ReturnBadges") + +local Games = require(Modules:WaitForChild("Menu"):WaitForChild("Games")) +local TweenWrapper = require(Modules:WaitForChild("Menu"):WaitForChild("TweenWrapper")) +local Customization = require(Modules:WaitForChild("Menu"):WaitForChild("GrabStuff")) +local Raycast = require(Modules:WaitForChild("Menu"):WaitForChild("VpfRayCast")) +local Blog = require(Modules:WaitForChild("Menu"):WaitForChild("Blog")) +local UILibrary = require(Modules:WaitForChild("Menu"):WaitForChild("UILibrary")) + +local MainUI = script.Parent +local Content = MainUI.Content +local MenuBar = Content.MenuBar +local Loading = MainUI.Loading + +local LocalPlayer = Players.LocalPlayer +local Mouse = LocalPlayer:GetMouse() +local IdleCursorTexture = "rbxassetid://6271122911" +local GameIconPlaceholder = "rbxassetid://11715077635" + +local IsMobile = (not UserInputService.KeyboardEnabled) and UserInputService.TouchEnabled +local ColorSelected = nil +local PartSelected = nil +local MusicToggle = false + +StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, false) + +local Camera = workspace.CurrentCamera +local CameraAngles = { + ["AvatarPage"] = CFrame.new(-134.900864, 77.58284, 176.459869, 0.85539639, 0.107710674, -0.506651223, -7.4505806e-09, 0.978140354, 0.207946107, 0.517973959, -0.177876353, 0.836697757), + ["GamePage"] = CFrame.new(-147.462372, -8.81184006 + 2000, -103.498672, -0.761540592, 0.167673036, -0.626052499, -0, 0.965955675, 0.258707851, 0.648117304, 0.197016537, -0.735614359), + ["NewsPage"] = CFrame.new(-176.333145, 46.2607384, 348.454163, -0.506578326, -0.152747974, 0.848555505, -0, 0.984181762, 0.177161962, -0.862194002, 0.0897464082, -0.498565078), + ["SettingsPage"] = CFrame.new(-211.77037, 14.8653183, -1676.98462, 0.910399914, -0.0838500038, 0.405143589, -0, 0.979247451, 0.202668592, -0.413729638, -0.184509471, 0.891506612), + ["HomePage"] = CFrame.new(28.9110603, 13.0086212 - 1000, -40.6203995 + 1000, 0.41397649, -0.0476040989, -0.90904206, -1.86264515e-09, 0.998631775, -0.0522956662, 0.910287619, 0.0216491781, 0.413410038), + ["AdminPage"] = CFrame.new(-213.834137, 40.4706573, 306.680054, -0.331278294, -0.207361117, 0.920465171, -0, 0.975551605, 0.219770893, -0.943533123, 0.0728053302, -0.323179036), + ["ProfilesPage"] = CFrame.new(44.3511848, 885.117981, 1565.74316, -0.694744408, 0.129150063, -0.707566619, -0, 0.983747065, 0.179560438, 0.719256759, 0.12474861, -0.683452725) +} + +local Wooshes = {SoundService.Woosh, SoundService.Woosh1} + +local SpecialGameTypes = { + ["ROBLOX Game"] = { + GameNameColor = Color3.fromRGB(212, 0, 0), + + PlayButtonOutline = Color3.fromRGB(212, 0, 0), + PlayButtonColor = ColorSequence.new(Color3.fromRGB(196, 0, 0), Color3.fromRGB(240, 0, 0)), + + DefaultLayoutOrder = -999 + }, + + ["Event Game"] = { + GameNameColor = Color3.fromRGB(232, 77, 0), + + PlayButtonOutline = Color3.fromRGB(255, 85, 0), + PlayButtonColor = ColorSequence.new(Color3.fromRGB(232, 77, 0), Color3.fromRGB(255, 81, 0)), + + DefaultLayoutOrder = -99999 + }, +} + +local AvatarEditorTweens = { + [2006] = { + AvatarSelectionFrame = UDim2.new(0, 0, 0, 0), + AdvancedCustomizationFrame = UDim2.new(1, 0, 0, 0) + }, + + [2007] = { + AvatarSelectionFrame = UDim2.new(-1, 0, 0, 0), + AdvancedCustomizationFrame = UDim2.new(0, 0, 0, 0) + } +} + +local SettingsContainers = { + Content.SettingsPage.SettingsPageContainer.GraphicsCategoryContainer.Settings.Scroll, + Content.SettingsPage.SettingsPageContainer.MiscCategoryContainer.Settings.Scroll, + Content.SettingsPage.SettingsPageContainer.PlayersCategoryContainer.Settings.Scroll +} + +-- Format: +-- [InternalRenderName] = PreviewModel (Model must be inside a ViewportFrame) +local LocalAvatarRenderTypes = { + ["Avatar"] = Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Preview, + ["Home"] = Content.HomePage.HomePageContainer.ProfileContainer.Container.Profile.AvatarPreview.ViewportFrame.Preview +} + +local SearchEasterEggs = { + ["i love fwm"] = function() + SoundService:PlayLocalSound(SoundService.Boing) + + MainUI.KeyboardCombination.Size = UDim2.new(0, 0, 0, 0) + MainUI.KeyboardCombination.Visible = true + + TweenWrapper(MainUI.KeyboardCombination, {"Size"}, {UDim2.new(1, 0, 1, 0)}, 1, Enum.EasingStyle.Elastic) + TweenWrapper(MainUI.KeyboardCombination, {"ImageTransparency"}, {0}, 0.25) + + for i = 1, 5 do + local TransparencyValue = i < 4 and 0 or 1 + + if i == 3 then + task.wait(4) + + TweenWrapper(MainUI.KeyboardCombination, {"ImageTransparency"}, {1}, 0.25) + + continue + end + + for Index, Object in pairs(MainUI.KeyboardCombination:GetChildren()) do + TweenWrapper(Object, {"TextTransparency"}, {TransparencyValue}, 0.25) + end + + for Index, Object in pairs(MainUI.KeyboardCombination:GetChildren()) do + TweenWrapper(Object, {"TextStrokeTransparency"}, {TransparencyValue}, 0.25) + end + end + + task.wait(4) + + TweenWrapper(MainUI.KeyboardCombination, {"ImageTransparency"}, {1}, 0.25) + + task.wait(1) + + MainUI.KeyboardCombination.Visible = false + end +} + +-- Settings that are executed right as they're returned +local ExecuteSetting = { + ["LobbyMusic"] = function(Value) + MusicToggle = Value + + Sound.Volume = MusicToggle and 0.5 or 0 + + MainUI.MusicPlayer.ToggleContainer.Toggle.Image = MusicToggle and "rbxassetid://11298056533" or "rbxassetid://11298057902" + end +} + +-- Inputs that change before changing a setting +local ExecuteForInputs = { + ["CameraLerp"] = function(TextBox) + local NewValue = tonumber(TextBox.Text) + + if NewValue then + local Clamped = math.clamp(NewValue, 0.1, 1) + ChangeSetting:FireServer("CameraLerp", NewValue) + + TextBox.Text = tostring(Clamped) + end + end +} + +local RaycastIgnore = {} + +--Functions: +local function CursorUpdate(Cursor: ImageLabel) + --Cursor.Visible = not UserInputService.GamepadEnabled + Cursor.Position = UDim2.new(0, Mouse.X, 0, Mouse.Y + 36) + + local GetGuiObjects = LocalPlayer.PlayerGui:GetGuiObjectsAtPosition(Mouse.X, Mouse.Y) + + if GetGuiObjects then + for _, v in pairs(GetGuiObjects) do + if v:IsA("TextButton") or v:IsA("ImageButton") then + Cursor.Image = "rbxassetid://7167515791" + break + end + + Cursor.Image = IdleCursorTexture + end + end +end + +local function CursorInit() + UserInputService.MouseIconEnabled = false + + if IsMobile then + MainUI.Cursor.Visible = false + return + end + + CursorUpdate(MainUI.Cursor) + UserInputService.InputChanged:Connect(function(input: InputObject, gameProcessedEvent: boolean): () + if input.UserInputType == Enum.UserInputType.MouseMovement then + CursorUpdate(MainUI.Cursor) + end + end) +end + +local function LoadLighting(folder: Folder) --TODO: this function sucks + for i : number, v : Instance in pairs(folder:GetChildren()) do + if Lighting[v.Name] and v:IsA("ValueBase") then + Lighting[v.Name] = v.Value + end + end +end + +local function PreviewUpdate(Map: string) + --Load lighting: + LoadLighting(ReplicatedStorage.Maps:FindFirstChild(Map).Lighting) + + SoundService:PlayLocalSound(Wooshes[math.random(1, #Wooshes)]) + MainUI.Background.BackgroundTransparency = 0 + Camera.FieldOfView = 90 + Lighting.Blur.Size = 24 + + workspace.CamRef.CFrame = CameraAngles[Map] + + TweenWrapper(MainUI.Background, {"BackgroundTransparency"}, {0.2}, 0.5) + TweenWrapper(Camera, {"FieldOfView"}, {70}, 0.5) + TweenWrapper(Lighting.Blur, {"Size"}, {0}, 0.5) +end + +local function TopbarInit() + MenuBar.CurrentTime.Text = `{os.date("%A")}, {os.date("%B")} {os.date("%d"):match("0*(%d+)")}, {os.date("%Y")}` + MenuBar.LoggedInAs.Text = "Logged in as "..LocalPlayer.Name + + for _, Button in MenuBar.ButtonList:GetChildren() do + if Button:IsA("TextButton") then + local ButtonText = Button.ButtonText.Text + + Button.MouseButton1Click:Connect(function() + for Index, Object in pairs(Content:GetChildren()) do + local GetPage = string.sub(Object.Name, #Object.Name - 3, #Object.Name) == "Page" + + if GetPage then + Object.Visible = false + end + end + + local UIElement = Content:FindFirstChild(Button.Name.."Page") + + if UIElement then + PartSelected = nil + + if ColorSelected then + ColorSelected.Gui.ColorFrame.Stroke.UIStroke.Color = Color3.fromRGB(0, 0, 0) + ColorSelected.Gui.ColorFrame.Stroke.UIStroke.Transparency = 0.95 + + ColorSelected = nil + end + + UIElement.Visible = true + PreviewUpdate(UIElement.Name) + end + end) + + Button.MouseButton1Down:Connect(function() + TweenWrapper(Button.ButtonText, {"Size"}, {UDim2.new(1, 0, 0.825, 0)}, .5, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + end) + + Button.MouseButton1Up:Connect(function() + TweenWrapper(Button.ButtonText, {"Size"}, {UDim2.new(1, 0, 1, 0)}, .5, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + end) + + Button.MouseEnter:Connect(function() + Button.ButtonText.Text = ""..ButtonText.."" + Button.ButtonText.TextColor3 = Color3.fromRGB(227, 242, 253) + TweenWrapper(Button.ButtonText, {"Size"}, {UDim2.new(1, 0, 1.125, 0)}, .5, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + end) + + Button.MouseLeave:Connect(function() + Button.ButtonText.Text = ButtonText + Button.ButtonText.TextColor3 = Color3.fromRGB(255, 255, 255) + TweenWrapper(Button.ButtonText, {"Size"}, {UDim2.new(1, 0, 1, 0)}, .5, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + end) + end + end +end + +local function LoadAvatar(Character, AvatarAppearance) + for Part, Color in AvatarAppearance do + local CharacterPart = Character:FindFirstChild(Part) + + if CharacterPart then + CharacterPart.BrickColor = BrickColor.new(Color) + + if Part == "Head" then + local Face = CharacterPart:FindFirstChild("Face", true) + + if Face then + Face.Texture = `rbxassetid://{AvatarAppearance.Face}` + end + elseif Part == "Torso" then + local Shirt = CharacterPart:FindFirstChild("roblox", true) + + if Shirt then + Shirt.Texture = `rbxassetid://{AvatarAppearance.TShirt}` + end + end + end + end +end + +local function AvatarReturned(ReturnedAppearance, Type) + if Type and LocalAvatarRenderTypes[Type] then + LoadAvatar(LocalAvatarRenderTypes[Type], ReturnedAppearance) + + return + end + + for AppearanceType, Object in pairs(LocalAvatarRenderTypes) do + LoadAvatar(Object, ReturnedAppearance) + end +end + +-- Now includes: KDR issues fixed +local function StatsReturned(StatsTable) + local KDREquation = math.floor(StatsTable.KOs / StatsTable.WOs * 100) / 100 + local FinalKDR = KDREquation + + if KDREquation == 1 / 0 then + FinalKDR = StatsTable.KOs + elseif KDREquation == 0 / 1 then + FinalKDR = 0 + end + + Content.HomePage.HomePageContainer.ProfileContainer.Container.Statistics.Container.Data.KOs.Value.Text = StatsTable.KOs + Content.HomePage.HomePageContainer.ProfileContainer.Container.Statistics.Container.Data.WOs.Value.Text = StatsTable.WOs + + Content.HomePage.HomePageContainer.ProfileContainer.Container.Statistics.Container.Data.KDR.Value.Text = FinalKDR +end + +local function SettingsReturned(SettingsTable) + local IsTable = typeof(SettingsTable) == "table" + local SettingsGiven = IsTable and SettingsTable or {SettingsTable} + + for SettingName, SettingValue in pairs(SettingsGiven) do + local Executable = ExecuteSetting[SettingName] + + if Executable then + ExecuteSetting[SettingName](SettingValue) + end + end + + for Index, Container in pairs(SettingsContainers) do + for Index, Object in pairs(Container:GetChildren()) do + local SettingAttribute = Object:GetAttribute("Setting") + + if (not SettingAttribute) then + continue + end + + local CheckContainer = Object:FindFirstChild("CheckContainer") + + local CheckItem = CheckContainer:FindFirstChild("Check") + local TextInput = CheckContainer:FindFirstChild("TextBox") + + if CheckItem then + CheckItem.ImageLabel.Visible = SettingsTable[SettingAttribute] + elseif TextInput then + TextInput.Text = tostring(SettingsTable[SettingAttribute]) + end + end + end +end + +local function BadgesReturned(BadgesTable) + for Badge, CanShow in pairs(BadgesTable) do + local HasBadge = Content.HomePage.HomePageContainer.ProfileContainer.Container.Statistics.Container.Data.Badges:FindFirstChild(Badge) + + if HasBadge and HasBadge:IsA("ImageLabel") then + if not CanShow then + continue + end + + HasBadge.ImageTransparency = 0 + HasBadge.Visible = true + else + warn(Badge.." is not shown on the badge frame!") + end + end +end + +local function UpdateFriendsList() + local FriendsContainer = Content.HomePage.HomePageContainer.InformationContainer.FriendsContainer + local FriendCount = 0 + + local FriendsOnlineReturned, FriendsList = pcall(function() + return LocalPlayer:GetFriendsOnline() + end) + + if FriendsOnlineReturned then + for _, Friend in FriendsList do + if Friend.LocationType ~= 4 then + continue + end + + local RequestStatus, RequestInfo = pcall(function() + return MarketplaceService:GetProductInfo(Friend.PlaceId) + end) + + if not RequestStatus then + continue + end + + if RequestInfo.Creator.Name ~= "FWM Official" then + continue + end + + local InMenu = Friend.VisitorId == game.PlaceId + + local NewFriendCard = Templates.Guis.Friend:Clone() + NewFriendCard.Metadata.PlayerName.Text = Friend.UserName + NewFriendCard.Metadata.Playing.Text = (not InMenu) and `Playing: {RequestInfo.Name}` or "FWM Menu" + + local FriendPreviewCamera = Instance.new("Camera") + FriendPreviewCamera.CFrame = CFrame.new(2.23306537, 132.73306465, 4.01013613, 0.896169126, -0.179960817, 0.405579776, -2.23517418e-008, 0.914059639, 0.405579746, -0.443712562, -0.363468051, 0.819152057) + FriendPreviewCamera.Parent = NewFriendCard.FriendAvatar.ViewportFrame + + NewFriendCard.FriendAvatar.ViewportFrame.CurrentCamera = FriendPreviewCamera + + local FriendAvatarAppearance = Protocols.GetAvatar:InvokeServer(Friend.VisitorId) + + if FriendAvatarAppearance then + LoadAvatar(NewFriendCard.FriendAvatar.ViewportFrame.Preview, FriendAvatarAppearance) + end + + NewFriendCard.Metadata.JoinButton.Visible = (not InMenu) + + if NewFriendCard.Metadata.JoinButton.Visible then + UILibrary:SetupButtonFeedback(NewFriendCard.Metadata.JoinButton.TextButton, { + ["HoverSize"] = UDim2.new(1.1, 0, 1.1, 0), + ["DownSize"] = UDim2.new(0.9, 0, 0.9, 0), + ["FrameStyled"] = false, + }) + + NewFriendCard.Metadata.JoinButton.TextButton.MouseButton1Click:Connect(function() + SoundService:PlayLocalSound(SoundService.Tap) + TeleportPlayer:FireServer(Friend.PlaceId, Friend.UserName, "play") + end) + else + NewFriendCard.BackgroundColor3 = Color3.fromRGB(124, 155, 237) + NewFriendCard.Stroke.UIStroke.Color = Color3.fromRGB(124, 155, 237) + end + + NewFriendCard.Parent = FriendsContainer.Friends.FriendsList + FriendCount += 1 + end + end + + Content.HomePage.HomePageContainer.InformationContainer.FriendsContainer.Friends.OnlineCount.Text = string.format("Friends Online [%s]", FriendCount) + Content.HomePage.HomePageContainer.InformationContainer.FriendsContainer.InviteFriends.Visible = (FriendCount == 0) +end + +local function HomePageInit() + Content.HomePage.HomePageContainer.ProfileContainer.Container.Profile.WelcomeText.Text = `Hi, {LocalPlayer.Name}` + + local ProfilePreviewCamera = Instance.new("Camera") + ProfilePreviewCamera.CFrame = CFrame.new(2.23306537, 260.73306465, 4.01013613, 0.896169126, -0.179960817, 0.405579776, -2.23517418e-008, 0.914059639, 0.405579746, -0.443712562, -0.363468051, 0.819152057) + ProfilePreviewCamera.Parent = Content.HomePage.HomePageContainer.ProfileContainer.Container.Profile.AvatarPreview.ViewportFrame + + Content.HomePage.HomePageContainer.ProfileContainer.Container.Profile.AvatarPreview.ViewportFrame.CurrentCamera = ProfilePreviewCamera + + --if Players.LocalPlayer.FollowUserId ~= 0 then + -- MainUI.Loading.LoadingContainer.TextLabel.Text = "Joining friend..." + -- MainUI.Loading.Visible = true + --end +end + +local function GameSearchInit() + Content.GamePage.SearchBar:GetPropertyChangedSignal("Text"):Connect(function() + local SearchLower = string.lower(Content.GamePage.SearchBar.Text) + + for _, v in pairs(Content.GamePage.GamePageContainer:GetChildren()) do + if v:IsA("Frame") then + local GameName = v.GameName.Text + local IsVisible = SearchLower == "" or string.find(string.lower(GameName), SearchLower) ~= nil + + v.Visible = IsVisible + end + end + end) + + Content.GamePage.SearchBar.FocusLost:Connect(function(EnterPressed) + if (not EnterPressed) then + return + end + + local SearchLower = string.lower(Content.GamePage.SearchBar.Text) + + if SearchEasterEggs[SearchLower] then + SearchEasterEggs[SearchLower]() + end + end) +end + +local function GamesPageInit() + GameSearchInit() + + for Name, Information in pairs(Games) do + local NewGame = Templates.Guis.GameContainer:Clone() + local IsSpecialGameType = SpecialGameTypes[Information.Type] + + NewGame.Name = Information.TeleportID + NewGame.GameName.Text = tostring(Name) + NewGame.GameDescription.Text = Information.Description + + NewGame.GameThumbnail.Image = Information.GameIcon or GameIconPlaceholder + NewGame.GameThumbnail.TimePeriod.Text = Information.Period + + NewGame.GameId.Value = Information.TeleportID + + if IsSpecialGameType then + NewGame.GameName.TextColor3 = IsSpecialGameType.GameNameColor + + NewGame.PlayButton.UIStroke.Color = IsSpecialGameType.PlayButtonOutline + NewGame.PlayButton.UIGradient.Color = IsSpecialGameType.PlayButtonColor + + NewGame.LayoutOrder = IsSpecialGameType.DefaultLayoutOrder or 0 + end + + UILibrary:SetupButtonFeedback(NewGame.PlayButton, { + ["HoverSize"] = UDim2.new(0, 102, 0, 102), + ["DownSize"] = UDim2.new(0, 84, 0, 84), + ["HoverRotation"] = 10, + ["FrameStyled"] = true, + }) + + UILibrary:SetupButtonFeedback(NewGame.PlaySoloButton, { + ["HoverSize"] = UDim2.new(0, 72, 0, 72), + ["DownSize"] = UDim2.new(0, 58, 0, 58), + ["HoverRotation"] = 10, + ["FrameStyled"] = true, + }) + + NewGame.Parent = Content.GamePage.GamePageContainer + end +end + +local function BodyColorsInit() + for Index, Color in pairs(Customization.BrickColors) do + local NewColor = Templates.Guis.ColorContainer:Clone() + + NewColor.ColorFrame.BackgroundColor3 = BrickColor.new(Color).Color + + UILibrary:SetupButtonFeedback(NewColor.ColorFrame, { + ["HoverSize"] = UDim2.new(1.1, 0, 1.1, 0), + ["DownSize"] = UDim2.new(0.9, 0, 0.9, 0), + ["FrameStyled"] = true, + }) + + NewColor.ColorFrame.TextButton.MouseButton1Click:Connect(function() + if ColorSelected then + ColorSelected.Gui.ColorFrame.Stroke.UIStroke.Color = Color3.fromRGB(0, 0, 0) + ColorSelected.Gui.ColorFrame.Stroke.UIStroke.Transparency = 0.95 + end + + ColorSelected = { + Gui = NewColor, + Color = Color + } + + NewColor.ColorFrame.Stroke.UIStroke.Color = Color3.fromRGB(0,255,0) + NewColor.ColorFrame.Stroke.UIStroke.Transparency = 0 + end) + + NewColor.Parent = Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer.ColorPalette.PageContainer + end +end + +local function InitializeAvatarSearch(ItemType) + local SearchBar = Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer[ItemType]:FindFirstChild("SearchBar") + + if (not SearchBar) then + return + end + + SearchBar:GetPropertyChangedSignal("Text"):Connect(function() + local SearchLower = string.lower(SearchBar.Text) + + for _, v in pairs(Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer[ItemType].PageContainer:GetChildren()) do + if v:IsA("Frame") then + local ItemName = v.Name + local IsVisible = SearchLower == "" or string.find(string.lower(ItemName), SearchLower) ~= nil + + v.Visible = IsVisible + end + end + end) +end + +local function GiveItem(ItemType, ItemID, ItemName, Index) + local NewItem = Templates.Guis.TShirt:Clone() + local AvatarPart = string.sub(ItemType, 1, #ItemType - 1) + + NewItem.Shirt.Image = "rbxassetid://"..tostring(ItemID) + NewItem.LayoutOrder = Index + NewItem.Name = ItemName or "" + + NewItem.Shirt.MouseButton1Click:Connect(function(): () + Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Size = UDim2.new(0, 0, 0, 0) + TweenWrapper(Content.AvatarPage.AvatarPreviewContainer.AvatarPreview, {"Size"}, {UDim2.new(1, 0, 1, 0)}, 1, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + + ChangeAvatar:FireServer(nil, AvatarPart, ItemID, 2007) + end) + + NewItem.Parent = Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer[ItemType].PageContainer +end + +local function TypeInit(ItemType) + if (not Customization[ItemType]) then + return + end + + InitializeAvatarSearch(ItemType) + + for Index, ItemInformation in pairs(Customization[ItemType]) do + local ItemID = ItemInformation[1] + local IsVisibleByDefault = ItemInformation[2] + local ItemName = ItemInformation[3] or ItemID + + if (not IsVisibleByDefault) then + continue + end + + GiveItem(ItemType, ItemID, ItemName, Index) + end + + local ChipOfItem = Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.Chips[ItemType] + ChipOfItem.Visible = true +end + +local function InitAvatarTimePeriodPage(TimePeriod) + local CustomizationContainer = Content.AvatarPage.CustomizationContainer + + PartSelected = nil + if ColorSelected then + ColorSelected.Gui.ColorFrame.Stroke.UIStroke.Color = Color3.fromRGB(0, 0, 0) + ColorSelected.Gui.ColorFrame.Stroke.UIStroke.Transparency = 0.95 + + ColorSelected = nil + end + + TweenWrapper(CustomizationContainer.AvatarSelectionFrame, {"Position"}, {AvatarEditorTweens[TimePeriod].AvatarSelectionFrame}, 1.25, Enum.EasingStyle.Elastic) + TweenWrapper(CustomizationContainer.AdvancedCustomizationFrame, {"Position"}, {AvatarEditorTweens[TimePeriod].AdvancedCustomizationFrame}, 1.25, Enum.EasingStyle.Elastic) + + Content.AvatarPage.Notice.Visible = TimePeriod == 2006 + Content.AvatarPage.TypeOfAvatar.Text = TimePeriod == 2006 and "2006 Avatar" or "2007 Avatar" + + Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Animations.Value = TimePeriod == 2007 + GetAvatar:FireServer(TimePeriod) +end + +local function FiguresInit() + local Figures = Content.AvatarPage.CustomizationContainer.AvatarSelectionFrame.Container + + for Index, Object in pairs(Figures:GetChildren()) do + local FigureButton = Object:FindFirstChild("FigureButton") + + if FigureButton and FigureButton:IsA("ImageButton") then + local StringedNumber = string.gsub(FigureButton.Parent.Name, "Figure", "") + local ButtonNumber = tonumber(StringedNumber) + + UILibrary:SetupButtonFeedback(FigureButton, { + ["HoverSize"] = UDim2.new(1.025, 0, 1.025, 0), + ["DownSize"] = UDim2.new(0.95, 0, 0.95, 0), + ["BackgroundTransparency"] = 0.95, + ["BackgroundTransparencyDown"] = 0.85, + ["FrameStyled"] = false, + }) + + FigureButton.MouseButton1Click:Connect(function() + Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Size = UDim2.new(0, 0, 0, 0) + + TweenWrapper(Content.AvatarPage.AvatarPreviewContainer.AvatarPreview, {"Size"}, {UDim2.new(1, 0, 1, 0)}, 1, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + + ChangeAvatar:FireServer(ButtonNumber, nil, nil, 2006) + end) + end + end +end + +local function HighlightObject(Object) + if PartSelected then + local FindHighlight = PartSelected:FindFirstChild("Highlight") + + if FindHighlight and FindHighlight:IsA("BasePart") then + FindHighlight.Transparency = 1 + end + + PartSelected = nil + end + + if (not Object) then + return + end + + local FindHighlight = Object:FindFirstChild("Highlight") + + if FindHighlight and FindHighlight:IsA("BasePart") then + FindHighlight.Transparency = 0.5 + PartSelected = Object + end +end + +local function InitRaycaster(PreviewCamera) + local RaycastMouse = Raycast.new(Mouse, Content.AvatarPage.AvatarPreviewContainer.AvatarPreview, PreviewCamera) + + UserInputService.InputBegan:Connect(function(Input, GameProcessedEvent) + if GameProcessedEvent then + return + end + + if Input.UserInputType == Enum.UserInputType.MouseButton1 or Input.UserInputType == Enum.UserInputType.Touch or Input.KeyCode == Enum.KeyCode.ButtonA then + local Part, Pos = RaycastMouse.MouseHit(RaycastIgnore) + + if Part and Content.AvatarPage.Visible and ColorSelected then + ChangeAvatar:FireServer(nil, Part.Name, ColorSelected.Color, 2007) + SoundService:PlayLocalSound(SoundService.Splat) + end + end + end) + + -- No mobile support, back out + if IsMobile then + return + end + + -- Huge performance issues cause of this being called even if AvatarPage was closed + UserInputService.InputChanged:Connect(function(Input, GameProcessedEvent) + if GameProcessedEvent then + return + end + + if Input.UserInputType == Enum.UserInputType.MouseMovement and Content.AvatarPage.Visible and ColorSelected then + local Part, Pos = RaycastMouse.MouseHit(RaycastIgnore) + + HighlightObject(Part) + IdleCursorTexture = Part and "rbxassetid://12198344754" or "rbxassetid://6271122911" + end + end) +end + +local function AddHighlightsToIgnore() + for Index, Object in pairs(Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Preview:GetChildren()) do + local Highlight = Object:FindFirstChild("Highlight") + + if Object:IsA("BasePart") and Highlight and Highlight:IsA("BasePart") then + table.insert(RaycastIgnore, Highlight) + end + end + + for Index, Object in pairs(Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.AvatarPreviewShadow.Preview:GetChildren()) do + if Object:IsA("BasePart") then + table.insert(RaycastIgnore, Object) + end + end +end + +-- Mmm... yummy chips +local function CrispsInit() + local Chips = Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.Chips + + local ChipButtons = {} + local ChipCategories = {} + + for Index, Object in pairs(Chips:GetChildren()) do + if Object:IsA("Frame") then + local ChipButton = Object:FindFirstChild("Button") + local ChipCategory = Chips.Parent.CategoryContainer:FindFirstChild(Object.Name) + + if (not ChipButton) or (not ChipCategory) then + continue + end + + table.insert(ChipButtons, ChipButton.Parent) + table.insert(ChipCategories, ChipCategory) + + ChipButton.MouseButton1Click:Connect(function() + SoundService:PlayLocalSound(SoundService.Tap) + + PartSelected = nil + if ColorSelected then + ColorSelected.Gui.ColorFrame.Stroke.UIStroke.Color = Color3.fromRGB(0, 0, 0) + ColorSelected.Gui.ColorFrame.Stroke.UIStroke.Transparency = 0.95 + + ColorSelected = nil + end + + for Index, Object in ChipCategories do + Object.Visible = false + end + + ChipCategory.Position = UDim2.new(1, 0, 0, 0) + ChipCategory.Visible = true + + ChipCategory:TweenPosition(UDim2.new(0, 0, 0, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Elastic, 1, true) + + for _, Object in ChipButtons do + if Object == ChipButton.Parent then + Object.Label.FontFace = Font.new("rbxasset://fonts/families/GothamSSm.json", Enum.FontWeight.Bold) + + Object.Stroke:TweenPosition(UDim2.new(0.5, 0, 0.5, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, .05, true) + Object.Label:TweenPosition(UDim2.new(0, 0, 0, -4), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, .05, true) + + continue + end + + Object.Label.FontFace = Font.new("rbxasset://fonts/families/GothamSSm.json", Enum.FontWeight.Medium) + + Object.Stroke:TweenPosition(UDim2.new(0.5, 0, 0.5, 4), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, .05, true) + Object.Label:TweenPosition(UDim2.new(0, 0, 0, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, .05, true) + end + end) + end + end +end + +local function AvatarPageInit() + local CustomizationContainer = Content.AvatarPage.CustomizationContainer + + local PreviewCamera = Instance.new("Camera") + PreviewCamera.CFrame = CFrame.new(2.23306537, 4.73306465, 4.01013613, 0.896169126, -0.179960817, 0.405579776, -2.23517418e-008, 0.914059639, 0.405579746, -0.443712562, -0.363468051, 0.819152057) + PreviewCamera.Parent = Content.AvatarPage.AvatarPreviewContainer.AvatarPreview + + local CameraReplica = PreviewCamera:Clone() + CameraReplica.Parent = PreviewCamera.Parent.AvatarPreviewShadow + + PreviewCamera.Parent.CurrentCamera = PreviewCamera + CameraReplica.Parent.CurrentCamera = CameraReplica + + FiguresInit() + BodyColorsInit() + + AddHighlightsToIgnore() + InitRaycaster(PreviewCamera) + + TypeInit("TShirts") + --TypeInit("Face") + CrispsInit() + + CustomizationContainer.AvatarSelectionFrame.Container.Size = UDim2.new(1, 0, 1, -32) + CustomizationContainer.AvatarSelectionFrame.AdvancedCustomization.Visible = true + + CustomizationContainer.AdvancedCustomizationFrame.BackButton.MouseButton1Click:Connect(function() + InitAvatarTimePeriodPage(2006) + end) + + CustomizationContainer.AvatarSelectionFrame.AdvancedCustomization.MouseButton1Click:Connect(function() + InitAvatarTimePeriodPage(2007) + end) +end + +local function BackButtonInit() + local NewsPage = Content.NewsPage + local Reader = NewsPage.Reader + + UILibrary:SetupButtonFeedback(Reader.Container.Exit.ImageButton, { + ["HoverSize"] = UDim2.new(1.1, 0, 1.1, 0), + ["DownSize"] = UDim2.new(0.9, 0, 0.9, 0), + ["FrameStyled"] = false + }) + + Reader.Container.Exit.ImageButton.MouseButton1Click:Connect(function() + Reader.Visible = false + NewsPage.List.Visible = true + end) +end + +local function NewsPageInit() + local Reader = Content.NewsPage.Reader + local BeforeSize = Reader.Container.Size + + BackButtonInit() + + for Index, Information in pairs(Blog) do + local NewPost = Templates.Guis.Post:Clone() + local BlogDate = Information.Date + + NewPost.TextButton.Title.Text = Information.Title + NewPost.TextButton.Description.Text = Information.Content + NewPost.TextButton.Date.Text = os.date("%x", BlogDate) + NewPost.TextButton.ImageLabel.Image = Information.HeaderImage + NewPost.LayoutOrder = -BlogDate + + UILibrary:SetupButtonFeedback(NewPost.TextButton, { + ["HoverSize"] = UDim2.new(1.01, 0, 1.01, 0), + ["DownSize"] = UDim2.new(0.99, 0, 0.99, 0), + ["FrameStyled"] = false + }) + + NewPost.TextButton.MouseButton1Click:Connect(function() + Content.NewsPage.List.Visible = false + + Reader.Container.Content.Title.Text = Information.Title + Reader.Container.Content.Date.Text = `Published {os.date("%B %d, %Y @ %I:%M %p", BlogDate)}` + Reader.Container.Content.HeaderImage.Image = Information.HeaderImage + Reader.Container.Content.Text.Text = Information.Content + + Reader.Container.Size = UDim2.new(BeforeSize.X.Scale, 0, BeforeSize.Y.Scale, #Information.Content / 2) + + Reader.Visible = true + end) + + NewPost.Parent = Content.NewsPage.List + end +end + +local function SettingsPageInit() + for Index, Container in pairs(SettingsContainers) do + for Index, Object in pairs(Container:GetChildren()) do + local SettingAttribute = Object:GetAttribute("Setting") + + if (not SettingAttribute) then + continue + end + + local CheckContainer = Object:FindFirstChild("CheckContainer") + + local CheckItem = CheckContainer:FindFirstChild("Check") + local TextInput = CheckContainer:FindFirstChild("TextBox") + + if CheckItem then + UILibrary:SetupButtonFeedback(CheckItem, { + ["HoverSize"] = UDim2.new(1.1, 0, 1.1, 0), + ["DownSize"] = UDim2.new(0.9, 0, 0.9, 0), + ["FrameStyled"] = false, + }) + + CheckItem.MouseButton1Click:Connect(function() + CheckItem.ImageLabel.Visible = not CheckItem.ImageLabel.Visible + + SoundService:PlayLocalSound(CheckItem.ImageLabel.Visible and SoundService.Check or SoundService.Uncheck) + + ChangeSetting:FireServer(SettingAttribute, CheckItem.ImageLabel.Visible) + end) + elseif TextInput then + TextInput.FocusLost:Connect(function() + local SpecialExecution = ExecuteForInputs[SettingAttribute] + + if SpecialExecution then + ExecuteForInputs[SettingAttribute](TextInput) + + return + end + + ChangeSetting:FireServer(SettingAttribute, TextInput.Text) + end) + else + print(SettingAttribute.." isn't set up correctly!") + end + end + end +end + +local function MusicInit() + MainUI.MusicPlayer.SongName.Text = Sound.Name + + UILibrary:SetupButtonFeedback(MainUI.MusicPlayer.ToggleContainer.Toggle, { + ["HoverSize"] = UDim2.new(1.1, 0, 1.1, 0), + ["DownSize"] = UDim2.new(0.9, 0, 0.9, 0), + ["FrameStyled"] = false + }) + + Sound:GetPropertyChangedSignal("Name"):Connect(function(): () + MainUI.MusicPlayer.SongName.Text = Sound.Name + end) + + MainUI.MusicPlayer.ToggleContainer.Toggle.MouseButton1Click:Connect(function(): () + ExecuteSetting.LobbyMusic(not MusicToggle) + + ChangeSetting:FireServer("LobbyMusic", MusicToggle) + end) +end + +local function OnLoading() + SoundService.Loading.Playing = MainUI.Loading.Visible +end + +--Hookups: +PreviewUpdate("HomePage") + +CursorInit() +TopbarInit() +HomePageInit() +GamesPageInit() +AvatarPageInit() +NewsPageInit() +SettingsPageInit() +MusicInit() + +--Protocol hookups: +ReturnAvatar.OnClientEvent:Connect(AvatarReturned) +ReturnStats.OnClientEvent:Connect(StatsReturned) +ReturnSettings.OnClientEvent:Connect(SettingsReturned) +ReturnBadges.OnClientEvent:Connect(BadgesReturned) + +Loading:GetPropertyChangedSignal("Visible"):Connect(OnLoading) + +--Hookups with Yields: +UpdateFriendsList() \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/UIHandler.client.lua b/rojo/MainMenu/src/StarterGui/MainUI/UIHandler.client.lua new file mode 100644 index 0000000..3bf1eb7 --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/UIHandler.client.lua @@ -0,0 +1,1340 @@ +--!nonstrict +--[[ + Classic Roblox Clothes! 2022 + + Handle UI. + + (i hate non oop code) + idc - Vibin +]] +local Lighting = game:GetService("Lighting") +local MarketplaceService: MarketplaceService = game:GetService("MarketplaceService") +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local SoundService = game:GetService("SoundService") +local StarterGui = game:GetService("StarterGui") +local UserInputService: UserInputService = game:GetService("UserInputService") + +local Protocols = ReplicatedStorage:WaitForChild("Protocols") +local Modules = ReplicatedStorage:WaitForChild("Modules") +local Templates = ReplicatedStorage:WaitForChild("Templates") + +local TeleportPlayer = Protocols:FindFirstChild("TeleportPlayer") +local SettingsChanger = Protocols:FindFirstChild("ChangeSettings") +local GetLocalPlayerAvatar = Protocols:FindFirstChild("GetLocalPlayerAvatar") +local ItemAwarded = Protocols:FindFirstChild("AwardItem") + +local PlayerCounter = Protocols:FindFirstChild("ReturnPlayerCount") + +local Games = require(Modules:WaitForChild("Menu"):WaitForChild("Games")) +local TweenWrapper = require(Modules:WaitForChild("Menu"):WaitForChild("TweenWrapper")) +local Customization = require(Modules:WaitForChild("Menu"):WaitForChild("GrabStuff")) +local Raycast = require(Modules:WaitForChild("Menu"):WaitForChild("VpfRayCast")) + +local Blog = require(Modules:WaitForChild("Menu"):WaitForChild("Blog")) + +local Camera = workspace.CurrentCamera +local MainUI = script.Parent + +local Wooshes = {SoundService.Woosh, SoundService.Woosh1} + +local LocalPlayer = Players.LocalPlayer +local Mouse = LocalPlayer:GetMouse() + +local TestRescript = false + +if TestRescript then + local WhiteListedIDs = { + [385867863] = true, + [151461991] = true + } + + if WhiteListedIDs[LocalPlayer.UserId] then + MainUI.UIHandler.Enabled = false + MainUI.NewGuiHandler.Enabled = true + + return + end +end + +--Background angle table: +local CameraAngles = { + ["AvatarPage"] = CFrame.new(-134.900864, 77.58284, 176.459869, 0.85539639, 0.107710674, -0.506651223, -7.4505806e-09, 0.978140354, 0.207946107, 0.517973959, -0.177876353, 0.836697757), + ["GamePage"] = CFrame.new(-147.462372, -8.81184006 + 2000, -103.498672, -0.761540592, 0.167673036, -0.626052499, -0, 0.965955675, 0.258707851, 0.648117304, 0.197016537, -0.735614359), + ["NewsPage"] = CFrame.new(-176.333145, 46.2607384, 348.454163, -0.506578326, -0.152747974, 0.848555505, -0, 0.984181762, 0.177161962, -0.862194002, 0.0897464082, -0.498565078), + ["SettingsPage"] = CFrame.new(-211.77037, 14.8653183, -1676.98462, 0.910399914, -0.0838500038, 0.405143589, -0, 0.979247451, 0.202668592, -0.413729638, -0.184509471, 0.891506612), + ["HomePage"] = CFrame.new(28.9110603, 13.0086212 - 1000, -40.6203995 + 1000, 0.41397649, -0.0476040989, -0.90904206, -1.86264515e-09, 0.998631775, -0.0522956662, 0.910287619, 0.0216491781, 0.413410038), + ["AdminPage"] = CFrame.new(-213.834137, 40.4706573, 306.680054, -0.331278294, -0.207361117, 0.920465171, -0, 0.975551605, 0.219770893, -0.943533123, 0.0728053302, -0.323179036), + ["ProfilesPage"] = CFrame.new(44.3511848, 885.117981, 1565.74316, -0.694744408, 0.129150063, -0.707566619, -0, 0.983747065, 0.179560438, 0.719256759, 0.12474861, -0.683452725) +} + +local SpecialFrameColors = { + [1] = Color3.fromRGB(255, 213, 79), + [2] = Color3.fromRGB(176, 190, 197), + [3] = Color3.fromRGB(161, 136, 127) +} + +local toggle = true + +local SelectedColor +local IdleCursorTexture = "rbxassetid://6271122911" + +--Setup lighting with info from a folder +local function LoadLighting(folder: Folder): () + for i : number, v : Instance in pairs(folder:GetChildren()) do + if v:IsA("Sky") then + local CurrentSkybox = v:Clone() + CurrentSkybox.Parent = Lighting + elseif v:IsA("ColorCorrectionEffect") then + local CurrentColorCorrection = v:Clone() + CurrentColorCorrection.Parent = Lighting + elseif v:IsA("BloomEffect") then + local CurrentBloom = v:Clone() + CurrentBloom.Parent = Lighting + elseif v:IsA("SunRaysEffect") then + local CurrentSunrays = v:Clone() + CurrentSunrays.Parent = Lighting + else + if Lighting[v.Name] then + if v:IsA("BoolValue") then + Lighting[v.Name] = v.Value + elseif v:IsA("Color3Value") then + Lighting[v.Name] = v.Value + elseif v:IsA("IntValue") then + Lighting[v.Name] = v.Value + elseif v:IsA("NumberValue") then + Lighting[v.Name] = v.Value + elseif v:IsA("StringValue") then + Lighting[v.Name] = v.Value + end + end + end + end +end + +local function CursorUpdate(Cursor: ImageLabel): () + Cursor.Visible = (not UserInputService.GamepadEnabled) + --if UserInputService.GamepadEnabled then + -- Cursor.Visible = false + --else + -- Cursor.Visible = true + --end + + Cursor.Position = UDim2.new(0, Mouse.X, 0, Mouse.Y + 36) + + local GetGuiObjects = LocalPlayer.PlayerGui:GetGuiObjectsAtPosition(Mouse.X, Mouse.Y) + + if GetGuiObjects then + for _, v in pairs(GetGuiObjects) do + if v:IsA("TextButton") or v:IsA("ImageButton") then + Cursor.Image = "rbxassetid://7167515791" + break + --elseif v:IsA("TextBox") then + -- Cursor.Image = "rbxassetid://0" + -- break + --elseif SelectedColor ~= nil then + -- Cursor.Image = "rbxassetid://12198344754" + -- break + end + + Cursor.Image = IdleCursorTexture + end + end +end + +local function AvatarHighlight(BodyPart: Part?): () + for _, v in ipairs(MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Preview:GetDescendants()) do + if v:IsA("BasePart") and v.Name == "Highlight" then + v.Transparency = 1 + end + end + + if BodyPart then + for _, v in ipairs(BodyPart:GetChildren()) do + if v:IsA("BasePart") and v.Name == "Highlight" then + v.Transparency = 0.5 + end + end + end +end + +local function Loading(Returned: string): () + local PlaceName = Returned + + script.Parent.Loading.Visible = true + script.Parent.Loading.LoadingContainer.TextLabel.Text = string.format("Joining %q", PlaceName) +end + +local function UpdatePlayerCount(Information: any) + for GameId, PlayerCountInformation in pairs(Information) do + local GamePlayerCount = 0 + + for Server, PlayerCount in pairs(PlayerCountInformation) do + GamePlayerCount += PlayerCount + end + + local GrabbedGame = MainUI.Content.GamePage.GamePageContainer:FindFirstChild(GameId) + + if GrabbedGame then + GrabbedGame.PlayersOnline.Text = tostring(GamePlayerCount).." player(s) online" + + if GrabbedGame.GameName.TextColor3 ~= Color3.fromRGB(232, 77, 0) then + GrabbedGame.LayoutOrder = -GamePlayerCount + + if GrabbedGame:GetAttribute("RobloxGame") then -- GLORY SYSTEM! GOOD FORTUNE! + GrabbedGame.LayoutOrder = -(999 + GamePlayerCount) + end + end + end + end +end + +local function ReturnedBadgeInfo(Information: any): () + for Badge, CanShow in pairs(Information) do + local HasBadge = MainUI.Content.HomePage.HomePageContainer.ProfileContainer.Container.Statistics.Container.Data.Badges:FindFirstChild(Badge) + + if HasBadge and HasBadge:IsA("ImageLabel") then + if not CanShow then + continue + end + + HasBadge.ImageTransparency = 0 + HasBadge.Visible = true + else + warn(Badge.." is not shown on the badge frame!") + end + end +end + +local function AwardItem(ItemType: string, ItemId: number, Name: string, Order: number): () + local NewFace = Templates.Guis.TShirt:Clone() + NewFace.Shirt.Image = "rbxassetid://"..tostring(ItemId) + NewFace.LayoutOrder = Order + NewFace.Name = Name or "" + NewFace.Parent = MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer[ItemType.."s"].PageContainer + + NewFace.Shirt.MouseButton1Click:Connect(function(): () + local Subbed = string.gsub(NewFace.Shirt.Image, "rbxassetid://", "") + + MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Size = UDim2.new(0, 0, 0, 0) + TweenWrapper(MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview, {"Size"}, {UDim2.new(1, 0, 1, 0)}, 1, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + + Protocols.ChangeAvatar:FireServer(nil, ItemType, tonumber(Subbed)) + end) +end + +local function UpdatePointsLeaderboard(BoardInformation) + for _, v in pairs(MainUI.Content.HomePage.HomePageContainer.InformationContainer.Leaderboard.Container.Placements:GetChildren()) do + if v:IsA("Frame") then + v:Destroy() + end + end + + for Placement, Information in pairs(BoardInformation) do + + local UserId = Information.key + local Points = Information.value + + + + local NewPlacement = Templates.Guis.Placement:Clone() + local Metadata = NewPlacement.Metadata + + local GrabbedUsername + local Success, Failed = pcall(function() + GrabbedUsername = Players:GetNameFromUserIdAsync(UserId) + end) + + Metadata.PlayerName.Text = (not Failed) and GrabbedUsername or "ERROR: "..UserId + Metadata.Stats.Text = `Points: {math.clamp(Points, 0, 10e9)}` + + NewPlacement.Number.Text = `#{Placement}` + NewPlacement.LayoutOrder = Placement + + local SpecialFrameColor = SpecialFrameColors[Placement] + + if SpecialFrameColor then + NewPlacement.Number.TextColor3 = SpecialFrameColor + NewPlacement.Stroke.UIStroke.Color = SpecialFrameColor + NewPlacement.BackgroundColor3 = SpecialFrameColor + + NewPlacement.Number.UIStroke.Thickness = 2 + end + + NewPlacement.Parent = MainUI.Content.HomePage.HomePageContainer.InformationContainer.Leaderboard.Container.Placements + + end +end + +local function NewToggle(sound): () + if toggle then + sound.Volume = 0 + MainUI.MusicPlayer.ToggleContainer.Toggle.Image = "rbxassetid://11298057902" + toggle = false + else + sound.Volume = 0.5 + MainUI.MusicPlayer.ToggleContainer.Toggle.Image = "rbxassetid://11298056533" + toggle = true + end +end + +local function PreviewUpdate(CframeRef: CFrame, Map: string): () + --Load lighting: + LoadLighting(ReplicatedStorage.Maps:FindFirstChild(Map).Lighting) + + SoundService:PlayLocalSound(Wooshes[math.random(1, #Wooshes)]) + MainUI.Background.BackgroundTransparency = 0 + Camera.FieldOfView = 90 + Lighting.Blur.Size = 24 + + workspace.CamRef.CFrame = CframeRef + + TweenWrapper(MainUI.Background, {"BackgroundTransparency"}, {0.2}, 0.5) + TweenWrapper(Camera, {"FieldOfView"}, {70}, 0.5) + TweenWrapper(Lighting.Blur, {"Size"}, {0}, 0.5) +end + +--Buttons: +local function SetupButtonFeedback(Button, Config): () + --Cache the initial stuff so we dont need an extra dumb parameter just for that: + local NormalSize: UDim2 = Button.Size + local NormalRotation: number = Button.Rotation + local NormalBackgroundTransparency: number = Button.BackgroundTransparency + + --Config stuff into vars for safe keeping: + local HoverSize = Config["HoverSize"] or NormalSize + local DownSize = Config["DownSize"] or NormalSize + local BackgroundTransparency = Config["BackgroundTransparency"] or NormalBackgroundTransparency + local BackgroundTransparencyDown = Config["BackgroundTransparencyDown"] or NormalBackgroundTransparency + local HoverRotation = Config["HoverRotation"] or Button.Rotation + local Style = Config["Style"] or Enum.EasingStyle.Elastic + + if Config["FrameStyled"] ~= nil and Config["FrameStyled"] == true then --Some buttons use different methods of styling, such as the "JoinButton" having styling and resizing in the TextButton itself + local TextButton: Instance? = Button:FindFirstChildOfClass("TextButton") + + if TextButton and TextButton:IsA("TextButton") then + + --Hookup everything: + TextButton.MouseEnter:Connect(function() + TweenWrapper(Button, {"Size"}, {HoverSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {HoverRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {BackgroundTransparency}, .5, Style, Enum.EasingDirection.Out) + end) + + TextButton.MouseLeave:Connect(function() + TweenWrapper(Button, {"Size"}, {NormalSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {NormalRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {NormalBackgroundTransparency}, .5, Style, Enum.EasingDirection.Out) + end) + + TextButton.MouseButton1Down:Connect(function() + TweenWrapper(Button, {"Size"}, {DownSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {NormalRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {BackgroundTransparencyDown}, .5, Style, Enum.EasingDirection.Out) + end) + + TextButton.MouseButton1Up:Connect(function() + TweenWrapper(Button, {"Size"}, {NormalSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {NormalRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {NormalBackgroundTransparency}, .5, Style, Enum.EasingDirection.Out) + end) + end + elseif Config["FrameStyled"] ~= nil and Config["FrameStyled"] == false then --Just use the button instance directly + --Hookup everything: + Button.MouseEnter:Connect(function() + TweenWrapper(Button, {"Size"}, {HoverSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {HoverRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {BackgroundTransparency}, .5, Style, Enum.EasingDirection.Out) + end) + + Button.MouseLeave:Connect(function() + TweenWrapper(Button, {"Size"}, {NormalSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {NormalRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {NormalBackgroundTransparency}, .5, Style, Enum.EasingDirection.Out) + end) + + Button.MouseButton1Down:Connect(function() + TweenWrapper(Button, {"Size"}, {DownSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {NormalRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {BackgroundTransparencyDown}, .5, Style, Enum.EasingDirection.Out) + end) + + Button.MouseButton1Up:Connect(function() + TweenWrapper(Button, {"Size"}, {NormalSize}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"Rotation"}, {NormalRotation}, .5, Style, Enum.EasingDirection.Out) + TweenWrapper(Button, {"BackgroundTransparency"}, {NormalBackgroundTransparency}, .5, Style, Enum.EasingDirection.Out) + end) + end +end + +--Menu stuff: +local function MenuBarButtonClick(Button: TextButton): () + for _, v in pairs(MainUI.Content:GetChildren()) do + if v:IsA("Frame") and v.Name ~= "MenuBar" or v:IsA("ScrollingFrame") then + v.Visible = false + end + end + + local UIElement = MainUI.Content:FindFirstChild(Button.Name.."Page") + + if UIElement then + UIElement.Visible = true + PreviewUpdate(CameraAngles[UIElement.Name], UIElement.Name) + + --if UIElement.Name == "AvatarPage" then --do da AVATAR back rond + -- PreviewUpdate(CFrame.new(-134.900864, 77.58284, 176.459869, 0.85539639, 0.107710674, -0.506651223, -7.4505806e-09, 0.978140354, 0.207946107, 0.517973959, -0.177876353, 0.836697757), "AvatarRoom") + --elseif UIElement.Name == "GamePage" then + -- PreviewUpdate(CFrame.new(-147.462372, -8.81184006 + 2000, -103.498672, -0.761540592, 0.167673036, -0.626052499, -0, 0.965955675, 0.258707851, 0.648117304, 0.197016537, -0.735614359), "Crossroads") + --elseif UIElement.Name == "HelpPage" then + -- PreviewUpdate(CFrame.new(-176.333145, 46.2607384, 348.454163, -0.506578326, -0.152747974, 0.848555505, -0, 0.984181762, 0.177161962, -0.862194002, 0.0897464082, -0.498565078), "MiniOffice") + --elseif UIElement.Name == "SettingsPage" then + -- PreviewUpdate(CFrame.new(-211.77037, 14.8653183, -1676.98462, 0.910399914, -0.0838500038, 0.405143589, -0, 0.979247451, 0.202668592, -0.413729638, -0.184509471, 0.891506612), "Settings") + --elseif UIElement.Name == "HomePage" then + -- PreviewUpdate(CFrame.new(28.9110603, 13.0086212 - 1000, -40.6203995 + 1000, 0.41397649, -0.0476040989, -0.90904206, -1.86264515e-09, 0.998631775, -0.0522956662, 0.910287619, 0.0216491781, 0.413410038), "Home") + --end + end +end + +local function AvatarButtonClick(Button: ImageButton): () + if Button.Parent then + local NewNumber = string.gsub(Button.Parent.Name, "Figure", "") + + --MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.ImageTransparency = 1 + MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Size = UDim2.new(0, 0, 0, 0) + --MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Image = Button.Image + + --TweenWrapper(MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview, {"ImageTransparency"}, {0}, .5, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + TweenWrapper(MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview, {"Size"}, {UDim2.new(1, 0, 1, 0)}, 1, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + + Protocols.ChangeAvatar:FireServer(tonumber(NewNumber), nil, nil, 2006) + end +end + +local function SettingsReturned(ReturnedTable: any): () + local GraphicsSetting = MainUI.Content.SettingsPage.SettingsPageContainer.GraphicsCategoryContainer.Settings:FindFirstChild("Scroll") + local MiscSetting = MainUI.Content.SettingsPage.SettingsPageContainer.MiscCategoryContainer.Settings:FindFirstChild("Scroll") + local PlayersSetting = MainUI.Content.SettingsPage.SettingsPageContainer.PlayersCategoryContainer.Settings:FindFirstChild("Scroll") + + if GraphicsSetting and MiscSetting and PlayersSetting then + for i, v in pairs(GraphicsSetting:GetChildren()) do + if v:IsA("Frame") and v.Name == "Setting" and v:GetAttribute("Setting") then + local Attribute = v:GetAttribute("Setting") + local Visibility = ReturnedTable[Attribute] + + if Visibility ~= nil then + v.CheckContainer.Check.ImageLabel.Visible = Visibility + end + end + end + + for i, v in pairs(MiscSetting:GetChildren()) do + if v:IsA("Frame") and v.Name == "Setting" and v:GetAttribute("Setting") then + local Attribute = v:GetAttribute("Setting") + local Visibility = ReturnedTable[Attribute] + + if Visibility ~= nil then + v.CheckContainer.Check.ImageLabel.Visible = Visibility + end + elseif v:IsA("Frame") and v.Name == "CameraLerp" and v:GetAttribute("Setting") then + local Attribute = v:GetAttribute("Setting") + local Value = ReturnedTable[Attribute] + + v.CheckContainer.TextBox.Text = tostring(Value) + end + end + + for i, v in pairs(PlayersSetting:GetChildren()) do + if v:IsA("Frame") and v.Name == "Setting" and v:GetAttribute("Setting") then + local Attribute = v:GetAttribute("Setting") + local Visibility = ReturnedTable[Attribute] + + if Visibility ~= nil then + v.CheckContainer.Check.ImageLabel.Visible = Visibility + end + end + end + + if ReturnedTable["LobbyMusic"] ~= nil then + local sound = workspace:FindFirstChildOfClass("Sound") + toggle = ReturnedTable["LobbyMusic"] + + if toggle then + sound.Volume = 0.5 + MainUI.MusicPlayer.ToggleContainer.Toggle.Image = "rbxassetid://11298056533" + else + sound.Volume = 0 + MainUI.MusicPlayer.ToggleContainer.Toggle.Image = "rbxassetid://11298057902" + end + end + end +end + +local function StatsReturned(ReturnedTable: any): () + MainUI.Content.HomePage.HomePageContainer.ProfileContainer.Container.Statistics.Container.Data.KOs.Value.Text = ReturnedTable["KOs"] + MainUI.Content.HomePage.HomePageContainer.ProfileContainer.Container.Statistics.Container.Data.WOs.Value.Text = ReturnedTable["WOs"] + MainUI.Content.HomePage.HomePageContainer.ProfileContainer.Container.Statistics.Container.Data.KDR.Value.Text = math.floor(ReturnedTable["KOs"]/ReturnedTable["WOs"] * 100)/100 +end + +local function UpdateForCustomizationFrame(ReturnedTable: any): () + local GetPreview = MainUI.Content.AvatarPage.AvatarPreviewContainer:FindFirstChild("AvatarPreview") + local AdvancedCustomization = MainUI.Content.AvatarPage.CustomizationContainer:FindFirstChild("AdvancedCustomizationFrame") + + if GetPreview then + local PreviewModel = GetPreview:FindFirstChild("Preview") + + if PreviewModel then + for i, v in pairs(ReturnedTable) do + local FindPart = PreviewModel:FindFirstChild(i) + + if FindPart then + local TShirtFind = FindPart:FindFirstChild("roblox") + local FaceFind = FindPart:FindFirstChild("Face") + + if TShirtFind then + TShirtFind.Texture = "rbxassetid://"..ReturnedTable["TShirt"] + end + + if FaceFind then + FaceFind.Texture = "rbxassetid://"..ReturnedTable["Face"] + end + + FindPart.BrickColor = BrickColor.new(v) + end + end + end + end +end + +local function AvatarReturned(ReturnedTable: any, Type: string?): () -- eggs d + local GetPreview = MainUI.Content.AvatarPage.AvatarPreviewContainer:FindFirstChild("AvatarPreview") + local GetProfilePreview = MainUI.Content.HomePage.HomePageContainer.ProfileContainer.Container.Profile.AvatarPreview:FindFirstChild("ViewportFrame") + local AdvancedCustomization = MainUI.Content.AvatarPage.CustomizationContainer:FindFirstChild("AdvancedCustomizationFrame") + + if Type == "All" then + if GetPreview and GetProfilePreview then + local PreviewModel = GetPreview:FindFirstChild("Preview") + local ProfilePreviewModel = GetProfilePreview:FindFirstChild("Preview") + + if PreviewModel and ProfilePreviewModel then + for i, v in pairs(ReturnedTable) do + local FindPart = PreviewModel:FindFirstChild(i) + local FindPart2 = ProfilePreviewModel:FindFirstChild(i) + + if FindPart then + local TShirtFind = FindPart:FindFirstChild("roblox") + local FaceFind = FindPart:FindFirstChild("Face") + + if TShirtFind then + TShirtFind.Texture = "rbxassetid://"..ReturnedTable["TShirt"] + end + + if FaceFind then + FaceFind.Texture = "rbxassetid://"..ReturnedTable["Face"] + end + + FindPart.BrickColor = BrickColor.new(v) + + --if AdvancedCustomization then -- feel free to recode this if you consider this stank + -- local BodyColor = AdvancedCustomization:FindFirstChild("BodyColors"):FindFirstChild(i) + + -- if BodyColor then + -- local Shirt = BodyColor:FindFirstChild("roblox") + + -- if Shirt then + -- Shirt.Image = "rbxassetid://"..ReturnedTable["TShirt"] + -- end + + -- BodyColor.BackgroundColor3 = BrickColor.new(v).Color + -- end + --end + end + + if FindPart2 then + local TShirtFind = FindPart2:FindFirstChild("roblox") + local FaceFind = FindPart2:FindFirstChild("Face") + + if TShirtFind then + TShirtFind.Texture = "rbxassetid://"..ReturnedTable["TShirt"] + end + + if FaceFind then + FaceFind.Texture = "rbxassetid://"..ReturnedTable["Face"] + end + + FindPart2.BrickColor = BrickColor.new(v) + end + end + end + end + else + UpdateForCustomizationFrame(ReturnedTable) + end +end + +local function UpdateFriendsList(): () + if Players.LocalPlayer.FollowUserId ~= 0 then + MainUI.Loading.LoadingContainer.TextLabel.Text = "Joining friend..." + MainUI.Loading.Visible = true + end + + for _, v in pairs(MainUI.Content.HomePage.HomePageContainer.InformationContainer.FriendsContainer.Friends.FriendsList:GetChildren()) do + if v:IsA("Frame") then + v:Destroy() + end + end + + MainUI.Content.HomePage.HomePageContainer.InformationContainer.FriendsContainer.InviteFriends.Visible = false + + local GrabLocalFriends = nil + + local Grab, Errored = pcall(function() + GrabLocalFriends = LocalPlayer:GetFriendsOnline() + end) + + if Errored then + GrabLocalFriends = nil + end + + local FriendCount = 0 + + if GrabLocalFriends then + for _, v in pairs(GrabLocalFriends) do + if v.LocationType == 4 then + if v.PlaceId and v.PlaceId ~= 10789607669 and MarketplaceService:GetProductInfo(v.PlaceId).Creator["Name"] == "FWM Official" then + local New = Templates.Guis.Friend:Clone() + + local GameName = MarketplaceService:GetProductInfo(v.PlaceId).Name + + New.Metadata.PlayerName.Text = v.UserName + New.Metadata.Playing.Text = "Playing: "..GameName + + --local ImageRender, Ready = Players:GetUserThumbnailAsync(v.VisitorId, Enum.ThumbnailType.AvatarThumbnail, Enum.ThumbnailSize.Size180x180) + --New.FriendAvatar.ImageLabel.Image = ImageRender + + local FriendPreviewCamera = Instance.new("Camera") + FriendPreviewCamera.CFrame = CFrame.new(2.23306537, 132.73306465, 4.01013613, 0.896169126, -0.179960817, 0.405579776, -2.23517418e-008, 0.914059639, 0.405579746, -0.443712562, -0.363468051, 0.819152057) + FriendPreviewCamera.Parent = New.FriendAvatar.ViewportFrame + + New.FriendAvatar.ViewportFrame.CurrentCamera = FriendPreviewCamera + + local AvatarAppearance = Protocols.GetAvatar:InvokeServer(v.VisitorId) + + for i, v in pairs(AvatarAppearance) do + local FindPart = New.FriendAvatar.ViewportFrame.Preview:FindFirstChild(i) + + if FindPart then + local TShirtFind = FindPart:FindFirstChild("roblox") + local FaceFind = FindPart:FindFirstChild("Face") + + if TShirtFind then + TShirtFind.Texture = "rbxassetid://"..AvatarAppearance["TShirt"] + end + + if FaceFind then + FaceFind.Texture = "rbxassetid://"..AvatarAppearance["Face"] + end + + FindPart.BrickColor = BrickColor.new(v) + end + end + + SetupButtonFeedback(New.Metadata.JoinButton.TextButton, { + ["HoverSize"] = UDim2.new(1.1, 0, 1.1, 0), + ["DownSize"] = UDim2.new(0.9, 0, 0.9, 0), + ["FrameStyled"] = false, + }) + + New.Metadata.JoinButton.TextButton.MouseButton1Click:Connect(function(): () + SoundService:PlayLocalSound(SoundService.Tap) + if TeleportPlayer:IsA("RemoteEvent") then + TeleportPlayer:FireServer(v.PlaceId, GameName, "play") + end + end) + + if Players.LocalPlayer.FollowUserId == v.VisitorId then + MainUI.Loading.LoadingContainer.TextLabel.Text = "Joining friend..." + MainUI.Loading.Visible = true + + if TeleportPlayer:IsA("RemoteEvent") then + TeleportPlayer:FireServer(v.PlaceId, GameName, "play") + end + end + + New.Parent = MainUI.Content.HomePage.HomePageContainer.InformationContainer.FriendsContainer.Friends.FriendsList + FriendCount = FriendCount + 1 + end + end + end + end + + MainUI.Content.HomePage.HomePageContainer.InformationContainer.FriendsContainer.Friends.OnlineCount.Text = "Friends Online ".."["..FriendCount.."]" + + if FriendCount == 0 then + MainUI.Content.HomePage.HomePageContainer.InformationContainer.FriendsContainer.InviteFriends.Visible = true + end +end + +local function Init() + + UserInputService.InputChanged:Connect(function(input: InputObject, gameProcessedEvent: boolean): () + if input.UserInputType == Enum.UserInputType.MouseMovement then + CursorUpdate(MainUI.Cursor) + end + end) + + StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, false) + UserInputService.MouseIconEnabled = false + + MainUI.Content.HomePage.HomePageContainer.ProfileContainer.Container.Profile.WelcomeText.Text = "Hi, " .. Players.LocalPlayer.Name + + local ProfilePreviewCamera = Instance.new("Camera") + ProfilePreviewCamera.CFrame = CFrame.new(2.23306537, 260.73306465, 4.01013613, 0.896169126, -0.179960817, 0.405579776, -2.23517418e-008, 0.914059639, 0.405579746, -0.443712562, -0.363468051, 0.819152057) + ProfilePreviewCamera.Parent = MainUI.Content.HomePage.HomePageContainer.ProfileContainer.Container.Profile.AvatarPreview.ViewportFrame + + MainUI.Content.HomePage.HomePageContainer.ProfileContainer.Container.Profile.AvatarPreview.ViewportFrame.CurrentCamera = ProfilePreviewCamera + + --local dev + --local success, failed = pcall(function() + -- dev = LocalPlayer:GetRankInGroup(5201932) > 250 + --end) + + for i, v in pairs(Games) do + local NewContainer = Templates.Guis.GameContainer:Clone() + NewContainer.Parent = MainUI.Content.GamePage.GamePageContainer + NewContainer.Name = v["TeleportID"] + NewContainer.GameName.Text = tostring(i) + NewContainer.GameDescription.Text = v["Description"] + NewContainer.GameThumbnail.Image = v["GameIcon"] or "rbxassetid://11715077635" + NewContainer.GameId.Value = v["TeleportID"] + NewContainer.GameThumbnail.TimePeriod.Text = v["Period"] + --NewContainer.PreviewCameraCFrame.Value = v["PreviewCameraCFrame"] + + --Play button: + SetupButtonFeedback(NewContainer.PlayButton, { + ["HoverSize"] = UDim2.new(0, 102, 0, 102), + ["DownSize"] = UDim2.new(0, 84, 0, 84), + ["HoverRotation"] = 10, + ["FrameStyled"] = true, + }) + + --Play solo button: + SetupButtonFeedback(NewContainer.PlaySoloButton, { + ["HoverSize"] = UDim2.new(0, 72, 0, 72), + ["DownSize"] = UDim2.new(0, 58, 0, 58), + ["HoverRotation"] = 10, + ["FrameStyled"] = true, + }) + + if v["Type"] == "ROBLOX Game" then + NewContainer.GameName.TextColor3 = Color3.fromRGB(212, 0, 0) + NewContainer:SetAttribute("RobloxGame", true) + NewContainer.LayoutOrder = -999 + + NewContainer.PlayButton.UIGradient.Color = ColorSequence.new(Color3.fromRGB(196, 0, 0), Color3.fromRGB(240, 0, 0)) + --NewContainer.PlayButton.BackgroundColor3 = Color3.fromRGB(196, 0, 0) + NewContainer.PlayButton.UIStroke.Color = Color3.fromRGB(212, 0, 0) + + elseif v["Type"] == "Event Game" then + NewContainer.GameName.TextColor3 = Color3.fromRGB(232, 77, 0) + + NewContainer.PlayButton.UIGradient.Color = ColorSequence.new(Color3.fromRGB(232, 77, 0), Color3.fromRGB(255, 81, 0)) + --NewContainer.PlayButton.BackgroundColor3 = Color3.fromRGB(232, 77, 0) + NewContainer.PlayButton.UIStroke.Color = Color3.fromRGB(255, 85, 0) + + --NewContainer.PlayButton.UIStroke:Clone().Parent = NewContainer + + NewContainer.LayoutOrder = -99999 + --elseif v["Type"] == "Unlisted" then + -- NewContainer.Visible = false + + -- if dev then + -- NewContainer.GameName.Text = NewContainer.GameName.Text.." (Unlisted)" + -- NewContainer.Visible = true + -- end + end + end + + MainUI.Content.MenuBar.CurrentTime.Text = `{os.date("%A")}, {os.date("%B")} {os.date("%d"):match("0*(%d+)")}, {os.date("%Y")}` + MainUI.Content.MenuBar.LoggedInAs.Text = "Logged in as "..LocalPlayer.Name + + for _, v in pairs(MainUI.Content.MenuBar.ButtonList:GetChildren()) do + if v:IsA("TextButton") then + local OrigText = v.ButtonText.Text + local OrigColor = v.ButtonText.TextColor3 + + v.MouseButton1Click:Connect(function(): () + MenuBarButtonClick(v) + end) + + v.MouseButton1Down:Connect(function(x: number, y: number): () + TweenWrapper(v.ButtonText, {"Size"}, {UDim2.new(1, 0, 0.825, 0)}, .5, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + end) + + v.MouseButton1Up:Connect(function(x: number, y: number): () + TweenWrapper(v.ButtonText, {"Size"}, {UDim2.new(1, 0, 1, 0)}, .5, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + end) + + v.MouseEnter:Connect(function(x: number, y: number): () + v.ButtonText.Text = ""..OrigText.."" + v.ButtonText.TextColor3 = Color3.fromRGB(227, 242, 253) + TweenWrapper(v.ButtonText, {"Size"}, {UDim2.new(1, 0, 1.125, 0)}, .5, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + end) + + v.MouseLeave:Connect(function(x: number, y: number): () + v.ButtonText.Text = OrigText + v.ButtonText.TextColor3 = OrigColor + TweenWrapper(v.ButtonText, {"Size"}, {UDim2.new(1, 0, 1, 0)}, .5, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + end) + end + end + + local HasAdvanced = MainUI.Content.AvatarPage.CustomizationContainer:FindFirstChild("AdvancedCustomizationFrame") + + local PreviewCamera = Instance.new("Camera") + PreviewCamera.CFrame = CFrame.new(2.23306537, 4.73306465, 4.01013613, 0.896169126, -0.179960817, 0.405579776, -2.23517418e-008, 0.914059639, 0.405579746, -0.443712562, -0.363468051, 0.819152057) + PreviewCamera.Parent = MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview + + MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.CurrentCamera = PreviewCamera + + local CameraReplica = PreviewCamera:Clone() + CameraReplica.Parent = MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.AvatarPreviewShadow + MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.AvatarPreviewShadow.CurrentCamera = CameraReplica + + GetLocalPlayerAvatar:FireServer(2006) + if HasAdvanced then + local Transparency = MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer.ColorPalette.PropertyPalette.TransparencyInput.TextBox + local Reflectance = MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer.ColorPalette.PropertyPalette.TransparencyInput.TextBox + --GetLocalPlayerAvatar:FireServer(2006) + + MainUI.Content.AvatarPage.CustomizationContainer.AvatarSelectionFrame.Container.Size = UDim2.new(1, 0, 1, -32) + MainUI.Content.AvatarPage.CustomizationContainer.AvatarSelectionFrame.AdvancedCustomization.Visible = true + + MainUI.Content.AvatarPage.CustomizationContainer.AvatarSelectionFrame.AdvancedCustomization.MouseButton1Click:Connect(function(): () + TweenWrapper(MainUI.Content.AvatarPage.CustomizationContainer.AvatarSelectionFrame, {"Position"}, {UDim2.new(-1, 0, 0, 0)}, 1.25, Enum.EasingStyle.Elastic) + TweenWrapper(MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame, {"Position"}, {UDim2.new(0, 0, 0, 0)}, 1.25, Enum.EasingStyle.Elastic) + MainUI.Content.AvatarPage.Notice.Visible = false + MainUI.Content.AvatarPage.TypeOfAvatar.Text = "2007 Avatar" + + MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Animations.Value = true + --MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Preview.Animate.Disabled = false + GetLocalPlayerAvatar:FireServer(2007) + end) + + MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.BackButton.MouseButton1Click:Connect(function(): () + TweenWrapper(MainUI.Content.AvatarPage.CustomizationContainer.AvatarSelectionFrame, {"Position"}, {UDim2.new(0, 0, 0, 0)}, 1.25, Enum.EasingStyle.Elastic) + TweenWrapper(MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame, {"Position"}, {UDim2.new(1, 0, 0, 0)}, 1.25, Enum.EasingStyle.Elastic) + MainUI.Content.AvatarPage.Notice.Visible = true + MainUI.Content.AvatarPage.TypeOfAvatar.Text = "2006 Avatar" + + MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Animations.Value = false + --MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Preview.Animate.Disabled = true + GetLocalPlayerAvatar:FireServer(2006) + end) + + -- this next part is bad but it works + + --for i, v in pairs(MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.BodyColors:GetChildren()) do + -- if v:IsA("TextButton") then + -- v.MouseButton1Click:Connect(function() + -- SelectedBodyPart = v.Name + -- end) + -- end + --end + + for i, color in pairs(Customization["BrickColors"]) do + local NewColor = Templates.Guis.ColorContainer:Clone() + NewColor.ColorFrame.BackgroundColor3 = BrickColor.new(color).Color + + NewColor.Parent = MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer.ColorPalette.PageContainer + + --NewColor.TextButton.MouseButton1Click:Connect(function() + -- if SelectedBodyPart then + -- MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Size = UDim2.new(0, 0, 0, 0) + -- TweenWrapper(MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview, {"Size"}, {UDim2.new(1, 0, 1, 0)}, 1, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + + -- Protocols.ChangeAvatar:FireServer(nil, SelectedBodyPart, BrickColor.new(v.Color).Number) + -- end + --end) + + --local toggle = false + + SetupButtonFeedback(NewColor.ColorFrame, { + ["HoverSize"] = UDim2.new(1.1, 0, 1.1, 0), + ["DownSize"] = UDim2.new(0.9, 0, 0.9, 0), + ["FrameStyled"] = true, + }) + + NewColor.ColorFrame.TextButton.MouseButton1Click:Connect(function(): () + + for _, c in pairs(MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer.ColorPalette.PageContainer:GetChildren()) do + if c:IsA("Frame") and c.Name ~= "Stroke" then + c.ColorFrame.Stroke.UIStroke.Color = Color3.fromRGB(0, 0, 0) + c.ColorFrame.Stroke.UIStroke.Transparency = 0.95 + end + end + + SelectedColor = {color, tonumber(Transparency.Text), tonumber(Reflectance.Text)} + + NewColor.ColorFrame.Stroke.UIStroke.Color = Color3.fromRGB(0,255,0) + NewColor.ColorFrame.Stroke.UIStroke.Transparency = 0 + end) + end + + local Chips = MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.Chips + + --im crying idek if this will work LOL + Transparency:GetPropertyChangedSignal("Text"):Connect(function() + SelectedColor = {SelectedColor[1], tonumber(Transparency.Text), tonumber(Reflectance.Text)} + end) + + Reflectance:GetPropertyChangedSignal("Text"):Connect(function() + SelectedColor = {SelectedColor[1], tonumber(Transparency.Text), tonumber(Reflectance.Text)} + end) + + -- why am i like this + + --[[ + I thought you was conflicted, + Misusing your influence. + Sometimes I did the same. + Abusing my power full of resentment. + Resentment that turned into a deep depression. + Found myself screaming in the hotel room. + ]] + + for _, v in pairs(Chips:GetChildren()) do + if v:IsA("Frame") then + v.Button.MouseButton1Click:Connect(function() + SoundService:PlayLocalSound(SoundService.Tap) + + for _, category in pairs(MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer:GetChildren()) do + if category:IsA("Frame") and category.Name ~= "Stroke" then + category.Visible = false + end + end + + if MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer:FindFirstChild(v.Name) then + MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer:FindFirstChild(v.Name).Position = UDim2.new(1, 0, 0, 0) + MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer:FindFirstChild(v.Name).Visible = true + + + MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer:FindFirstChild(v.Name):TweenPosition(UDim2.new(0, 0, 0, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Elastic, 1, true) + end + + for _, button in pairs(Chips:GetChildren()) do + if button:IsA("Frame") then + if button.Name == v.Name then + button.Label.FontFace = Font.new("rbxasset://fonts/families/GothamSSm.json", Enum.FontWeight.Bold) + + button.Stroke:TweenPosition(UDim2.new(0.5, 0, 0.5, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, .05, true) + button.Label:TweenPosition(UDim2.new(0, 0, 0, -4), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, .05, true) + else + button.Label.FontFace = Font.new("rbxasset://fonts/families/GothamSSm.json", Enum.FontWeight.Medium) + + button.Stroke:TweenPosition(UDim2.new(0.5, 0, 0.5, 4), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, .05, true) + button.Label:TweenPosition(UDim2.new(0, 0, 0, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, .05, true) + end + end + end + end) + end + end + + local ignore = {} + + for _, v in pairs(MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Preview:GetDescendants()) do + if v.Name == "Highlight" then + table.insert(ignore, v) + end + end + + for _, v in pairs(MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.AvatarPreviewShadow:GetDescendants()) do + if v:IsA("BasePart") then + table.insert(ignore, v) + end + end + + local Mouse = Raycast.new(Mouse, MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview, PreviewCamera) + local Advanced = MainUI.Content.AvatarPage + + UserInputService.InputBegan:Connect(function(input: InputObject, gameProcessedEvent: boolean): () + if not gameProcessedEvent then + if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch or input.KeyCode == Enum.KeyCode.ButtonA then + local Part, Pos = Mouse.MouseHit(ignore) + + if Part and Advanced.Visible == true and SelectedColor then + Protocols.ChangeAvatar:FireServer(nil, Part.Name, SelectedColor[1], 2007) + SoundService:PlayLocalSound(SoundService.Splat) + end + end + end + end) + + UserInputService.InputChanged:Connect(function(input: InputObject, gameProcessedEvent: boolean): () + if not gameProcessedEvent then + if input.UserInputType == Enum.UserInputType.MouseMovement then + local Part, Pos = Mouse.MouseHit(ignore) + + + if Advanced.Visible == true and SelectedColor then + if Part then + print(Part) + AvatarHighlight(Part) + IdleCursorTexture = "rbxassetid://12198344754" + else + AvatarHighlight(nil) + IdleCursorTexture = "rbxassetid://6271122911" + end + end + end + end + end) + + for ind, information in pairs(Customization["TShirts"]) do + local id = information[1] + local isvisible = information[2] + local name = information[3] or id + + if (not isvisible) then + continue + end + + AwardItem("TShirt", id, name, ind) + + --local NewShirt = Templates.Guis.TShirt:Clone() + --NewShirt.Shirt.Image = "rbxassetid://"..tostring(id) + + --NewShirt.Parent = MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer.TShirts.PageContainer + + --NewShirt.Shirt.MouseButton1Click:Connect(function(): () + -- local Subbed = string.gsub(NewShirt.Shirt.Image, "rbxassetid://", "") + + -- MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Size = UDim2.new(0, 0, 0, 0) + -- TweenWrapper(MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview, {"Size"}, {UDim2.new(1, 0, 1, 0)}, 1, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + + -- Protocols.ChangeAvatar:FireServer(nil, "TShirt", tonumber(Subbed)) + --end) + end + + for ind, information in pairs(Customization["Faces"]) do + local id = information[1] + local isvisible = information[2] + + if (not isvisible) then + continue + end + + AwardItem("Face", id, "", ind) + + --local NewFace = Templates.Guis.TShirt:Clone() + --NewFace.Shirt.Image = "rbxassetid://"..tostring(id) + + --NewFace.Parent = MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer.Faces.PageContainer + + --NewFace.Shirt.MouseButton1Click:Connect(function(): () + -- local Subbed = string.gsub(NewFace.Shirt.Image, "rbxassetid://", "") + + -- MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview.Size = UDim2.new(0, 0, 0, 0) + -- TweenWrapper(MainUI.Content.AvatarPage.AvatarPreviewContainer.AvatarPreview, {"Size"}, {UDim2.new(1, 0, 1, 0)}, 1, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out) + + -- Protocols.ChangeAvatar:FireServer(nil, "Face", tonumber(Subbed)) + --end) + end + else + MainUI.Content.AvatarPage.CustomizationContainer.AvatarSelectionFrame.AdvancedCustomization:Destroy() + end + + for _, v in pairs(MainUI.Content.AvatarPage.CustomizationContainer.AvatarSelectionFrame.Container:GetDescendants()) do + if v:IsA("ImageButton") then + SetupButtonFeedback(v, { + ["HoverSize"] = UDim2.new(1.025, 0, 1.025, 0), + ["DownSize"] = UDim2.new(0.95, 0, 0.95, 0), + ["BackgroundTransparency"] = 0.95, + ["BackgroundTransparencyDown"] = 0.85, + ["FrameStyled"] = false, + }) + + v.MouseButton1Click:Connect(function() + AvatarButtonClick(v) + end) + end + end + + PreviewUpdate(CameraAngles["HomePage"], "HomePage") + + --local GlobalStatsButton = MainUI.Content.HomePage.HomePageContainer.StatsContainer.Stats.StatsInfoContainer.GlobalStatsButton.TextButton + + --SetupButtonFeedback(GlobalStatsButton, { + -- ["HoverSize"] = UDim2.new(1.025, 0, 1.025, 0), + -- ["DownSize"] = UDim2.new(0.975, 0, 0.975, 0), + -- ["FrameStyled"] = false, + --}) + + --GlobalStatsButton.MouseButton1Click:Connect(function(): () + -- SoundService:PlayLocalSound(SoundService.Tap) + --end) + + for _, v in pairs(MainUI.Content.SettingsPage.SettingsPageContainer.GraphicsCategoryContainer.Settings.Scroll:GetChildren()) do + if v.Name == "Setting" then + SetupButtonFeedback(v.CheckContainer.Check, { + ["HoverSize"] = UDim2.new(1.1, 0, 1.1, 0), + ["DownSize"] = UDim2.new(0.9, 0, 0.9, 0), + ["FrameStyled"] = false, + }) + + v.CheckContainer.Check.MouseButton1Click:Connect(function(): () + local Changing = v:GetAttribute("Setting") + + v.CheckContainer.Check.ImageLabel.Visible = not v.CheckContainer.Check.ImageLabel.Visible + + if v.CheckContainer.Check.ImageLabel.Visible then + SoundService:PlayLocalSound(SoundService.Check) + else + SoundService:PlayLocalSound(SoundService.Uncheck) + end + + SettingsChanger:FireServer(Changing, v.CheckContainer.Check.ImageLabel.Visible) + end) + end + end + + for _, v in pairs(MainUI.Content.SettingsPage.SettingsPageContainer.MiscCategoryContainer.Settings.Scroll:GetChildren()) do + if v.Name == "Setting" then + SetupButtonFeedback(v.CheckContainer.Check, { + ["HoverSize"] = UDim2.new(1.1, 0, 1.1, 0), + ["DownSize"] = UDim2.new(0.9, 0, 0.9, 0), + ["FrameStyled"] = false, + }) + + v.CheckContainer.Check.MouseButton1Click:Connect(function(): () + local Changing = v:GetAttribute("Setting") + + v.CheckContainer.Check.ImageLabel.Visible = not v.CheckContainer.Check.ImageLabel.Visible + + if v.CheckContainer.Check.ImageLabel.Visible then + SoundService:PlayLocalSound(SoundService.Check) + else + SoundService:PlayLocalSound(SoundService.Uncheck) + end + + SettingsChanger:FireServer(Changing, v.CheckContainer.Check.ImageLabel.Visible) + end) + elseif v.Name == "CameraLerp" then + local Changing = v:GetAttribute("Setting") + + v.CheckContainer.TextBox.FocusLost:Connect(function(): () + local NewValue = tonumber(v.CheckContainer.TextBox.Text) + + if NewValue then + local Clamped = math.clamp(NewValue, 0.1, 1) + SettingsChanger:FireServer(Changing, tonumber(Clamped)) + v.CheckContainer.TextBox.Text = Clamped + end + end) + end + end + + for _, v in pairs(MainUI.Content.SettingsPage.SettingsPageContainer.PlayersCategoryContainer.Settings.Scroll:GetChildren()) do + if v.Name == "Setting" then + SetupButtonFeedback(v.CheckContainer.Check, { + ["HoverSize"] = UDim2.new(1.1, 0, 1.1, 0), + ["DownSize"] = UDim2.new(0.9, 0, 0.9, 0), + ["FrameStyled"] = false, + }) + + v.CheckContainer.Check.MouseButton1Click:Connect(function(): () + local Changing = v:GetAttribute("Setting") + + v.CheckContainer.Check.ImageLabel.Visible = not v.CheckContainer.Check.ImageLabel.Visible + + if v.CheckContainer.Check.ImageLabel.Visible then + SoundService:PlayLocalSound(SoundService.Check) + else + SoundService:PlayLocalSound(SoundService.Uncheck) + end + + SettingsChanger:FireServer(Changing, v.CheckContainer.Check.ImageLabel.Visible) + end) + end + end + + --Search bar + MainUI.Content.GamePage.SearchBar:GetPropertyChangedSignal("Text"):Connect(function() + local SearchLower = string.lower(MainUI.Content.GamePage.SearchBar.Text) + + for _, v in pairs(MainUI.Content.GamePage.GamePageContainer:GetChildren()) do + if v:IsA("Frame") then + local GameName = v.GameName.Text + if SearchLower == "" or string.find(string.lower(GameName), SearchLower) ~= nil then + v.Visible = true + else + v.Visible = false + end + end + end + end) + + --Search bar part 2 + local shirtSearch = MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer.TShirts.SearchBar + shirtSearch:GetPropertyChangedSignal("Text"):Connect(function() + local SearchLower = string.lower(shirtSearch.Text) + + for _, v in pairs(MainUI.Content.AvatarPage.CustomizationContainer.AdvancedCustomizationFrame.Container.CategoryContainer.TShirts.PageContainer:GetChildren()) do + if v:IsA("Frame") then + + local GameName = v.Name + if SearchLower == "" or string.find(string.lower(GameName), SearchLower) ~= nil then + v.Visible = true + else + v.Visible = false + end + end + end + end) + + MainUI.Content.GamePage.SearchBar.FocusLost:Connect(function(enterPressed) + if enterPressed then + local SearchLower = string.lower(MainUI.Content.GamePage.SearchBar.Text) + + if SearchLower == "i love fwm" then + SoundService:PlayLocalSound(SoundService.Boing) + + MainUI.KeyboardCombination.Size = UDim2.new(0, 0, 0, 0) + MainUI.KeyboardCombination.Visible = true + + TweenWrapper(MainUI.KeyboardCombination, {"Size"}, {UDim2.new(1, 0, 1, 0)}, 1, Enum.EasingStyle.Elastic) + + + TweenWrapper(MainUI.KeyboardCombination, {"ImageTransparency"}, {0}, 0.25) + + TweenWrapper(MainUI.KeyboardCombination.TextLabel, {"TextTransparency"}, {0}, 0.25) + TweenWrapper(MainUI.KeyboardCombination.TextLabel, {"TextTransparency"}, {0}, 0.25) + TweenWrapper(MainUI.KeyboardCombination.TextLabel, {"TextStrokeTransparency"}, {0}, 0.25) + TweenWrapper(MainUI.KeyboardCombination.TextLabel, {"TextStrokeTransparency"}, {0}, 0.25) + + TweenWrapper(MainUI.KeyboardCombination.TextLabel2, {"TextTransparency"}, {0}, 0.25) + TweenWrapper(MainUI.KeyboardCombination.TextLabel2, {"TextTransparency"}, {0}, 0.25) + TweenWrapper(MainUI.KeyboardCombination.TextLabel2, {"TextStrokeTransparency"}, {0}, 0.25) + TweenWrapper(MainUI.KeyboardCombination.TextLabel2, {"TextStrokeTransparency"}, {0}, 0.25) + + task.wait(4) + TweenWrapper(MainUI.KeyboardCombination, {"ImageTransparency"}, {1}, 0.25) + + TweenWrapper(MainUI.KeyboardCombination.TextLabel, {"TextTransparency"}, {1}, 0.25) + TweenWrapper(MainUI.KeyboardCombination.TextLabel, {"TextTransparency"}, {1}, 0.25) + TweenWrapper(MainUI.KeyboardCombination.TextLabel, {"TextStrokeTransparency"}, {1}, 0.25) + TweenWrapper(MainUI.KeyboardCombination.TextLabel, {"TextStrokeTransparency"}, {1}, 0.25) + + TweenWrapper(MainUI.KeyboardCombination.TextLabel2, {"TextTransparency"}, {1}, 0.25) + TweenWrapper(MainUI.KeyboardCombination.TextLabel2, {"TextTransparency"}, {1}, 0.25) + TweenWrapper(MainUI.KeyboardCombination.TextLabel2, {"TextStrokeTransparency"}, {1}, 0.25) + TweenWrapper(MainUI.KeyboardCombination.TextLabel2, {"TextStrokeTransparency"}, {1}, 0.25) + + task.wait(1) + MainUI.KeyboardCombination.Visible = false + end + end + end) + + local NewsPage = MainUI.Content.NewsPage + local Reader = NewsPage.Reader + local BeforeSize = Reader.Container.Size + + --Blog population: + for _, v in pairs(Blog) do + local Post = Templates:WaitForChild("Guis"):WaitForChild("Post"):Clone() + Post.TextButton.Title.Text = v["Title"] + Post.TextButton.Description.Text = v["Content"] + Post.TextButton.Date.Text = os.date("%x", v["Date"]) + Post.TextButton.ImageLabel.Image = v["HeaderImage"] + Post.LayoutOrder = -v["Date"] + + SetupButtonFeedback(Post.TextButton, { + ["HoverSize"] = UDim2.new(1.01, 0, 1.01, 0), + ["DownSize"] = UDim2.new(0.99, 0, 0.99, 0), + ["FrameStyled"] = false + }) + + Post.TextButton.MouseButton1Click:Connect(function() + NewsPage.List.Visible = false + + -- jesus forgive my sins for this string formatting in jesus name amen + Reader.Container.Content.Title.Text = v["Title"] + Reader.Container.Content.Date.Text = `Published {os.date("%B", v["Date"])} {os.date("%d", v["Date"])}, {os.date("%Y", v["Date"])} @ {os.date("%I", v["Date"])}:{os.date("%M", v["Date"])} {string.upper(os.date("%p", v["Date"]))}` + Reader.Container.Content.HeaderImage.Image = v["HeaderImage"] + Reader.Container.Content.Text.Text = v["Content"] + Reader.Container.Size = UDim2.new(BeforeSize.X.Scale, 0, BeforeSize.Y.Scale, #v["Content"] / 2) + + Reader.Visible = true + end) + + Post.Parent = NewsPage.List + end + + SetupButtonFeedback(Reader.Container.Exit.ImageButton, { + ["HoverSize"] = UDim2.new(1.1, 0, 1.1, 0), + ["DownSize"] = UDim2.new(0.9, 0, 0.9, 0), + ["FrameStyled"] = false + }) + + Reader.Container.Exit.ImageButton.MouseButton1Click:Connect(function() + Reader.Visible = false + NewsPage.List.Visible = true + end) + + --Music: + local sound = workspace:FindFirstChildOfClass("Sound") + + MainUI.MusicPlayer.SongName.Text = workspace:FindFirstChildOfClass("Sound").Name + + sound:GetPropertyChangedSignal("Name"):Connect(function(): () + MainUI.MusicPlayer.SongName.Text = sound.Name + end) + + MainUI.MusicPlayer.ToggleContainer.Toggle.MouseButton1Click:Connect(function(): () + NewToggle(sound) + SettingsChanger:FireServer("LobbyMusic", toggle) + end) + + SetupButtonFeedback(MainUI.MusicPlayer.ToggleContainer.Toggle, { + ["HoverSize"] = UDim2.new(1.1, 0, 1.1, 0), + ["DownSize"] = UDim2.new(0.9, 0, 0.9, 0), + ["FrameStyled"] = false + }) + + --Setup visualizer + + for i = 1, 32 do + local Step = Instance.new("Frame") + Step.BackgroundColor3 = Color3.fromRGB(124, 155, 237) + Step.BorderSizePixel = 0 + Step.Size = UDim2.new(0, 32, 0, 0) + + Step.Name = `Step{i}` + + Step.Parent = MainUI.MusicPlayer.Visualizer + end + + Protocols.ReturnPlace.OnClientEvent:Connect(Loading) + Protocols.ReturnAvatar.OnClientEvent:Connect(AvatarReturned) + Protocols.ReturnSettings.OnClientEvent:Connect(SettingsReturned) + Protocols.ReturnStats.OnClientEvent:Connect(StatsReturned) + Protocols.ReturnPlayerCount.OnClientEvent:Connect(UpdatePlayerCount) + Protocols.ReturnBadgeInfo.OnClientEvent:Connect(ReturnedBadgeInfo) + Protocols.UpdatePointsLeaderboard.OnClientEvent:Connect(UpdatePointsLeaderboard) + ItemAwarded.OnClientEvent:Connect(AwardItem) + + TweenWrapper(MainUI.Loading.LoadingContainer.LoadingBar.Fill, {"Position"}, {UDim2.new(1, 0, 0, 0)}, 1, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut, math.huge, true) +end + +Init() + +MainUI.Loading:GetPropertyChangedSignal("Visible"):Connect(function(): () + SoundService.Loading.Playing = MainUI.Loading.Visible +end) + +UpdateFriendsList() + +while task.wait(120) do + UpdateFriendsList() +end \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterGui/MainUI/init.meta.json b/rojo/MainMenu/src/StarterGui/MainUI/init.meta.json new file mode 100644 index 0000000..118e2ca --- /dev/null +++ b/rojo/MainMenu/src/StarterGui/MainUI/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ScreenGui", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterPack/RocketLauncher/Client.client.lua b/rojo/MainMenu/src/StarterPack/RocketLauncher/Client.client.lua new file mode 100644 index 0000000..c0ee99d --- /dev/null +++ b/rojo/MainMenu/src/StarterPack/RocketLauncher/Client.client.lua @@ -0,0 +1,9 @@ +local Tool = script.Parent + +local Remote = Tool:WaitForChild("MouseLoc") + +local Mouse = game.Players.LocalPlayer:GetMouse() + +function Remote.OnClientInvoke() + return Mouse.Hit.p +end \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterPack/RocketLauncher/MouseIcon.client.lua b/rojo/MainMenu/src/StarterPack/RocketLauncher/MouseIcon.client.lua new file mode 100644 index 0000000..60a3f77 --- /dev/null +++ b/rojo/MainMenu/src/StarterPack/RocketLauncher/MouseIcon.client.lua @@ -0,0 +1,26 @@ +local MOUSE_ICON = 'rbxasset://textures/GunCursor.png' +local RELOADING_ICON = 'rbxasset://textures/GunWaitCursor.png' + +local Tool = script.Parent + +local Mouse = nil + +local function UpdateIcon() + if Mouse then + Mouse.Icon = Tool.Enabled and MOUSE_ICON or RELOADING_ICON + end +end + +local function OnEquipped(mouse) + Mouse = mouse + UpdateIcon() +end + +local function OnChanged(property) + if property == 'Enabled' then + UpdateIcon() + end +end + +Tool.Equipped:Connect(OnEquipped) +Tool.Changed:Connect(OnChanged) diff --git a/rojo/MainMenu/src/StarterPack/RocketLauncher/Server/Rocket.server.lua b/rojo/MainMenu/src/StarterPack/RocketLauncher/Server/Rocket.server.lua new file mode 100644 index 0000000..589fcd6 --- /dev/null +++ b/rojo/MainMenu/src/StarterPack/RocketLauncher/Server/Rocket.server.lua @@ -0,0 +1,154 @@ +----------------- +--| Constants |-- +----------------- + +local BLAST_RADIUS = 8 -- Blast radius of the explosion +local BLAST_DAMAGE = 60 -- Amount of damage done to players +local BLAST_FORCE = 1000 -- Amount of force applied to parts + +local IGNORE_LIST = {rocket = 1, handle = 1, effect = 1, water = 1} -- Rocket will fly through things named these +--NOTE: Keys must be lowercase, values must evaluate to true + +----------------- +--| Variables |-- +----------------- + +local DebrisService = game:GetService('Debris') +local PlayersService = game:GetService('Players') + +local Rocket = script.Parent + +local CreatorTag = Rocket:WaitForChild('creator') +local SwooshSound = Rocket:WaitForChild('Swoosh') + +----------------- +--| Functions |-- +----------------- + +-- Removes any old creator tags and applies a new one to the target +local function ApplyTags(target) + while target:FindFirstChild('creator') do + target.creator:Destroy() + end + + local creatorTagClone = CreatorTag:Clone() + DebrisService:AddItem(creatorTagClone, 1.5) + creatorTagClone.Parent = target +end + +-- Returns the ancestor that contains a Humanoid, if it exists +local function FindCharacterAncestor(subject) + if subject and subject ~= workspace then + local humanoid = subject:FindFirstChildOfClass('Humanoid') + if humanoid then + return subject, humanoid + else + return FindCharacterAncestor(subject.Parent) + end + end + return nil +end + +local function IsInTable(Table,Value) + for _,v in pairs(Table) do + if v == Value then + return true + end + end + return false +end + +-- Customized explosive effect that doesn't affect teammates and only breaks joints on dead parts +local TaggedHumanoids = {} +local function OnExplosionHit(hitPart, hitDistance, blastCenter) + if hitPart and hitDistance then + local character, humanoid = FindCharacterAncestor(hitPart.Parent) + + if character then + local myPlayer = CreatorTag.Value + if myPlayer and not myPlayer.Neutral then -- Ignore friendlies caught in the blast + local player = PlayersService:GetPlayerFromCharacter(character) + if player and player ~= myPlayer and player.TeamColor == Rocket.BrickColor then + return + end + end + end + + if humanoid and humanoid.Health > 0 then -- Humanoids are tagged and damaged + if not IsInTable(TaggedHumanoids,humanoid) then + print("Tagged") + table.insert(TaggedHumanoids,humanoid) + ApplyTags(humanoid) + humanoid:TakeDamage(BLAST_DAMAGE) + end + else -- Loose parts and dead parts are blasted + if hitPart.Name ~= 'Handle' then + hitPart:BreakJoints() + local blastForce = Instance.new('BodyForce', hitPart) --NOTE: We will multiply by mass so bigger parts get blasted more + blastForce.Force = (hitPart.Position - blastCenter).unit * BLAST_FORCE * hitPart:GetMass() + DebrisService:AddItem(blastForce, 0.1) + end + end + end +end + +local function OnTouched(otherPart) + if Rocket and otherPart then + -- Fly through anything in the ignore list + if IGNORE_LIST[string.lower(otherPart.Name)] then + return + end + + local myPlayer = CreatorTag.Value + if myPlayer then + -- Fly through the creator + if myPlayer.Character and myPlayer.Character:IsAncestorOf(otherPart) then + return + end + + -- Fly through friendlies + if not myPlayer.Neutral then + local character = FindCharacterAncestor(otherPart.Parent) + local player = PlayersService:GetPlayerFromCharacter(character) + if player and player ~= myPlayer and player.TeamColor == Rocket.BrickColor then + return + end + end + end + + -- Fly through terrain water + if otherPart == workspace.Terrain then + --NOTE: If the rocket is large, then the simplifications made here will cause it to fly through terrain in some cases + local frontOfRocket = Rocket.Position + (Rocket.CFrame.lookVector * (Rocket.Size.Z / 2)) + local cellLocation = workspace.Terrain:WorldToCellPreferSolid(frontOfRocket) + local cellMaterial = workspace.Terrain:GetCell(cellLocation.X, cellLocation.Y, cellLocation.Z) + if cellMaterial == Enum.CellMaterial.Water or cellMaterial == Enum.CellMaterial.Empty then + return + end + end + + -- Create the explosion + local explosion = Instance.new('Explosion') + explosion.BlastPressure = 0 -- Completely safe explosion + explosion.BlastRadius = BLAST_RADIUS + explosion.ExplosionType = Enum.ExplosionType.NoCraters + explosion.Position = Rocket.Position + explosion.Parent = workspace + + -- Connect custom logic for the explosion + explosion.Hit:Connect(function(hitPart, hitDistance) OnExplosionHit(hitPart, hitDistance, explosion.Position) end) + + -- Move this script and the creator tag (so our custom logic can execute), then destroy the rocket + script.Parent = explosion + CreatorTag.Parent = script + Rocket:Destroy() + end +end + +-------------------- +--| Script Logic |-- +-------------------- + +SwooshSound:Play() + +Rocket.Touched:Connect(OnTouched) diff --git a/rojo/MainMenu/src/StarterPack/RocketLauncher/Server/init.meta.json b/rojo/MainMenu/src/StarterPack/RocketLauncher/Server/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainMenu/src/StarterPack/RocketLauncher/Server/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterPack/RocketLauncher/Server/init.server.lua b/rojo/MainMenu/src/StarterPack/RocketLauncher/Server/init.server.lua new file mode 100644 index 0000000..977975f --- /dev/null +++ b/rojo/MainMenu/src/StarterPack/RocketLauncher/Server/init.server.lua @@ -0,0 +1,112 @@ +----------------- +--| Constants |-- +----------------- + +local GRAVITY_ACCELERATION = workspace.Gravity + +local RELOAD_TIME = 3 -- Seconds until tool can be used again +local ROCKET_SPEED = 60 -- Speed of the projectile + +local MISSILE_MESH_ID = 'http://www.roblox.com/asset/?id=2251534' +local MISSILE_MESH_SCALE = Vector3.new(0.35, 0.35, 0.25) +local ROCKET_PART_SIZE = Vector3.new(1.2, 1.2, 3.27) + +----------------- +--| Variables |-- +----------------- + +local DebrisService = game:GetService('Debris') +local PlayersService = game:GetService('Players') + +local MyPlayer + +local Tool = script.Parent +local ToolHandle = Tool:WaitForChild("Handle") + +local MouseLoc = Tool:WaitForChild("MouseLoc",10) + +local RocketScript = script:WaitForChild('Rocket') +local SwooshSound = script:WaitForChild('Swoosh') +local BoomSound = script:WaitForChild('Boom') + +--NOTE: We create the rocket once and then clone it when the player fires +local Rocket = Instance.new('Part') do + -- Set up the rocket part + Rocket.Name = 'Rocket' + Rocket.FormFactor = Enum.FormFactor.Custom --NOTE: This must be done before changing Size + Rocket.Size = ROCKET_PART_SIZE + Rocket.CanCollide = false + + -- Add the mesh + local mesh = Instance.new('SpecialMesh', Rocket) + mesh.MeshId = MISSILE_MESH_ID + mesh.Scale = MISSILE_MESH_SCALE + + -- Add fire + local fire = Instance.new('Fire', Rocket) + fire.Heat = 5 + fire.Size = 2 + + -- Add a force to counteract gravity + local bodyForce = Instance.new('BodyForce', Rocket) + bodyForce.Name = 'Antigravity' + bodyForce.Force = Vector3.new(0, Rocket:GetMass() * GRAVITY_ACCELERATION, 0) + + -- Clone the sounds and set Boom to PlayOnRemove + local swooshSoundClone = SwooshSound:Clone() + swooshSoundClone.Parent = Rocket + local boomSoundClone = BoomSound:Clone() + boomSoundClone.PlayOnRemove = true + boomSoundClone.Parent = Rocket + + -- Attach creator tags to the rocket early on + local creatorTag = Instance.new('ObjectValue', Rocket) + creatorTag.Value = MyPlayer + creatorTag.Name = 'creator' --NOTE: Must be called 'creator' for website stats + local iconTag = Instance.new('StringValue', creatorTag) + iconTag.Value = Tool.TextureId + iconTag.Name = 'icon' + + -- Finally, clone the rocket script and enable it + local rocketScriptClone = RocketScript:Clone() + rocketScriptClone.Parent = Rocket + rocketScriptClone.Disabled = false +end + +----------------- +--| Functions |-- +----------------- + +local function OnActivated() + local myModel = MyPlayer.Character + if Tool.Enabled and myModel and myModel:FindFirstChildOfClass("Humanoid") and myModel.Humanoid.Health > 0 then + Tool.Enabled = false + local Pos = MouseLoc:InvokeClient(MyPlayer) + -- Create a clone of Rocket and set its color + local rocketClone = Rocket:Clone() + DebrisService:AddItem(rocketClone, 30) + rocketClone.BrickColor = MyPlayer.TeamColor + + -- Position the rocket clone and launch! + local spawnPosition = (ToolHandle.CFrame * CFrame.new(5, 0, 0)).p + rocketClone.CFrame = CFrame.new(spawnPosition, Pos) --NOTE: This must be done before assigning Parent + rocketClone.Velocity = rocketClone.CFrame.lookVector * ROCKET_SPEED --NOTE: This should be done before assigning Parent + rocketClone.Parent = workspace + rocketClone:SetNetworkOwner(nil) + + wait(RELOAD_TIME) + + Tool.Enabled = true + end +end + +function OnEquipped() + MyPlayer = PlayersService:GetPlayerFromCharacter(Tool.Parent) +end + +-------------------- +--| Script Logic |-- +-------------------- + +Tool.Equipped:Connect(OnEquipped) +Tool.Activated:Connect(OnActivated) diff --git a/rojo/MainMenu/src/StarterPack/RocketLauncher/init.meta.json b/rojo/MainMenu/src/StarterPack/RocketLauncher/init.meta.json new file mode 100644 index 0000000..babcc53 --- /dev/null +++ b/rojo/MainMenu/src/StarterPack/RocketLauncher/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Tool", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterPlayer/StarterPlayerScripts/CameraHandler.client.lua b/rojo/MainMenu/src/StarterPlayer/StarterPlayerScripts/CameraHandler.client.lua new file mode 100644 index 0000000..af4296f --- /dev/null +++ b/rojo/MainMenu/src/StarterPlayer/StarterPlayerScripts/CameraHandler.client.lua @@ -0,0 +1,30 @@ +--!strict +--[[ + KeyboardCombination 2022 + + Handle camera manipulation. +]] +local RunService: RunService = game:GetService("RunService") + +local camera = workspace.CurrentCamera +local xSeed: number = math.random(10000, 100000) +local ySeed: number = math.random(10000, 100000) +local zSeed: number = math.random(10000, 100000) +local roughness: number = 4 + +local function initialize(): () + camera.CameraType = Enum.CameraType.Scriptable + camera.CFrame = workspace.CamRef.CFrame +end + +local function update(deltaTime: number): () + local x = math.noise(xSeed, os.clock() % 1000 * 0.5) * roughness + local y = math.noise(ySeed, os.clock() % 1000 * 0.5) * roughness + local z = math.noise(zSeed, os.clock() % 1000 * 0.5) * roughness + + camera.CFrame = workspace.CamRef.CFrame * CFrame.new(0, math.sin(tick()) * 4, 0) * CFrame.Angles(math.rad(x), math.rad(y), math.rad(z)) +end + +initialize() + +RunService.RenderStepped:Connect(update) \ No newline at end of file diff --git a/rojo/MainMenu/src/StarterPlayer/StarterPlayerScripts/LegacyVisualsClient.client.lua b/rojo/MainMenu/src/StarterPlayer/StarterPlayerScripts/LegacyVisualsClient.client.lua new file mode 100644 index 0000000..3dab2a1 --- /dev/null +++ b/rojo/MainMenu/src/StarterPlayer/StarterPlayerScripts/LegacyVisualsClient.client.lua @@ -0,0 +1,400 @@ +--!strict +--[[ + Classic Roblox Clothes! 2022 + + Handles stuff related to Visuals on the client side -- Roblox_Gamer2030 +]] +local Lighting = game:GetService("Lighting") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local RunService = game:GetService("RunService") + +local Templates = ReplicatedStorage:WaitForChild("Templates") + +type LensFlareConfiguration = { + scale: number, + texture: string, + transparency: number, +} + +type Lense = { + attachment0: Attachment?, + attachment1: Attachment?, + beam: Beam?, + distance: number, + color: Color3, + radius: number, +} + +local BODY_PART_NAMES: {string} = { + "Left Arm", + "Left Leg", + "Right Arm", + "Right Leg", + "Torso", +} +local PART_SIDES: { [string] : Enum.NormalId } = { + ["TopSurface"] = Enum.NormalId.Top, + ["BottomSurface"] = Enum.NormalId.Bottom, + ["LeftSurface"] = Enum.NormalId.Left, + ["RightSurface"] = Enum.NormalId.Right, + ["FrontSurface"] = Enum.NormalId.Front, + ["BackSurface"] = Enum.NormalId.Back +} + +local surfacesToTextures = { + [Enum.SurfaceType.Glue] = Templates.Textures.Surfaces.Glue, + [Enum.SurfaceType.Inlet] = Templates.Textures.Surfaces.Inlet, + [Enum.SurfaceType.Studs] = Templates.Textures.Surfaces.Studs, + [Enum.SurfaceType.Weld] = Templates.Textures.Surfaces.Weld, + -- [Enum.SurfaceType.Smooth] = Templates.Textures.Surfaces.Smooth, + -- [Enum.SurfaceType.Motor] = Templates.Textures.Surfaces.Smooth, + -- [Enum.SurfaceType.Hinge] = Templates.Textures.Surfaces.Smooth, +} + +local lensFlareNode: Part = Instance.new("Part") +lensFlareNode.Name = "LensFlareNode" +lensFlareNode.Anchored = true +lensFlareNode.CanCollide = false +lensFlareNode.CanQuery = false +lensFlareNode.CanTouch = false +lensFlareNode.Locked = true +lensFlareNode.Transparency = 1 +lensFlareNode.Parent = workspace.CurrentCamera + +local moonHolder: Part? + +local lensFlareConfiguration: LensFlareConfiguration = { + scale = 1 / 8; + texture = "rbxasset://textures/whiteCircle.png"; + transparency = 0.9; +} + +local LENSES: {Lense} = +{ + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB(200, 255, 200), + distance = 0.000, + radius = 1.00, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB( 0, 255, 0), + distance = 0.200, + radius = 0.50, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB(255, 0, 0), + distance = 0.225, + radius = 0.30, + }; + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB(255, 170, 0), + distance = 0.250, + radius = 1.50, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB(255, 170, 0), + distance = 0.250, + radius = 3.00, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB( 0, 255, 0), + distance = 0.300, + radius = 0.50, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB( 0, 255, 0), + distance = 0.600, + radius = 0.20, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB( 0, 255, 0), + distance = 0.650, + radius = 0.40, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB(255, 0, 0), + distance = 0.780, + radius = 0.20, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB( 0, 255, 0), + distance = 0.900, + radius = 0.25, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB( 63, 63, 63), + distance = 1.200, + radius = 0.15, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB( 63, 63, 63), + distance = 1.500, + radius = 0.15, + }, +} + +local function asVector2(vector3: Vector3, ...): (Vector2, any) + -- Roblox likes to kill my OCD. + return Vector2.new(vector3.X, vector3.Y), ... +end + +local function isSunOccluded(sunDir: Vector3): () + local origin = workspace.CurrentCamera.CFrame.Position + (workspace.CurrentCamera.CFrame.LookVector * 2) + local ray = Ray.new(origin,origin + (sunDir * 10e6)) + local ignore = {} + local occluded = false + while true do + local hit,pos = workspace:FindPartOnRayWithIgnoreList(ray,ignore) + if hit then + local t = hit.Transparency + hit.LocalTransparencyModifier + if t <= 0 then + occluded = true + break + else + table.insert(ignore,hit) + end + else + break + end + end + return occluded +end + +local function createLenseBeam(lense: Lense, id: number): Beam + local radius: number = lense.radius * lensFlareConfiguration.scale + + local attachment0: Attachment = Instance.new("Attachment") + attachment0.Name = id .. "_A0" + attachment0.Parent = lensFlareNode + lense.attachment0 = attachment0 + + local attachment1: Attachment = Instance.new("Attachment") + attachment1.Name = id .. "_A1" + attachment1.Parent = lensFlareNode + lense.attachment1 = attachment1 + + local beam: Beam = Instance.new("Beam") + beam.Attachment0 = attachment0 + beam.Attachment1 = attachment1 + beam.Color = ColorSequence.new(lense.color) + beam.LightEmission = 1 + beam.Name = tostring(id) + beam.Texture = lensFlareConfiguration.texture + beam.TextureSpeed = 0 + beam.Transparency = NumberSequence.new(lensFlareConfiguration.transparency) + beam.Width0 = radius + beam.Width1 = radius + beam.Parent = lensFlareNode + + lense.beam = beam + + return beam +end + +local function moonScript(): () + if workspace.CurrentCamera:FindFirstChild("FWM_LEGACY_MOON") == nil then + moonHolder = Instance.new("Part") + + if moonHolder then + moonHolder.Transparency = 1 + moonHolder.CanCollide = false + moonHolder.Anchored = true + moonHolder.Parent = workspace.CurrentCamera + moonHolder.Name = "FWM_LEGACY_MOON" + end + + local moonTextureHolder: BillboardGui = Instance.new("BillboardGui") + moonTextureHolder.ClipsDescendants = false + moonTextureHolder.LightInfluence = 0 + moonTextureHolder.Name = "Interface" + moonTextureHolder.Size = UDim2.new(0, 75, 0, 75) + moonTextureHolder.Parent = moonHolder + + local moonTexture: ImageLabel = Instance.new("ImageLabel") + moonTexture.BackgroundTransparency = 1 + moonTexture.Image = "rbxassetid://8753438296" + moonTexture.Name = "Texture" + moonTexture.Rotation = 270 + moonTexture.Size = UDim2.new(1, 0, 1, 0) + moonTexture.Parent = moonTextureHolder + end + + if moonHolder then + moonHolder.Position = Vector3.new(4748.924, 2565.836, 4768.066) + workspace.CurrentCamera.CFrame.Position + end +end + +local function updateLensFlare(): () + local vpSize: Vector2 = workspace.CurrentCamera.ViewportSize + local sunDir: Vector3 = Lighting:GetSunDirection() + local sunWrldSpace: Vector3 = sunDir * 10e6 + local sunScrnSpace: Vector2, inView: boolean = asVector2(workspace.CurrentCamera:WorldToViewportPoint(sunWrldSpace)) + local sunScrnSpaceInv: Vector2 = workspace.CurrentCamera.ViewportSize - sunScrnSpace + local enabled: boolean = (inView and not isSunOccluded(sunDir)) + + for i: number, lense: Lense in ipairs(LENSES) do + local beam = lense.beam or createLenseBeam(lense, i) + beam.Enabled = enabled + + if enabled then + local radius: number = lense.radius * lensFlareConfiguration.scale + local lenseSP: Vector2 = sunScrnSpaceInv:Lerp(sunScrnSpace, lense.distance) + local lenseWP: Vector3 = workspace.CurrentCamera:ViewportPointToRay(lenseSP.X, lenseSP.Y, 1).Origin + local lenseCF: CFrame = CFrame.new(lenseWP, lenseWP - sunDir) + + if lense.attachment0 and lense.attachment1 then + lense.attachment0.CFrame = lenseCF * CFrame.new(-radius / 2, 0, 0) + lense.attachment1.CFrame = lenseCF * CFrame.new(radius / 2, 0, 0) + end + end + end +end + +local function oldifyCharacter(object: Model): () + for _, v in pairs(object:GetDescendants()) do + if v:IsA("Part") and table.find(BODY_PART_NAMES, v.Name, 1) then + if not v:FindFirstChildOfClass("SpecialMesh") then + local unbeveled = Templates.Meshes.FWM_BLOCK_MESH:Clone() + unbeveled.Parent = v + end + end + end +end + +local function getSurfaceType(basePart: BasePart, normalId: Enum.NormalId): Enum.SurfaceType + if normalId == Enum.NormalId.Back then + return basePart.BackSurface + elseif normalId == Enum.NormalId.Bottom then + return basePart.BottomSurface + elseif normalId == Enum.NormalId.Front then + return basePart.FrontSurface + elseif normalId == Enum.NormalId.Left then + return basePart.LeftSurface + elseif normalId == Enum.NormalId.Right then + return basePart.RightSurface + elseif normalId == Enum.NormalId.Top then + return basePart.TopSurface + else + return Enum.SurfaceType.Smooth + end +end + +local function applyLegacySurfaces(basePart: BasePart): () + for surface, classicTexture in pairs(surfacesToTextures) do + for sides, normalId in pairs(PART_SIDES) do + if getSurfaceType(basePart, normalId) == surface then + local legacyTexture = classicTexture:Clone() + legacyTexture.Face = normalId + legacyTexture.Name = "FWM_LEGACY_TEXTURE" + legacyTexture.Transparency = basePart.Transparency + 0.2 + legacyTexture.Parent = basePart + + basePart:GetPropertyChangedSignal("Transparency"):Connect(function(): () + legacyTexture.Transparency = basePart.Transparency + 0.2 + end) + end + end + end +end + +local function addCylinderPlus(cylinder: Part): () + local cylinderPlusLeft = ReplicatedStorage.Templates.Textures.Adornees.CylinderPlus:Clone() + cylinderPlusLeft.Face = Enum.NormalId.Left + cylinderPlusLeft.Parent = cylinder + + local cylinderPlusRight = ReplicatedStorage.Templates.Textures.Adornees.CylinderPlus:Clone() + cylinderPlusRight.Face = Enum.NormalId.Right + cylinderPlusRight.Parent = cylinder +end + +local function applyOpenGl(part: BasePart): () + part.Color = BrickColor.new(part.Color).Color + + local randomAmount: number = 6 / 255 + local random: Random = Random.new() + local hue: number, saturation: number, value: number = part.Color:ToHSV() + + part.Color = Color3.fromHSV(hue, math.clamp(random:NextNumber(saturation - randomAmount * 1.0, saturation + randomAmount * 1.0), 0, 1), math.clamp(random:NextNumber(value - randomAmount * 0.5, value + randomAmount * 0.5), 0, 1)) +end + +local function main(descendant: Instance): () + if descendant:IsA("Terrain") then + return + end + + if descendant:IsA("Decal") then + -- Converts all face.png's to a custom one! + if descendant.Texture == "rbxasset://textures/face.png" then + descendant.Texture = "rbxassetid://8349195378" + end + end + + if descendant:IsA("Model") then + if descendant:FindFirstChildOfClass("Humanoid") then + oldifyCharacter(descendant) + end + end + + if descendant:IsA("Part") then + -- Adds OpenGL + applyOpenGl(descendant) + + -- Makes the object 06ey + descendant.Material = Enum.Material.SmoothPlastic + + -- Apply the old surfaces + applyLegacySurfaces(descendant) + + -- 06ify the Cylinder! + if descendant.Shape == Enum.PartType.Ball and descendant:GetAttribute("ConvertedToCylinder") == true then + addCylinderPlus(descendant) + end + end +end + +task.wait(1) + +for i: number, v: Instance in ipairs(workspace:GetDescendants()) do + main(v) +end + +workspace.DescendantAdded:Connect(main) + +RunService:BindToRenderStep("updateLensFlare", 201, updateLensFlare) +RunService:BindToRenderStep("moonScript", 202, moonScript) \ No newline at end of file diff --git a/rojo/MainModule/default.project.json b/rojo/MainModule/default.project.json new file mode 100644 index 0000000..56e231c --- /dev/null +++ b/rojo/MainModule/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "project", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/BreakJoints.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/BreakJoints.lua new file mode 100644 index 0000000..6861997 --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/BreakJoints.lua @@ -0,0 +1,24 @@ +--!strict +-- https://devforum.roblox.com/t/release-notes-for-564/2196195/20 +local BreakJoints +BreakJoints = function(root: BasePart | Model): () + if (not root) then + return + end + + if root:IsA("Model") then + for _: number, child: Instance in root:GetChildren() do + if child:IsA("BasePart") or child:IsA("Model") then + BreakJoints(child) + end + end + elseif root:IsA("BasePart") then + for _: number, joint: Instance in root:GetJoints() do + if joint:IsA("JointInstance") or joint:IsA("WeldConstraint") then + joint:Destroy() + end + end + end +end + +return BreakJoints diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/BrickBattleToolsHandler.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/BrickBattleToolsHandler.lua new file mode 100644 index 0000000..edb5b1f --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/BrickBattleToolsHandler.lua @@ -0,0 +1,4 @@ +local module = {} + + +return module diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/BrickColor.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/BrickColor.lua new file mode 100644 index 0000000..8f878e5 --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/BrickColor.lua @@ -0,0 +1,67 @@ +--[[ + + Replica of ROBLOX's BrickColor library from 2006 + +]]-- + +local colorCodes: {number} = {1, 208, 194, 199, 26, 21, 24, 226, 23, 107, 102, 11, 45, 135, 106, 105, 141, 28, 37, 119, 29, 151, 38, 192, 104, 9, 101, 5, 153, 217, 18, 125} +local module = {} + +function module.Random(): BrickColor + return BrickColor.new(colorCodes[math.random(1, #colorCodes)]) +end + +function module.random(): BrickColor + return BrickColor.new(colorCodes[math.random(1, #colorCodes)]) +end + +function module.Blue() : BrickColor + return BrickColor.Blue() +end + +function module.Yellow() : BrickColor + return BrickColor.Yellow() +end + +function module.Red() : BrickColor + return BrickColor.Red() +end + +function module.Gray() : BrickColor + return BrickColor.Gray() +end + +function module.Black() : BrickColor + return BrickColor.Black() +end + +function module.Green() : BrickColor + return BrickColor.Green() +end + +function module.White() : BrickColor + return BrickColor.White() +end + +function module.DarkGray() : BrickColor + return BrickColor.DarkGray() +end + +--TODO: Make it act like how March 2007 would handle RGB colors (finds nearest brickcolor in color palette) +function module.new(R, G, B) : BrickColor + local brickColor = R or 0 + local validColorCode = table.find(colorCodes, brickColor) + local validBrickColor = table.find(colorCodes, BrickColor.new(brickColor).Number) + + if (G == nil and B == nil) then + if (validColorCode or validBrickColor) then + return BrickColor.new(brickColor) + end + else + return BrickColor.new(R, G, B) + end + + return BrickColor.new("Medium stone grey") +end + +return module diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/CustomCamera.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/CustomCamera.lua new file mode 100644 index 0000000..f48f365 --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/CustomCamera.lua @@ -0,0 +1,61 @@ +local CurrentCamera = workspace.CurrentCamera; +local Camera = {}; +Camera.__index = Camera; + +Camera.viewportScale = Vector2.zero; +Camera.viewportOffset = Vector2.zero; +Camera.billboards = {}; + +function Camera:AddBillboard(x) + table.insert(self.billboards, x); +end + +function Camera:ViewportPointToWorld(x, y) + x += self.viewportOffset.X; + + local vps = CurrentCamera.ViewportSize; + local depth = 0.1; + + local sx, sy = x/vps.X, y/vps.Y; + local r = vps.X/vps.Y; + local h = depth*math.tan(math.rad(CurrentCamera.FieldOfView*0.5)); + local w = r*h; + + local corner = Vector3.new(-w, h, -depth); + local lp = corner + Vector3.new(2*sx*w, -2*sy*h, 0); + + local cframe = CurrentCamera.CFrame*CFrame.new( + 0,0,0, + 1,0,0, + 0,1,0, + -self.viewportScale.X,0,1 + ); + + local p = cframe*lp; -- MATRIX?? PLEASE + local direction = (p - cframe.Position).unit; + + return Ray.new(cframe.Position+direction*depth, direction); +end + +function Camera:WorldToScreenPoint(p) + local lp = CurrentCamera.CFrame*CFrame.new( + 0,0,0, + 1,0,0, + 0,1,0, + -self.viewportScale.X,0,1 + )*p; + + local vps = CurrentCamera.ViewportSize; + local r = vps.X/vps.Y; + + local h = -math.min(lp.z,-0.1)*r; + local w = r*h; + local corner = Vector3.new(-w, h, lp.z); + local relative = lp - corner; + + local sx = relative.X / (w*2); + local sy = -relative.Y / (h*2); + return Vector3.new(sx*vps.X, sy*vps.Y, -lp.Z); +end + +return Camera; \ No newline at end of file diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/CustomFont.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/CustomFont.lua new file mode 100644 index 0000000..f132029 --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/CustomFont.lua @@ -0,0 +1,349 @@ +local CustomFont = {} +CustomFont.__index = CustomFont + +local chars = { + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "60", + "1A", + "1A", + "00", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "1A", + "07", + "08", + "09", + "10", + "10", + "16", + "13", + "05", + "09", + "09", + "0D", + "10", + "07", + "07", + "07", + "0B", + "10", + "10", + "10", + "10", + "10", + "10", + "10", + "10", + "10", + "10", + "07", + "07", + "0D", + "10", + "0D", + "0D", + "16", + "14", + "11", + "11", + "14", + "10", + "0F", + "14", + "14", + "08", + "0C", + "11", + "0E", + "17", + "14", + "16", + "0F", + "16", + "10", + "0D", + "0F", + "14", + "12", + "1B", + "11", + "0F", + "10", + "09", + "0B", + "09", + "0D", + "0D", + "0D", + "0F", + "10", + "0D", + "10", + "0F", + "09", + "10", + "11", + "07", + "07", + "0E", + "07", + "17", + "11", + "10", + "10", + "10", + "0A", + "0B", + "0A", + "10", + "0E", + "17", + "0E", + "0E", + "0D", + "0B", + "0D", + "0B", + "11", + "1A" +} + +local OutlineOffsets = { + UDim2.new(0, -1, 0, -1), + UDim2.new(0, 1, 0, 1), + UDim2.new(0, 1, 0, -1), + UDim2.new(0, -1, 0, 1), +} + +local function calculateNumber(currentCharacter: string): (number, number) + local subbed = currentCharacter:byte() % 128 + local char = utf8.char(subbed) + local xNum = tonumber(chars[char:byte()], 16) + local fnt = (32 - xNum) / 2 + local num = subbed * 32 + local xValue = (num % 512) + fnt + local yValue = (math.floor(num / 512) * 32) + + return xValue, yValue +end + +function CustomFont.redraw(theString, multiplier, textLabel, textStrokeTransarency) + local Frame = textLabel:FindFirstChild("TextContent"); + if(not Frame)then + return; + end + + Frame:SetAttribute("CustomFont", true); + + -- inorder hopefully?? + textStrokeTransarency = textLabel:GetAttribute("TextStrokeTransparency") or textStrokeTransarency; + textLabel:SetAttribute("TextStrokeTransparency", textStrokeTransarency); + + local previousSize = 0; + for i = 1, #theString do + -- u stupid liberal why do u do thius + local byte = theString:byte(i,i); + local xNum = tonumber(chars[byte]or chars[1], 16); + + local xScale = xNum / 32 + local container = Frame:FindFirstChild(i) + + if (not container) then + continue + end + + container.Size = UDim2.new(0, xScale * multiplier, 0, 1 * multiplier) + container.BackgroundTransparency = 1; + container.Position = UDim2.new(0, previousSize, 0, 0); + container.ZIndex = textLabel.ZIndex + 1; + container.ImageLabel.ImageColor3 = textLabel.TextColor3; + + previousSize = previousSize + (xScale * multiplier) + for i, outline in container:GetChildren()do + if(outline.Name ~= "Outline")then + continue; + end + + outline.ImageColor3 = textLabel.TextStrokeColor3; + outline.ImageTransparency = textStrokeTransarency; + outline.Position = OutlineOffsets[i]; + end + end + + + local SmallestXY = 0 + local BiggestX = previousSize + local BiggestY = multiplier + Frame.Size = UDim2.new(0, BiggestX, 0, BiggestY) + + local AnchorX = 0 + local AnchorY = 0 + local SizeX = 0 + local SizeY = 0 + + if textLabel.TextXAlignment == Enum.TextXAlignment.Center then + AnchorX = 0.5 + SizeX = 0.5 + elseif textLabel.TextXAlignment == Enum.TextXAlignment.Right then + AnchorX = 1 + SizeX = 1 + end + + if textLabel.TextYAlignment == Enum.TextYAlignment.Center then + AnchorY = 0.5 + SizeY = 0.5 + elseif textLabel.TextYAlignment == Enum.TextYAlignment.Bottom then + AnchorY = 1 + SizeY = 1 + end + + Frame.Position = UDim2.new(SizeX, 0, SizeY, 0) + Frame.AnchorPoint = Vector2.new(AnchorX, AnchorY) +end + +function CustomFont.draw(theString: string, multiplier: number, textLabel, textStrokeTransparency) + if (not textLabel) then + return + end + + local Frame = textLabel:FindFirstChild("TextContent"); + if Frame then + Frame:Destroy() + end + + local Frame = Instance.new("Frame", textLabel) + Frame.Name = "TextContent"; + Frame.BackgroundTransparency = 1 + Frame:SetAttribute("CustomFont", true) + + textLabel.TextTransparency = 1 + --textLabel.TextStrokeTransparency = 0 + + local PreviousSize = 0 + for CharOffset, Character in utf8.codes(theString) do + Character = utf8.char(Character) + + if not chars[Character:byte()] then + Character = utf8.char(1) + end + + local container = Instance.new("Frame"); + local xNum = tonumber(chars[Character:byte()], 16) + local xScale = xNum / 32 + + container.Size = UDim2.new(0, xScale * multiplier, 0, 1 * multiplier) + container.BackgroundTransparency = 1; + container.Position = UDim2.new(0, PreviousSize, 0, 0) + container.ZIndex = textLabel.ZIndex + 1 + container.Parent = Frame + container.Name = CharOffset; + + local Image = Instance.new("ImageLabel") + Image.Image = "rbxassetid://11363842965" + Image.ImageRectSize = Vector2.new(xNum, 32) + Image.BackgroundTransparency = 1 + Image.ImageColor3 = textLabel.TextColor3 + Image.ZIndex = container.ZIndex + Image.Size = UDim2.new(1,0,1,0); + Image.ImageRectOffset = Vector2.new(calculateNumber(Character)) + PreviousSize = PreviousSize + (xScale * multiplier) + + --if (textStrokeTransparency < 1) or (textLabel:GetAttribute("TextStrokeTransparency") and textLabel:GetAttribute("TextStrokeTransparency") < 1) then + local FinalTextStroke = textLabel:GetAttribute("TextStrokeTransparency") or textStrokeTransparency + textLabel:SetAttribute("TextStrokeTransparency", FinalTextStroke) + + for i = 1, 4 do + local Outline = Image:Clone() + Outline.Name = "Outline"; + Outline.ZIndex = Image.ZIndex - 1 + Outline.ImageColor3 = textLabel.TextStrokeColor3 + Outline.ImageTransparency = FinalTextStroke + Outline.Position = OutlineOffsets[i] + + Outline.Parent = container + end + + --if not textLabel:SetAttribute("TextStrokeTransparency") then + -- textLabel:SetAttribute("TextStrokeTransparency", FinalTextStroke) + --end + --end + + Image.Parent = container; + end + + textLabel.TextStrokeTransparency = 1 + + local SmallestXY = 0 + local BiggestX = PreviousSize + local BiggestY = multiplier + + Frame.Size = UDim2.new(0, BiggestX, 0, BiggestY) + + local AnchorX = 0 + local AnchorY = 0 + local SizeX = 0 + local SizeY = 0 + + if textLabel.TextXAlignment == Enum.TextXAlignment.Center then + AnchorX = 0.5 + SizeX = 0.5 + elseif textLabel.TextXAlignment == Enum.TextXAlignment.Right then + AnchorX = 1 + SizeX = 1 + end + + if textLabel.TextYAlignment == Enum.TextYAlignment.Center then + AnchorY = 0.5 + SizeY = 0.5 + elseif textLabel.TextYAlignment == Enum.TextYAlignment.Bottom then + AnchorY = 1 + SizeY = 1 + end + + Frame.Position = UDim2.new(SizeX, 0, SizeY, 0) + Frame.AnchorPoint = Vector2.new(AnchorX, AnchorY) +end + +function CustomFont.displayString(theString: string, multiplier: number, textLabel, textStrokeTransparency): () + if(textLabel:GetAttribute("displayString") == theString)then + return CustomFont.redraw( + theString, + multiplier, + textLabel, + textStrokeTransparency + ); + else + textLabel:SetAttribute("displayString", theString); + return CustomFont.draw( + theString, + multiplier, + textLabel, + textStrokeTransparency + ); + end +end + +return CustomFont \ No newline at end of file diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/CustomMouseFunctions.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/CustomMouseFunctions.lua new file mode 100644 index 0000000..4e4fe9f --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/CustomMouseFunctions.lua @@ -0,0 +1,197 @@ +--[[ + Serves as a cross-platform activated module + Note: PC is the only platform to support KeyUp and KeyDown + https://create.roblox.com/docs/reference/engine/classes/Mouse + + Supports: + - PC + - Mobile + - XBoxOne + + Initiation: + local CustomMouseFunctions = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("CustomMouseFunctions")):Init() + + Button1Down: + Acts like Mouse.Button1Down, activates when the left mouse button goes down + + - CustomMouseFunctions:Button1Down(callback) + + Button1Up: + Acts like Mouse.Button1Up, activates when the left mouse button goes up + + - CustomMouseFunctions:Button1Up(callback) + + KeyDown: + Acts like Mouse.KeyDown, activates when a key is pressed down + + NOTES: + - This function returns the key pressed down + - Only works on PC + + - CustomMouseFunctions:KeyDown(callback) + + KeyUp: + Acts like Mouse.KeyUp, activates when a key is let go + + NOTES: + - This function returns the key that was just let go + - Only works on PC + + - CustomMouseFunctions:KeyUp(callback) + + Move: + Acts like Mouse.Move, activates when the mouse is moving + + - CustomMouseFunctions:Move(callback) + + Idle: + Acts like Mouse.Idle, activates when the mouse is in idle + - CustomMouseFunctions:Idle(callback) +--]] + +local Players: Players = game:GetService("Players"); +local RunService: RunService = game:GetService("RunService") +local UserInputService: UserInputService = game:GetService("UserInputService") + +local CustomCamera = require(script.Parent:WaitForChild("CustomCamera")); + +local LocalPlayer = Players.LocalPlayer; +local Camera: Camera = workspace.CurrentCamera; +local Mouse: Mouse = LocalPlayer:GetMouse(); + +local CustomMouseFunctions = {} +CustomMouseFunctions.__index = CustomMouseFunctions + +local fflagUseDefaultMouse = false; +function CustomMouseFunctions:Target(): any + if(fflagUseDefaultMouse)then + return Mouse.Target; + end + + local params = RaycastParams.new(); + params.FilterType = Enum.RaycastFilterType.Exclude; + params.FilterDescendantsInstances = {Mouse.TargetFilter}; + + local unitRay = self:UnitRay(); + local result = workspace:Raycast(unitRay.Origin, unitRay.Direction*1000, params); + local cf = CFrame.lookAt(Vector3.zero, unitRay.Direction); + if(result)then + return result.Instance, cf.Rotation + result.Position; + else + return nil, cf.Rotation + (unitRay.Origin+unitRay.Direction*1000); + end +end + +function CustomMouseFunctions:UnitRay(): Ray + if(fflagUseDefaultMouse)then + return Mouse.UnitRay; + end + + local x = Mouse.X; + local y = Mouse.Y+32; + return CustomCamera:ViewportPointToWorld(x, y); +end + +function CustomMouseFunctions:AddBillboard(billboard) + table.insert(self.billboards, billboard); +end + +function CustomMouseFunctions:Hit(): CFrame + if(fflagUseDefaultMouse)then + return Mouse.Hit; + end + + local params = RaycastParams.new(); + params.FilterType = Enum.RaycastFilterType.Exclude; + params.FilterDescendantsInstances = {Mouse.TargetFilter}; + + local unitRay = self:UnitRay(); + local result = workspace:Raycast(unitRay.Origin, unitRay.Direction*1000, params); + local cf = CFrame.lookAt(Vector3.zero, unitRay.Direction); + if(result)then + return cf + result.Position; + else + return cf + (unitRay.Origin+unitRay.Direction*1000); + end +end + +function CustomMouseFunctions:Init() + return CustomMouseFunctions +end + +function CustomMouseFunctions:Button1Down(callback: () -> any): () + if not UserInputService.TouchEnabled then + return UserInputService.InputBegan:Connect(function(input: InputObject, gameProcessedEvent: boolean): () + if not gameProcessedEvent then + if input.UserInputType == Enum.UserInputType.MouseButton1 or input.KeyCode == Enum.KeyCode.ButtonR2 then + return callback() + end + end + end) + else + return UserInputService.TouchTapInWorld:Connect(function(position: Vector2, processedByUI: boolean): () -- we should RLY fix this ngl... + if not processedByUI then + return callback() + end + end) + end +end + +function CustomMouseFunctions:Button1Up(callback: () -> any): () + return UserInputService.InputEnded:Connect(function(input: InputObject, gameProcessedEvent: boolean): () + if not gameProcessedEvent then + if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch or input.KeyCode == Enum.KeyCode.ButtonR2 then + return callback() + end + end + end) +end + +function CustomMouseFunctions:KeyDown(callback: (string) -> any) + if not UserInputService.TouchEnabled then + return UserInputService.InputBegan:Connect(function(input: InputObject, gameProcessedEvent: boolean): () + if not gameProcessedEvent then + if input.UserInputType == Enum.UserInputType.Keyboard then + return callback(input.KeyCode.Name) + end + end + end) + end +end + +function CustomMouseFunctions:KeyUp(callback: (string) -> any): () + if not UserInputService.TouchEnabled then + return UserInputService.InputEnded:Connect(function(input: InputObject, gameProcessedEvent: boolean): () + if not gameProcessedEvent then + if input.UserInputType == Enum.UserInputType.Keyboard then + return callback(input.KeyCode.Name) + end + end + end) + end +end + +function CustomMouseFunctions:Move(callback: () -> any): () + return UserInputService.InputChanged:Connect(function(input: InputObject, gameProcessedEvent: boolean): () + if (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) and input.UserInputState == Enum.UserInputState.Change then + return callback() + end + end) +end + +function CustomMouseFunctions:Idle(callback: () -> any): () + local lastPosition: Vector2 = Vector2.zero + + return RunService.PostSimulation:Connect(function(deltaTimeSim: number): () + local currentPosition: Vector2 = UserInputService:GetMouseLocation() + + if currentPosition ~= lastPosition then + lastPosition = currentPosition + else + return callback() + end + end) +end + + +return CustomMouseFunctions diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/Diogenes.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/Diogenes.lua new file mode 100644 index 0000000..d8e2f16 --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/Diogenes.lua @@ -0,0 +1,7 @@ +local diogenes = { + "blockland.us", + "www.blockland.us", + "http://www.blockland.us" +} + +return diogenes \ No newline at end of file diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/DraggableObject.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/DraggableObject.lua new file mode 100644 index 0000000..fa661da --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/DraggableObject.lua @@ -0,0 +1,120 @@ +--[[@Author: Spynaz +@Description: Enables dragging on GuiObjects. Supports both mouse and touch. + +For instructions on how to use this module, go to this link: +https://devforum.roblox.com/t/simple-module-for-creating-draggable-gui-elements/230678 + --]] + +local UDim2_new = UDim2.new + +local UserInputService = game:GetService("UserInputService") + +local DraggableObject = {} +DraggableObject.__index = DraggableObject + +-- Check if either mouse movement or touch input +function MouseOrTouchMovement(input) + return input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch +end + +-- Sets up a new draggable object +function DraggableObject.new(Object) + local self = {} + self.Object = Object --lol + self.DragStarted = nil + self.DragEnded = nil + self.Dragged = nil + self.Dragging = false + + setmetatable(self, DraggableObject) + + return self +end + +-- Enables dragging +function DraggableObject:Enable() + local object = self.Object + local dragInput = nil + local dragStart = nil + local startPos = nil + local preparingToDrag = false + + -- Updates the element + local function update(input) + local delta = input.Position - dragStart + local newPosition = UDim2_new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y) + object.Parent.Parent.Position = newPosition + + return newPosition + end + + self.InputBegan = object.InputBegan:Connect(function(input) + if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then + preparingToDrag = true + + local connection + connection = input.Changed:Connect(function() + if input.UserInputState == Enum.UserInputState.End and (self.Dragging or preparingToDrag) then + self.Dragging = false + connection:Disconnect() + + if self.DragEnded and not preparingToDrag then + self.DragEnded() + end + + preparingToDrag = false + end + end) + end + end) + + self.InputChanged = object.InputChanged:Connect(function(input) + if MouseOrTouchMovement(input) then + dragInput = input + end + end) + + self.InputChanged2 = UserInputService.InputChanged:Connect(function(input) + if object.Parent == nil then + self:Disable() + return + end + + if MouseOrTouchMovement(input) and preparingToDrag then + preparingToDrag = false + + if self.DragStarted then + self.DragStarted() + end + + self.Dragging = true + dragStart = input.Position + startPos = object.Parent.Parent.Position + end + + if input == dragInput and self.Dragging then + local newPosition = update(input) + + if self.Dragged then + self.Dragged(newPosition) + end + end + end) +end + +-- Disables dragging +function DraggableObject:Disable() + self.InputBegan:Disconnect() + self.InputChanged:Disconnect() + self.InputChanged2:Disconnect() + + if self.Dragging then + self.Dragging = false + + if self.DragEnded then + self.DragEnded() + end + end +end + +return DraggableObject \ No newline at end of file diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/MakeJoints.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/MakeJoints.lua new file mode 100644 index 0000000..ca2b8a0 --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/MakeJoints.lua @@ -0,0 +1,104 @@ +-- created by madgangz + +local matrix_right = CFrame.new(0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 1); +local function make_att(part, where) + local att = Instance.new("Attachment"); + att.CFrame = part.CFrame:inverse() * where * matrix_right; + att.Parent = part; + return att; +end + +local function apply_constraint(part0, part1, where, axis) + local constraint = Instance.new("HingeConstraint"); + constraint.Attachment0 = make_att(part0, where); + constraint.Attachment1 = make_att(part1, where); + constraint.Parent = part0; + return constraint; +end + +local directions = { + [Vector3.xAxis] = "Right"; + [Vector3.yAxis] = "Top"; + [Vector3.zAxis] = "Front"; + [-Vector3.xAxis] = "Left"; + [-Vector3.yAxis] = "Bottom"; + [-Vector3.zAxis] = "Back"; +}; + +local caster_region = 1; +local caster_point = 0; +local caster_modes = { + [Enum.SurfaceType.Motor] = caster_point; + [Enum.SurfaceType.Hinge] = caster_point; + + [Enum.SurfaceType.Studs] = caster_region; + [Enum.SurfaceType.Inlet] = caster_region; + [Enum.SurfaceType.Weld] = caster_region; +}; + +local paramA = "%sParamA"; +local function weld(part0, part1, cframe, dir, prop) + local constraint = Instance.new("WeldConstraint"); + constraint.Part0 = part0; + constraint.Part1 = part1; + constraint.Parent = part0; +end + +local whitelisted = { + [Enum.SurfaceType.Motor] = function(part0, part1, cframe, dir, prop) + local constraint = apply_constraint(part0, part1, cframe, dir); + constraint.ActuatorType = Enum.ActuatorType.Motor; + constraint.MotorMaxTorque = part0[paramA:format(prop)]; + end; + + [Enum.SurfaceType.Hinge] = function(part0, part1, cframe, dir, prop) + local constraint = apply_constraint(part0, part1, cframe, dir); + constraint.ActuatorType = Enum.ActuatorType.Servo; + constraint.ServoMaxTorque = part0[paramA:format(prop)]; + end; + + [Enum.SurfaceType.Studs] = weld; + [Enum.SurfaceType.Inlet] = weld; + [Enum.SurfaceType.Weld] = weld; +}; + +local surface_type = "%sSurface"; +local epsilon = 0.1; +return function(part) + if(not part:IsA("BasePart"))then + return; + end + + local cframe = part.CFrame; + local origin = cframe:inverse(); + local size = part.Size*0.5; + + local joints = {}; + for dir, prop in directions do + local surface = part[surface_type:format(prop)]; + local actuator = whitelisted[surface]; + if(not actuator)then + continue; + end + + if(caster_modes[surface] == caster_region)then + for _, hit in workspace:GetPartBoundsInBox(cframe*CFrame.new(size*dir + dir*0.25), size - dir*size:Dot(dir) + Vector3.one)do + if(not hit.CanCollide or part==hit or joints[hit])then + continue; + end + + joints[hit] = true; + actuator(part, hit, cframe*CFrame.new(size*dir), dir, prop); + end + else + for _, hit in workspace:GetPartBoundsInRadius(cframe * (size * dir), 0.25) do + if(not hit.CanCollide or part==hit or joints[hit])then + continue; + end + + joints[hit] = true; + actuator(part, hit, cframe*CFrame.new(size*dir), dir, prop); + end + end + end +end \ No newline at end of file diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/MouseIcon.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/MouseIcon.lua new file mode 100644 index 0000000..0523b37 --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/MouseIcon.lua @@ -0,0 +1,61 @@ +--[[ + + File Name: MouseIcon.lua + Written by: Gamer (@Roblox_Gamer2030) + Description: Mouse module for FWM, has a IconLibrary set up for it + +]]-- +local Players = game:GetService("Players") +local player = Players.LocalPlayer +local MouseIcon = {} + +-- Library of 2006 cursors set up +local ICONLIBRARY: {[string] : string} = { + + -- rbxasset://textures\\TEXTURE.png + ["rbxasset://textures\\ArrowCursor.png"] = "rbxassetid://7167309450", + ["rbxasset://textures\\ArrowFarCursor.png"] = "rbxassetid://7167309465", + + ["rbxasset://textures\\GunCursor.png"] = "rbxassetid://6958990174", + ["rbxasset://textures\\GunWaitCursor.png"] = "rbxassetid://6958990714", + + ["rbxasset://textures\\CloneCursor.png"] = "rbxassetid://7167495528", + ["rbxasset://textures\\CloneOverCursor.png"] = "rbxassetid://7167545116", + ["rbxasset://textures\\DragCursor.png"] = "rbxassetid://7167515791", + ["rbxasset://textures\\GrabRotateCursor.png"] = "rbxassetid://7167495541", + ["rbxasset://textures\\HammerCursor.png"] = "rbxassetid://7167495543", + ["rbxasset://textures\\HammerOverCursor.png"] = "rbxassetid://7167495538", + + ["rbxasset://textures\\FillCursor.png"] = "rbxassetid://9799205192", + ["rbxasset://textures\\DropperCursor.png"] = "rbxassetid://9799203397", + + ["rbxasset://textures\\AnchorCursor.png"] = "rbxassetid://9802191685", + ["rbxasset://textures\\UnAnchorCursor.png"] = "rbxassetid://9802192705", + + + -- rbxasset://textures//TEXTURE.png + ["rbxasset://textures//ArrowCursor.png"] = "rbxassetid://7167309450", + ["rbxasset://textures//ArrowFarCursor.png"] = "rbxassetid://7167309465", + + ["rbxasset://textures//GunCursor.png"] = "rbxassetid://6958990174", + ["rbxasset://textures//GunWaitCursor.png"] = "rbxassetid://6958990714", + + ["rbxasset://textures//CloneCursor.png"] = "rbxassetid://7167495528", + ["rbxasset://textures//CloneOverCursor.png"] = "rbxassetid://7167545116", + ["rbxasset://textures//DragCursor.png"] = "rbxassetid://7167515791", + ["rbxasset://textures//GrabRotateCursor.png"] = "rbxassetid://7167495541", + ["rbxasset://textures//HammerCursor.png"] = "rbxassetid://7167495543", + ["rbxasset://textures//HammerOverCursor.png"] = "rbxassetid://7167495538", + + ["rbxasset://textures//AnchorCursor.png"] = "rbxassetid://9802191685", + ["rbxasset://textures//UnAnchorCursor.png"] = "rbxassetid://9802192705" + +} + +function MouseIcon.Icon(icon) + if player.PlayerGui:FindFirstChild("MainGui") ~= nil then + player.PlayerGui.MainResetGui.Cursor.Image = ICONLIBRARY[icon] or icon + end +end + +return MouseIcon diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/StockSound.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/StockSound.lua new file mode 100644 index 0000000..6451799 --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/StockSound.lua @@ -0,0 +1,27 @@ +--!strict +local SoundService: SoundService = game:GetService("SoundService") + +local StockSound = {} +StockSound.__index = StockSound + +function StockSound:PlaySound(stockSound: string, object: BasePart): () + local Sound: Instance? = SoundService:FindFirstChild(stockSound) + + if Sound and Sound:IsA("Sound") then + local newSound: Sound = Sound:Clone() + newSound.PlayOnRemove = true + newSound.Parent = object or workspace -- If we have an object parameter we can parent the sound to the part for 3D sound, otherwise it's 2D or "global". + + newSound:Destroy() + end +end + +function StockSound:PlaySoundLocal(stockSound: string): () + local Sound: Instance? = SoundService:FindFirstChild(stockSound) + + if Sound then + SoundService:PlayLocalSound(Sound) + end +end + +return StockSound diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/SuperSafeChat.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/SuperSafeChat.lua new file mode 100644 index 0000000..fdf2050 --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/SuperSafeChat.lua @@ -0,0 +1,773 @@ +-- I used an online decoder to decode an xml to JSON, I'm surprised this actually worked well! +-- this dude +-- ^ this dude + +return[[ + { + "roblox": { + "External": [ + "null", + "nil" + ], + "utterance": [ + { + "#text": "Hello", + "utterance": [ + { + "#text": "Hi", + "utterance": [ + "Hi there!", + "Hi everyone" + ] + }, + { + "#text": "Howdy", + "utterance": "Howdy partner!" + }, + { + "#text": "Greetings", + "utterance": [ + "Greetings eveyone", + "Greetings robloxians!", + "Seaons greetings!" + ] + }, + { + "#text": "Welcome", + "utterance": [ + "Welcome to my place", + "Welcome to our base", + "Welcome to my barbecque" + ] + }, + "Hey there!", + { + "#text": "What's up?", + "utterance": [ + "How are you doing?", + "How's it going?", + "What's new?" + ] + }, + { + "#text": "Good day", + "utterance": [ + "Good morning", + "Good afternoon", + "Good evening", + "Good night" + ] + }, + { + "#text": "Silly", + "utterance": [ + "Waaaaaaaz up?!", + "Hullo!", + "Behold greatness, mortals!" + ] + }, + { + "#text": "Holidays", + "utterance": [ + "Happy New Year!", + "Happy Valentine's Day!", + "Beware the Ides of March!", + "Happy Easter!", + "Happy 4th of July!", + "Happy Thanksgiving!", + "Happy Halloween!", + "Happy Hanukkah!", + "Merry Christmas!", + "Happy Holidays!" + ] + } + ] + }, + { + "#text": "Goodbye", + "utterance": [ + { + "#text": "Good Night", + "utterance": [ + "Sweet dreams", + "Go to sleep!", + "Lights out!", + "Bedtime" + ] + }, + { + "#text": "Later", + "utterance": [ + "See ya later", + "Later gator!", + "See you tomorrow" + ] + }, + { + "#text": "Bye", + "utterance": "Hasta la bye bye!" + }, + "I'll be right back", + "I have to go", + { + "#text": "Farewell", + "utterance": [ + "Take care", + "Have a nice day", + "Goodluck!", + "Ta-ta for now!" + ] + }, + { + "#text": "Peace", + "utterance": [ + "Peace out!", + "Peace dudes!", + "Rest in pieces!" + ] + }, + { + "#text": "Silly", + "utterance": [ + "To the batcave!", + "Over and out!", + "Happy trails!", + "I've got to book it!", + "Tootles!", + "Smell you later!", + "GG!", + "My house is on fire! gtg." + ] + } + ] + }, + { + "#text": "Friend", + "utterance": [ + "Wanna be friends?", + { + "#text": "Follow me", + "utterance": [ + "Come to my place!", + "Come to my base!", + "Follow me, team!" + ] + }, + { + "#text": "Your place is cool", + "utterance": [ + "Your place is fun", + "Your place is awesome", + "Your place looks good" + ] + }, + { + "#text": "Thank you", + "utterance": [ + "Thanks for playing", + "Thanks for visiting", + "Thanks for everything", + "No thank you" + ] + }, + { + "#text": "No problem", + "utterance": [ + "Don't worry", + "That's ok" + ] + }, + { + "#text": "You are ...", + "utterance": [ + "You are great!", + "You are good!", + "You are cool!", + "You are funny!", + "You are silly!", + "You are awesome!" + ] + }, + { + "#text": "I like ...", + "utterance": [ + "I like your name", + "I like your shirt", + "I like your place", + "I like your style" + ] + }, + { + "#text": "Sorry", + "utterance": [ + "My bad!", + "I'm sorry", + "Whoops!", + "Please forgive me", + "I forgive you" + ] + } + ] + }, + { + "#text": "Questions", + "utterance": [ + { + "#text": "Who?", + "utterance": [ + "Who wants to be my friend?", + "Who wants to be on my team?", + "Who made this brilliant game?" + ] + }, + { + "#text": "What?", + "utterance": [ + "What is your favorite animal?", + "What is your favorite game?", + "What is your favorite movie?", + "What is your favorite TV show?", + "What is your favorite music?", + "What are your hobbies?" + ] + }, + { + "#text": "When?", + "utterance": [ + "When are you online?", + "When is the new version coming out?", + "When can we play again?", + "When will your place be done?" + ] + }, + { + "#text": "Where?", + "utterance": [ + "Where do you want to go?", + "Where are you going?", + "Where am I?!" + ] + }, + { + "#text": "How?", + "utterance": [ + "How are you today?", + "How did you make this cool place?" + ] + }, + { + "#text": "Can I...", + "utterance": [ + "Can I have a tour?", + "Can I be on your team?", + "Can I be your friend?", + "Can I try something?" + ] + } + ] + }, + { + "#text": "Answers", + "utterance": [ + { + "#text": "You need help?", + "utterance": [ + "Check out the news section", + "Check out the help section", + "Read the wiki!", + "All the answers are in the wiki!" + ] + }, + { + "#text": "Some people ...", + "utterance": [ + "Me", + "Not me", + "You", + "All of us", + "Everyone but you", + "Builderman!", + "Telamon!" + ] + }, + { + "#text": "Time ...", + "utterance": [ + "In the morning", + "In the afternoon", + "At night", + "Tomorrow", + "This week", + "This month", + "Sometime", + "Sometimes", + "Whenever you want", + "Never" + ] + }, + { + "#text": "Animals", + "utterance": [ + { + "#text": "Cats", + "utterance": [ + "Lion", + "Tiger", + "Leopard", + "Cheetah" + ] + }, + { + "#text": "Dogs", + "utterance": [ + "Wolves", + "Beagle", + "Collie", + "Dalmatian", + "Poodle", + "Spaniel", + "Shepherd", + "Terrier", + "Retriever" + ] + }, + { + "#text": "Horses", + "utterance": [ + "Ponies", + "Stallions" + ] + }, + { + "#text": "Reptiles", + "utterance": [ + "Dinosaurs", + "Lizards", + "Snakes", + "Turtles!" + ] + }, + "Hamster", + "Monkey", + "Bears", + { + "#text": "Fish", + "utterance": [ + "Goldfish", + "Sharks", + "Sea Bass", + "Halibut" + ] + }, + { + "#text": "Birds", + "utterance": [ + "Eagles", + "Penguins", + "Turkeys" + ] + }, + "Elephants", + { + "#text": "Mythical Beasts", + "utterance": [ + "Dragons", + "Unicorns", + "Sea Serpents", + "Sphinx", + "Cyclops", + "Minotaurs", + "Goblins", + "Honest Politicians", + "Ghosts", + "Scylla and Charybdis" + ] + } + ] + }, + { + "#text": "Games", + "utterance": [ + { + "#text": "Roblox", + "utterance": [ + "BrickBattle", + "Community Building", + "Roblox Minigames" + ] + }, + "Action", + "Puzzle", + "Strategy", + "Racing", + "RPG", + { + "#text": "Board games", + "utterance": [ + "Chess", + "Checkers", + "Settlers of Catan", + "Tigris and Euphrates", + "El Grande", + "Stratego", + "Carcassonne" + ] + } + ] + }, + { + "#text": "Sports", + "utterance": [ + "Hockey", + "Soccer", + "Football", + "Baseball", + "Basketball", + "Volleyball", + "Tennis", + { + "#text": "Watersports", + "utterance": [ + "Surfing", + "Swimming", + "Water Polo" + ] + }, + { + "#text": "Winter sports", + "utterance": [ + "Skiing", + "Snowboarding", + "Sledding", + "Skating" + ] + }, + { + "#text": "Adventure", + "utterance": [ + "Rock climbing", + "Hiking", + "Fishing" + ] + }, + { + "#text": "Wacky", + "utterance": [ + "Foosball", + "Calvinball", + "Croquet", + "Cricket", + "Dodgeball", + "Squash" + ] + } + ] + }, + { + "#text": "Movies/TV", + "utterance": [ + "Science Fiction", + { + "#text": "Animated", + "utterance": "Anime" + }, + "Comedy", + "Romantic", + "Action", + "Fantasy" + ] + }, + { + "#text": "Music", + "utterance": [ + "Country", + "Jazz", + "Rap", + "Hip-hop", + "Techno", + "Classical", + "Pop", + "Rock" + ] + }, + { + "#text": "Hobbies", + "utterance": [ + { + "#text": "Computers", + "utterance": [ + "Building computers", + "Videogames", + "Coding", + "Hacking" + ] + }, + { + "#text": "The Internet", + "utterance": "lol. teh internets!" + }, + "Dance", + "Gynastics", + { + "#text": "Martial Arts", + "utterance": [ + "Karate", + "Judo", + "Taikwon Do", + "Wushu", + "Street fighting" + ] + }, + "Listening to music", + { + "#text": "Music lessons", + "utterance": [ + "Playing in my band", + "Playing piano", + "Playing guitar", + "Playing violin", + "Playing drums", + "Playing a weird instrument" + ] + }, + "Arts and crafts" + ] + }, + { + "#text": "Location", + "utterance": [ + { + "#text": "USA", + "utterance": [ + { + "#text": "West", + "utterance": [ + "Alaska", + "Arizona", + "California", + "Colorado", + "Hawaii", + "Idaho", + "Montana", + "Nevada", + "New Mexico", + "Oregon", + "Utah", + "Washington", + "Wyoming" + ] + }, + { + "#text": "Midwest", + "utterance": [ + "Illinois", + "Indiana", + "Iowa", + "Kansas", + "Michigan", + "Minnesota", + "Missouri", + "Nebraska", + "North Dakota", + "Ohio", + "South Dakota", + "Wisconsin" + ] + }, + { + "#text": "Northeast", + "utterance": [ + "Connecticut", + "Delaware", + "Maine", + "Maryland", + "Massachusetts", + "New Hampshire", + "New Jersey", + "New York", + "Pennsylvania", + "Rhode Island", + "Vermont", + "Virginia", + "West Virginia" + ] + }, + { + "#text": "South", + "utterance": [ + "Alabama", + "Arkansas", + "Florida", + "Georgia", + "Kentucky", + "Louisiana", + "Mississippi", + "North Carolina", + "Oklahoma", + "South Carolina", + "Tennessee", + "Texas" + ] + } + ] + }, + { + "#text": "Canada", + "utterance": [ + "Alberta", + "British Columbia", + "Manitoba", + "New Brunswick", + "Newfoundland", + "Northwest Territories", + "Nova Scotia", + "Nunavut", + "Ontario", + "Prince Edward Island", + "Quebec", + "Saskatchewan", + "Yukon" + ] + }, + "Mexico", + "Central America", + { + "#text": "Europe", + "utterance": [ + { + "#text": "Great Britain", + "utterance": [ + "England", + "Scotland", + "Wales", + "Northern Ireland" + ] + }, + "France", + "Germany", + "Spain", + "Italy", + "Poland", + "Switzerland", + "Greece", + "Romania" + ] + }, + { + "#text": "Asia", + "utterance": [ + "China", + "India", + "Japan", + "Korea" + ] + }, + { + "#text": "South America", + "utterance": [ + "Argentina", + "Brazil" + ] + }, + { + "#text": "Africa", + "utterance": [ + "Eygpt", + "Swaziland" + ] + }, + "Australia", + "Middle East", + "Antarctica" + ] + }, + { + "#text": "Age", + "utterance": [ + "Rugrat", + "Kid", + "Teen", + "Twenties", + "Old", + "Ancient", + "Mesozoic" + ] + }, + { + "#text": "Mood", + "utterance": [ + "Good", + "Great!", + "Not bad", + "Sad", + "Hyper", + "Chill" + ] + }, + "Boy", + "Girl" + ] + }, + { + "#text": "Game", + "utterance": [ + "Let's build", + "Let's battle", + "Nice one!", + "So far so good!", + "Lucky shot!", + "Oh man!" + ] + }, + { + "#text": "Silly", + "utterance": [ + "Muahahahaha!", + { + "#text": "1337", + "utterance": [ + "i r teh pwnz0r!", + "w00t!", + "z0mg h4x!", + "ub3rR0xXorzage!", + "all your base are belong to me!" + ] + } + ] + }, + { + "#text": "Yes", + "utterance": [ + "Absolutely!", + "Rock on!", + "Totally!", + "Juice!" + ] + }, + { + "#text": "No", + "utterance": [ + "Ummm. No.", + "..." + ] + }, + { + "#text": "Ok", + "utterance": [ + "Well... ok", + "Sure" + ] + }, + { + "#text": ":-)", + "utterance": [ + ":-(", + ":D", + ":-O", + "lol" + ] + } + ] + } +} +]] \ No newline at end of file diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/TextureGroups.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/TextureGroups.lua new file mode 100644 index 0000000..df0ac0f --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/TextureGroups.lua @@ -0,0 +1,308 @@ +local TextureGroups = { + { + base = "rbxasset://Textures/A_Key.png", + disabled = "rbxasset://Textures/A_Key.png", + down = "rbxasset://Textures/A_Key_dn.png", + over = "rbxasset://Textures/A_Key.png", + }, + { + base = "rbxasset://Textures/AnchorTool.png", + disabled = "rbxasset://Textures/AnchorTool.png", + down = "rbxasset://Textures/AnchorTool_dn.png", + over = "rbxasset://Textures/AnchorTool.png", + }, + { + base = "rbxasset://Textures/ArrowTool.png", + disabled = "rbxasset://Textures/ArrowTool_ds.png", + down = "rbxasset://Textures/ArrowTool_dn.png", + over = "rbxasset://Textures/ArrowTool_ovr.png", + }, + { + base = "rbxasset://Textures/CameraCenter.png", + disabled = "rbxasset://Textures/CameraCenter_ds.png", + down = "rbxasset://Textures/CameraCenter_dn.png", + over = "rbxasset://Textures/CameraCenter_ovr.png", + }, + { + base = "rbxasset://Textures/CameraPanLeft.png", + disabled = "rbxasset://Textures/CameraPanLeft.png", + down = "rbxasset://Textures/CameraPanLeft_dn.png", + over = "rbxasset://Textures/CameraPanLeft_ovr.png", + }, + { + base = "rbxasset://Textures/CameraPanRight.png", + disabled = "rbxasset://Textures/CameraPanRight.png", + down = "rbxasset://Textures/CameraPanRight_dn.png", + over = "rbxasset://Textures/CameraPanRight_ovr.png", + }, + { + -- CameraTiltDown + base = "rbxassetid://6270912147", + disabled = "rbxassetid://6270912147", + down = "rbxassetid://6680556069", + over = "rbxassetid://6680556292", + }, + { + -- CameraTiltUp + base = "rbxassetid://6270911470", + disabled = "rbxassetid://6270911470", + down = "rbxassetid://6680556654", + over = "rbxassetid://6680556883", + }, + { + -- CameraZoomIn + base = "rbxassetid://6270912438", + disabled = "rbxassetid://6270912438", + down = "rbxassetid://6680557150", + over = "rbxassetid://6680557474", + }, + { + -- CameraZoomOut + base = "rbxassetid://6270912749", + disabled = "rbxassetid://6270912749", + down = "rbxassetid://6680557657", + over = "rbxassetid://6680557849", + }, + { + base = "rbxasset://Textures/Card.png", + disabled = "rbxasset://Textures/Card_ds.png", + down = "rbxasset://Textures/Card_dn.png", + over = "rbxasset://Textures/Card_ovr.png", + }, + { + base = "rbxasset://Textures/Chat.png", + disabled = "rbxasset://Textures/Chat_ds.png", + down = "rbxasset://Textures/Chat_dn.png", + over = "rbxasset://Textures/Chat_ovr.png", + }, + { + base = "rbxasset://Textures/Chat.png", + disabled = "rbxasset://Textures/Chat_ds.png", + down = "rbxasset://Textures/Chat_dn.png", + over = "rbxasset://Textures/Chat_ovr.png", + }, + { + base = "rbxasset://Textures/Controller1.png", + disabled = "rbxasset://Textures/Controller1_ds.png", + down = "rbxasset://Textures/Controller1_dn.png", + over = "rbxasset://Textures/Controller1_ovr.png", + }, + { + base = "rbxasset://Textures/Controller1Tool.png", + disabled = "rbxasset://Textures/Controller1Tool.png", + down = "rbxasset://Textures/Controller1Tool_dn.png", + over = "rbxasset://Textures/Controller1Tool.png", + }, + { + base = "rbxasset://Textures/Controller2.png", + disabled = "rbxasset://Textures/Controller2_ds.png", + down = "rbxasset://Textures/Controller2_dn.png", + over = "rbxasset://Textures/Controller2_ovr.png", + }, + { + base = "rbxasset://Textures/Controller2Tool.png", + disabled = "rbxasset://Textures/Controller2Tool.png", + down = "rbxasset://Textures/Controller2Tool_dn.png", + over = "rbxasset://Textures/Controller2Tool.png", + }, + { + base = "rbxasset://Textures/ControllerAI1Tool.png", + disabled = "rbxasset://Textures/ControllerAI1Tool.png", + down = "rbxasset://Textures/ControllerAI1Tool_dn.png", + over = "rbxasset://Textures/ControllerAI1Tool.png", + }, + { + base = "rbxasset://Textures/ControllerAI2Tool.png", + disabled = "rbxasset://Textures/ControllerAI2Tool.png", + down = "rbxasset://Textures/ControllerAI2Tool_dn.png", + over = "rbxasset://Textures/ControllerAI2Tool.png", + }, + { + base = "rbxasset://Textures/ControllerNoneTool.png", + disabled = "rbxasset://Textures/ControllerNoneTool.png", + down = "rbxasset://Textures/ControllerNoneTool_dn.png", + over = "rbxasset://Textures/ControllerNoneTool.png", + }, + { + base = "rbxasset://Textures/D_Key.png", + disabled = "rbxasset://Textures/D_Key.png", + down = "rbxasset://Textures/D_Key_dn.png", + over = "rbxasset://Textures/D_Key.png", + }, + { + base = "rbxasset://Textures/Delete.png", + disabled = "rbxasset://Textures/Delete_ds.png", + down = "rbxasset://Textures/Delete_dn.png", + over = "rbxasset://Textures/Delete_ovr.png", + }, + { + base = "rbxasset://Textures/Down_key.png", + disabled = "rbxasset://Textures/Down_key.png", + down = "rbxasset://Textures/Down_key_dn.png", + over = "rbxasset://Textures/Down_key.png", + }, + { + base = "rbxasset://Textures/DropperTool.png", + disabled = "rbxasset://Textures/DropperTool.png", + down = "rbxasset://Textures/DropperTool_dn.png", + over = "rbxasset://Textures/DropperTool.png", + }, + { + base = "rbxasset://Textures/FillTool.png", + disabled = "rbxasset://Textures/FillTool.png", + down = "rbxasset://Textures/FillTool_dn.png", + over = "rbxasset://Textures/FillTool.png", + }, + { + base = "rbxasset://Textures/FlatTool.png", + disabled = "rbxasset://Textures/FlatTool.png", + down = "rbxasset://Textures/FlatTool_dn.png", + over = "rbxasset://Textures/FlatTool.png", + }, + { + base = "rbxasset://Textures/H_Key.png", + disabled = "rbxasset://Textures/H_Key.png", + down = "rbxasset://Textures/H_Key_dn.png", + over = "rbxasset://Textures/H_Key.png", + }, + { + base = "rbxasset://Textures/HingeTool.png", + disabled = "rbxasset://Textures/HingeTool.png", + down = "rbxasset://Textures/HingeTool_dn.png", + over = "rbxasset://Textures/HingeTool.png", + }, + { + base = "rbxasset://Textures/J_Key.png", + disabled = "rbxasset://Textures/J_Key.png", + down = "rbxasset://Textures/J_Key_dn.png", + over = "rbxasset://Textures/J_Key.png", + }, + { + base = "rbxasset://Textures/LeftMotorFastTool.png", + disabled = "rbxasset://Textures/LeftMotorFastTool.png", + down = "rbxasset://Textures/LeftMotorFastTool_dn.png", + over = "rbxasset://Textures/LeftMotorFastTool.png", + }, + { + base = "rbxasset://Textures/LeftMotorTool.png", + disabled = "rbxasset://Textures/LeftMotorTool.png", + down = "rbxasset://Textures/LeftMotorTool_dn.png", + over = "rbxasset://Textures/LeftMotorTool.png", + }, + { + base = "rbxasset://Textures/LockTool.png", + disabled = "rbxasset://Textures/LockTool.png", + down = "rbxasset://Textures/LockTool_dn.png", + over = "rbxasset://Textures/LockTool.png", + }, + { + base = "rbxasset://Textures/MoveTool.png", + disabled = "rbxasset://Textures/MoveTool_ds.png", + down = "rbxasset://Textures/MoveTool_dn.png", + over = "rbxasset://Textures/MoveTool_ovr.png", + }, + { + base = "rbxasset://Textures/PlayDelete.png", + disabled = "rbxasset://Textures/PlayDelete_ds.png", + down = "rbxasset://Textures/PlayDelete_dn.png", + over = "rbxasset://Textures/PlayDelete_ovr.png", + }, + { + base = "rbxasset://Textures/ReportAbuse.png", + disabled = "rbxasset://Textures/ReportAbuse_ds.png", + down = "rbxasset://Textures/ReportAbuse_dn.png", + over = "rbxasset://Textures/ReportAbuse_ovr.png", + }, + { + base = "rbxasset://Textures/Reset.png", + disabled = "rbxasset://Textures/Reset_ds.png", + down = "rbxasset://Textures/Reset_dn.png", + over = "rbxasset://Textures/Reset_ovr.png", + }, + { + base = "rbxasset://Textures/ResetOrg.png", + disabled = "rbxasset://Textures/ResetOrg_ds.png", + down = "rbxasset://Textures/ResetOrg_dn.png", + over = "rbxasset://Textures/ResetOrg_ovr.png", + }, + { + base = "rbxasset://Textures/Right_key.png", + disabled = "rbxasset://Textures/Right_key.png", + down = "rbxasset://Textures/Right_key_dn.png", + over = "rbxasset://Textures/Right_key.png", + }, + { + base = "rbxasset://Textures/Run.png", + disabled = "rbxasset://Textures/Run_ds.png", + down = "rbxasset://Textures/Run_dn.png", + over = "rbxasset://Textures/Run_ovr.png", + }, + { + base = "rbxasset://Textures/S_Key.png", + disabled = "rbxasset://Textures/S_Key.png", + down = "rbxasset://Textures/S_Key_dn.png", + over = "rbxasset://Textures/S_Key.png", + }, + { + base = "rbxasset://Textures/SelectionDown.png", + disabled = "rbxasset://Textures/SelectionDown_ds.png", + down = "rbxasset://Textures/SelectionDown.png", + over = "rbxasset://Textures/SelectionDown_ovr.png", + }, + { + base = "rbxasset://Textures/SelectionRotate.png", + disabled = "rbxasset://Textures/SelectionRotate_ds.png", + down = "rbxasset://Textures/SelectionRotate.png", + over = "rbxasset://Textures/SelectionRotate_ovr.png", + }, + { + base = "rbxasset://Textures/SelectionTilt.png", + disabled = "rbxasset://Textures/SelectionTilt_ds.png", + down = "rbxasset://Textures/SelectionTilt.png", + over = "rbxasset://Textures/SelectionTilt_ovr.png", + }, + { + base = "rbxasset://Textures/SelectionUp.png", + disabled = "rbxasset://Textures/SelectionUp_ds.png", + down = "rbxasset://Textures/SelectionUp.png", + over = "rbxasset://Textures/SelectionUp_ovr.png", + }, + { + base = "rbxasset://Textures/Stop.png", + disabled = "rbxasset://Textures/Stop_ds.png", + down = "rbxasset://Textures/Stop_dn.png", + over = "rbxasset://Textures/Stop_ovr.png", + }, + { + base = "rbxasset://Textures/StopReset.png", + disabled = "rbxasset://Textures/StopReset_ds.png", + down = "rbxasset://Textures/StopReset_dn.png", + over = "rbxasset://Textures/StopReset_ovr.png", + }, + { + base = "rbxasset://Textures/U_Key.png", + disabled = "rbxasset://Textures/U_Key.png", + down = "rbxasset://Textures/U_Key_dn.png", + over = "rbxasset://Textures/U_Key.png", + }, + { + base = "rbxasset://Textures/Up_key.png", + disabled = "rbxasset://Textures/Up_key.png", + down = "rbxasset://Textures/Up_key_dn.png", + over = "rbxasset://Textures/Up_key.png", + }, + { + base = "rbxasset://Textures/VelocityTool.png", + disabled = "rbxasset://Textures/VelocityTool_ds.png", + down = "rbxasset://Textures/VelocityTool_dn.png", + over = "rbxasset://Textures/VelocityTool_ovr.png", + }, + { + base = "rbxasset://Textures/W_Key.png", + disabled = "rbxasset://Textures/W_Key.png", + down = "rbxasset://Textures/W_Key_dn.png", + over = "rbxasset://Textures/W_Key.png", + }, +} + +return TextureGroups \ No newline at end of file diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/TimePeriods.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/TimePeriods.lua new file mode 100644 index 0000000..bce169f --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/TimePeriods.lua @@ -0,0 +1,12 @@ +return{ + ["August 2006"] = 1, + ["September 2006"] = 2, + ["October 2006"] = 3, + ["November 2006"] = 4, + ["December 2006"] = 5, + ["January 2007"] = 6, + ["February 2007"] = 7, + ["Eras March 2007"] = 7.5, + ["March 2007"] = 8, + ["April 2007"] = 9 +} \ No newline at end of file diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/Toolbox.lua b/rojo/MainModule/src/ReplicatedStorage/Modules/Toolbox.lua new file mode 100644 index 0000000..4b681df --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/Toolbox.lua @@ -0,0 +1,61 @@ +--[[ + Toolbox format: + + {Model ID, Thumbnail ID, Model name} +]] + +local Toolbox = { + {771, "rbxassetid://0", "Block 2x4x1"}, + {772, "rbxassetid://0", "Block 2x4x1 no join"}, + {773, "rbxassetid://0", "Block 2x4x1 hinged"}, + {774, "rbxassetid://0", "Block 2x2x6"}, + {775, "rbxassetid://0", "Block 4x8x1"}, + {776, "rbxassetid://0", "Block 4x4x1 turntable"}, + {777, "rbxassetid://0", "Ball 2x2x2"}, + {780, "rbxassetid://0", "Vertical Motor - Controllable"}, + {781, "rbxassetid://0", "Motorized Block Pair - Controllable"}, + {782, "rbxassetid://0", "Motorized Block Pair - Controllable"}, + {783, "rbxassetid://0", "Constant Velocity Motor Pair"}, + {784, "rbxassetid://0", "Motorized Block - Controllable"}, + {788, "rbxassetid://0", "Tree"}, + {789, "rbxassetid://0", "Chassis"}, + {794, "rbxassetid://0", "Dog"}, + {796, "rbxassetid://0", "Skateboard"}, + {797, "rbxassetid://0", "Skooter"}, + {801, "rbxassetid://0", "Bouncy Chassis"}, + {802, "rbxassetid://0", "Micro Chassis"}, + {805, "rbxassetid://0", "Truck Chassis"}, + {807, "rbxassetid://0", "Tank Chassis"}, + {808, "rbxassetid://0", "The Hammer"}, + {809, "rbxassetid://0", "Man on Scooter"}, + {810, "rbxassetid://0", "Blue Figure on Scooter"}, + {813, "rbxassetid://0", "Elevated Ramp"}, + {814, "rbxassetid://0", "Tilted Ramp"}, + {818, "rbxassetid://0", "Rotating Barrier"}, + {819, "rbxassetid://0", "Push Through Barrier"}, + {820, "rbxassetid://0", "100 Point Arch"}, + {825, "rbxassetid://0", "House"}, + {826, "rbxassetid://0", "Building"}, + {827, "rbxassetid://0", "Chassis with Figure"}, + {828, "rbxassetid://0", "Spasmotron"}, + {829, "rbxassetid://0", "Wimpotron"}, + {830, "rbxassetid://0", "Micro-troublemaker"}, + {832, "rbxassetid://0", "Attacking Bug"}, + {833, "rbxassetid://0", "Fleeing Bug"}, + {843, "rbxassetid://0", "25 Point flag"}, + {851, "rbxassetid://0", "Electron Canon - Mounted"}, + {852, "rbxassetid://0", "Electron Cannon"}, + {853, "rbxassetid://0", "Fragment Bomb"}, + {854, "rbxassetid://0", "Crazy Railroad Gate"}, + {855, "rbxassetid://0", "Spinner"}, + {856, "rbxassetid://0", "Rotating Obstacle"}, + {857, "rbxassetid://0", "Windmill Obstacle - Anchored"}, + {858, "rbxassetid://0", "5 Second Jewel"}, + {859, "rbxassetid://0", "Lose Game Beacon"}, + {860, "rbxassetid://0", "Win Game Beacon"}, + {862, "rbxassetid://0", "Man figure"}, + {863, "rbxassetid://0", "Blue figure"}, + {864, "rbxassetid://0", "Red Figure"}, +} + +return Toolbox diff --git a/rojo/MainModule/src/ReplicatedStorage/Modules/init.meta.json b/rojo/MainModule/src/ReplicatedStorage/Modules/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/Modules/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ReplicatedStorage/init.meta.json b/rojo/MainModule/src/ReplicatedStorage/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/ReplicatedStorage/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerScriptService/AdminServer/KillAura.server.lua b/rojo/MainModule/src/ServerScriptService/AdminServer/KillAura.server.lua new file mode 100644 index 0000000..f738011 --- /dev/null +++ b/rojo/MainModule/src/ServerScriptService/AdminServer/KillAura.server.lua @@ -0,0 +1,57 @@ +local Players = game:GetService("Players") +local RunService = game:GetService("RunService") +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local LocalPlayer = Players:GetPlayerFromCharacter(script.Parent) +local StockSound = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("StockSound")) + +local HeartbeatConnection + +local function Heartbeat(dt) + local LocalPrimaryPart = script.Parent.PrimaryPart + local LocalHumanoid = script.Parent:FindFirstChild("Humanoid") + + if (not LocalPrimaryPart) or (not LocalHumanoid) or (LocalHumanoid and LocalHumanoid.Health <= 0) then + HeartbeatConnection:Disconnect() + HeartbeatConnection = nil + + return + end + + for _, Player in pairs(Players:GetPlayers()) do + if Player == LocalPlayer then + continue + end + + local OtherCharacter = Player.Character + + if OtherCharacter then + local OtherHumanoid = OtherCharacter:FindFirstChild("Humanoid") + local OtherPrimaryPart = OtherCharacter.PrimaryPart + + if (not OtherPrimaryPart) or (not OtherHumanoid) then + continue + end + + local Distance = (OtherPrimaryPart.Position - LocalPrimaryPart.Position).Magnitude + + if Distance < 10 and OtherHumanoid.Health > 0 then + local Explosion = Instance.new("Explosion") + Explosion.Position = OtherPrimaryPart.Position + Explosion.BlastPressure = 0 + Explosion.DestroyJointRadiusPercent = 0 + Explosion.Parent = workspace + + local CreatorTag = Instance.new("ObjectValue") + CreatorTag.Name = "creator" + CreatorTag.Value = Players:GetPlayerFromCharacter(script.Parent) + CreatorTag.Parent = OtherHumanoid + + OtherHumanoid.Health = 0 + StockSound:PlaySound("Bomb") + end + end + end +end + +HeartbeatConnection = RunService.Heartbeat:Connect(Heartbeat) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerScriptService/AdminServer/init.server.lua b/rojo/MainModule/src/ServerScriptService/AdminServer/init.server.lua new file mode 100644 index 0000000..17445d2 --- /dev/null +++ b/rojo/MainModule/src/ServerScriptService/AdminServer/init.server.lua @@ -0,0 +1,391 @@ +-- FWM Admin Commands +-- I prefer having the commands be set in 1 script because it makes it easier for me imo +-- feel free to convince me otherwise + +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local ServerStorage = game:GetService("ServerStorage") +local ServerScriptService = game:GetService("ServerScriptService") +local TeleportService = game:GetService("TeleportService") +local TextService = game:GetService("TextService") +local DataStoreService = game:GetService("DataStoreService") +local MessengingService = game:GetService("MessagingService") +local Chat = game:GetService("Chat") + +local BannedUsers = DataStoreService:GetDataStore("FWM_MAIN_DATA", "Banned") +local BreakJoints = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("BreakJoints", nil)) + +local Protocols = ReplicatedStorage:WaitForChild("Protocols") + +local MuteSystem = require(ServerScriptService:WaitForChild("Chat"):WaitForChild("MuteSystem")) + +local BanList = {} +local commandBlacklistForUser = {} +-- [userid] = {"commandname", "commandname", "commandname"} + +local ServerLocked = false +local ShuttingDown = false + +local MenuPlaceId = 10789607669 +local DefaultGravity = workspace.Gravity + +local TriedFiringMessage = "this a jordan watch custom made my GG, my GG this stuff custom made" + +local function getById(id) + return Players:GetPlayerByUserId(id) +end + +local Commands = { + ["ban"] = function(commander, params) + local Player = getById(params[1]) + local Reason = params[2] or "No given reason" + + if Player then + local textFilterResult = TextService:FilterStringAsync(Reason, commander.UserId, Enum.TextFilterContext.PublicChat) + + if textFilterResult:IsA("TextFilterResult") then + local Filtered = textFilterResult:GetNonChatStringForBroadcastAsync() + + Player:Kick("\nYou have been banned from the server \nReason: "..Filtered) + BanList[Player.UserId] = Filtered + end + + Protocols.AdminRemotes.UpdateBanList:FireAllClients() + end + end, + + ["unban"] = function(commander, params) + local Id = params[1] + + if Id and tonumber(Id) and BanList[Id] then + BanList[Id] = nil + + Protocols.AdminRemotes.UpdateBanList:FireAllClients() + end + end, + + ["kick"] = function(commander, params) + local Player = getById(params[1]) + local Reason = params[2] or "No reason given" + + if Player then + local textFilterResult = TextService:FilterStringAsync(Reason, commander.UserId, Enum.TextFilterContext.PublicChat) + + if textFilterResult:IsA("TextFilterResult") then + local Filtered = textFilterResult:GetNonChatStringForBroadcastAsync() + + Player:Kick("\nYou have been kicked from the server \nReason: "..Filtered) + end + end + end, + + ["mute"] = function(commander, params) + local Player = getById(params[1]) + + if Player then + if not MuteSystem.isUserMuted(Player.UserId) then + MuteSystem.muteUser(Player.UserId) + else + MuteSystem.unmuteUser(Player.UserId) + end + end + end, + + ["teleport"] = function(commander, params) + local Player = getById(params[1]) + local PlayerTo = getById(params[2]) + + if (Player and PlayerTo) and (Player ~= PlayerTo) then + local PlayerCharacter = Player.Character + local PlayerToCharacter = PlayerTo.Character + + if PlayerCharacter and PlayerToCharacter then + local CharacterTorso = PlayerCharacter:FindFirstChild("Torso") + local ToCharacterTorso = PlayerToCharacter:FindFirstChild("Torso") + + if CharacterTorso and ToCharacterTorso then + local ToPosition = ToCharacterTorso.Position + local NewPosition = Vector3.new(ToPosition.X, ToPosition.Y + 5, ToPosition.Z) + + PlayerCharacter.Torso.CFrame = CFrame.new(NewPosition) + end + end + end + end, + + ["shutdown"] = function(commander, params) + local message = Instance.new("Message") + message.Name = "FWM_SHUTDOWN_MESSAGE" + message.Text = "Server shutting down..." + message.Parent = workspace + + ShuttingDown = true + ServerLocked = true + + TeleportService.TeleportInitFailed:Connect(function(player: Instance, teleportResult: Enum.TeleportResult, errorMessage: string, placeId: number, teleportOptions: Instance): () + if player:IsA("Player") then + player:Kick("Server shutdown, failed to send back to the menu.") + end + end) + + for _, v in pairs(Players:GetPlayers()) do + TeleportService:Teleport(MenuPlaceId, v, nil, nil) + end + end, + + ["lock"] = function(commander, params) + if not ShuttingDown then + ServerLocked = not ServerLocked + + local LockedMessage = Instance.new("Message") + LockedMessage.Name = "FWM_SERVERLOCK_NOTIFICATION" + LockedMessage.Text = "Server locked: "..tostring(ServerLocked) + LockedMessage.Parent = workspace + + task.wait(1) + + LockedMessage:Destroy() + end + end, + + ["message"] = function(commander, params) + local Message = params[1] + --local TimeUntilDeletion = math.max(60, tonumber(params[2]) or 5) + local TimeUntilDeletion = math.clamp(tonumber(params[2]) or 5, 0, 60) + + --if TimeUntilDeletion > 60 then + -- TimeUntilDeletion = 60 + --end + + if Message ~= "" then + local textFilterResult = TextService:FilterStringAsync(Message, commander.UserId, Enum.TextFilterContext.PublicChat) + + if textFilterResult:IsA("TextFilterResult") then + local Filtered = textFilterResult:GetNonChatStringForBroadcastAsync() + + local NewMessage = Instance.new("Message") + NewMessage.Name = "FWM_SENT_MESSAGE" + NewMessage.Text = commander.Name..": "..Filtered + NewMessage.Parent = workspace + + task.wait(TimeUntilDeletion) + + NewMessage:Destroy() + end + end + end, + + ["kill"] = function(commander, params) + local Target = getById(params[1]) + + if Target and Target.Character then + BreakJoints(Target.Character) + end + end, + + ["gravity"] = function(commander, params) + local GravitySetting = tonumber(params[1]) or DefaultGravity + + workspace.Gravity = GravitySetting + end, + + ["speed"] = function(commander, params) + local Target = getById(params[1]) + local SpeedAmt = tonumber(params[2]) or 16 + + if Target and Target.Character then + local Humanoid = Target.Character:FindFirstChild("Humanoid") + + if Humanoid then + Humanoid.WalkSpeed = SpeedAmt + end + end + end, + + ["jump"] = function(commander, params) + local Target = getById(params[1]) + local JumpAmt = tonumber(params[2]) or 50 + + if Target and Target.Character then + local Humanoid = Target.Character:FindFirstChild("Humanoid") + + if Humanoid then + Humanoid.JumpPower = JumpAmt + end + end + end, + + ["god"] = function(commander, params) + local Target = getById(params[1]) + + if Target and Target.Character then + local Forcefield = Target.Character:FindFirstChildOfClass("ForceField") + local Humanoid = Target.Character:FindFirstChild("Humanoid") + + if Humanoid then + if Forcefield then + Forcefield:Destroy() + + Humanoid.Health = 100 + Humanoid.MaxHealth = 100 + else + local New = Instance.new("ForceField") + New.Visible = false + New.Parent = Target.Character + + Humanoid.Health = Humanoid.MaxHealth + Humanoid.MaxHealth = math.huge + end + end + end + end, + + ["killaura"] = function(commander, params) + local TheresCharacter = commander.Character + + if TheresCharacter then + local HasAura = TheresCharacter:FindFirstChild("KillAura") + + if HasAura then + HasAura:Destroy() + else + local KillauraScript = script.KillAura:Clone() + KillauraScript.Parent = TheresCharacter + KillauraScript.Enabled = true + end + end + end, + + ["hopperbin"] = function(commander, params) + local Target = getById(params[1]) + local SelectedHopper = params[2] + if not (Target and SelectedHopper) then + return + end + + local HopperBinFolder = ServerStorage:FindFirstChild("HopperBins") + local Hopper = HopperBinFolder:FindFirstChild(SelectedHopper) + + if Hopper then + local NewHop = Hopper:Clone() + local PlayerBackpack = Target.Backpack + + if PlayerBackpack then + NewHop.Parent = PlayerBackpack + end + end + end, + + ["game ban"] = function(commander, params) + local IsUser = params[1] + local TheresType = params[2] + local BanReason = params[3] + + if IsUser and tostring(IsUser) and TheresType and BanReason then + local IsPerma = tonumber(params[2]) == 0 + + local UserId + local Success, Failed = pcall(function() + UserId = Players:GetUserIdFromNameAsync(IsUser) + end) + + if (not Failed) then + local BannedData = { + UnbanTime = IsPerma and "Never" or os.time() + params[2], + Reason = BanReason + } + + local Banned, FailedToBan = pcall(function() + return BannedUsers:UpdateAsync(UserId, function() + return BannedData + end) + end) + + if Banned then + local Published, PublishFailed = pcall(function() + MessengingService:PublishAsync("BanCheck", { + BannedUserId = UserId, + }) + end) + end + end + end + end, + + ["game unban"] = function(commander, params) + local UserName = params[1] + + if UserName and tostring(UserName) then + local UserId + local Success, Failed = pcall(function() + UserId = Players:GetUserIdFromNameAsync(UserName) + end) + + if (not Failed) then + local Unbanned, FailedToUnban = pcall(function() + return BannedUsers:RemoveAsync(UserId) + end) + end + end + end, +} + +local function adminEventFired(Player, Command, ...) + local Parameters = ... + + if Player:GetAttribute("IsAdmin") then + if Parameters then + local commandName = string.lower(Command) + local validCommand = Commands[commandName] + + local canUse = true + local existsInBlacklistTable = commandBlacklistForUser[Player.UserId] + + if existsInBlacklistTable then + canUse = (table.find(existsInBlacklistTable, commandName) == nil) + end + + if validCommand and canUse then + task.spawn(function() + validCommand(Player, Parameters) + end) + end + end + else + Player:Kick("\nYou have been kicked from the server \nReason: "..TriedFiringMessage) + BanList[Player.UserId] = TriedFiringMessage + end +end + +local function getBannedPlayers() + return BanList +end + +-- the acts of ENPHOSO... +local function playerAdded(player: Player) + --if ServerLocked and player:GetRankInGroup(5201932) < 250 then + if ServerLocked then + if player:GetRankInGroup(5201932) < 250 then + player:Kick("The server has been locked by an admin!") + end + elseif BanList[player.UserId] then + player:Kick("\nYou have been banned from the server \nReason: "..BanList[player.UserId]) + end +end + +local function SyncWithBan(Information) + local GrabbedData = Information.Data + local PlayerUserId = GrabbedData.BannedUserId + + local IsInServer = Players:GetPlayerByUserId(PlayerUserId) + + if IsInServer then + IsInServer:Kick("You have been moderated. Rejoin to view more information.") + end +end + +Players.PlayerAdded:Connect(playerAdded) +MessengingService:SubscribeAsync("BanCheck", SyncWithBan) + +Protocols:WaitForChild("AdminRemotes"):WaitForChild("AdminEvent").OnServerEvent:Connect(adminEventFired) +Protocols:WaitForChild("AdminRemotes"):WaitForChild("GetBanned").OnServerInvoke = getBannedPlayers \ No newline at end of file diff --git a/rojo/MainModule/src/ServerScriptService/Chat/MuteSystem.lua b/rojo/MainModule/src/ServerScriptService/Chat/MuteSystem.lua new file mode 100644 index 0000000..30bad93 --- /dev/null +++ b/rojo/MainModule/src/ServerScriptService/Chat/MuteSystem.lua @@ -0,0 +1,39 @@ +--[[ + Returns a table that chat reads and if a player is in it they are muted. +]] +local MuteSystem = {} +local TextChatService = game:GetService("TextChatService") + +local mutedUsers = {} + +function MuteSystem.muteUser(userId: number) + mutedUsers[userId] = true; + + --for _, v in pairs(TextChatService:WaitForChild("TextChannels"):WaitForChild("RBXGeneral"):GetDescendants()) do + -- if v:IsA("TextSource") then + -- if v.UserId == userId then + -- v.CanSend = false + -- end + -- end + --end +end + +function MuteSystem.unmuteUser(userId: number) + if userId then + mutedUsers[userId] = nil; + end + + --for _, v in pairs(TextChatService:WaitForChild("TextChannels"):WaitForChild("RBXGeneral"):GetDescendants()) do + -- if v:IsA("TextSource") then + -- if v.UserId == userId then + -- v.CanSend = true + -- end + -- end + --end +end + +function MuteSystem.isUserMuted(userId: number) + return mutedUsers[userId]; +end + +return MuteSystem \ No newline at end of file diff --git a/rojo/MainModule/src/ServerScriptService/Chat/init.server.lua b/rojo/MainModule/src/ServerScriptService/Chat/init.server.lua new file mode 100644 index 0000000..d82fb9a --- /dev/null +++ b/rojo/MainModule/src/ServerScriptService/Chat/init.server.lua @@ -0,0 +1,154 @@ +--!strict +--[[ + Classic Roblox Clothes! 2022 + + Handle chat messages serverside for text-filtering and broadcasting to players. +]] +local Chat = game:GetService("Chat") +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local ServerStorage = game:GetService("ServerStorage") +local TextService: TextService = game:GetService("TextService") +local ScriptContext: ScriptContext = game:GetService("ScriptContext") +local HttpService: HttpService = game:GetService("HttpService") + +local SuperSafeChat = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("SuperSafeChat")) +local DecodedSuperSafeChat = HttpService:JSONDecode(SuperSafeChat) +local FullDecoded = DecodedSuperSafeChat["roblox"]["utterance"] + +local CurrentTimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value + +local MuteSystem = require(script:WaitForChild("MuteSystem")) +local protocols = ReplicatedStorage:WaitForChild("Protocols") + +local function findSSC(tabl) + local candecode = tabl[1] + local isValid = tonumber(candecode) + local currentDecode = nil + + if isValid then + currentDecode = FullDecoded[isValid + 1] + + if candecode and currentDecode then + for i, v in pairs(tabl) do + if i == 1 then + continue + end + + local newValue = tonumber(v) + + if newValue then + if not currentDecode then + break + end + + local trueValue = newValue + 1 + + if currentDecode["utterance"] then + local getType = typeof(currentDecode["utterance"]) + + if getType == "table" then + local grabbedDecode = currentDecode["utterance"][trueValue] + + if grabbedDecode then + currentDecode = grabbedDecode + else + currentDecode = currentDecode[trueValue] + end + else + currentDecode = (trueValue == 1 and currentDecode["utterance"]) or nil + end + end + end + end + + if currentDecode and currentDecode["#text"] then + currentDecode = currentDecode["#text"] + end + end + end + + return currentDecode or "" +end + +Players.PlayerAdded:Connect(function(player: Player): () + player.Chatted:Connect(function(message: string, recipient: Player): () + if MuteSystem.isUserMuted(player.UserId) then + return + end + + local noWhiteSpace = string.gsub(message, "\n", " ") + local textFilterResult: Instance = TextService:FilterStringAsync(noWhiteSpace, player.UserId, Enum.TextFilterContext.PublicChat) + + if textFilterResult:IsA("TextFilterResult") then + for i: number, v: Player in ipairs(Players:GetPlayers()) do + if Chat:CanUsersChatAsync(player.UserId, v.UserId) then + + local filteredMessage: string = textFilterResult:GetChatForUserAsync(v.UserId) + local gotFiltered: boolean = message ~= filteredMessage + + if CurrentTimePeriod >= 8 then + local findSc = string.sub(filteredMessage, 1, 3) + + if findSc == "/sc" then + local subbedsc = string.split(filteredMessage, " ") + table.remove(subbedsc, 1) + + filteredMessage = (#subbedsc >= 1 and findSSC(subbedsc)) or "ROOT" + end + end + + if gotFiltered and player.UserId ~= v.UserId then + continue + end + + protocols.Chat:FireClient(v, player, filteredMessage, gotFiltered) + + if message:match("//") then -- anti-thomas technology + player:Kick() + end + + end + end + end + end) +end) + +ScriptContext.Error:Connect(function(message: string, stackTrace: string, script: Instance): () + for i: number, v: Player in ipairs(Players:GetPlayers()) do + --if Chat:CanUsersChatAsync(player.UserId, v.UserId) then + --local filteredMessage: string = textFilterResult:GetChatForUserAsync(v.UserId) + + protocols.Chat:FireClient(v, "[ERROR!]", message) + --end + end +end) + +-- april fools + +--local aprilfoolsmessage = { +-- "YOU ARE BEING WATCHED", +-- "I AM COMING...", +-- "HACKING PLACE...", +-- "I have you PC NAME", +-- "consider yourself lucky...", +-- "JohnsPuzzleGame is a FRAUD", +-- "whoever made this you caused all this pain and agony", +-- "I'm watching...", +-- "HACKED BY MADGANGZ", +-- "PBB seems like a GREAT game to upload onto FWM!", +-- "SFOTH I release date: NEVER", +-- "TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO Do not touch the keyboard TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO TECHNO", +-- ":baldi all", +-- "127.0.0.1" +--} + +--while true do +-- local ran = math.random(1, 60) +-- local randommes = aprilfoolsmessage[math.random(1, #aprilfoolsmessage)] +-- task.wait(ran) + +-- for i: number, v: Player in ipairs(Players:GetPlayers()) do +-- protocols.Chat:FireClient(v, "[MADGANGZ]", randommes) +-- end +--end \ No newline at end of file diff --git a/rojo/MainModule/src/ServerScriptService/GameCount.server.lua b/rojo/MainModule/src/ServerScriptService/GameCount.server.lua new file mode 100644 index 0000000..fb4f222 --- /dev/null +++ b/rojo/MainModule/src/ServerScriptService/GameCount.server.lua @@ -0,0 +1,46 @@ +local MarketplaceService = game:GetService("MarketplaceService") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local RunService = game:GetService("RunService") +local MessagingService = game:GetService("MessagingService") +local Players = game:GetService("Players") +local HttpsService = game:GetService("HttpService") + +local IsSolo = ReplicatedStorage:WaitForChild("Solo") +local GameServerId = HttpsService:GenerateGUID(false) -- could've used JobId, but tbh this looks cooler + +local Message + +local function UpdateCount() + local PlayerCount = #Players:GetPlayers() + + local Success, Errored = pcall(function() + Message = MessagingService:PublishAsync("PlayersOnline", { + GameId = game.PlaceId, + ServerId = GameServerId, + PlayersOnline = PlayerCount, + }) + end) + + if PlayerCount <= 0 then + if Message then + Message:Disconnect() + Message = nil + end + end + + if Success then + print("Data sent!") + end +end + +if game.PrivateServerId == "" and not RunService:IsStudio() then + game:BindToClose(function() + UpdateCount() + end) + + while task.wait(25) do + UpdateCount() + end +else + print("Cannot update count in solo!") +end \ No newline at end of file diff --git a/rojo/MainModule/src/ServerScriptService/LegacyVisualsServer.server.lua b/rojo/MainModule/src/ServerScriptService/LegacyVisualsServer.server.lua new file mode 100644 index 0000000..e00478f --- /dev/null +++ b/rojo/MainModule/src/ServerScriptService/LegacyVisualsServer.server.lua @@ -0,0 +1,173 @@ +--!strict +--[[ + Classic Roblox Clothes! 2022 + + Handles serverside effects such as configuration, collision, etc. +]] +local CollectionService: CollectionService = game:GetService("CollectionService") +local Debris: Debris = game:GetService("Debris") +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local StarterPlayer = game:GetService("StarterPlayer") +local ContentProvider = game:GetService("ContentProvider") +local Lighting = game:GetService("Lighting") + +local Templates = ReplicatedStorage:WaitForChild("Templates") +local Protocols = ReplicatedStorage:WaitForChild("Protocols") + +local CurrentTimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value + +StarterPlayer.AutoJumpEnabled = false +StarterPlayer.EnableMouseLockOption = false + +StarterPlayer.DevComputerCameraMovementMode = Enum.DevComputerCameraMovementMode.Follow +StarterPlayer.DevTouchCameraMovementMode = Enum.DevTouchCameraMovementMode.Follow +StarterPlayer.DevComputerMovementMode = Enum.DevComputerMovementMode.KeyboardMouse + +StarterPlayer.CameraMaxZoomDistance = 358 -- 258 + +local function fakeCylinderEffect(cylinder: Part): () + cylinder.Shape = Enum.PartType.Ball + cylinder:SetAttribute("Cylinder", true) +end + +local function convertRotate(object : Rotate) + local convert : Rotate = Instance.new("Rotate") + convert.Parent = object.Parent + convert.C0 = object.C0 + convert.C1 = object.C1 + convert.Part0 = object.Part0 + convert.Part1 = object.Part1 + convert.Name = object.Name + + object:Destroy() +end + +local function createWeld(parent: Instance?, part0: BasePart?, part1: BasePart?): () + local weld: WeldConstraint = Instance.new("WeldConstraint") + weld.Part0 = part0 + weld.Part1 = part1 + weld.Parent = parent +end + +local function applyControllerFlag(model: Model, color: string): () + if model.PrimaryPart ~= nil and model.Parent then + if not model.Parent:FindFirstChildOfClass("VehicleSeat") then + local primarypart : Instance? = model.PrimaryPart + local primaryPosition: Vector3 = model.PrimaryPart.Position + + local _: CFrame, modelSize: Vector3 = model:GetBoundingBox() + + local vehicleSeat: VehicleSeat = Instance.new("VehicleSeat") + vehicleSeat.BrickColor = BrickColor.new(color) + vehicleSeat.CanCollide = false + vehicleSeat.CanQuery = false + vehicleSeat.CanTouch = false + vehicleSeat.Locked = true + vehicleSeat.Transparency = 1 + vehicleSeat.Name = "VS" + vehicleSeat.Orientation = model.PrimaryPart.Orientation + vehicleSeat.Position = primaryPosition + vehicleSeat.Size = model.PrimaryPart.Size + vehicleSeat.Parent = model + + createWeld(vehicleSeat, vehicleSeat, model.PrimaryPart) + CollectionService:AddTag(vehicleSeat, "ControllerSeat") + + local triangleNode1: Part = Instance.new("Part") + triangleNode1.Anchored = false + triangleNode1.CanCollide = false + triangleNode1.CanQuery = false + triangleNode1.CanTouch = false + triangleNode1.Locked = true + triangleNode1.Orientation = Vector3.new(0, 90, 90) + triangleNode1.Position = Vector3.new(primaryPosition.X, modelSize.Y + 0.52, primaryPosition.Z + 1.5) + triangleNode1.Size = Vector3.new(0.001, 0.001, 0.001) + triangleNode1.Transparency = 1 + triangleNode1.Parent = primarypart + + createWeld(primarypart, triangleNode1, model.PrimaryPart) + + local triangleNode2: Part = Instance.new("Part") + triangleNode2.Anchored = false + triangleNode2.CanCollide = false + triangleNode2.CanQuery = false + triangleNode2.CanTouch = false + triangleNode2.Locked = true + triangleNode2.Orientation = Vector3.new(0, -90, -90) + triangleNode2.Position = Vector3.new(primaryPosition.X, modelSize.Y + 0.52, primaryPosition.Z + 1.5) + triangleNode2.Size = Vector3.new(0.001, 0.001, 0.001) + triangleNode2.Transparency = 1 + triangleNode2.Parent = primarypart + + createWeld(primarypart, triangleNode2, model.PrimaryPart) + + local flagPole = Templates.Textures.Adornees.FlagPole:Clone() + flagPole.Adornee = primarypart + flagPole.Color3 = BrickColor.new(color).Color + flagPole.Length = modelSize.Y + flagPole.Parent = primarypart + + local triangle1 = Templates.Textures.Adornees.FlagTriangle:Clone() + triangle1.Adornee = triangleNode1 + triangle1.Color3 = BrickColor.new(color).Color + triangle1.Parent = primarypart + + local triangle2 = Templates.Textures.Adornees.FlagTriangle:Clone() + triangle2.Adornee = triangleNode2 + triangle2.Color3 = BrickColor.new(color).Color + triangle2.Parent = primarypart + + if primarypart and primarypart:IsA("Part") then + createWeld(primarypart, primarypart, model.PrimaryPart) + end + end + end +end + +--local function removeVehicleSeatTag(object: VehicleSeat): () +-- CollectionService:RemoveTag(object, "ControllerSeat") +--end + +local function oldifyMain(descendant: Instance): () + if descendant:IsA("Terrain") then + return + end + + if descendant:IsA("Part") and descendant.Shape == Enum.PartType.Cylinder then + fakeCylinderEffect(descendant) + end +end + +--local function disconnect(descendant: Instance): () +-- if descendant:IsA("VehicleSeat") then +-- removeVehicleSeatTag(descendant) +-- end +--end + +for _: number, v: Instance in pairs(workspace:GetDescendants()) do + oldifyMain(v) +end + +workspace.DescendantAdded:Connect(oldifyMain) +--workspace.DescendantRemoving:Connect(disconnect) + +if ReplicatedStorage.Solo.Value == true then + Players.PlayerAdded:Connect(function(player: Player) --very nice spaghetti pasta code + print(player.Name.." is the solo player") + + for _, v in pairs(workspace:GetDescendants()) do + if v:IsA("Model") and v:GetAttribute("Controller") ~= nil then + if v:GetAttribute("Controller") ~= "None" then + for _, part in pairs(v:GetDescendants()) do + if part:IsA("BasePart") then + if part.Anchored == false then + part:SetNetworkOwner(player) + end + end + end + end + end + end + end) +end \ No newline at end of file diff --git a/rojo/MainModule/src/ServerScriptService/PlayerHandler.server.lua b/rojo/MainModule/src/ServerScriptService/PlayerHandler.server.lua new file mode 100644 index 0000000..8d59db9 --- /dev/null +++ b/rojo/MainModule/src/ServerScriptService/PlayerHandler.server.lua @@ -0,0 +1,427 @@ +--[[ + Classic Roblox Clothes! 2022 + + Handles loading characters, including loading character appearance. +]] +local AssetService: AssetService = game:GetService("AssetService") +local DataStoreService: DataStoreService = game:GetService("DataStoreService") +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local RunService: RunService = game:GetService("RunService") +local ServerStorage = game:GetService("ServerStorage") +local TeleportService: TeleportService = game:GetService("TeleportService") +local StarterGui: StarterGui = game:GetService("StarterGui") + +local UI = ServerStorage:WaitForChild("UI") + +local StarterGuis = UI:WaitForChild("StarterGui") +local AdminGuis = UI:WaitForChild("AdminGuis") + +local Main: GlobalDataStore = DataStoreService:GetDataStore("FWM_MAIN_DATA") +local TimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value + +local JoinDatas = {} +local Loaded = {} + +local BodyParts: { [string] : string } = { + ["Head"] = "Head", + ["Torso"] = "Torso", + ["LeftArm"] = "Left Arm", + ["RightArm"] = "Right Arm", + ["LeftLeg"] = "Left Leg", + ["RightLeg"] = "Right Leg", +} + +local SpecialHats = { + [151461991] = { + ServerStorage:WaitForChild("Accessories"):WaitForChild("Gloves"), + }, + + [351006260] = { + ServerStorage:WaitForChild("Accessories"):WaitForChild("Pumpkin"), + ServerStorage:WaitForChild("Accessories"):WaitForChild("Stem") + }, +} + +local function InsertAccessories(Character): () + local Player = Players:GetPlayerFromCharacter(Character) + + if Player then + if SpecialHats[Player.UserId] ~= nil then + for Obj, _ in pairs(SpecialHats[Player.UserId]) do + local NewAccessory = SpecialHats[Player.UserId][Obj]:Clone() + NewAccessory.Parent = Character + end + end + end +end + +local function GrabSetting(Player: Player, Setting: string): boolean | number + local Data = JoinDatas[Player.UserId] + + if RunService:IsStudio() or Data then + local TeleportData = Data + + if TeleportData ~= nil then + local SettingFound = TeleportData["UserData"]["Settings"] + local Specific = SettingFound[Setting] + + if type(Specific) == "boolean" then + return Specific + elseif type(Specific) == "number" then + return Specific + else + + return false + end + else + print("Request failed!") + + return false + end + else + return false + end +end + +local function LoadCharacterAppearance(Player): () + local Data = JoinDatas[Player.UserId] + + local isClimbing = Instance.new("BoolValue") + isClimbing.Name = "isClimbing" + isClimbing.Value = false + isClimbing:SetAttribute("FWMClimb", true) + isClimbing.Parent = Player.Character + + if TimePeriod >= 9 then + local isDiscWalking = Instance.new("BoolValue") + isDiscWalking.Name = "isDiscWalking" + isDiscWalking.Value = false + isDiscWalking:SetAttribute("FWMDiscWalk", true) + isDiscWalking.Parent = Player.Character + end + + if RunService:IsStudio() or Data then + local TeleportData = Data + + if TeleportData ~= nil then + local AvatarToGive = (TimePeriod <= 7 and TeleportData["Avatar2006"]) or TeleportData["Avatar"] + + if Player:GetAttribute("IsAdmin") then + AvatarToGive = TeleportData["Avatar"] --sorry vivin + end + + for i, v in pairs(AvatarToGive) do + if BodyParts[i] then + Player.Character[BodyParts[i]].BrickColor = BrickColor.new(v) + end + end + + if AvatarToGive["TShirt"] then + Player.Character.Torso.roblox.Texture = "rbxassetid://"..AvatarToGive["TShirt"] + end + + if AvatarToGive["Face"] then + Player.Character.Head.face.Texture = "rbxassetid://"..AvatarToGive["Face"] + end + else + print("No Teleport data found, using defaults.") + end + else + print("Unauthorized player request sent! | FWM Debug") + end +end + +-- returns the player object that killed this humanoid +-- returns nil if the killer is no longer in the game +function getKillerOfHumanoidIfStillInGame(humanoid) + + -- check for kill tag on humanoid - may be more than one - todo: deal with this + local tag = humanoid:findFirstChild("creator") + + -- find player with name on tag + if tag then + local killer = tag.Value + if killer.Parent then -- killer still in game + return killer + end + end + + return nil +end + +-- complete port (with minor modification) of ROBLOX's 2007 brick battle stat handler LOLOLOL +local function onDied(victim : Player, humanoid : Humanoid): () + local VictimData = JoinDatas[victim.UserId] + + if VictimData then -- makes sure that the victim's data has loaded + local killer = getKillerOfHumanoidIfStillInGame(humanoid) + + local victorId = 0 + + local VictimDataStats = VictimData["UserData"]["BrickBattleData"] + local KillerDataStats + + if killer and JoinDatas[killer.UserId] then + victorId = killer.UserId + KillerDataStats = JoinDatas[victorId]["UserData"]["BrickBattleData"] + print("STAT: kill by "..victorId .." of "..victim.UserId) + KillerDataStats["KOs"] += 1 + end + + print("STAT: death of " .. victim.UserId .. " by " .. victorId) + VictimDataStats["WOs"] += 1 + end +end + +local function FixUIsFor2006(Player: Player): () + local PlayerGui = Player:FindFirstChild("PlayerGui") + + local findMainGui = PlayerGui:FindFirstChild("MainGui") + local findMainResetGui = PlayerGui:FindFirstChild("MainResetGui") + + if findMainGui then + findMainGui.Enabled = true + end + + if findMainResetGui then + findMainResetGui.Enabled = true + end +end + +local function GiveUIsToPlayer(Player: Player, GiveUIs: boolean): () + if (not GiveUIs) then + return + end + + task.defer(function() + local PlayerGui = Player:FindFirstChild("PlayerGui") + + for _, obj in pairs(StarterGuis:GetChildren()) do + local canGiveObj = obj:GetAttribute("DontGiveAgain") + + if (not (obj:IsA("ScreenGui") and (not obj.ResetOnSpawn))) and (not canGiveObj) then + local clonedObject = obj:Clone() + clonedObject.Parent = PlayerGui + end + end + + FixUIsFor2006(Player) + end) +end + +local function HandleDeath(Player: Player): () + if Player then + task.wait(Players.RespawnTime) + + if Player ~= nil then + Player:LoadCharacter() + --ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("CharacterAdded"):FireAllClients(Player.CharacterAdded) + --LoadCharacterAppearance(Player) + end + end +end + +local function PlayerRemoving(player: Player): () + local CurrentData = JoinDatas[player.UserId] + + if CurrentData then + JoinDatas[player.UserId] = nil -- removes before starting UpdateAsync, which yields + + local findLoaded = Loaded[player] + + if findLoaded then + Loaded[player] = nil + end + + local NewData = { + ["FWM_USER_DATA_"..player.UserId] = { + ["PlayerData"] = CurrentData + } + } + + local Saved, Failed = pcall(function() + Main:UpdateAsync("FWM_TESTING_DATA_"..player.UserId, function(OldData) + return NewData + end) + end) + + if Saved then + print(string.format("Saved data for %s (Display Name: %s, UserId: %d)", player.Name, player.DisplayName, player.UserId)) + else + print(string.format("Failed to save data for %s (Display Name: %s, UserId: %d)", player.Name, player.DisplayName, player.UserId)) + end + end +end + +-- not an ideal thing at all, im just doing this so animations remain accurate +local function discWalkingFired(player: Player, value: boolean): () + local playerChar = player.Character + local hasDiscValue = playerChar:FindFirstChild("isDiscWalking") + + if (TimePeriod < 9) or (not hasDiscValue) then + return + end + + hasDiscValue.Value = value +end + +local function oldClimbFired(player: Player, value: boolean): () + local playerChar = player.Character + local climbValue = playerChar:FindFirstChild("isClimbing") + + if (not climbValue) then + return + end + + climbValue.Value = value +end + +local function loadForFirstTime(player: Player) + local findLoaded = Loaded[player] + local uiOnRespawn = false + + if not findLoaded then + Loaded[player] = true + + task.wait(3) + + player.CharacterAdded:Connect(function(character) + LoadCharacterAppearance(player) + GiveUIsToPlayer(player, uiOnRespawn) + InsertAccessories(character) + + if (not uiOnRespawn) then + uiOnRespawn = true + end + + local humanoid = character:WaitForChild("Humanoid", 5) + + if humanoid then + humanoid.Died:Connect(function() + onDied(player, humanoid) + HandleDeath(player) + end) + end + end) + + player:LoadCharacter() + + --ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("CharacterAdded"):FireAllClients(player.Character) + --LoadCharacterAppearance(player) + + print(player.Name .. " Loaded") + + local playerGui = player:FindFirstChildOfClass("PlayerGui") + playerGui.Loading:Destroy() + + FixUIsFor2006(player) + end +end + +local function PlayerAdded(player: Player) + local playerUI = player:WaitForChild("PlayerGui") + local isAdmin + + local success, failed = pcall(function() + isAdmin = (player:GetRankInGroup(15820336) > 251) + end) + + if success and isAdmin then + player:SetAttribute("IsAdmin", true) + + for _, obj in pairs(AdminGuis:GetChildren()) do + obj:Clone().Parent = playerUI + end + --ServerStorage:WaitForChild("UI"):WaitForChild("Admi"):Clone().Parent = playerUI + --ServerStorage:WaitForChild("UI"):WaitForChild("ESP"):Clone().Parent = playerUI + end + + local Data = player:GetJoinData() + + --if table.find(PlaceIDs, Data.SourcePlaceId) then + if Data.SourceGameId == game.GameId then + JoinDatas[player.UserId] = Data.TeleportData + end + + for _, obj in pairs(StarterGuis:GetChildren()) do + obj:Clone().Parent = playerUI + end + + --for _, obj in pairs(StarterGui:GetChildren()) do + -- obj:Clone().Parent = playerUI + --end + --end + + --ServerStorage:WaitForChild("UI"):WaitForChild("Loading"):Clone().Parent = playerUI + + --ServerStorage:WaitForChild("UI"):WaitForChild("MainGui"):Clone().Parent = playerUI + --ServerStorage:WaitForChild("UI"):WaitForChild("MainResetGui"):Clone().Parent = playerUI +end + +local function hatDropServer(player: Player): () + local playerChar = player.Character + + if not playerChar then + return + end + + for _, obj in pairs(playerChar:GetChildren()) do + if obj:IsA("Accoutrement") then + obj.Parent = workspace + end + end +end + +--local standardPages = AssetService:GetGamePlacesAsync() + +--for _, Places in pairs(standardPages:GetCurrentPage()) do +-- table.insert(PlaceIDs, tonumber(Places.PlaceId)) +--end + +if TimePeriod < 8 then + local TheresMainGui = StarterGuis:FindFirstChild("MainGui") + local TheresResetGui = StarterGui:FindFirstChild("MainResetGui") + + if TheresMainGui then + TheresMainGui.Enabled = false + end + + if TheresResetGui then + TheresResetGui.Enabled = false + end +end + +ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("LoadForFirstTime").OnServerEvent:Connect(loadForFirstTime) + +-- dumb fix for playerhandler being created after player exists +for _, Player in pairs(Players:GetPlayers()) do + PlayerAdded(Player) +end + +Players.PlayerAdded:Connect(PlayerAdded) +Players.PlayerRemoving:Connect(PlayerRemoving) + +ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("GetSetting").OnServerInvoke = GrabSetting + +ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("DiscWalking").OnServerEvent:Connect(discWalkingFired) +ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("Climbing").OnServerEvent:Connect(oldClimbFired) + +ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("Drop").OnServerEvent:Connect(hatDropServer) + +game:BindToClose(function() + local message: Message = Instance.new("Message") + message.Name = "FWM_SHUTDOWN_MESSAGE" + message.Text = "Server shutting down..." + message.Parent = workspace + + TeleportService.TeleportInitFailed:Connect(function(player: Instance, teleportResult: Enum.TeleportResult, errorMessage: string, placeId: number, teleportOptions: Instance): () + if player:IsA("Player") then + player:Kick("Server shutdown, failed to send back to the menu.") + end + end) + + for _, v in pairs(Players:GetPlayers()) do + TeleportService:Teleport(10789607669, v, nil, nil) + end +end) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerScriptService/ToolboxServer.server.lua b/rojo/MainModule/src/ServerScriptService/ToolboxServer.server.lua new file mode 100644 index 0000000..3ecda5b --- /dev/null +++ b/rojo/MainModule/src/ServerScriptService/ToolboxServer.server.lua @@ -0,0 +1,42 @@ +--[[ + Toolbox server code +]] +local RunService = game:GetService("RunService"); +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local ServerStorage = game:GetService("ServerStorage") + +local insertProtocol = ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("InsertContent") +local solo = ReplicatedStorage:FindFirstChild("Solo") +local models = ServerStorage:WaitForChild("Models") + +local function toolboxShouldBeEnabled(): boolean + return solo.Value or RunService:IsStudio(); +end + +local function authenticateInsertContent(player: Player, assetId: number): number? + print(player, assetId) + + if not toolboxShouldBeEnabled() then + return + end + + if player then + local model: Instance? = models:FindFirstChild(assetId) + + if model then + local model: Model? = model:FindFirstChildOfClass("Model") + + if model then + model:Clone().Parent = workspace + end + + return assetId + end + + return nil + else + return nil + end +end + +insertProtocol.OnServerInvoke = authenticateInsertContent \ No newline at end of file diff --git a/rojo/MainModule/src/ServerScriptService/init.meta.json b/rojo/MainModule/src/ServerScriptService/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/ServerScriptService/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/Accessories/Gloves/Script.server.lua b/rojo/MainModule/src/ServerStorage/Accessories/Gloves/Script.server.lua new file mode 100644 index 0000000..b92b0e2 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/Accessories/Gloves/Script.server.lua @@ -0,0 +1,17 @@ +local Character = script.Parent.Parent + +local LeftWeld = Instance.new("Weld") +LeftWeld.Part0 = script.Parent.LeftGlove +LeftWeld.Part1 = Character["Left Arm"] +LeftWeld.C0 = CFrame.new(0, 0.65, 0) * CFrame.Angles(0, math.rad(-180), 0) + +LeftWeld.Parent = script.Parent.LeftGlove + +local RightWeld = Instance.new("Weld") +RightWeld.Part0 = script.Parent.RightGlove +RightWeld.Part1 = Character["Right Arm"] +RightWeld.C0 = CFrame.new(0, 0.65, 0) * CFrame.Angles(0, math.rad(-180), 0) + +RightWeld.Parent = script.Parent.RightGlove + +script:Destroy() \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/Accessories/Gloves/init.meta.json b/rojo/MainModule/src/ServerStorage/Accessories/Gloves/init.meta.json new file mode 100644 index 0000000..aa46eea --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/Accessories/Gloves/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Model", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/Accessories/init.meta.json b/rojo/MainModule/src/ServerStorage/Accessories/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/Accessories/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/Dependencies/Explosion.lua b/rojo/MainModule/src/ServerStorage/Dependencies/Explosion.lua new file mode 100644 index 0000000..7febc36 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/Dependencies/Explosion.lua @@ -0,0 +1,73 @@ +--[[ + + FWM Official, 2022 + Modification of ROBLOX Battle's Explosion Module, for FWM + +]]-- + +local module = {} +local Debris = game:GetService("Debris") + +--local function HandleExplosion(Position) +-- local delta = p.Position - TimeBomb.Position + +-- --Vector3 normal = +-- -- (delta == Vector3::zero()) +-- -- ? Vector3::unitY() +-- -- : delta.direction(); +-- local normal = (delta == Vector3.new(0,0,0)) +-- and Vector3.new(0,1,0) +-- or delta.unit + +-- --float radius = p->getRadius(); +-- local radius = p.Size.magnitude / 2 + +-- --float surfaceArea = radius * radius; +-- local surfaceArea = radius * radius + +-- --Vector3 impulse = normal * blastPressure * surfaceArea * (1.0f / 4560.0f); // normalizing factor +-- local impulse = normal * BLAST_PRESSURE * surfaceArea * (1.0 / 4560.0) + +-- -- How much force to apply (for characters, ramp it down towards the edge) +-- local frac; +-- if isInCharacter then +-- frac = 1 - math.max(0, math.min(1, (r-2)/BLAST_RADIUS)) +-- else +-- frac = 1 +-- end + +-- --p->getBody()->accumulateLinearImpulse(impulse, p->getCoordinateFrame().translation); +-- local currentVelocity = p.Velocity +-- local deltaVelocity = impulse / p:GetMass() -- m * del-v = F * del-t = Impulse +-- local bodyV = Instance.new('BodyVelocity', p) +-- bodyV.velocity = currentVelocity + deltaVelocity +-- local forceNeeded = 196.2 * p:GetMass() -- F = ma +-- bodyV.maxForce = Vector3.new(forceNeeded, forceNeeded, forceNeeded) * 10 * frac +-- game.Debris:AddItem(bodyV, 0.2/FORCE_GRANULARITY) + +-- --p->getBody()->accumulateRotationalImpulse(impulse * 0.5 * radius); // a somewhat arbitrary, but nice torque +-- local rotImpulse = impulse * 0.5 * radius +-- local currentRotVelocity = p.RotVelocity +-- local momentOfInertia = (2 * p:GetMass() * radius * radius / 5) -- moment of inertia = 2/5*m*r^2 (assuming roughly spherical) +-- local deltaRotVelocity = rotImpulse / momentOfInertia +-- local rot = Instance.new('BodyAngularVelocity', p) +-- local torqueNeeded = 20 * momentOfInertia -- torque = r x F, want about alpha = 20 rad/s^2, alpha * P = torque +-- rot.maxTorque = Vector3.new(torqueNeeded, torqueNeeded, torqueNeeded) * 10 * frac +-- rot.angularvelocity = currentRotVelocity + deltaRotVelocity +-- game.Debris:AddItem(rot, 0.2/FORCE_GRANULARITY) +--end + + +--function module:CreateExplosion() +-- local New = Instance.new("Explosion") +-- New.BlastRadius = 6 -- Default Radius + +-- New.Hit:Connect(function(PartTouched, Distance) +-- local FakeBlastPressure = New.BlastPressure +-- New.BlastPressure = 0 +-- end) + +-- return New +--end + +--return module \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/Dependencies/init.meta.json b/rojo/MainModule/src/ServerStorage/Dependencies/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/Dependencies/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Clone/Client.client.lua b/rojo/MainModule/src/ServerStorage/HopperBins/Clone/Client.client.lua new file mode 100644 index 0000000..e20a071 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Clone/Client.client.lua @@ -0,0 +1,146 @@ +--!strict +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local RunService: RunService = game:GetService("RunService") + +local BreakJoints = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("BreakJoints", nil)) +local CustomMouseFunctions = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("CustomMouseFunctions", nil)) +local MouseIcon = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("MouseIcon")) + +local tool = script.Parent + +local CustomMouseFunctionsInitialized = CustomMouseFunctions:Init() + +local player = Players.LocalPlayer + +local cloneSound = tool:WaitForChild("CloneSound") +local mouseDownRemote = tool:WaitForChild("MouseDown") +local moveRemote = tool:WaitForChild("Move") +local mouseUpRemote = tool:WaitForChild("MouseUp") + +local mouse: Mouse? = nil +local partDragging: BasePart? = nil +local dragger: Dragger? = nil +local postSimulationConnection: RBXScriptConnection? = nil +local lastPartCFrame: CFrame? = nil + +local dragStartMousePos = Vector2.zero +local mouseMovedFromStart: boolean = false + +local mouseUpTimes: number = 0 + +local selectionbox: SelectionBox = Instance.new("SelectionBox") +selectionbox.Color3 = Color3.fromRGB(25, 153, 255) +selectionbox.LineThickness = 0.1 +selectionbox.Parent = tool + +-- Redo mouse every frame that the tool is equipped +local function onPostSimulation(deltaTimeSim: number): () + if mouse then + if dragger and partDragging and (mouseMovedFromStart or (dragStartMousePos ~= Vector2.new(mouse.X, mouse.Y))) then + MouseIcon.Icon("rbxasset://textures\\GrabRotateCursor.png", player) + + BreakJoints(partDragging) + dragger:MouseMove(mouse.UnitRay) + if partDragging.CFrame ~= lastPartCFrame then + moveRemote:FireServer(partDragging, partDragging.CFrame) + lastPartCFrame = partDragging.CFrame + end + elseif not dragger then + local target = mouse.Target + local hit = mouse.Hit + local primarypart = player.Character.PrimaryPart + if target and not target.Locked and primarypart then + MouseIcon.Icon("rbxasset://textures\\CloneOverCursor.png", player) + else + MouseIcon.Icon("rbxasset://textures\\CloneCursor.png", player) + end + end + end +end + +-- Stops dragging +local function MouseUp() + mouseUpTimes += 1 + + if dragger then + dragger:MouseUp() + dragger:Destroy() + dragger = nil + + -- For some reason roblox calls makejoints here when it shouldn't + BreakJoints(partDragging) + + partDragging = nil + lastPartCFrame = nil + + mouseUpRemote:FireServer() + selectionbox.Adornee = nil + end +end + +local function ClientFire() + if mouse and not tool.Parent:IsA("Backpack") then + local target = mouse.Target + local hit = mouse.Hit + local primarypart = player.Character.PrimaryPart + + if not dragger and target and not target.Locked and primarypart and tool.Enabled then + tool.Enabled = false + + local hold = mouseUpTimes + local newPart = mouseDownRemote:InvokeServer(target) + + tool.Enabled = true + + if newPart then + if hold == mouseUpTimes then + dragger = Instance.new("Dragger") + + if dragger then + dragger:MouseDown(newPart, Vector3.new(0, 0, 0), {newPart}) + end + + partDragging = newPart + selectionbox.Adornee = newPart + + dragStartMousePos = Vector2.new(mouse.X, mouse.Y) + mouseMovedFromStart = false + + MouseIcon.Icon("rbxasset://textures\\CloneCursor.png", player) + else + mouseUpRemote:FireServer() + end + end + end + end +end + +CustomMouseFunctionsInitialized:Button1Down(ClientFire) +CustomMouseFunctionsInitialized:Button1Up(MouseUp) +CustomMouseFunctionsInitialized:KeyDown(function(key) + if dragger then + if key == "R" then + dragger:AxisRotate(Enum.Axis.Z) + elseif key == "T" then + dragger:AxisRotate(Enum.Axis.Y) + end + end +end) + +tool:GetPropertyChangedSignal("Parent"):Connect(function(): () + if not tool.Parent:IsA("Backpack") then + mouse = Players.LocalPlayer:GetMouse() + postSimulationConnection = RunService.PostSimulation:Connect(onPostSimulation) + else + mouse = nil + + if postSimulationConnection then + postSimulationConnection:Disconnect() + end + + MouseIcon.Icon("rbxasset://textures//ArrowCursor.png", player) + + MouseUp() + end +end) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Clone/Server.server.lua b/rojo/MainModule/src/ServerStorage/HopperBins/Clone/Server.server.lua new file mode 100644 index 0000000..f733d8c --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Clone/Server.server.lua @@ -0,0 +1,71 @@ +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local BreakJoints = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("BreakJoints", nil)) + +local tool = script.Parent + +local partsDragging = {} +local wasAnchored = {} +local wasDisabled = {} + +tool.MouseDown.OnServerInvoke = function(player, part) + if part and not part.Locked and part:IsDescendantOf(workspace) then + local tempModel = Instance.new("Model") + tempModel.Parent = workspace + + local dingsound = Instance.new("Sound") + dingsound.SoundId = "rbxassetid://12221990" + dingsound.Parent = workspace + dingsound.PlayOnRemove = true + dingsound:Destroy() + + local newPart = part:Clone() + newPart.Parent = tempModel + + partsDragging[newPart] = true + wasAnchored[newPart] = newPart.Anchored + + if newPart:IsA("Seat") or newPart:IsA("VehicleSeat") then + wasDisabled[newPart] = newPart.Disabled + newPart.Disabled = true + end + + newPart.Anchored = true + BreakJoints(newPart) + + --Moves part ontop of its predecessor + tempModel:MoveTo(newPart.Position) + newPart.Parent = workspace + tempModel:Destroy() + print(player.Name.." has cloned "..part.Name) + + return newPart + end +end + +tool.Move.OnServerEvent:Connect(function(player, part, cframe) + if part and partsDragging[part] then + BreakJoints(part) + part.CFrame = cframe + end +end) + +function StopDragging() + for part,_ in pairs(partsDragging) do + part.Anchored = wasAnchored[part] + + if wasDisabled[part] ~= nil then + part.Disabled = wasDisabled[part] + end + + BreakJoints(part) + part:MakeJoints() + + partsDragging[part] = nil + wasAnchored[part] = nil + wasDisabled[part] = nil + end +end + +tool.MouseUp.OnServerEvent:Connect(StopDragging) +tool.Unequipped:Connect(StopDragging) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Clone/init.meta.json b/rojo/MainModule/src/ServerStorage/HopperBins/Clone/init.meta.json new file mode 100644 index 0000000..babcc53 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Clone/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Tool", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/GameTool/GameToolLocal.client.lua b/rojo/MainModule/src/ServerStorage/HopperBins/GameTool/GameToolLocal.client.lua new file mode 100644 index 0000000..71fe08f --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/GameTool/GameToolLocal.client.lua @@ -0,0 +1,170 @@ +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local UserInputService = game:GetService("UserInputService") + +local BreakJoints = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("BreakJoints", nil)) +local MouseIcon = require(ReplicatedStorage.Modules:WaitForChild("MouseIcon")) +local CustomMouseFunctions = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("CustomMouseFunctions", nil)):Init() +local tool = script.Parent +local player = Players.LocalPlayer +local mouseDownRemote = tool:WaitForChild("MouseDown") +local moveRemote = tool:WaitForChild("Move") +local mouseUpRemote = tool:WaitForChild("MouseUp") + +local mouse = nil +local partDragging = nil +local dragger = nil +local renderSteppedEvent = nil +local lastPartCFrame = nil + +local dragStartMousePos = nil +local mouseMovedFromStart = false + +local selectionbox = Instance.new("SelectionBox") +selectionbox.Color3 = Color3.fromRGB(25, 153, 255) +selectionbox.LineThickness = 0.15 +selectionbox.Parent = tool + +local function ClientFire() + local target = mouse.Target + local hit = mouse.Hit + local primarypart = player.Character.PrimaryPart + + if not dragger and target and not target.Locked and primarypart and (primarypart.Position-hit.Position).magnitude < 50 then + mouseDownRemote:FireServer(target) + + dragger = Instance.new("Dragger") + dragger:MouseDown(target, target.CFrame:toObjectSpace(hit).Position, {target}) + + partDragging = target + selectionbox.Adornee = target + + dragStartMousePos = Vector2.new(mouse.X, mouse.Y) + mouseMovedFromStart = false + end +end + +-- Redo mouse every frame that the tool is equipped +function RenderStepped() + if dragger and partDragging and (mouseMovedFromStart or (dragStartMousePos ~= Vector2.new(mouse.X, mouse.Y))) then + MouseIcon.Icon("rbxasset://textures//GrabRotateCursor.png", Players.LocalPlayer) + --mouse.Icon = "rbxassetid://7167495541" + + BreakJoints(partDragging) + dragger:MouseMove(mouse.UnitRay) + if partDragging.CFrame ~= lastPartCFrame then + moveRemote:FireServer(partDragging, partDragging.CFrame) + lastPartCFrame = partDragging.CFrame + end + elseif not dragger then + local target = mouse.Target + local hit = mouse.Hit + local primarypart = player.Character.PrimaryPart + if target and not target.Locked and primarypart and (primarypart.Position-hit.Position).magnitude < 50 then + MouseIcon.Icon("rbxasset://textures//DragCursor.png", Players.LocalPlayer) + --mouse.Icon = "rbxassetid://7167515791" + else + MouseIcon.Icon("rbxasset://textures//ArrowCursor.png", Players.LocalPlayer) + --mouse.Icon = "rbxassetid://7167309450" + end + end +end + +--Stops dragging +function MouseUp() + if dragger then + dragger:MouseUp() + dragger:Destroy() + dragger = nil + + --For some reason roblox calls makejoints here when it shouldn't + BreakJoints(partDragging) + + partDragging = nil + lastPartCFrame = nil + + mouseUpRemote:FireServer() + selectionbox.Adornee = nil + end +end + +--tool.Deactivated:Connect(MouseUp) + +CustomMouseFunctions:Button1Down(function() + if not tool.Parent:IsA("Backpack") then + ClientFire() + end +end) + +CustomMouseFunctions:Button1Up(function() + if not tool.Parent:IsA("Backpack") then + MouseUp() + end +end) + +CustomMouseFunctions:KeyDown(function(key) + if dragger then + if key == "R" then + dragger:AxisRotate(Enum.Axis.Z) + elseif key == "T" then + dragger:AxisRotate(Enum.Axis.Y) + end + end +end) + +--tool.Activated:Connect(function() +-- local target = mouse.Target +-- local hit = mouse.Hit +-- local primarypart = player.Character.PrimaryPart + +-- if not dragger and target and not target.Locked and primarypart and (primarypart.Position-hit.Position).magnitude < 50 then +-- mouseDownRemote:FireServer(target) + +-- dragger = Instance.new("Dragger") +-- dragger:MouseDown(target, target.CFrame:toObjectSpace(hit).Position, {target}) + +-- partDragging = target +-- selectionbox.Adornee = target + +-- dragStartMousePos = Vector2.new(mouse.X, mouse.Y) +-- mouseMovedFromStart = false +-- end +--end) + +--tool.Equipped:Connect(function(newMouse) +-- mouse = newMouse +-- renderSteppedEvent = game:GetService("RunService").RenderStepped:Connect(RenderStepped) +--end) + +--tool.Unequipped:Connect(function() +-- mouse = nil +-- renderSteppedEvent:Disconnect() + +-- MouseUp() +--end) + +--sub for equipped/unequipped +tool:GetPropertyChangedSignal("Parent"):Connect(function() + if not tool.Parent:IsA("Backpack") then + mouse = Players.LocalPlayer:GetMouse() + renderSteppedEvent = game:GetService("RunService").RenderStepped:Connect(RenderStepped) + else + mouse = nil + renderSteppedEvent:Disconnect() + --mouseVisual.Image = "http://www.roblox.com/asset/?id=6271177050" + MouseIcon.Icon("rbxasset://textures//ArrowCursor.png", Players.LocalPlayer) + + MouseUp() + end +end) + +--Rotate keys +--UserInputService.InputEnded:Connect(function(input: InputObject, gameProcessedEvent: boolean): () +-- if dragger and not gameProcessedEvent and input.UserInputType == Enum.UserInputType.Keyboard then +-- if input.KeyCode == Enum.KeyCode.R then +-- dragger:AxisRotate(Enum.Axis.Z) +-- elseif input.KeyCode == Enum.KeyCode.T then +-- dragger:AxisRotate(Enum.Axis.Y) +-- end +-- end +--end) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/GameTool/GameToolScript.server.lua b/rojo/MainModule/src/ServerStorage/HopperBins/GameTool/GameToolScript.server.lua new file mode 100644 index 0000000..e264dd9 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/GameTool/GameToolScript.server.lua @@ -0,0 +1,61 @@ +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local TimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value + +local BreakJoints = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("BreakJoints", nil)) + +local tool = script.Parent +local makeJoints = nil + +local partsDragging = {} +local wasAnchored = {} +local wasDisabled = {} + +makeJoints = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("MakeJoints")) + +tool.MouseDown.OnServerEvent:Connect(function(player, part) + if part and not part.Locked and part:IsDescendantOf(workspace) then + partsDragging[part] = true + wasAnchored[part] = part.Anchored + + if part:IsA("Seat") or part:IsA("VehicleSeat") then + wasDisabled[part] = part.Disabled + part.Disabled = true + end + + part.Anchored = true + BreakJoints(part) + print(player.Name.." has moved "..part.Name) + end +end) + +tool.Move.OnServerEvent:Connect(function(player, part, cframe) + if part and not part.Locked and partsDragging[part] then + BreakJoints(part) + part.CFrame = cframe + end +end) + +function StopDragging() + for part,_ in pairs(partsDragging) do + part.Anchored = wasAnchored[part] + + if wasDisabled[part] ~= nil then + part.Disabled = wasDisabled[part] + end + + BreakJoints(part) + part:MakeJoints() + + partsDragging[part] = nil + wasAnchored[part] = nil + wasDisabled[part] = nil + end +end + +tool.MouseUp.OnServerEvent:Connect(StopDragging) +tool.Unequipped:Connect(StopDragging) + +-- Don't do this, I will 100% eventually figure out a more productive and good way of doing it +if TimePeriod <= 2 then + script.Parent.TextureId = "rbxassetid://12852119857" +end \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/GameTool/init.meta.json b/rojo/MainModule/src/ServerStorage/HopperBins/GameTool/init.meta.json new file mode 100644 index 0000000..babcc53 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/GameTool/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Tool", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Grab/GrabToolLocal.client.lua b/rojo/MainModule/src/ServerStorage/HopperBins/Grab/GrabToolLocal.client.lua new file mode 100644 index 0000000..164d7ff --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Grab/GrabToolLocal.client.lua @@ -0,0 +1,212 @@ +-- games unite +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local UserInputService = game:GetService("UserInputService") + +local BreakJoints = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("BreakJoints", nil)) +local MouseIcon = require(ReplicatedStorage.Modules:WaitForChild("MouseIcon")) +local CustomMouseFunctions = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("CustomMouseFunctions", nil)):Init() +local tool = script.Parent +local player = Players.LocalPlayer +local mouseDownRemote = tool:WaitForChild("MouseDown") +local moveRemote = tool:WaitForChild("Move") +local mouseUpRemote = tool:WaitForChild("MouseUp") + +local mouse = nil +local partDragging = nil +local dragger = nil +local heartbeatEvent = nil +local lastPartCFrame = nil + +local dragStartMousePos = nil +local mouseMovedFromStart = false + +local fullParent = nil +local partsDraggingTable = {} +local cframetable = {} + +local selectionbox = Instance.new("SelectionBox") +selectionbox.Color3 = Color3.fromRGB(25, 153, 255) +selectionbox.LineThickness = 0.15 +selectionbox.Parent = tool + +--Redo mouse every frame that the tool is equipped +local function recursive(object) + if object and object.Parent ~= nil then + local parentOfObject = object.Parent + + if parentOfObject:IsA("Model") then + if parentOfObject.Parent == workspace then + return parentOfObject + else + return recursive(parentOfObject) + end + end + end +end + +local function modelToPartsDragging(model) + for i, v in ipairs(model:GetDescendants()) do + if v:IsA("Part") then + table.insert(partsDraggingTable, v) + end + end +end + +local function ClientFire() + local target = mouse.Target + local hit = mouse.Hit + local primarypart = player.Character.PrimaryPart + fullParent = recursive(target) + + if not dragger and target and fullParent and not target.Locked and primarypart then + mouseDownRemote:FireServer(fullParent) + modelToPartsDragging(fullParent) + + dragger = Instance.new("Dragger") + dragger:MouseDown(target, target.CFrame:toObjectSpace(hit).Position, partsDraggingTable) + + partDragging = target + lastPartCFrame = target.CFrame + --selectionbox.Adornee = target + + dragStartMousePos = Vector2.new(mouse.X, mouse.Y) + mouseMovedFromStart = false + end +end + +function Heartbeat() + if dragger and partDragging and partsDraggingTable and fullParent and (mouseMovedFromStart or (dragStartMousePos ~= Vector2.new(mouse.X, mouse.Y))) then + MouseIcon.Icon("rbxasset://textures//ArrowCursor.png", Players.LocalPlayer) + --mouse.Icon = "rbxassetid://7167495541" + + dragger:MouseMove(mouse.UnitRay) + + if partDragging.CFrame ~= lastPartCFrame then + for i, v in ipairs(partsDraggingTable) do + if v:IsA("Part") then + table.insert(cframetable, v.CFrame) + end + end + + moveRemote:FireServer(partsDraggingTable, cframetable) + lastPartCFrame = partDragging.CFrame + cframetable = {} + end + + elseif not dragger then + local target = mouse.Target + local hit = mouse.Hit + local primarypart = player.Character.PrimaryPart + if target and target.Parent and target.Parent:IsA("Model") and target.Parent ~= workspace and not target.Locked and primarypart then + MouseIcon.Icon("rbxasset://textures//DragCursor.png", Players.LocalPlayer) + --mouse.Icon = "rbxassetid://7167515791" + else + MouseIcon.Icon("rbxasset://textures//ArrowCursor.png", Players.LocalPlayer) + --mouse.Icon = "rbxassetid://7167309450" + end + end +end + +--Stops dragging +function MouseUp() + if dragger then + dragger:MouseUp() + dragger:Destroy() + dragger = nil + + BreakJoints(fullParent) + fullParent:MakeJoints() + + partDragging = nil + lastPartCFrame = nil + + fullParent = nil + partsDraggingTable = {} + cframetable = {} + + mouseUpRemote:FireServer() + end +end + +--tool.Deactivated:Connect(MouseUp) + +--sub for .deactivated +CustomMouseFunctions:Button1Down(function() + if not tool.Parent:IsA("Backpack") then + ClientFire() + end +end) + +CustomMouseFunctions:Button1Up(function() + if not tool.Parent:IsA("Backpack") then + MouseUp() + end +end) + +CustomMouseFunctions:KeyUp(function(key) + if dragger then + if key == "R" then + dragger:AxisRotate(Enum.Axis.Z) + elseif key == "T" then + dragger:AxisRotate(Enum.Axis.Y) + end + end +end) + +--tool.Activated:Connect(function() +-- local target = mouse.Target +-- local hit = mouse.Hit +-- local primarypart = player.Character.PrimaryPart + +-- if not dragger and target and not target.Locked and primarypart and (primarypart.Position-hit.Position).magnitude < 50 then +-- mouseDownRemote:FireServer(target) + +-- dragger = Instance.new("Dragger") +-- dragger:MouseDown(target, target.CFrame:toObjectSpace(hit).Position, {target}) + +-- partDragging = target +-- selectionbox.Adornee = target + +-- dragStartMousePos = Vector2.new(mouse.X, mouse.Y) +-- mouseMovedFromStart = false +-- end +--end) + +--tool.Equipped:Connect(function(newMouse) +-- mouse = newMouse +-- renderSteppedEvent = game:GetService("RunService").RenderStepped:Connect(RenderStepped) +--end) + +--tool.Unequipped:Connect(function() +-- mouse = nil +-- renderSteppedEvent:Disconnect() + +-- MouseUp() +--end) + +--sub for equipped/unequipped +tool:GetPropertyChangedSignal("Parent"):Connect(function() + if not tool.Parent:IsA("Backpack") then + mouse = Players.LocalPlayer:GetMouse() + heartbeatEvent = game:GetService("RunService").Heartbeat:Connect(Heartbeat) + else + mouse = nil + heartbeatEvent:Disconnect() + --mouseVisual.Image = "http://www.roblox.com/asset/?id=6271177050" + MouseIcon.Icon("rbxasset://textures//ArrowCursor.png", Players.LocalPlayer) + + MouseUp() + end +end) + +--Rotate keys +--UserInputService.InputEnded:Connect(function(input: InputObject, gameProcessedEvent: boolean): () +-- if dragger and not gameProcessedEvent and input.UserInputType == Enum.UserInputType.Keyboard then +-- if input.KeyCode == Enum.KeyCode.R then +-- dragger:AxisRotate(Enum.Axis.Z) +-- elseif input.KeyCode == Enum.KeyCode.T then +-- dragger:AxisRotate(Enum.Axis.Y) +-- end +-- end +--end) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Grab/GrabToolScript.server.lua b/rojo/MainModule/src/ServerStorage/HopperBins/Grab/GrabToolScript.server.lua new file mode 100644 index 0000000..658dc6f --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Grab/GrabToolScript.server.lua @@ -0,0 +1,63 @@ +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local BreakJoints = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("BreakJoints", nil)) + +local tool = script.Parent +local makeJoints = nil + +local partsDragging = {} +local wasAnchored = {} +local wasDisabled = {} + +local modelDragging = nil + +makeJoints = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("MakeJoints")) + +tool.MouseDown.OnServerEvent:Connect(function(player, model) + if model and model:IsA("Model") and model.Parent == workspace then + modelDragging = model + + for i, v in pairs(modelDragging:GetDescendants()) do + if v:IsA("Part") then + partsDragging[v] = true + wasAnchored[v] = v.Anchored + + v.Anchored = true + end + end + + BreakJoints(modelDragging) + print(player.Name.." has dragged "..modelDragging.Name) + end +end) + +tool.Move.OnServerEvent:Connect(function(player, parts, cframes) + if parts and cframes then + workspace:BulkMoveTo(parts, cframes) + end +end) + +function StopDragging() + for part,_ in pairs(partsDragging) do + part.Anchored = wasAnchored[part] + + if wasDisabled[part] ~= nil then + part.Disabled = wasDisabled[part] + end + + --modelDragging:MakeJoints() + + partsDragging[part] = nil + wasAnchored[part] = nil + wasDisabled[part] = nil + end + + if modelDragging ~= nil then + BreakJoints(modelDragging) + modelDragging:MakeJoints() + modelDragging = nil + end +end + +tool.MouseUp.OnServerEvent:Connect(StopDragging) +tool.Unequipped:Connect(StopDragging) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Grab/init.meta.json b/rojo/MainModule/src/ServerStorage/HopperBins/Grab/init.meta.json new file mode 100644 index 0000000..babcc53 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Grab/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Tool", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Hammer/HammerLocal.client.lua b/rojo/MainModule/src/ServerStorage/HopperBins/Hammer/HammerLocal.client.lua new file mode 100644 index 0000000..0fb834c --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Hammer/HammerLocal.client.lua @@ -0,0 +1,101 @@ +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local MouseIcon = require(ReplicatedStorage.Modules:WaitForChild("MouseIcon")) +local CustomMouseFunctions = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("CustomMouseFunctions", nil)):Init() +local runservice = game:GetService("RunService") + +local player = Players.LocalPlayer +local mouse = player:GetMouse() +local tool = script.Parent + +local mousedownremote = tool:WaitForChild("MouseDown") + +--local toolmouse = nil -- Mouse from the equipped function, used for cursor stuff + +local rendersteppedevent = nil + +local selectionbox = Instance.new("SelectionBox") +selectionbox.Color3 = Color3.fromRGB(25, 153, 255) +selectionbox.LineThickness = 0.15 +selectionbox.Parent = tool + +--Redo mouse every frame that the tool is equipped +local function ClientFire() + local target = CustomMouseFunctions:Target() + + if target and not target.Locked and target:IsDescendantOf(game) then + local hit = CustomMouseFunctions:Hit() + local primarypart = player.Character.PrimaryPart + if primarypart then + + local CameraCFrame: CFrame = workspace.CurrentCamera.CFrame + local LookVector: Vector3 = CustomMouseFunctions:Hit().LookVector + + mousedownremote:FireServer(CameraCFrame, LookVector) + end + end +end + + +local function RenderStepped() + local target, hit = CustomMouseFunctions:Target() + local primarypart = player.Character.PrimaryPart + if target and not target.Locked and primarypart then + MouseIcon.Icon("rbxasset://textures//HammerOverCursor.png", player) + --toolmouse.Icon = "rbxassetid://7167495538" + selectionbox.Adornee = target + else + MouseIcon.Icon("rbxasset://textures//HammerCursor.png", player) + --toolmouse.Icon = "rbxassetid://7167495543" + selectionbox.Adornee = nil + end +end + +CustomMouseFunctions:Button1Down(function() + if not tool.Parent:IsA("Backpack") then + ClientFire() + end +end) + +--tool.Activated:Connect(function() +-- local target = mouse.Target +-- if target and not target.Locked and target:IsDescendantOf(game) then +-- local hit = mouse.Hit +-- local primarypart = player.Character.PrimaryPart +-- if primarypart then +-- mousedownremote:FireServer(target) +-- end +-- end +--end) + + +--Equipped and Unequipped +--tool.Equipped:Connect(function(newtoolmouse) +-- rendersteppedevent = runservice.RenderStepped:Connect(RenderStepped) + +-- toolmouse = newtoolmouse +--end) +--tool.Unequipped:Connect(function() +-- rendersteppedevent:Disconnect() + +-- --toolmouse = nil + +-- selectionbox.Adornee = nil +--end) + +tool:GetPropertyChangedSignal("Parent"):Connect(function() + if not tool.Parent:IsA("Backpack") then + rendersteppedevent = runservice.RenderStepped:Connect(RenderStepped) + + --toolmouse = newtoolmouse + else + rendersteppedevent:Disconnect() + + --toolmouse = nil + + selectionbox.Adornee = nil + + MouseIcon.Icon("rbxasset://textures\\ArrowCursor.png", Players.LocalPlayer) + end +end) diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Hammer/HammerScript.server.lua b/rojo/MainModule/src/ServerStorage/HopperBins/Hammer/HammerScript.server.lua new file mode 100644 index 0000000..eace2ac --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Hammer/HammerScript.server.lua @@ -0,0 +1,45 @@ +--!strict + +-- Variables +local tool = script.Parent + +-- Code + +tool.MouseDown.OnServerEvent:Connect(function(player: Player, CameraCFrame: CFrame, LookVector: Vector3): () + if player.Name == tool.Parent.Name then + local Raycast: RaycastResult = workspace:Raycast(CameraCFrame.Position, LookVector * 10000) + + if Raycast then + if Raycast.Instance then + if Raycast.Instance:IsA("BasePart") then + if not Raycast.Instance.Locked and Raycast.Instance:IsDescendantOf(workspace) then + local PartPosition: Vector3 = Raycast.Instance.Position + local PartBrickColor: BrickColor = Raycast.Instance.BrickColor + local PartName: string = Raycast.Instance.Name + + Raycast.Instance:Destroy() + + local explosion: Explosion = Instance.new("Explosion") + + + local explosionsound: Sound = Instance.new("Sound") + explosionsound.SoundId = "rbxasset://sounds/collide.wav" + explosionsound.Parent = workspace + explosionsound.PlayOnRemove = true + explosionsound:Destroy() + + explosion.BlastPressure = 0 + explosion.BlastRadius = 6 + explosion.DestroyJointRadiusPercent = 0 + explosion.ExplosionType = Enum.ExplosionType.NoCraters + explosion.Position = PartPosition + + explosion.Parent = workspace + + print(player.Name.." has destroyed "..PartName.." which had a color of "..tostring(PartBrickColor)) + end + end + end + end + end +end) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Hammer/init.meta.json b/rojo/MainModule/src/ServerStorage/HopperBins/Hammer/init.meta.json new file mode 100644 index 0000000..babcc53 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Hammer/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Tool", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Laser/Client.client.lua b/rojo/MainModule/src/ServerStorage/HopperBins/Laser/Client.client.lua new file mode 100644 index 0000000..c24bad0 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Laser/Client.client.lua @@ -0,0 +1,40 @@ +--!strict + +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local UserInputService = game:GetService("UserInputService") +local Soundscape = game:GetService("SoundService") +local CustomMouseFunctions = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("CustomMouseFunctions", nil)):Init() + +local Player: Player = Players.LocalPlayer +local MouseIcon = require(ReplicatedStorage.Modules:WaitForChild("MouseIcon")) +local Mouse: Mouse = Player:GetMouse() +local Tool = script.Parent + +local function ClientFire(): () + if not Tool.Parent:IsA("Backpack") then + local CameraCFrame: CFrame = workspace.CurrentCamera.CFrame + local LookVector = CustomMouseFunctions:Hit().LookVector + + Tool.Input:FireServer(CameraCFrame, LookVector) + end +end + +local function GunCursor(): () + if not Tool.Parent:IsA("Backpack") then + if Tool.Enabled then + MouseIcon.Icon("rbxasset://textures\\GunCursor.png", Player) + end + else + MouseIcon.Icon("rbxasset://textures\\ArrowCursor.png", Player) + end +end + +--Tool.Activated:Connect(ClientFire) + +CustomMouseFunctions:Button1Down(ClientFire) + +--Tool.Equipped:Connect(GunCursor) +--Tool.Unequipped:Connect(GunCursor) +Tool:GetPropertyChangedSignal("Enabled"):Connect(GunCursor) +Tool:GetPropertyChangedSignal("Parent"):Connect(GunCursor) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Laser/Server.server.lua b/rojo/MainModule/src/ServerStorage/HopperBins/Laser/Server.server.lua new file mode 100644 index 0000000..a7a4a47 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Laser/Server.server.lua @@ -0,0 +1,44 @@ +--!strict + +--[[ + + Roblox_Gamer2030, 2022 + Rescript of the 2006 "Laser" HopperBin + Secured and converted to LuaU by GuestIsJustBest and KeyboardCombination + +]]-- + +local Soundscape = game:GetService("SoundService") +local Tool = script.Parent +local Input: RemoteEvent = Tool.Input + +local function LaserServer(player: Player, CameraCFrame: CFrame, LookVector: Vector3): () + if player.Name == Tool.Parent.Name then + local Raycast: RaycastResult = workspace:Raycast(CameraCFrame.Position, LookVector * 10000) + + if Raycast then + if Raycast.Position and Raycast.Instance then + + local Explosion = Instance.new("Explosion") + Explosion.Position = Vector3.new(Raycast.Position.X, Raycast.Position.Y, Raycast.Position.Z) + Explosion.BlastRadius = 4 + Explosion.BlastPressure = 0 + Explosion.DestroyJointRadiusPercent = 0 + Explosion.Parent = workspace + + local Sound = Instance.new("Sound") + Sound.SoundId = "rbxassetid://12222140" + Sound.Parent = workspace + Sound.PlayOnRemove = true + + Sound:Destroy() + + if Raycast.Instance.Locked == false then + Raycast.Instance:Destroy() + end + end + end + end +end + +Tool.Input.OnServerEvent:Connect(LaserServer) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Laser/init.meta.json b/rojo/MainModule/src/ServerStorage/HopperBins/Laser/init.meta.json new file mode 100644 index 0000000..babcc53 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Laser/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Tool", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Rocket/Client.client.lua b/rojo/MainModule/src/ServerStorage/HopperBins/Rocket/Client.client.lua new file mode 100644 index 0000000..152303c --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Rocket/Client.client.lua @@ -0,0 +1,36 @@ +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local Player = Players.LocalPlayer +local PlayerGui = Player.PlayerGui +local MouseIcon = require(ReplicatedStorage.Modules:WaitForChild("MouseIcon")) +local CustomMouseFunctions = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("CustomMouseFunctions", nil)):Init() +local Mouse = Player:GetMouse() +local Tool = script.Parent +local UserInputService = game:GetService("UserInputService") + +local function ClientFire() + if not Tool.Parent:IsA("Backpack") then + Tool.Input:FireServer(Mouse.Hit) + end +end + +local function GunCursor() + if not Tool.Parent:IsA("Backpack") then + if Tool.Enabled then + MouseIcon.Icon("rbxasset://textures\\GunCursor.png", Player) + else + MouseIcon.Icon("rbxasset://textures\\GunWaitCursor.png", Player) + end + else + MouseIcon.Icon("rbxasset://textures\\ArrowCursor.png", Player) + end +end + +--Tool.Activated:Connect(ClientFire) +CustomMouseFunctions:Button1Down(ClientFire) + +--Tool.Equipped:Connect(GunCursor) +--Tool.Unequipped:Connect(GunCursor) +Tool:GetPropertyChangedSignal("Enabled"):Connect(GunCursor) +Tool:GetPropertyChangedSignal("Parent"):Connect(GunCursor) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Rocket/Launcher.server.lua b/rojo/MainModule/src/ServerStorage/HopperBins/Rocket/Launcher.server.lua new file mode 100644 index 0000000..2aa72de --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Rocket/Launcher.server.lua @@ -0,0 +1,64 @@ +--!strict +local Players = game:GetService("Players") +local BrickColor = require(game:GetService("ReplicatedStorage"):WaitForChild("Modules"):WaitForChild("BrickColor")) +local Cooldown = 3 +local Bin = script.Parent + +local function computeDirection(vector: Vector3): () + local lengthSquared = vector.Magnitude * vector.Magnitude + local inverseSquareRoot = 1 / math.sqrt(lengthSquared) + + return Vector3.new(vector.X * inverseSquareRoot, vector.Y * inverseSquareRoot, vector.Z * inverseSquareRoot) +end + +local function fireServer(player: Player, Hit : CFrame): () + local Character: Model? = Bin.Parent + + if Character and player.Character == Character then + if Bin.Enabled then + Bin.Enabled = false + + local Head = Character:FindFirstChild("Head") + + if Character.PrimaryPart and Head and Head:IsA("BasePart") then + local position = Hit.Position + local spawnPos = Character.PrimaryPart.Position + + local direction = position - Head.Position + direction = computeDirection(direction) + + local pos = spawnPos + (direction * 6) + + local rocket = Instance.new("Part", nil) + rocket.BackSurface = Enum.SurfaceType.Studs + rocket.BottomSurface = Enum.SurfaceType.Studs + rocket.BrickColor = BrickColor.Blue() + rocket.CFrame = CFrame.lookAt(pos, pos + direction) + rocket.FrontSurface = Enum.SurfaceType.Studs + rocket.LeftSurface = Enum.SurfaceType.Studs + rocket.Locked = true + rocket.Name = "Rocket" + rocket.RightSurface = Enum.SurfaceType.Studs + rocket.Size = Vector3.new(1, 1, 4) + rocket.TopSurface = Enum.SurfaceType.Studs + + local RocketScript = Bin.RocketScript:Clone() + RocketScript.Disabled = false + RocketScript.Parent = rocket + + local creator_tag = Instance.new("ObjectValue") + creator_tag.Value = Players:GetPlayerFromCharacter(Character) + creator_tag.Name = "creator" + creator_tag.Parent = rocket + + rocket.Parent = workspace + Bin.Ping:Play() + + task.wait(Cooldown) + Bin.Enabled = true + end + end + end +end + +Bin.Input.OnServerEvent:Connect(fireServer) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Rocket/RocketScript.server.lua b/rojo/MainModule/src/ServerStorage/HopperBins/Rocket/RocketScript.server.lua new file mode 100644 index 0000000..e24923e --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Rocket/RocketScript.server.lua @@ -0,0 +1,71 @@ +local Players = game:GetService("Players") +local RunService: RunService = game:GetService("RunService") + +local shaft = script.Parent +local pos = Vector3.new(0, 0, 0) + +local function fly(part: BasePart): () + local dir = part.CFrame.LookVector + + pos = pos + dir + + local err = pos - part.Position + + part.AssemblyLinearVelocity = err * 7 +end + +local function fire(): () + local swoosh = Instance.new("Sound") + swoosh.SoundId = "rbxasset://sounds/Rocket whoosh 01.wav" + swoosh.Looped = true + swoosh.Parent = shaft + swoosh:Play() + + local kaboom = Instance.new("Sound") + kaboom.Name = "Kaboom" + kaboom.SoundId = "rbxasset://sounds/collide.wav" + kaboom.PlayOnRemove = true + kaboom.Parent = shaft + + pos = shaft.Position + + local t, s = RunService.Stepped:Wait() -- bad 2006 code I don't understand + + local d = t + 10.0 - s + + local connection + connection = shaft.Touched:Connect(function(otherPart: BasePart): () + swoosh:Stop() + kaboom:Destroy() + + local Explosion = Instance.new("Explosion") + Explosion.Position = shaft.Position + Explosion.BlastRadius = 6 + + Explosion.Hit:Connect(function(part) + if Players:GetPlayerFromCharacter(part.Parent) then + local tag = shaft:FindFirstChild("creator") + local player = Players:GetPlayerFromCharacter(part.Parent) + + if tag and player then + tag:Clone().Parent = player.Character.Humanoid + end + end + end) + + Explosion.Parent = workspace + connection:Disconnect() + + task.wait(0.1) + + shaft:Destroy() + end) + + while t < d do + fly(shaft) + + t, s = RunService.Stepped:Wait() + end +end + +fire() \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Rocket/init.meta.json b/rojo/MainModule/src/ServerStorage/HopperBins/Rocket/init.meta.json new file mode 100644 index 0000000..babcc53 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Rocket/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Tool", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/Client.client.lua b/rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/Client.client.lua new file mode 100644 index 0000000..79d15b4 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/Client.client.lua @@ -0,0 +1,58 @@ +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local Player = Players.LocalPlayer +local PlayerGui = Player.PlayerGui +local MouseIcon = require(ReplicatedStorage.Modules:WaitForChild("MouseIcon")) +local CustomMouseFunctions = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("CustomMouseFunctions", nil)):Init() +local Mouse = Player:GetMouse() +local Tool = script.Parent +local UserInputService = game:GetService("UserInputService") +local StarterGui = game:GetService("StarterGui") + +local Heartbeat + +local function ClientFire() + if not Tool.Parent:IsA("Backpack") then + Tool.Input:FireServer(Mouse.Hit) + end +end + +local function GunCursor() + if not Tool.Parent:IsA("Backpack") then + MouseIcon.Icon("rbxasset://textures\\GunCursor.png", Player) + else + MouseIcon.Icon("rbxasset://textures\\ArrowCursor.png", Player) + end +end + +--Tool.Activated:Connect(ClientFire) + +--Heartbeat = game:GetService("RunService").Heartbeat:Connect(function() +-- if UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) then +-- ClientFire() +-- end +--end) + +CustomMouseFunctions:Button1Down(function() + if not Heartbeat then + Heartbeat = game:GetService("RunService").Heartbeat:Connect(function() + ClientFire() + end) + else + Heartbeat:Disconnect() + Heartbeat = nil + end +end) + +CustomMouseFunctions:Button1Up(function() + if Heartbeat then + Heartbeat:Disconnect() + Heartbeat = nil + end +end) + +--Tool.Equipped:Connect(GunCursor) +--Tool.Unequipped:Connect(GunCursor) +Tool:GetPropertyChangedSignal("Enabled"):Connect(GunCursor) +Tool:GetPropertyChangedSignal("Parent"):Connect(GunCursor) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/PelletScript.server.lua b/rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/PelletScript.server.lua new file mode 100644 index 0000000..b14d5c4 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/PelletScript.server.lua @@ -0,0 +1,50 @@ +local pellet = script.Parent +local damage = 8 +local connection + +local function tagHumanoid(humanoid) + -- todo: make tag expire + local tag = pellet:FindFirstChild("creator") + if tag ~= nil then + local new_tag = tag:Clone() + new_tag.Parent = humanoid + + end +end + +local function untagHumanoid(humanoid) + if humanoid ~= nil then + local tag = humanoid:FindFirstChild("creator") + if tag ~= nil then + + tag.Parent = nil + end + end +end + +local function onTouched(otherPart) + local humanoid = otherPart.Parent:FindFirstChild("Humanoid") + if humanoid~=nil then + tagHumanoid(humanoid) + humanoid.Health = humanoid.Health - damage + task.wait(2) + + untagHumanoid(humanoid) + else + damage = damage / 2 + if damage < 0.1 then + connection:Disconnect() + end + end +end + +connection = pellet.Touched:Connect(onTouched) + +local r = game:GetService("RunService") +local t, s = r.Stepped:Wait() +local d = t + 2.0 - s +while t < d do + t = r.Stepped:Wait() +end + +pellet:Destroy() \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/Slingshot.server.lua b/rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/Slingshot.server.lua new file mode 100644 index 0000000..6519c1e --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/Slingshot.server.lua @@ -0,0 +1,115 @@ +--!strict +print("Slingshot script loaded") + +local BrickColor = require(game:GetService("ReplicatedStorage"):WaitForChild("Modules"):WaitForChild("BrickColor")) +local Players = game:GetService("Players") +local Bin = script.Parent +local VELOCITY = 85 -- constant + +local function computeLaunchAngle(dx : number, dy : number, grav : number): number + -- arcane + -- http://en.wikipedia.org/wiki/Trajectory_of_a_projectile + + local g = math.abs(grav) + local inRoot = (VELOCITY ^ 4) - (g * ((g * dx ^ 2) + (2 * dy * VELOCITY ^ 2))) + + if inRoot <= 0 then + return .25 * math.pi + end + + local root = math.sqrt(inRoot) + + local inATan1 = ((VELOCITY ^ 2) + root) / (g * dx) + local inATan2 = ((VELOCITY ^ 2) - root) / (g * dx) + + local answer1 = math.atan(inATan1) + local answer2 = math.atan(inATan2) + + if answer1 < answer2 then + return answer1 + end + + return answer2 +end + +local function computeDirection(vector : Vector3): Vector3 + local lengthSquared = vector.Magnitude * vector.Magnitude + local inverseSquareRoot = 1 / math.sqrt(lengthSquared) + + return Vector3.new(vector.X * inverseSquareRoot, vector.Y * inverseSquareRoot, vector.Z * inverseSquareRoot) +end + +local function fireServer(player : Player, Hit : CFrame): () + local Character : Model? = Bin.Parent + + if Character and player.Character == Character then + if Bin.Enabled then + Bin.Enabled = false + + local Head = Bin.Parent:FindFirstChild("Head") + + if Head and Head:IsA("BasePart") then + local sound = Instance.new("Sound") + sound.SoundId = "rbxassetid://844029237" + sound.Parent = script.Parent + sound:Play() + + local position = Hit.Position + + local dir = position - Head.Position + dir = computeDirection(dir) + + local launch = Head.Position + 5 * dir + + local delta = position - launch + + local dy = delta.Y + + local new_delta = Vector3.new(delta.X, 0, delta.Z) + delta = new_delta + + local dx = delta.magnitude + local unit_delta = delta.unit + + -- acceleration due to gravity in RBX units + local g = (-9.81 * 20) + + local theta = computeLaunchAngle(dx, dy, g) + + local vy = math.sin(theta) + local xz = math.cos(theta) + local vx = unit_delta.X * xz + local vz = unit_delta.Z * xz + + + local missile = Instance.new("Part") + missile.Name = "Pellet" + missile.BrickColor = BrickColor.new("Medium stone grey") + missile.Size = Vector3.new(1, 1, 1) + missile.Shape = Enum.PartType.Ball + missile.TopSurface = Enum.SurfaceType.Smooth + missile.BottomSurface = Enum.SurfaceType.Smooth + + local new_script = Bin.PelletScript:Clone() + new_script.Parent = missile + + missile.Position = launch + new_script.Disabled = false + + local creator_tag = Instance.new("ObjectValue") + creator_tag.Value = Players:GetPlayerFromCharacter(Character) + creator_tag.Name = "creator" + creator_tag.Parent = missile + + missile.Parent = workspace + missile.AssemblyLinearVelocity = Vector3.new(vx, vy, vz) * VELOCITY + + task.wait(.1) + + Bin.Enabled = true + end + end + end +end + +Bin.Input.OnServerEvent:Connect(fireServer) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/init.meta.json b/rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/init.meta.json new file mode 100644 index 0000000..babcc53 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/Slingshot/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Tool", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/HopperBins/init.meta.json b/rojo/MainModule/src/ServerStorage/HopperBins/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/HopperBins/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/ToolHandlers/Rocket.lua b/rojo/MainModule/src/ServerStorage/ToolHandlers/Rocket.lua new file mode 100644 index 0000000..4c5b729 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/ToolHandlers/Rocket.lua @@ -0,0 +1,13 @@ +local module = {} +module.__index = module + +function module:Init() + local NewTool = {} + setmetatable(NewTool, module) +end + +function module:ApplySettings(SettingsTable) + self.Settings = SettingsTable +end + +return module diff --git a/rojo/MainModule/src/ServerStorage/ToolHandlers/init.meta.json b/rojo/MainModule/src/ServerStorage/ToolHandlers/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/ToolHandlers/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/AdminGuis/Admi/AdminClient.client.lua b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/Admi/AdminClient.client.lua new file mode 100644 index 0000000..8c8d48d --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/Admi/AdminClient.client.lua @@ -0,0 +1,575 @@ +-- made entirely by Vibin +-- games unite, GAMES UNITE!!!! + +local PropElements = script:WaitForChild("PropsElements") +local AdminButton = script:WaitForChild("Admin") + +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local LocalPlayer = Players.LocalPlayer + +local Protocols = ReplicatedStorage:WaitForChild("Protocols") +local AdminRemotes = Protocols:WaitForChild("AdminRemotes") +local AdminEvent = AdminRemotes:WaitForChild("AdminEvent") +local GetBanned = AdminRemotes:WaitForChild("GetBanned") + +local Modules = ReplicatedStorage:WaitForChild("Modules") +local DraggableObject = require(Modules:WaitForChild("DraggableObject")) + +local RunService = game:GetService("RunService") + +local MainGui = script.Parent:WaitForChild("PanelWindow") +local UpdatingVariable +local Cloning + +local PlayerCount = 0 + +local function setVisibilityOfExecutionGuis(visibility) + for _, v in pairs(MainGui.Execution:GetChildren()) do + if v:IsA("GuiBase") then + v.Visible = visibility + end + end +end + +local Props = { + ["text"] = function(Text, Ind) + local NewText = PropElements.PropText:Clone() + NewText.Text = Text + NewText.LayoutOrder = Ind + NewText.Visible = true + NewText.Parent = MainGui.Execution + end, + + ["playerlist"] = function(Placeholder, Ind) + local NewListButton = PropElements.PropPlayerlistButton:Clone() + NewListButton.Text = Placeholder + NewListButton.LayoutOrder = Ind + NewListButton.Visible = true + NewListButton:SetAttribute("Parameter", true) + NewListButton.Parent = MainGui.Execution + + NewListButton.MouseButton1Click:Connect(function() + setVisibilityOfExecutionGuis(false) + + local GetPlayerList = MainGui.PlayerList:Clone() + GetPlayerList.Visible = true + GetPlayerList.Parent = MainGui + + for _, v in pairs(GetPlayerList:GetChildren()) do + local isValidUI = v:IsA("TextButton") and v.Visible and tonumber(v.Name) + + if (not isValidUI) then + continue + end + + v.MouseButton1Click:Connect(function() + NewListButton.Choosing.Value = v.Name + NewListButton.Text = v.Text + + GetPlayerList:Destroy() + setVisibilityOfExecutionGuis(true) + end) + end + + GetPlayerList.Exit.MouseButton1Click:Connect(function() + GetPlayerList:Destroy() + setVisibilityOfExecutionGuis(true) + end) + end) + end, + + ["serverbanlist"] = function(Placeholder, Ind) + local NewBanlist = PropElements.PropBanlistButton:Clone() + NewBanlist.Text = Placeholder + NewBanlist.LayoutOrder = Ind + NewBanlist.Visible = true + NewBanlist:SetAttribute("Parameter", true) + NewBanlist.Parent = MainGui.Execution + + NewBanlist.MouseButton1Click:Connect(function() + setVisibilityOfExecutionGuis(false) + + local GetBannedList = MainGui.BannedList:Clone() + GetBannedList.Visible = true + GetBannedList.Parent = MainGui + + for _, v in pairs(GetBannedList:GetChildren()) do + local isValidUI = v:IsA("TextButton") and v.Visible and tonumber(v.Name) + + if (not isValidUI) then + continue + end + + v.MouseButton1Click:Connect(function() + NewBanlist.Choosing.Value = v.Id.Value + NewBanlist.Text = v.Text + + GetBannedList:Destroy() + setVisibilityOfExecutionGuis(true) + end) + end + + GetBannedList.Exit.MouseButton1Click:Connect(function() + GetBannedList:Destroy() + setVisibilityOfExecutionGuis(true) + end) + end) + end, + + ["textbox"] = function(Placeholder, Ind) + local NewTextbox = PropElements.PropTextbox:Clone() + NewTextbox.PlaceholderText = Placeholder + NewTextbox.LayoutOrder = Ind + NewTextbox.Visible = true + NewTextbox:SetAttribute("Parameter", true) + NewTextbox.Parent = MainGui.Execution + end, + + ["list"] = function(Placeholder, Ind, Selection) + assert(Selection ~= nil, "This property requires a third parameter!") + assert(typeof(Selection) == "table", "List selection must be a table!") + + local Newlist = PropElements.PropListButton:Clone() + Newlist.Text = Placeholder + Newlist.LayoutOrder = Ind + Newlist.Visible = true + Newlist:SetAttribute("Parameter", true) + Newlist.Parent = MainGui.Execution + + Newlist.MouseButton1Click:Connect(function() + setVisibilityOfExecutionGuis(false) + + local List = MainGui.List:Clone() + List.Visible = true + List.Parent = MainGui + + for i, v in pairs(Selection) do + local IsTabled = typeof(v) == "table" + + local ListChoice = List.Choice:Clone() + ListChoice.LayoutOrder = i + + ListChoice.Text = IsTabled and v[1] or v + ListChoice.Choice.Value = IsTabled and v[2] or v + + ListChoice.Visible = true + ListChoice.Parent = List + + ListChoice.MouseButton1Click:Connect(function() + Newlist.Choosing.Value = ListChoice.Choice.Value + Newlist.Text = ListChoice.Text + + List:Destroy() + setVisibilityOfExecutionGuis(true) + end) + end + + List.Exit.MouseButton1Click:Connect(function() + List:Destroy() + setVisibilityOfExecutionGuis(true) + end) + end) + end, +} + + +local function setupExecutionFrame(props) + local newproptable = table.clone(props) + + for _, v in pairs(MainGui.Execution:GetChildren()) do + if not v:GetAttribute("DoNotDestroy") then + v:Destroy() + end + end + + for Index, currentProp in ipairs(newproptable) do + local propertyType = currentProp[1] + local placeholderText = currentProp[2] + local additionalThings = currentProp[3] or nil + + local trueType = string.lower(propertyType) + + Props[trueType](placeholderText, Index, additionalThings) + end +end + +-- Param builders +--[[ + + Format: + [command name (lowercase)] = { + {property type, placeholder text, misc}, + {property type, placeholder text, misc}, + } + + The commands are ordered based off table placement +]]-- +local CommandFrames = { + ["ban"] = { + {"Text", "Bans the player"}, + {"Playerlist", "Player banning"}, + {"Textbox", "Reason (Optional)"} + }, + + ["kick"] = { + {"Text", "Kicks the player"}, + {"Playerlist", "Player kicking"}, + {"Textbox", "Reason (Optional)"} + }, + + ["unban"] = { + {"Text", "Unbans the selected banned player"}, + {"ServerBanList", "Player unbanning"} + }, + + ["mute"] = { + {"Text", "Mutes or unmutes the selected player"}, + {"Playerlist", "Player muting/unmuting"} + }, + + ["message"] = { + {"Text", "Shows a message on the screen to everyone for a limited item"}, + {"Text", "NOTE: The message will be filtered"}, + {"Textbox", "Message showing"}, + {"Textbox", "Time shown (default: 5, max: 60)"} + }, + + ["shutdown"] = { + {"Text", "WARNING: Are you SURE you want to shutdown?"}, + {"Text", "This will send every player back to the FWM menu"} + }, + + ["teleport"] = { + {"Text", "Teleports one player to another"}, + {"Text", "NOTE: You cant teleport a player to themselves"}, + {"Playerlist", "Teleporting"}, + {"Playerlist", "Teleporting to"} + }, + + ["kill"] = { + {"Text", "Kills a player in the server"}, + {"Playerlist", "Person to kill"}, + }, + + ["gravity"] = { + {"Text", "Sets the gravity of the server"}, + {"Textbox", "Gravity to set (default: 196.2)"} + }, + + ["speed"] = { + {"Text", "Sets the walk speed of a player"}, + {"Playerlist", "Player to set speed"}, + {"Textbox", "Speed amount (default: 16)"} + }, + + ["jump"] = { + {"Text", "Sets the jump height of a player"}, + {"Playerlist", "Player to set jump height"}, + {"Textbox", "Height amount (default: 50)"} + }, + + ["god"] = { + {"Text", "God or ungod a player"}, + {"Playerlist", "Player to god/ungod"} + }, + + ["hopperbin"] = { + {"Text", "Grants a player the selected HopperBin"}, + {"Playerlist", "Player to give Hopper"}, + {"List", "HopperBin", {"Clone", "GameTool", "Grab", "Hammer", "Laser", "Rocket", "Slingshot"}} + }, + + ["game ban"] = { + {"Text", "Bans a player from the entire game for a certain time"}, + {"Text", "MAKE SURE THERE IS A REASON"}, + {"Textbox", "Username"}, + {"List", "Ban Time", { + {"1 Day", 86400}, + {"3 Days", 259200}, + {"1 Week", 604800}, + {"1 Month", 2628000}, + {"Permanently", 0}}, + }, + {"List", "Reason", { + "Swearing", + "Threatening", + "Spamming", + "Offensive Account Name", + "Inappropriate Behavior", + "Exploiting", + "Impersonation", + "Endangerment"} + } + }, + + ["game unban"] = { + {"Text", "Unbans the following user from the entire game"}, + {"Text", "Make sure the user is banned first!"}, + {"Textbox", "Username"} + } +} + +local function roundNumber(num, numPlaces) + if numPlaces then + return math.floor(num*(10^numPlaces))/(10^numPlaces) + end + + return math.floor(num*(10))/(10) +end + +local function playerAdded(player) + if player:IsA("Player") then + PlayerCount += 1 + MainGui.StatsContent.PlayerCount.Text = "Player count: "..PlayerCount + + local New = MainGui.PlayerList.PLAYER:Clone() + + New.Name = player.UserId + New.Text = player.Name + New.Visible = true + New:SetAttribute("Player", true) + + New.Parent = MainGui.PlayerList + end +end + +local function playerRemoved(player) + if player:IsA("Player") then + PlayerCount -= 1 + MainGui.StatsContent.PlayerCount.Text = "Player count: "..PlayerCount + + local FindPlayer = MainGui.PlayerList:FindFirstChild(player.UserId) + + if FindPlayer then + FindPlayer:Destroy() + end + end +end + +local function invisibleAndVisible(invisible, visible) + invisible.Visible = false + visible.Visible = true +end + +local function updateDebug() + MainGui.StatsContent.RunTime.Text = "Server Runtime: "..string.format("%02i:%02i:%02i", math.floor(workspace.DistributedGameTime / 3600), roundNumber(workspace.DistributedGameTime / 60 % 60), roundNumber(workspace.DistributedGameTime % 60)) +end + +local function exitPanel() + Cloning.ButtonText.Text = "Admin" + MainGui.Visible = false +end + +local function esp() + LocalPlayer.PlayerGui:FindFirstChild("ESP").Enabled = not LocalPlayer.PlayerGui:FindFirstChild("ESP").Enabled +end + +local function killaura() + AdminEvent:FireServer("killaura") +end + +local function setupBannedList() + for i, v in pairs(MainGui.BannedList:GetChildren()) do + if v:IsA("TextButton") and tonumber(v.Name) then + v:Destroy() + end + end + + local BannedPlayers = GetBanned:InvokeServer() + + for i, v in pairs(BannedPlayers) do + local New = MainGui.BannedList.UserId:Clone() + + New.Name = i + New.Id.Value = i + + local GrabbedName + + local Success, Failed = pcall(function() + GrabbedName = Players:GetNameFromUserIdAsync(i) + end) + + if Success then + New.Text = GrabbedName + else + New.Text = "User Id: "..i + end + + New.Visible = true + New:SetAttribute("UserId", true) + + New.Parent = MainGui.BannedList + end +end + +local function exitExec() + invisibleAndVisible(MainGui.Execution, MainGui.HomeContent) +end + +-- updateBanned() and executeCommand() was made while I WAS SMOKING GLOGNUTS +local function updateBanned() + local BannedPlayers = GetBanned:InvokeServer() + MainGui.StatsContent.BannedAmount.Text = "Banned players: "..#BannedPlayers + + if UpdatingVariable then + task.cancel(UpdatingVariable) + end + + UpdatingVariable = task.spawn(setupBannedList) +end + +local function executeCommand() + local tups = {} + local sortGuis = {} + + local getCommandName = MainGui.Execution.CommandTitle.Text + + for _, v in pairs(MainGui.Execution:GetChildren()) do + if v:GetAttribute("Parameter") then + table.insert(sortGuis, v) + end + end + + table.sort(sortGuis, function(a, b) + return a.LayoutOrder < b.LayoutOrder + end) + + for i, v in ipairs(sortGuis) do + if not v:IsA("TextBox") then + local GetChoosing = v:FindFirstChild("Choosing") + + if GetChoosing.Value ~= nil then + table.insert(tups, GetChoosing.Value) + continue + end + else + if v.Text ~= "" then + table.insert(tups, v.Text) + continue + end + end + + table.insert(tups, false) + end + + AdminEvent:FireServer(getCommandName, tups) + + for _, v in pairs(MainGui.Execution:GetChildren()) do + if not v:GetAttribute("DoNotDestroy") then + v:Destroy() + end + end + + exitExec() +end + +local function setupPanel() + MainGui.HomeContent.HelloText.Text = "Hello, "..LocalPlayer.Name + + --Stupid stylizing thing it gonna look REALLY cool... + for _, v in pairs(MainGui:GetDescendants()) do + if v:IsA("TextButton") then + if v.BackgroundColor3 == Color3.fromRGB(238, 238, 238) then + v.AutoButtonColor = false + + v.MouseEnter:Connect(function() + v.BorderColor3 = Color3.fromRGB(0,0,0) + v.TextColor3 = Color3.fromRGB(0, 0, 0) + end) + + v.MouseLeave:Connect(function() + v.BorderColor3 = Color3.fromRGB(119, 119, 119) + v.TextColor3 = Color3.fromRGB(119, 119, 119) + end) + end + end + end + + MainGui.MiscContent.ESP.MouseButton1Click:Connect(esp) + --MainGui.MiscContent.Killaura.MouseButton1Click:Connect(killaura) + + -- Sets up nearly EVERY button in the panel + for _, v in pairs(MainGui.HomeContent:GetChildren()) do + if v:IsA("TextButton") then + local Find = MainGui:FindFirstChild(v.Name.."Content") + + v.MouseButton1Click:Connect(function() + if Find then + invisibleAndVisible(v.Parent, Find) + end + end) + + local GetPrevious = Find:FindFirstChild("Previous") + + if GetPrevious and GetPrevious:IsA("TextButton") then + GetPrevious.MouseButton1Click:Connect(function() + invisibleAndVisible(GetPrevious.Parent, MainGui.HomeContent) + end) + end + + for _, v in pairs(Find:GetChildren()) do + if v:IsA("TextButton") and v ~= GetPrevious then + local Lowered = string.lower(v.Name) + local BuildParams = CommandFrames[Lowered] + + if BuildParams then + v.MouseButton1Click:Connect(function() + invisibleAndVisible(v.Parent, MainGui.Execution) + MainGui.Execution.CommandTitle.Text = v.Name + setupExecutionFrame(BuildParams) + end) + else + v.MouseButton1Click:Connect(function() + invisibleAndVisible(v.Parent, MainGui.HomeContent) + AdminEvent:FireServer(Lowered, {}) + end) + end + end + end + end + end + + MainGui.WindowStyle.FrameTop.X.MouseButton1Click:Connect(exitPanel) + MainGui.Execution.Exit.MouseButton1Click:Connect(exitExec) + MainGui.Execution.Execute.MouseButton1Click:Connect(executeCommand) + + local BannedPlayers = GetBanned:InvokeServer() + MainGui.StatsContent.BannedAmount.Text = "Banned players: "..#BannedPlayers + MainGui.StatsContent.ServerVersion.Text = "Server Version: "..game.PlaceVersion + + local NewDrag = DraggableObject.new(MainGui.WindowStyle.FrameTop) + NewDrag:Enable() + + UpdatingVariable = task.spawn(setupBannedList) -- yields + + RunService.RenderStepped:Connect(updateDebug) + + for _, v in pairs(Players:GetPlayers()) do + playerAdded(v) + end + + Players.ChildAdded:Connect(playerAdded) + Players.ChildRemoved:Connect(playerRemoved) + + Protocols:WaitForChild("AdminRemotes"):WaitForChild("UpdateBanList").OnClientEvent:Connect(updateBanned) + + if AdminButton then + Cloning = AdminButton:Clone() + Cloning.Parent = LocalPlayer.PlayerGui:WaitForChild("MainGui"):WaitForChild("Topbar") + Cloning.Visible = true + + Cloning.MouseButton1Click:Connect(function() + if not MainGui.Visible then + MainGui.Visible = true + Cloning.ButtonText.Text = "x Admin" + else + MainGui.Visible = false + Cloning.ButtonText.Text = "Admin" + end + end) + end +end + +setupPanel() \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/AdminGuis/Admi/AdminClient.meta.json b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/Admi/AdminClient.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/Admi/AdminClient.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/AdminGuis/Admi/init.meta.json b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/Admi/init.meta.json new file mode 100644 index 0000000..118e2ca --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/Admi/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ScreenGui", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/bounding.lua b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/bounding.lua new file mode 100644 index 0000000..25c8811 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/bounding.lua @@ -0,0 +1,58 @@ +-- nonet did not make this sorry for confusien + +local Function = {} + +local Vertices = { + Vector3.new(1,1,-1); + Vector3.new(1,-1,-1); + Vector3.new(-1,-1,-1); + Vector3.new(-1,1,-1); + + Vector3.new(1,1,1); + Vector3.new(1,-1,-1); + Vector3.new(-1,-1,1); + Vector3.new(-1,1,1); +}; + +function Function:getCorners(Part: PVInstance) + local Size = Part:IsA("BasePart") and Part.Size or Part:IsA("Model") and Part:GetExtentsSize() + + local t = {} + + local PartCF = Part:IsA("BasePart") and Part.CFrame or Part:GetPivot() + local Size = Size*0.5; + for _, Vector in Vertices do + table.insert(t, PartCF * (Size * Vector)); + end + + return t +end + +local cull = require(script.Parent.cull); +local cur = workspace.CurrentCamera; +function Function:bound2(p: PVInstance) + local c, visible = cull.worldToScreenPoint(p:IsA("BasePart") and p.Position or p:GetPivot().Position) + + local min = Vector3.one*math.huge; + local max = -min; + for _, point in Function:getCorners(p) do + local x = cull.worldToScreenPoint(point); + min = min:Min(x); + max = max:Max(x); + end + + local y = min.Y; + local y2 = max.Y; + local x = min.X; + local x2 = max.X; + + local n = y-y2 + local n22 = x2-x + local Size = UDim2.new(0,n22,0,n) + local Position = UDim2.new(0,x,0,y2) + + return Size, Position, visible +end + + +return Function \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/cull.lua b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/cull.lua new file mode 100644 index 0000000..bc9eb2c --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/cull.lua @@ -0,0 +1,53 @@ +local V3 = Vector3.new; + +local RunService = game:GetService("RunService"); +local Camera = workspace.CurrentCamera; +local Size = Camera.ViewportSize; +local Ratio = 0; + +--[[ + Used to convert 3d points into 2d points w/ + a depth buffer + @author EgoMoose + @submodule WorldToScreenPoint +]] + +local Projection = {}; +Projection.__index = Projection; + +-- purpose: world to screen point +function Projection.worldToScreenPoint(p) + local lp = Camera.CFrame:PointToObjectSpace(p); + local r = Size.X/Size.Y; + local h = -math.min(lp.z,0)*Ratio; + local w = r*h; + local corner = V3(-w, h, lp.z); + local relative = lp - corner; + local sx = relative.X / (w*2); + local sy = -relative.Y / (h*2); + local onscreen = -lp.Z > 0 and sx >=0 and sx <= 1 and sy >=0 and sy <= 1; + return V3(sx*Size.X, sy*Size.Y, -lp.z), onscreen; +end + +-- purpose: screen to world point +function Projection.screenToWorldPoint(vector) + local z=vector.Z; + local depth = z and math.max(z, 0.1) + 0.1 or 0.1; + local sx, sy = vector.X/Size.X, vector.Y/Size.Y; + local r = Size.X/Size.Y; + local h = depth*Ratio; + local w = r*h; + local corner = Vector3.new(-w, h, -depth); + local lp = corner + Vector3.new(sx*w*2, -sy*h*2, 0); + local p = Camera.CFrame:PointToWorldSpace(lp); + local direction = (p - Camera.CFrame.p).unit; + return Camera.CFrame.p+direction*(depth); +end + +-- purpose: heart beat check +RunService.Heartbeat:Connect(function() + Ratio = math.tan(math.rad(Camera.FieldOfView/2)); + Size = Camera.ViewportSize; +end) + +return Projection; \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/init.lua b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/init.lua new file mode 100644 index 0000000..d5a6443 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/init.lua @@ -0,0 +1,145 @@ +--!strict + +local GuiService = game:GetService("GuiService") +local Players = game:GetService("Players") + +local localPlayer = Players.LocalPlayer +local character = localPlayer.Character or localPlayer.CharacterAdded:Wait() +local humanoid = character:WaitForChild("Humanoid") + +local storage = script.Parent.Parent:WaitForChild("esp") +local esp_frame = script:WaitForChild("char_esp") + +local bounding = require(script:WaitForChild("bounding")) +local skeleton = require(script:WaitForChild("skeleton")) + +local lineThickness: number = 2 + +local display = {} +display.__index = display + +local function solveFrameLine(frame: GuiObject, pointA: Vector2, pointB: Vector2) : () + local distance: number = (pointA - pointB).Magnitude; + local center: Vector2 = Vector2.new((pointA.X + pointB.X) * 0.5, (pointA.Y + pointB.Y) * 0.5) + local rotation: number = math.atan2(pointA.Y - pointB.Y, pointA.X - pointB.X) + + frame.Size = UDim2.new(0, distance, 0, lineThickness) + frame.AnchorPoint = Vector2.new(0.5, 0.5) + frame.Position = UDim2.new(0, center.X, 0, center.Y) + frame.Rotation = math.deg(rotation) +end + +function display.new(humanoid : Humanoid) + local character: Instance? = humanoid.Parent + + local new_frame = esp_frame:Clone() + new_frame.Name = "box" + + -- plz apply + new_frame.entity_name.Text = (if character then character.Name else "lolwat") + + -- make frame storage + local storage_frame: Frame = Instance.new("Frame") + storage_frame.Size = UDim2.fromScale(1, 1) + storage_frame.Name = ":3" + storage_frame.Transparency = 1 + storage_frame.Parent = storage + + local new = setmetatable({ + ["connections"] = {}; + ["humanoid"] = humanoid; + ["frame"] = new_frame; + ["storage"] = storage_frame; + ["skeleton"] = skeleton.new(humanoid, storage_frame); + }, display) + + -- make ultra swag line + local line: Frame = Instance.new("Frame"); do + line.BackgroundColor3 = Color3.new(0, 1, 0) + line.BorderSizePixel = 0 + line.Name = "_espdrawline" + line.Parent = storage_frame + + new.line = line + end + + -- health bar + local function update_health(health: number): () + local ratio: number = (health / humanoid.MaxHealth) + + new_frame.health.fill.Size = UDim2.fromScale(ratio, 1) + new_frame.health.fill.BackgroundColor3 = Color3.fromHSV(ratio * 0.3, 1, 1) + end + + update_health(humanoid.Health) + + table.insert(new.connections, humanoid.HealthChanged:Connect(update_health)) + + -- We are done + new_frame.Parent = storage_frame + + return new +end + +function display:update(deltaTime : number) + local humanoid: Humanoid = self.humanoid + local character: Instance? = humanoid.Parent + + local frame: Frame = self.frame + local line: Frame = self.line + + local vp_size: Vector2 = workspace.CurrentCamera.ViewportSize + vp_size -= Vector2.new(vp_size.X / 2,0); + + if(character and character:IsA("Model"))then + -- updet pos + local bounding_s, bounding_p, bounding_vis = bounding:bound2(character) + + frame.Position = bounding_p + -- draw line + solveFrameLine(line, + vp_size, + frame.AbsolutePosition + (Vector2.new(frame.AbsoluteSize.X * 0.5, 0)) + ) + + if bounding_vis==true then + frame.Size = bounding_s + self.skeleton:update(deltaTime) + end + + frame.Visible = bounding_vis + + self.skeleton.storage.Visible = bounding_vis + + -- update labels + -- update distance + local RootPart: BasePart? = humanoid.RootPart + if RootPart then + local TargetRoot: BasePart? = humanoid.RootPart + + if TargetRoot then + local dist_lbl: Instance? = frame:FindFirstChild("distance", false) + + if dist_lbl and dist_lbl:IsA("TextLabel") then + local dist: number = (RootPart.Position - TargetRoot.Position).Magnitude + dist_lbl.Text = string.format("%.1fst", dist) + end + end + end + end +end + +function display:destroy() + for _: number, v: RBXScriptConnection in self.connections do + v:Disconnect() + end + + self.storage:Destroy() + self.skeleton:Destroy() + + table.clear(self) + + setmetatable(self, nil) +end + +return display \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/init.meta.json b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/skeleton.lua b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/skeleton.lua new file mode 100644 index 0000000..cda0645 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/display/skeleton.lua @@ -0,0 +1,122 @@ +--!strict +local skeleton = {} +skeleton.__index = skeleton + +local GuiService = game:GetService("GuiService") + +-- 2 lazy to make this not a copy +local LineThickness : number = 2 +local function SolveFrameLine(Frame : GuiObject, PointA : Vector2, PointB : Vector2) : () + local Distance = (PointA-PointB).Magnitude; + local Center = Vector2.new((PointA.X + PointB.X)*0.5, (PointA.Y + PointB.Y)*0.5) + local Rotation = math.atan2(PointA.Y - PointB.Y, PointA.X - PointB.X) + + Frame.Size = UDim2.new(0, Distance, 0, LineThickness) + Frame.AnchorPoint = Vector2.new(0.5,0.5) + Frame.Position = UDim2.new(0, Center.X, 0, Center.Y) + Frame.Rotation = math.deg(Rotation) +end + +function skeleton.new(humanoid : Humanoid, parent : Instance) + local new = setmetatable({ + ["connections"] = {}; + ["humanoid"] = humanoid; + ["storage"] = Instance.new("Frame"); + + bones = {}; + }, skeleton) + + new.storage.Name = "skeleton" + new.storage.Parent = parent + new.storage.Transparency, new.storage.Size = 1, UDim2.fromScale(1,1) + + local function add_bone(motor : Instance | Motor6D) + if motor:IsA("Motor6D") then + local Part0, Part1 = motor.Part0, motor.Part1 + + if Part0 and Part1 then + if Part0.Transparency==1 or Part1.Transparency==1 then + return + end + + local lines = {} + for i = 1, 2 do + local new_line = Instance.new("Frame") + new_line.BorderSizePixel = 0 + new_line.BackgroundColor3 = Color3.new(1,1,1) + + new_line.Name = motor.Name..i + new_line.Parent = new.storage + + table.insert(lines, new_line) + end + + new.bones[motor] = lines + end + end + end + + local function remove_bone(motor: Instance | Motor6D) + if(motor:IsA("Motor6D") and new.bones[motor])then + for _, line in new.bones[motor]do + line:Destroy(); + end + + new.bones[motor] = nil; + end + end + + if humanoid.Parent ~= nil then + for _, v in humanoid.Parent:GetDescendants() do + add_bone(v) + end + + table.insert(new.connections, humanoid.Parent.DescendantRemoving:Connect(remove_bone)); + table.insert(new.connections, humanoid.Parent.DescendantAdded:Connect(add_bone)) + end + + return new +end + +local cull = require(script.Parent.cull); +local wtvp = cull.worldToScreenPoint; +function skeleton:update(deltaTime : number) + local inset = GuiService:GetGuiInset() + + for motor : Motor6D, lines : {Frame} in self.bones do + local Part0, Part1 = motor.Part0, motor.Part1 + + if Part0 and Part1 then + local ToMotorLine, ToPartLine = lines[1], lines[2] + + local cop = wtvp((Part0.CFrame * motor.C0).Position); + SolveFrameLine( + ToMotorLine, + wtvp(Part0.Position), + cop + ); + + SolveFrameLine( + ToPartLine, + cop, + wtvp(Part1.Position) + ); + + ToMotorLine.Position -= UDim2.fromOffset(0, inset.Y) + ToPartLine.Position -= UDim2.fromOffset(0, inset.Y) + end + end +end + +function skeleton:Destroy() + for _,v : RBXScriptConnection in self.connections do + v:Disconnect() + end + + self.storage:Destroy() + + table.clear(self) + setmetatable(self, nil) +end + +return skeleton \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/init.client.lua b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/init.client.lua new file mode 100644 index 0000000..df3192d --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/fartware/init.client.lua @@ -0,0 +1,94 @@ +--!strict +local Players : Players = game:GetService("Players") +local RunService : RunService = game:GetService("RunService") + +local gui_frame : (ScreenGui | Frame) = script.Parent +local active = {} + +local display = require(script:WaitForChild("display")) + +------------------------------------------------------------- sponored by crazyblocks234 + +local function add_character(char : Model?) + if(typeof(char) == "Instance" and char:IsA("Model")) then + local Humanoid : Humanoid? = char:FindFirstChildWhichIsA("Humanoid") + + if Humanoid ~= nil and active[Humanoid]==nil then + local new_disp = display.new(Humanoid) + + local dat = { + ["display"] = new_disp; + } + + -- check destruction + local conns; + conns = { + Humanoid.AncestryChanged:Connect(function(child: Instance, parent: Instance): () + if not Humanoid:IsDescendantOf(workspace) then + for _, conn in conns do + conn:Disconnect(); + end + + active[Humanoid] = nil; + dat.display:destroy() + end + end); + + Humanoid.Died:Connect(function(): () + for _, conn in conns do + conn:Disconnect(); + end + + active[Humanoid] = nil; + dat.display:destroy() + end); + }; + + -- done + active[Humanoid] = dat + end + end +end + +-- add +local function add_player(player : Instance) + if player:IsA("Player") then + if player ~= Players.LocalPlayer then + local function check_chr(character : Model) + character:WaitForChild("Head", 1) + character:WaitForChild("Humanoid", 1) + + add_character(character) + end + + check_chr(player.Character or player.CharacterAdded:Wait()) + player.CharacterAdded:Connect(check_chr) + end + end +end + +for _,v in Players:GetChildren() do add_player(v) end +Players.ChildAdded:Connect(add_player) + +local function RenderTask() + RunService:UnbindFromRenderStep("frtware-yes"); + + if script.Parent.Parent.Enabled == true then + RunService:BindToRenderStep("frtware-yes", Enum.RenderPriority.Camera.Value+1, function(deltaTime) + for humanoid, tasks in active do + tasks.display:update(deltaTime); + end + end) + end +end + +RenderTask() +script.Parent.Parent:GetPropertyChangedSignal("Enabled"):Connect(RenderTask) + +if RunService:IsStudio() then + local Dummy = workspace:FindFirstChild("Dummy") + + if Dummy~=nil then + add_character(Dummy) + end +end \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/init.meta.json b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/init.meta.json new file mode 100644 index 0000000..dc7de63 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/ESP/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "Frame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/init.meta.json b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/init.meta.json new file mode 100644 index 0000000..118e2ca --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/ESP/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ScreenGui", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/AdminGuis/init.meta.json b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/AdminGuis/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/StarterGui/ClientLocalPlayerScripts.client.lua b/rojo/MainModule/src/ServerStorage/UI/StarterGui/ClientLocalPlayerScripts.client.lua new file mode 100644 index 0000000..e56f073 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/StarterGui/ClientLocalPlayerScripts.client.lua @@ -0,0 +1,112 @@ +--!strict +--[[ + FWM Official, 2022 + + This will handle stuff like the scrolling sound and stuff idk + -- KeyboardCombination +]] +local Lighting = game:GetService("Lighting") +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local RunService: RunService = game:GetService("RunService") +--local SoundService = game:GetService("SoundService") +local StarterGui = game:GetService("StarterGui") +local GuiService = game:GetService("GuiService") +local UserInputService: UserInputService = game:GetService("UserInputService") + +--GuiService.AutoSelectGuiEnabled = false + +local CustomFont = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("CustomFont")) +local StockSound = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("StockSound")) + +local CurrentTimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value + +local MAX_RETRIES: number = 8 + +local cameraKeys = { + [Enum.KeyCode.Comma] = true, + [Enum.KeyCode.I] = true, + [Enum.KeyCode.O] = true, + [Enum.KeyCode.PageDown] = true, + [Enum.KeyCode.PageUp]= true, + [Enum.KeyCode.Period] = true, +} + +local function cameraSound(input: InputObject, gameProcessedEvent: boolean): () + if not gameProcessedEvent and UserInputService:GetFocusedTextBox() == nil then + if input.UserInputType == Enum.UserInputType.MouseWheel or cameraKeys[input.KeyCode] then + StockSound:PlaySoundLocal("Step") + end + end +end + +-- disable reset button (from developer forum): +local function coreCall(method, ...) + local result = {} + + for retries = 1, MAX_RETRIES do + result = {pcall(StarterGui[method], StarterGui, ...)} + + if result[1] then + break + end + + local deltaTime: number = RunService.Heartbeat:Wait() + end + + return unpack(result) +end + +local function renderFont(ins: Instance): () + if ins:IsA("TextLabel") and ins.FontFace.Family == "rbxasset://fonts/families/GothamSSm.json" then + if CurrentTimePeriod < 8 then + local TextStrokeTransparency = ins.TextStrokeTransparency + + CustomFont.displayString(ins.Text, ins.TextBounds.Y + 4, ins, TextStrokeTransparency) + + ins:GetPropertyChangedSignal("Text"):Connect(function() + CustomFont.displayString(ins.Text, ins.TextBounds.Y + 4, ins, TextStrokeTransparency) + end) + + ins:GetPropertyChangedSignal("TextBounds"):Connect(function() + CustomFont.displayString(ins.Text, ins.TextBounds.Y + 4, ins, TextStrokeTransparency) + end) + + ins:GetPropertyChangedSignal("AbsoluteSize"):Connect(function() + CustomFont.displayString(ins.Text, ins.TextBounds.Y + 4, ins, TextStrokeTransparency) + end) + + ins:GetPropertyChangedSignal("AbsolutePosition"):Connect(function() + CustomFont.displayString(ins.Text, ins.TextBounds.Y + 4, ins, TextStrokeTransparency) + end) + + ins:GetPropertyChangedSignal("TextColor3"):Connect(function() + CustomFont.displayString(ins.Text, ins.TextBounds.Y + 4, ins, TextStrokeTransparency) + end) + + --ins:GetPropertyChangedSignal("Visible"):Connect(function() + -- CustomFont.displayString(ins.Text, ins.TextBounds.Y + 4, ins, TextStrokeTransparency) + --end) + else + ins.Font = Enum.Font.Cartoon + ins.TextSize += 2 + end + end +end + +coreCall("SetCore", "ResetButtonCallback", false) +-- if this causes havoc, assert() it again + +for _, v in pairs(script.Parent:WaitForChild("MainGui"):GetDescendants()) do + renderFont(v) +end + +for _, v in pairs(script.Parent:WaitForChild("MainResetGui"):GetDescendants()) do + renderFont(v) +end + +script.Parent:WaitForChild("MainGui").DescendantAdded:Connect(renderFont) +script.Parent:WaitForChild("MainResetGui").DescendantAdded:Connect(renderFont) + +UserInputService.InputChanged:Connect(cameraSound) +UserInputService.InputBegan:Connect(cameraSound) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/StarterGui/Loading/LoadingHandler.client.lua b/rojo/MainModule/src/ServerStorage/UI/StarterGui/Loading/LoadingHandler.client.lua new file mode 100644 index 0000000..cf81cb8 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/StarterGui/Loading/LoadingHandler.client.lua @@ -0,0 +1,161 @@ +--[[ + + FWM Official, 2023 + Rewrite of Loading Handler - Roblox_Gamer2030 + +]]-- + +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local StarterGui = game:GetService("StarterGui") +local UserInputService: UserInputService = game:GetService("UserInputService") + +local Protocols = ReplicatedStorage:WaitForChild("Protocols") +local CurrentTimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value +local CustomFont = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("CustomFont")) + +local LoadingUI = script.Parent.LoadingCharacter +local BrickSnapsLoadingUI = script.Parent.LoadingFrame +local currentCamera = workspace.CurrentCamera + +local Connections = {} + +local objectsLoading = {} +local partsLoaded = {} + +local snapsCount: number = 0 + +local timer = 0 + +local minLoadInFrame = 1 +local maxLoadInFrame = 1500 + +local validClasses: { [string] : boolean } = { + Part = true, + Decal = true +} + +local finishedLoading: boolean = false + +local function zoomToExtents(camera: Camera, instance: Instance) + local instanceCFrame: CFrame | false = instance:IsA("Model") and instance:GetPivot() or instance:IsA("BasePart") and instance.CFrame + local extentsSize: Vector3 | false = instance:IsA("Model") and instance:GetExtentsSize() or instance:IsA("BasePart") and instance.Size + + if instanceCFrame and extentsSize then + local cameraOffset: number = 500 + extentsSize.Magnitude + local cameraRotation: CFrame = camera.CFrame - camera.CFrame.Position + + local instancePosition: Vector3 = instanceCFrame.Position + camera.CFrame = cameraRotation + instancePosition + (-cameraRotation.LookVector * cameraOffset) + camera.Focus = cameraRotation + instancePosition + end +end + +local function handleObject(obj: Instance): () + if validClasses[obj.ClassName] then + local findObject = table.find(objectsLoading, obj) + + if findObject then + return + end + + table.insert(objectsLoading, obj) + + if obj:IsA("BasePart") then + obj.LocalTransparencyModifier = 1 + end + end +end + +local function addAndDestroy(obj: Instance): () + if validClasses[obj.ClassName] then + local findObject = table.find(objectsLoading, obj) + local alreadyLoaded = table.find(partsLoaded, obj) + + if findObject and not alreadyLoaded then + table.remove(objectsLoading, findObject) + + if obj:IsA("Part") then + table.insert(partsLoaded, obj) + + local getJoints = #obj:GetJoints() + snapsCount += getJoints + + zoomToExtents(workspace.CurrentCamera, obj) + end + + if obj:IsA("BasePart") then + obj.LocalTransparencyModifier = 0 + end + + BrickSnapsLoadingUI.MainLabel.Text = string.format("Bricks: %d Snaps: %d", #partsLoaded, snapsCount) + end + end +end + +local function onDestroyed(obj: Instance): () + if validClasses[obj.ClassName] then + local findObject = table.find(objectsLoading, obj) + local alreadyLoaded = table.find(partsLoaded, obj) + + if findObject then + table.remove(objectsLoading, findObject) + + if obj:IsA("Part") then + local getJoints = #obj:GetJoints() + snapsCount -= getJoints + end + elseif alreadyLoaded then + table.remove(partsLoaded, alreadyLoaded) + end + end +end + +StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, false) +UserInputService.MouseIconEnabled = false + +if CurrentTimePeriod < 8 then + LoadingUI.Visible = true + CustomFont.displayString(LoadingUI.Text, LoadingUI.TextBounds.Y + 4, LoadingUI, LoadingUI.TextStrokeTransparency) + Protocols.LoadForFirstTime:FireServer() +else + BrickSnapsLoadingUI.MainLabel.Font = Enum.Font.Cartoon + BrickSnapsLoadingUI.Visible = true + + currentCamera.CameraType = Enum.CameraType.Follow + + for i: number, v: Instance in pairs(workspace:GetDescendants()) do + handleObject(v) + end + + table.insert(Connections, workspace.DescendantAdded:Connect(handleObject)) + table.insert(Connections, workspace.DescendantRemoving:Connect(onDestroyed)) + + task.wait(2) + + while not finishedLoading do + for i: number = 1, math.random(minLoadInFrame, maxLoadInFrame) do + if objectsLoading[1] then + addAndDestroy(objectsLoading[1]) + end + end + + finishedLoading = #objectsLoading <= 0 + + task.wait(0.03) + end + + -- useless micro opt but WHATEVER LOL + for i: number, v: RBXScriptConnection in pairs(Connections) do + v:Disconnect() + end + table.clear(Connections) + + task.wait(2) + + BrickSnapsLoadingUI.MainLabel.Text = "Requesting character" + + task.wait(1.5) + + BrickSnapsLoadingUI.MainLabel.Text = "Waiting for character" + Protocols.LoadForFirstTime:FireServer() +end \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/StarterGui/Loading/init.meta.json b/rojo/MainModule/src/ServerStorage/UI/StarterGui/Loading/init.meta.json new file mode 100644 index 0000000..118e2ca --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/StarterGui/Loading/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ScreenGui", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/MainGuiHandler.client.lua b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/MainGuiHandler.client.lua new file mode 100644 index 0000000..ad2b2a4 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/MainGuiHandler.client.lua @@ -0,0 +1,1344 @@ +--!strict +--[[ + FWM Official, 2022 + + The main gui handler for FWM, does not reset +]] + +local Chat: Chat = game:GetService("Chat") +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local RunService: RunService = game:GetService("RunService") +local ScriptContext: ScriptContext = game:GetService("ScriptContext") +local StarterGui = game:GetService("StarterGui") +local TeleportService: TeleportService = game:GetService("TeleportService") +local TextChatService: TextChatService = game:GetService("TextChatService") +local UserInputService: UserInputService = game:GetService("UserInputService") +local Teams: Teams = game:GetService("Teams") +local HttpService: HttpService = game:GetService("HttpService") + +local DraggableObject = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("DraggableObject")) +local StockSound = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("StockSound")) +local SuperSafeChat = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("SuperSafeChat")) + +local DecodedSuperSafeChat = HttpService:JSONDecode(SuperSafeChat) +local FullDecoded = DecodedSuperSafeChat["roblox"]["utterance"] +local MainGui = script.Parent +local Templates = ReplicatedStorage:WaitForChild("Templates") +local GameSettings = UserSettings().GameSettings +local LocalPlayer = Players.LocalPlayer +local Mouse = LocalPlayer:GetMouse() +local Camera = workspace.CurrentCamera +local Solo = ReplicatedStorage:WaitForChild("Solo") + +local ErrorsInChat = ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("GetSetting"):InvokeServer("ErrorsInChat") +local DisplayNames = ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("GetSetting"):InvokeServer("DisplayNames") + +local CurrentTimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value +local HintFolder = ReplicatedStorage:WaitForChild("HintFolder") + +local chats = {} +local chatTasks = {} + +local registeredVisualInstances = {} + +local playerlistdata: any = { + players = {}, + teams = {}, +} + +local teamCount = 0 + +local canShowTeams = false +local safeChatOpened = false +local clickedExit = false +local color3Teams = CurrentTimePeriod < 8 + +local lb_big = UDim2.new(0.33, 0, 0.018, 0) +local lb_small = UDim2.new(0.162, 0, 0.018, 0) + +local NAME_COLORS: {Color3} = { + --BrickColor.new("Crimson"), --r + --BrickColor.new("Deep blue"), --g + --BrickColor.new("Earth green"), --b + --BrickColor.new("Bright violet"), + --BrickColor.new("Bright orange"), + --BrickColor.new("Bright yellow"), + --BrickColor.new("Light reddish violet"), + --BrickColor.new("Brick yellow"), + Color3.fromRGB(173, 35, 35), + Color3.fromRGB(42, 75, 215), + Color3.fromRGB(29, 105, 20), + Color3.fromRGB(129, 38, 192), + Color3.fromRGB(255, 146, 51), + Color3.fromRGB(255, 238, 51), + Color3.fromRGB(255, 205, 243), + Color3.fromRGB(233, 222, 187), +} + +local twoExtraButtons = { + MainGui.Topbar["Edit Mode"], + MainGui.Topbar.Toolbox +} + +local whitelistedStringsTalk: any = { + ["[ERROR!]"] = { + Username = { + TextColor3 = Color3.fromRGB(255, 0, 0), + TextStrokeTransparency = 0, + }, + + Text = { + TextColor3 = Color3.fromRGB(255, 0, 0), + } + }, +} + +local function toolboxShouldBeEnabled(): boolean + return Solo.Value or RunService:IsStudio(); +end + +local function GetNameValue(pName: string): number + local value = 0 + for index = 1, #pName do + local cValue = string.byte(string.sub(pName, index, index)) + local reverseIndex = #pName - index + 1 + if #pName%2 == 1 then + reverseIndex = reverseIndex - 1 + end + if reverseIndex%4 >= 2 then + cValue = -cValue + end + value = value + cValue + end + return value +end + +local color_offset = 0 + +local function ComputeNameColor(pName: string): Color3 + return NAME_COLORS[((GetNameValue(pName) + color_offset) % #NAME_COLORS) + 1] +end + +StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, false) +StarterGui:SetCore("ChatActive", false) +UserInputService.MouseIconEnabled = false + +--Functions: +local function ObjectAdded(obj): () + if (obj:IsA("Message") or obj:IsA("Hint")) and not registeredVisualInstances[obj] then + registeredVisualInstances[obj] = true + + local connections = {} + local parentChanging = false + local objectClass = obj.ClassName -- :IsA doesn't work but this does?? + + local grabbedInstanceGui = Templates.GuiInstances["FWM_"..tostring(objectClass).."_Instance"]:Clone() + grabbedInstanceGui.Name = "LEGACY_INSTANCE" + grabbedInstanceGui.Text = obj.Text + grabbedInstanceGui.Parent = MainGui + + if objectClass == "Message" then + grabbedInstanceGui.Visible = #obj.Text > 0 + obj.Text = "" + + if obj.Parent == LocalPlayer and CurrentTimePeriod >= 7 then + grabbedInstanceGui.Position = UDim2.new(0, 30, 0, 30) + grabbedInstanceGui.Size = UDim2.new(0.3, 0, 0.25, 0) + end + elseif objectClass == "Hint" then + task.defer(function() + obj.Parent = HintFolder + end) + + if not MainGui.ChatBar.Visible then + grabbedInstanceGui.AnchorPoint = Vector2.new(1, 0) + else + grabbedInstanceGui.AnchorPoint = Vector2.new(1, 1) + end + end + + table.insert(connections, obj:GetPropertyChangedSignal("Text"):Connect(function() + if objectClass == "Message" then + if obj.Text ~= "" then + grabbedInstanceGui.Text = obj.Text + grabbedInstanceGui.Visible = true + obj.Text = "" + end + elseif objectClass == "Hint" then + grabbedInstanceGui.Text = obj.Text + end + end)) + + table.insert(connections, MainGui.ChatBar:GetPropertyChangedSignal("Visible"):Connect(function() + if objectClass == "Hint" then + if not MainGui.ChatBar.Visible then + grabbedInstanceGui.AnchorPoint = Vector2.new(1, 0) + else + grabbedInstanceGui.AnchorPoint = Vector2.new(1, 1) + end + end + end)) + + table.insert(connections, obj.AncestryChanged:Connect(function(child, parent) + local canDestroy = false + + if objectClass == "Message" then + if obj:IsDescendantOf(workspace) then + grabbedInstanceGui.Position = UDim2.new(0, 0, 0, 0) + grabbedInstanceGui.Size = UDim2.new(1, 0, 1, 0) + elseif obj.Parent == LocalPlayer then + if CurrentTimePeriod >= 7 then + grabbedInstanceGui.Position = UDim2.new(0, 30, 0, 30) + grabbedInstanceGui.Size = UDim2.new(0.3, 0, 0.25, 0) + end + else + canDestroy = true + end + elseif objectClass == "Hint" then + if obj:IsDescendantOf(workspace) then + if parentChanging then + return + end + + parentChanging = true + + task.defer(function() + obj.Parent = HintFolder + end) + + parentChanging = false + elseif obj.Parent ~= HintFolder then + canDestroy = true + end + end + + if canDestroy then + for i, v in pairs(connections) do + v:Disconnect() + end + + grabbedInstanceGui:Destroy() + registeredVisualInstances[obj] = nil + end + end)) + end +end + +local function FullscreenMain(): () + local Topbar = MainGui:WaitForChild("Topbar") + if GameSettings:InFullScreen() then + Topbar.Fullscreen.ButtonText.Text = "x Fullscreen" + else + Topbar.Fullscreen.ButtonText.Text = "Fullscreen" + end +end + +local function getTeamCount(Team: Instance, StatName: string): number + if Team:IsA("Team") then + local Count = 0 + + for i, v in pairs(Team:GetPlayers()) do + local hasData = playerlistdata.players[v] + + if hasData then + local statFocusing = hasData.statFocusing + + if statFocusing then + local findValue = statFocusing:FindFirstChild(StatName) + + if findValue then + Count += findValue.Value + end + end + end + end + + return Count + end + + return 0 +end + +local function refreshTeamStats(Team: Instance): () + if Team:IsA("Team") then + local teamData = playerlistdata.teams[Team] + local localData = playerlistdata.players[LocalPlayer] + + if teamData and localData then + local isUI = localData.statsUI + + local statLabelConnections = localData.statLabelConnections + local statFocusing = localData.statFocusing + + if statFocusing then + local statAmount = #localData.statFocusing:GetChildren() + + if isUI then + local isColor3 = color3Teams and Team:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and Team:GetAttribute("Color3") or Team.TeamColor.Color + + for StatName, StatLabel in pairs(isUI) do + local getTeamUI = teamData.teamStats[StatName] + + if not getTeamUI then + local newStat = Templates.GuiInstances.Leaderstat:Clone() + newStat.Name = StatName + newStat.Text = getTeamCount(Team, StatName) + newStat.TextColor3 = TeamColor + newStat.TextStrokeTransparency = 0 + newStat.LayoutOrder = StatLabel.LayoutOrder + newStat.Parent = teamData.teamFrames.mainFrame.TeamPoints + + teamData.teamStats[StatName] = newStat + else + getTeamUI.Text = getTeamCount(Team, StatName) + end + end + + for i, v in pairs(teamData.teamFrames.mainFrame.TeamPoints:GetChildren()) do + if v:IsA("TextLabel") then + if not localData.statsUI[v.Name] then + v:Destroy() + end + end + end + end + + local getUIGrid = teamData.teamFrames.mainFrame.TeamPoints:FindFirstChildOfClass("UIGridLayout") + getUIGrid.CellSize = UDim2.new(1 / statAmount, 0, 1, 0) + end + end + end +end + +local function onTeamUpdate(Team: Instance): () + if Team:IsA("Team") and playerlistdata.teams[Team] then + local teamData = playerlistdata.teams[Team] + local mainFrame = teamData.teamFrames.mainFrame + local isColor3 = color3Teams and Team:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and Team:GetAttribute("Color3") or Team.TeamColor.Color + + --local TeamColor = Team.TeamColor.Color + + mainFrame.Name = "Team_"..Team.Name + mainFrame.TeamNameLabel.Text = Team.Name + mainFrame.TeamNameLabel.TextColor3 = TeamColor + mainFrame.TeamBar.BorderColor3 = TeamColor + + for i, v in pairs(teamData.teamStats) do + teamData.teamStats[i].TextColor3 = TeamColor + end + + for i, v in pairs(Team:GetPlayers()) do + local getData = playerlistdata.players[v] + + if getData then + local playerFrame = getData.playerFrame + + local isColor3 = color3Teams and Team:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and Team:GetAttribute("Color3") or Team.TeamColor.Color + --local TeamColor = Team.TeamColor.Color + + playerFrame.NameLabel.TextColor3 = TeamColor + + for i, v in pairs(getData.statsUI) do + getData.statsUI[i].TextColor3 = TeamColor + end + end + end + end +end + +local function TeamAdded(Team: Instance): () + if Team:IsA("Team") and not playerlistdata.teams[Team] and canShowTeams then + playerlistdata.teams[Team] = { + teamFrames = { + splitFrames = { + topFrame = nil, + bottomFrame = nil + }, + mainFrame = nil, + }, + + teamStats = {}, + teamConnections = {}, + teamPriority = 0 + } + + teamCount += 1 + + local teamData = playerlistdata.teams[Team] + teamData.teamPriority = teamCount + teamData.teamFrames.mainFrame = Templates.GuiInstances.Team:Clone() + teamData.teamFrames.splitFrames.topFrame = Templates.GuiInstances.TeamSplit_Top:Clone() + teamData.teamFrames.splitFrames.bottomFrame = Templates.GuiInstances.TeamSplit_Bottom:Clone() + + local mainFrame = teamData.teamFrames.mainFrame + local splitBottom = teamData.teamFrames.splitFrames.bottomFrame + local splitTop = teamData.teamFrames.splitFrames.topFrame + + local isColor3 = color3Teams and Team:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and Team:GetAttribute("Color3") or Team.TeamColor.Color + --local TeamColor = Team.TeamColor.Color + + mainFrame.Name = "Team_"..Team.Name + mainFrame.TeamNameLabel.Text = Team.Name + mainFrame.TeamNameLabel.TextColor3 = TeamColor + mainFrame.TeamBar.BorderColor3 = TeamColor + mainFrame.LayoutOrder = teamData.teamPriority * 100 + + splitBottom.LayoutOrder = mainFrame.LayoutOrder + 2 + splitTop.LayoutOrder = mainFrame.LayoutOrder + 1 + + mainFrame.Parent = MainGui.Leaderboard + splitBottom.Parent = MainGui.Leaderboard + splitTop.Parent = MainGui.Leaderboard + + MainGui.Leaderboard.TeamSplit_VeryBottom.Visible = true + + table.insert(teamData.teamConnections, Team:GetPropertyChangedSignal("TeamColor"):Connect(function() + onTeamUpdate(Team) + end)) + + table.insert(teamData.teamConnections, Team:GetPropertyChangedSignal("Name"):Connect(function() + onTeamUpdate(Team) + end)) + + if color3Teams then + Team:GetAttributeChangedSignal("Color3"):Connect(function() + onTeamUpdate(Team) + end) + end + + updatePlayerList() + end +end + +local function TeamRemoving(Team: Instance): () + if Team:IsA("Team") and playerlistdata.teams[Team] and teamCount > 0 then + --teamCount -= 1 + + local teamData = playerlistdata.teams[Team] + + for i, v in pairs(teamData.teamConnections) do + v:Disconnect() + end + teamData.teamConnections = {} + + teamData.teamFrames.mainFrame:Destroy() + + for i, v in pairs(teamData.teamFrames.splitFrames) do + teamData.teamFrames.splitFrames[i]:Destroy() + teamData.teamFrames.splitFrames[i] = nil + end + teamData.teamFrames.splitFrames = {} + + for i, v in pairs(teamData.teamStats) do + teamData.teamStats[i]:Destroy() + teamData.teamStats[i] = nil + end + teamData.teamStats = {} + + playerlistdata.teams[Team] = nil + + updatePlayerList() + end +end + +local function fixStatsLayout(statName: string, newOrder: number): () + local localData = playerlistdata.players[LocalPlayer] + + if localData then + for i, v in pairs(Players:GetPlayers()) do + local playerData = playerlistdata.players[v] + + if playerData then + local playerFrame = playerData.playerFrame + local findStat = playerFrame.Leaderstats:FindFirstChild(statName) + + if findStat then + findStat.LayoutOrder = newOrder + end + end + end + end +end + +-- TODO: separate for less usage +local function updateBoard(): () + local localData = playerlistdata.players[LocalPlayer] + + if localData then + local isFocusing = localData.statFocusing + local trueStatAmount = localData.statAmount + local statAmount = 1 + + if isFocusing then + statAmount = #isFocusing:GetChildren() + + MainGui.Leaderboard.TopBar.Player.Text = "Players" + canShowTeams = true + + if MainGui.Leaderboard.Size ~= lb_big then + MainGui.Leaderboard.Size = lb_big + end + + if CurrentTimePeriod >= 6 and #Teams:GetTeams() > 0 then + MainGui.Leaderboard.TopBar.Player.Text = "Team" + MainGui.Leaderboard.TopSplit.Visible = false + MainGui.Leaderboard.TeamSplit_VeryBottom.Visible = true + else + MainGui.Leaderboard.TopSplit.Visible = true + MainGui.Leaderboard.TeamSplit_VeryBottom.Visible = false + end + else + MainGui.Leaderboard.TopBar.Player.Text = "Player List" + canShowTeams = false + + if MainGui.Leaderboard.Size ~= lb_small then + MainGui.Leaderboard.Size = lb_small + end + + MainGui.Leaderboard.TopSplit.Visible = true + MainGui.Leaderboard.TeamSplit_VeryBottom.Visible = false + end + + -- update top bar + local getStatUI = localData.statsUI + + for StatObject, StatLabel in pairs(localData.statsUI) do + local getLocal = localData.statsUI[StatObject] + local findStat = MainGui.Leaderboard.TopBar.Leaderstats:FindFirstChild(StatObject) + + if not findStat then + localData.statAmount += 1 + + local newStat = Templates.GuiInstances.Leaderstat:Clone() + newStat.Name = StatObject + newStat.Text = StatObject + newStat.LayoutOrder = localData.statAmount + newStat.Parent = MainGui.Leaderboard.TopBar.Leaderstats + + fixStatsLayout(StatObject, localData.statAmount) + end + end + + for i, v in pairs(MainGui.Leaderboard.TopBar.Leaderstats:GetChildren()) do + if v:IsA("TextLabel") then + if not localData.statsUI[v.Name] then + localData.statAmount -= 1 + v:Destroy() + end + end + end + + local getUIGrid = MainGui.Leaderboard.TopBar.Leaderstats:FindFirstChildOfClass("UIGridLayout") + getUIGrid.CellSize = UDim2.new(1 / statAmount, 0, 1, 0) + end + + if CurrentTimePeriod >= 6 then + for i, v in pairs(Players:GetPlayers()) do + onTeamChange(v) + end + + if canShowTeams then + for i, v in ipairs(Teams:GetTeams()) do + TeamAdded(v) + refreshTeamStats(v) + end + else + for i, v in ipairs(Teams:GetTeams()) do + if v:IsA("Team") then + TeamRemoving(v) + + for i2, v2 in pairs(v:GetPlayers()) do + onTeamChange(v2) + end + end + end + end + end +end + +local function globalTeamRemoving(Team: Instance): () + TeamRemoving(Team) +end + +local function globalTeamAdded(Team: Instance): () + TeamAdded(Team) +end + +function updatePlayerList() + updateBoard() +end + +local function onStatRemoved(Stat: Instance, statName: string?, Player: Instance): () + if Stat:IsA("IntValue") then + local grabbedPlayer = Player + + if grabbedPlayer and grabbedPlayer:IsA("Player") and playerlistdata.players[grabbedPlayer] then + local data = playerlistdata.players[grabbedPlayer] + + local statFocusing = data.statFocusing + local statAmount = 1 + + local trueStatAmount = data.statAmount + + if statFocusing then + statAmount = #data.statFocusing:GetChildren() + end + + local dataFrame = data.playerFrame + + local grabbedName = statName or Stat.Name + + if data.statsUI[grabbedName] then + local getStatUI = data.statsUI[grabbedName] + getStatUI:Destroy() + + local getUIGrid = dataFrame.Leaderstats:FindFirstChildOfClass("UIGridLayout") + getUIGrid.CellSize = UDim2.new(1 / statAmount, 0, 1, 0) + + local objectConnections = data.statLabelConnections[grabbedName] + + for i, v in pairs(objectConnections) do + v:Disconnect() + end + data.statLabelConnections[grabbedName] = nil + data.statsUI[grabbedName] = nil + + --data.statAmount -= 1 + end + + updatePlayerList() + end + end +end + +local function onStatAdded(Stat: Instance): () + if Stat:IsA("IntValue") and Stat.Parent then + local grabbedPlayer = Stat.Parent.Parent + + if grabbedPlayer and grabbedPlayer:IsA("Player") and playerlistdata.players[grabbedPlayer] then + local data = playerlistdata.players[grabbedPlayer] + local statLabelConnections = data.statLabelConnections + local statFocusing = data.statFocusing + local statAmount = #statFocusing:GetChildren() + local dataFrame = data.playerFrame + + statLabelConnections[Stat.Name] = {} + + local focusedStatLabelConnection = statLabelConnections[Stat.Name] + + if not data.statsUI[Stat.Name] then + local newStat = Templates.GuiInstances.Leaderstat:Clone() + newStat.Name = Stat.Name + newStat.Text = tostring(Stat.Value) + newStat.LayoutOrder = statAmount + + if CurrentTimePeriod >= 6 and (not grabbedPlayer.Neutral) and grabbedPlayer.Team and playerlistdata.teams[grabbedPlayer.Team] then + newStat.TextColor3 = grabbedPlayer.Team.TeamColor.Color + end + + local currentName = Stat.Name + + table.insert(focusedStatLabelConnection, Stat:GetPropertyChangedSignal("Value"):Connect(function() + newStat.Text = tostring(Stat.Value) + + if CurrentTimePeriod >= 6 and canShowTeams and playerlistdata.teams[grabbedPlayer.Team] and grabbedPlayer.Team then + refreshTeamStats(grabbedPlayer.Team) + end + end)) + + -- TODO: make this NOT use onStatRemoved + --table.insert(focusedStatLabelConnection, Stat:GetPropertyChangedSignal("Name"):Connect(function() + -- onStatRemoved(Stat, currentName, grabbedPlayer) + -- onStatAdded(Stat) + --end)) + + newStat.Parent = dataFrame.Leaderstats + + local getUIGrid = dataFrame.Leaderstats:FindFirstChildOfClass("UIGridLayout") + getUIGrid.CellSize = UDim2.new(1 / statAmount, 0, 1, 0) + + data.statsUI[Stat.Name] = newStat + end + + updatePlayerList() + end + end +end + +local function HandleLeaderstats(Stat: Instance): () + if Stat:IsA("IntValue") and Stat.Name == "leaderstats" and Stat.Parent then + local grabbedPlayer = Stat.Parent + + if grabbedPlayer and grabbedPlayer:IsA("Player") and playerlistdata.players[grabbedPlayer] then + local playerData = playerlistdata.players[grabbedPlayer] + playerData.statFocusing = Stat + + local statFocusing = playerData.statFocusing + local statConnections = playerData.statConnections + + for i, v in ipairs(statFocusing:GetChildren()) do + onStatAdded(v) + end + + table.insert(statConnections, statFocusing.ChildAdded:Connect(onStatAdded)) + table.insert(statConnections, statFocusing.ChildRemoved:Connect(function(stat) + onStatRemoved(stat, stat.Name, grabbedPlayer) + end)) + + updatePlayerList() + end + end +end + +local function HandleLeaderstatsRemoval(Stat: Instance, Player: Instance): () + if Stat:IsA("IntValue") and Stat.Name == "leaderstats" then + local grabbedPlayer = Player + + if grabbedPlayer and grabbedPlayer:IsA("Player") and playerlistdata.players[grabbedPlayer] then + local playerData = playerlistdata.players[grabbedPlayer] + local statFocusing = playerData.statFocusing + + if statFocusing == Stat then + playerData.statFocusing = nil + + for i, v in pairs(playerData.statConnections) do + v:Disconnect() + end + playerData.statConnections = {} + + for i, v in pairs(playerData.statsUI) do + playerData.statsUI[i]:Destroy() + playerData.statsUI[i] = nil + end + playerData.statsUI = {} + + for i, v in pairs(Stat:GetChildren()) do + onStatRemoved(v, Stat.Name, grabbedPlayer) + end + end + + updatePlayerList() + end + end +end + +local function neutralizePlayer(Player: Instance): () + if Player:IsA("Player") and playerlistdata.players[Player] then + local playerData = playerlistdata.players[Player] + + if (#Teams:GetTeams() > 0) and canShowTeams then + playerData.playerFrame.LayoutOrder = 0 + playerData.playerFrame.Visible = false + + for i, v in pairs(Teams:GetTeams()) do + refreshTeamStats(v) + end + else + playerData.playerFrame.LayoutOrder = 0 + playerData.playerFrame.NameLabel.TextColor3 = ComputeNameColor(playerData.playerFrame.NameLabel.Text) + playerData.playerFrame.Visible = true + + for i, v in pairs(playerData.statsUI) do + playerData.statsUI[i].TextColor3 = Color3.fromRGB(242, 243, 243) + end + end + end +end + +local function changeTeam(Player: Instance): () + if Player:IsA("Player") then + local getData = playerlistdata.players[Player] + + if getData and Player.Team then + local acceptableTeam = playerlistdata.teams[Player.Team] + + if not acceptableTeam then + neutralizePlayer(Player) + else + local playerFrame = getData.playerFrame + + local isColor3 = color3Teams and Player.Team:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and Player.Team:GetAttribute("Color3") or Player.Team.TeamColor.Color + --local TeamColor = Player.Team.TeamColor.Color + + playerFrame.NameLabel.TextColor3 = TeamColor + + for i, v in pairs(getData.statsUI) do + getData.statsUI[i].TextColor3 = TeamColor + end + + if not playerFrame.Visible then + playerFrame.Visible = true + end + + if playerFrame.LayoutOrder ~= acceptableTeam.teamFrames.mainFrame.LayoutOrder + 1 then + playerFrame.LayoutOrder = acceptableTeam.teamFrames.mainFrame.LayoutOrder + 1 + end + end + end + + for i, v in pairs(Teams:GetTeams()) do + refreshTeamStats(v) + end + end +end + +function onTeamChange(Player: Instance): () + if Player:IsA("Player") and playerlistdata.players[Player] then + if (playerlistdata.teams[Player.Team] and not Player.Neutral) then + changeTeam(Player) + else + neutralizePlayer(Player) + end + end +end + +local function PlayerAdded(Player: Instance): () + if Player:IsA("Player") and not playerlistdata.players[Player] then + playerlistdata.players[Player] = { + playerFrame = nil, + statFocusing = nil, + statConnections = {}, + statLabelConnections = {}, + playerConnections = {}, + statsUI = {}, + statAmount = 0 + } + + local playerInData = playerlistdata.players[Player] + local playerConnections = playerInData.playerConnections + + playerInData.playerFrame = Templates.GuiInstances.Player:Clone() + + local newPlayerFrame = playerInData.playerFrame + newPlayerFrame.Name = Player.UserId + + if not Solo.Value then + if DisplayNames then + newPlayerFrame.NameLabel.Text = string.sub(Player.DisplayName, 1, 16) + else + newPlayerFrame.NameLabel.Text = string.sub(Player.Name, 1, 16) + end + + newPlayerFrame.NameLabel.TextColor3 = ComputeNameColor(newPlayerFrame.NameLabel.Text) + else + newPlayerFrame.NameLabel.Text = "Player" + newPlayerFrame.NameLabel.TextColor3 = Color3.fromRGB(42, 75, 215) + end + + newPlayerFrame.Visible = true + newPlayerFrame.Parent = MainGui.Leaderboard + + if CurrentTimePeriod >= 6 then + neutralizePlayer(Player) + end + + local foundStats = Player:FindFirstChild("leaderstats") + + if foundStats then + HandleLeaderstats(foundStats) + end + + table.insert(playerConnections, Player.ChildAdded:Connect(HandleLeaderstats)) + table.insert(playerConnections, Player.ChildRemoved:Connect(function(child) + HandleLeaderstatsRemoval(child, Player) + end)) + + if CurrentTimePeriod >= 6 then + table.insert(playerConnections, Player:GetPropertyChangedSignal("Neutral"):Connect(function() + onTeamChange(Player) + end)) + + table.insert(playerConnections, Player:GetPropertyChangedSignal("Team"):Connect(function() + onTeamChange(Player) + end)) + + onTeamChange(Player) + end + end +end + +local function PlayerRemoving(Player: Instance): () + if Player:IsA("Player") then + local getData = playerlistdata.players[Player] + + if getData then + for i, v in pairs(getData.statLabelConnections) do + for i2, v2 in pairs(getData.statLabelConnections[i]) do + v2:Disconnect() + end + + getData.statLabelConnections[i] = nil + end + table.clear(getData.statLabelConnections) + + for i, v in pairs(getData.playerConnections) do + v:Disconnect() + end + table.clear(getData.playerConnections) + + getData.statFocusing = nil + + for i, v in pairs(getData.statsUI) do + getData.statsUI[i]:Destroy() + getData.statsUI[i] = nil + end + getData.statsUI = {} + getData.playerFrame:Destroy() + + playerlistdata.players[Player] = nil + end + + updatePlayerList() + end +end + +local function CameraButtonMain(): () + StockSound:PlaySoundLocal("Step") +end + +local function DisplayChatMessage(Chatter: any, Message, gotFiltered: boolean?): () + local ChatterType = typeof(Chatter) + local IsWhitelisted = whitelistedStringsTalk[Chatter] + + local PlayerObject = ((ChatterType == "Instance") and Chatter:IsA("Player")) and Chatter + local PlayerName + + if PlayerObject then + PlayerName = DisplayNames and PlayerObject.DisplayName or PlayerObject.Name + else + PlayerName = tostring(Chatter) + end + + if PlayerObject or IsWhitelisted then + local ChatTemplate = ReplicatedStorage.Templates.GuiInstances.Message:Clone() + + table.insert(chats, ChatTemplate) + + if #chats >= 7 then + local firstChat = chats[1] + + task.cancel(chatTasks[firstChat]) + chatTasks[firstChat] = nil + + firstChat:Destroy() + table.remove(chats, 1) + end + + ChatTemplate.Username.Text = PlayerName.."; " + ChatTemplate.Username.TextColor3 = ComputeNameColor(PlayerName) + + if CurrentTimePeriod >= 6 and PlayerObject and PlayerObject.Team and (not PlayerObject.Neutral) then + local TeamOfPlayer = PlayerObject.Team + + local isColor3 = color3Teams and TeamOfPlayer:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and TeamOfPlayer:GetAttribute("Color3") or TeamOfPlayer.TeamColor.Color + + ChatTemplate.Username.TextColor3 = TeamColor + end + + -- Custom chats, refer to the "whiteListedStringsTalk" table for documentation + if IsWhitelisted then + local hasUserChange = whitelistedStringsTalk[Chatter].Username + local hasTextChange = whitelistedStringsTalk[Chatter].Text + + if hasUserChange then + for changing, value in pairs(hasUserChange) do + ChatTemplate.Username[changing] = value + end + end + + if hasTextChange then + for changing, value in pairs(hasTextChange) do + ChatTemplate.Username.Message[changing] = value + end + end + end + + ChatTemplate.Username.Message.Text = Message + ChatTemplate.Username.Message.TextColor3 = gotFiltered and Color3.fromRGB(255, 0, 0) or ChatTemplate.Username.Message.TextColor3 + + ChatTemplate.Parent = MainGui.ChatWindow + + ChatTemplate.Username.Size = UDim2.new(0,ChatTemplate.Username.TextBounds.X,1,0) + ChatTemplate.Username.Message.Size = UDim2.new(0,ChatTemplate.Username.Message.TextBounds.X + 12,1,0) + ChatTemplate.Size = UDim2.new(0,ChatTemplate.Username.TextBounds.X + ChatTemplate.Username.Message.TextBounds.X + 12,0,16) + + chatTasks[ChatTemplate] = task.delay(64, function() + local isStillInChat = table.find(chats, ChatTemplate) + + if isStillInChat then + ChatTemplate:Destroy() + chatTasks[ChatTemplate] = nil + + table.remove(chats, isStillInChat) + end + end) + end +end + +local function destroyFocusedSuperSafeChats(focusedElement): () + local buttonStyle = focusedElement:FindFirstChild("ButtonStyle") + + if buttonStyle then + buttonStyle.BackgroundColor3 = Color3.fromRGB(255, 255, 255) + end + + focusedElement.BackgroundColor3 = Color3.fromRGB(255, 255, 255) + + for i, v in pairs(focusedElement:GetDescendants()) do + if v.Name == "List" then + v.Visible = false + elseif v.Name == "ButtonStyle" and v.BackgroundColor3 ~= Color3.fromRGB(255, 255, 255) then + v.BackgroundColor3 = Color3.fromRGB(255, 255, 255) + end + end +end + +local function makeSuperSafeChatElementsVisible(optionElement: TextButton): () + local buttonStyle = optionElement:FindFirstChild("ButtonStyle") + + if buttonStyle and buttonStyle:IsA("Frame") then + buttonStyle.BackgroundColor3 = Color3.fromRGB(178, 178, 178) + end + + optionElement.BackgroundColor3 = Color3.fromRGB(178, 178, 178) + + local grabbedList: Instance? = optionElement:FindFirstChild("List") + + if grabbedList and grabbedList:IsA("Frame") then + grabbedList.Visible = true + end +end + +local function superSafeChatBubbleClicked(): () + if not safeChatOpened then + safeChatOpened = true + + MainGui.SuperSafeChatBubble.Image = "rbxassetid://12483705914" + MainGui.SuperSafeChatBubble.List.Visible = true + else + safeChatOpened = false + + MainGui.SuperSafeChatBubble.Image = "rbxassetid://12483706070" + MainGui.SuperSafeChatBubble.List.Visible = false + end +end + +local function createSuperSafeChatButton(indexTable, buttonParent): TextButton + local Option: TextButton = Templates:WaitForChild("GuiInstances"):WaitForChild("SafeChatOption"):Clone() + local buttonStyle = Option:FindFirstChild("ButtonStyle") + + if buttonStyle then + local textLabel = buttonStyle:FindFirstChild("TextLabel") + + if textLabel and textLabel:IsA("TextLabel") then + textLabel.Text = tostring(indexTable["#text"] or indexTable) + end + end + + Option.Parent = buttonParent:WaitForChild("List") + + return Option +end + +local function onSuperSafeChatOptionClicked(button: TextButton): () + StockSound:PlaySoundLocal("Click") + destroyFocusedSuperSafeChats(MainGui.SuperSafeChatBubble) + superSafeChatBubbleClicked() + + local ChatMain = require(LocalPlayer.PlayerScripts:WaitForChild("ChatScript", nil):WaitForChild("ChatMain", nil)) + local ButtonStyle = button:FindFirstChild("ButtonStyle") + + if ButtonStyle then + local TextLabel = ButtonStyle:FindFirstChild("TextLabel") + + if TextLabel and TextLabel:IsA("TextLabel") then + ChatMain.MessagePosted:fire(TextLabel.Text) + end + end +end + +local function HandleInputBegan(input: InputObject, gameProcessedEvent: boolean): () + if input.KeyCode == Enum.KeyCode.Slash and UserInputService:GetFocusedTextBox() == nil then + MainGui.ChatBar.TextBox:CaptureFocus() + + RunService.RenderStepped:Wait() + + MainGui.ChatBar.TextBox.Text = "" + elseif safeChatOpened and input.UserInputType ~= Enum.UserInputType.MouseMovement and not gameProcessedEvent then + superSafeChatBubbleClicked() + destroyFocusedSuperSafeChats(MainGui.SuperSafeChatBubble) + end +end + +local function OnChatBarFocusLost(enterPressed): () + if enterPressed then + if MainGui.ChatBar.TextBox.Text ~= "" then + local ChatMain = require(LocalPlayer.PlayerScripts:WaitForChild("ChatScript", nil):WaitForChild("ChatMain", nil)) + + ChatMain.MessagePosted:fire(MainGui.ChatBar.TextBox.Text) + + MainGui.ChatBar.TextBox:ReleaseFocus() + MainGui.ChatBar.TextBox.Text = "" + end + end +end + +local function OnExit(): () + if clickedExit then + return + end + + clickedExit = true + + local IsStudio = RunService:IsStudio() + local MessageDecided = IsStudio and "Cannot Teleport in the Studio." or "Teleporting to the Menu. Please wait..." + + local ExitMessage = Instance.new("Message") + ExitMessage.Name = "ExitMessage" + ExitMessage.Text = MessageDecided + ExitMessage.Parent = workspace + + if not IsStudio then + TeleportService:Teleport(10789607669, Players.LocalPlayer, nil, nil) + end +end + +local function HelpInit(): () + local FrameDrag = DraggableObject.new(MainGui.HelpWindow.WindowStyle.FrameTop) + FrameDrag:Enable() + + MainGui.HelpWindow.WindowStyle.FrameTop.X.MouseButton1Click:Connect(function() + MainGui.HelpWindow.Visible = false + end) +end + +local function OnHelp(): () + MainGui.HelpWindow.Visible = true +end + +local function AdditionalButtons(): () + for i, v in pairs(twoExtraButtons) do + v.Visible = (CurrentTimePeriod > 7) + + if toolboxShouldBeEnabled() then + v.ButtonText.TextColor3 = Color3.fromRGB(76, 76, 76) + v.HoverImage = "rbxassetid://8090188810" + v.Visible = true + end + end +end + +local function Errored(msg, trace, err) + DisplayChatMessage("[ERROR!]", tostring(msg)) +end + +local function superSafeChatParser(list, rootButton: GuiButton) + local focusedElement: any = nil + for i, v in pairs(list) do + local Option = createSuperSafeChatButton(v, rootButton) + + Option.MouseEnter:Connect(function() + if focusedElement then + destroyFocusedSuperSafeChats(focusedElement) + end + + focusedElement = Option + makeSuperSafeChatElementsVisible(focusedElement) + end) + + Option.MouseButton1Click:Connect(function() + onSuperSafeChatOptionClicked(Option) + focusedElement = nil + end) + + if v["utterance"] ~= nil then + local utteranceTable = v["utterance"] + local utteranceType = typeof(utteranceTable) + + local NewList = Templates:WaitForChild("GuiInstances"):WaitForChild("List"):Clone() + NewList:WaitForChild("UIListLayout").VerticalAlignment = Enum.VerticalAlignment.Center + + NewList.Parent = Option + + if utteranceType == "table" then + superSafeChatParser(utteranceTable, Option) + + NewList:WaitForChild("UIPadding").PaddingBottom = UDim.new(0, 24) + else + local newButton = createSuperSafeChatButton(utteranceTable, Option) + + newButton.MouseButton1Click:Connect(function() + onSuperSafeChatOptionClicked(newButton) + focusedElement = nil + end) + + newButton.MouseEnter:Connect(function() + focusedElement = newButton + makeSuperSafeChatElementsVisible(newButton) + end) + end + end + end +end + +local ToolboxConnections +local function DestroyToolboxConnections() + if not ToolboxConnections then + return + end + + local character = LocalPlayer.Character + if character then + character.Humanoid.CameraOffset = Vector3.zero + end + + for _, connection in ipairs(ToolboxConnections) do + connection:Disconnect() + end + + ToolboxConnections = nil +end + +local toolboxRightPadding = 225; +local function MakeToolboxConnections() + DestroyToolboxConnections() + + local character = LocalPlayer.Character + local function update() + if character then + + end + end + + if character then + update() + end + + ToolboxConnections = { + LocalPlayer.CharacterAdded:Connect(function() + character = LocalPlayer.Character + update() + end), + + Camera:GetPropertyChangedSignal("ViewportSize"):Connect(function() + update() + end) + } + + return ToolboxConnections +end + +local function OnToolbox() + if toolboxShouldBeEnabled() then + MainGui.ToolboxWindow.Visible = not MainGui.ToolboxWindow.Visible + + local isEnabled = MainGui.ToolboxWindow.Visible + MainGui.Topbar.Toolbox.ButtonText.Text = isEnabled and "x Toolbox" or "Toolbox" + MainGui.UIPadding.PaddingRight = UDim.new(0, isEnabled and toolboxRightPadding or 0) + + -- IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE + MainGui.Parent.MainResetGui.UIPadding.PaddingRight = MainGui.UIPadding.PaddingRight; + -- IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE + + -- who the hell made this code + -- KEY U R STUPID 4 THIS + return isEnabled and MakeToolboxConnections() or DestroyToolboxConnections() + end +end + +--Hookup: + +if (not ErrorsInChat) then + whitelistedStringsTalk["[ERROR!]"] = nil +end + +UserInputService.InputBegan:Connect(HandleInputBegan) + +MainGui.ChatBar.TextBox.FocusLost:Connect(OnChatBarFocusLost) +ReplicatedStorage.Protocols.Chat.OnClientEvent:Connect(function(player, message, gotFiltered) + local getType = typeof(player) + local isWhitelistedString = whitelistedStringsTalk[player] + + if player and (getType == "string" and isWhitelistedString) or (getType == "Instance" and player:IsA("Player")) then + DisplayChatMessage(player, message, gotFiltered) + end +end) + +MainGui.Topbar.Exit.MouseButton1Click:Connect(OnExit) +HelpInit() +MainGui.Topbar.Help.MouseButton1Click:Connect(OnHelp) +MainGui.Topbar.Toolbox.MouseButton1Click:Connect(OnToolbox) + +for _, v in pairs(workspace:GetDescendants()) do + ObjectAdded(v) +end + +FullscreenMain() +AdditionalButtons() + +workspace.DescendantAdded:Connect(ObjectAdded) +LocalPlayer.ChildAdded:Connect(ObjectAdded) +GameSettings.FullscreenChanged:Connect(FullscreenMain) + +for _, v in pairs(Players:GetPlayers()) do + PlayerAdded(v) +end + +Players.PlayerAdded:Connect(PlayerAdded) +Players.PlayerRemoving:Connect(PlayerRemoving) + +for _, v in pairs(LocalPlayer:GetChildren()) do + ObjectAdded(v) +end + +for _, v in pairs(MainGui:WaitForChild("CameraControl"):WaitForChild("CameraButtons"):GetChildren()) do + if v:IsA("ImageButton") then + v.MouseButton1Click:Connect(CameraButtonMain) + end +end + +if CurrentTimePeriod >= 6 then + Teams.ChildAdded:Connect(TeamAdded) + Teams.ChildRemoved:Connect(TeamRemoving) +end + +ScriptContext.Error:Connect(Errored) + +if CurrentTimePeriod >= 8 then + superSafeChatParser(FullDecoded, MainGui.SuperSafeChatBubble) + MainGui.SuperSafeChatBubble.Visible = true + MainGui.SuperSafeChatBubble.MouseButton1Click:Connect(superSafeChatBubbleClicked) + MainGui.HelpWindow.Size = UDim2.new(0, 803, 0, 236) + MainGui.HelpWindow.MainContent.Image = "rbxassetid://12761386129" + --MainGui.HelpWindow.Size.Y.Offset = 236 +end + +if CurrentTimePeriod >= 7 then + MainGui.CameraControl.Position = UDim2.new(1, 5, 1, -15) + MainGui.CameraControl.ReportButton.Visible = true +end + +-- disables camera buttons for mobile, since we kept getting complaints about that +if (UserInputService.TouchEnabled and not UserInputService.MouseEnabled) then + MainGui.CameraControl.Visible = false +end + +-- disable chat if privacy settings say so +if Solo.Value == false and Chat:CanUserChatAsync(LocalPlayer.UserId) then + return +else + MainGui.ChatBar.Visible = false + MainGui.ChatWindow.Visible = false + MainGui.SuperSafeChatBubble.Visible = false + MainGui.CameraControl.ReportButton.Visible = false + MainGui.CameraControl.Position = UDim2.new(1, MainGui.CameraControl.Position.X.Offset, 1, 6) +end + +-- make a house diff --git a/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/MainGuiOffset.client.lua b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/MainGuiOffset.client.lua new file mode 100644 index 0000000..d56d519 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/MainGuiOffset.client.lua @@ -0,0 +1,53 @@ +local CurrentCamera = workspace.CurrentCamera; +local ReplicatedStorage = game:GetService("ReplicatedStorage"); + +local CustomCamera = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("CustomCamera")); +local RunService = game:GetService("RunService"); + +local UIPadding = script.Parent:WaitForChild("UIPadding"); + +local ViewportSize; +local function getPositionMatrix() + local offset = -UIPadding.PaddingRight.Offset; + local position = offset/ViewportSize; + + local r = ViewportSize.X/ViewportSize.Y; + local h = math.tan(math.rad(CurrentCamera.FieldOfView)*0.5); + local w = h*r; + + return -position.X*w, -offset; +end + +RunService:BindToRenderStep("cameraOffsetMatrix", Enum.RenderPriority.Camera.Value+1, function() + local vp = CurrentCamera.ViewportSize; + ViewportSize = Vector2.new(vp.X, vp.Y); + + local x, px = getPositionMatrix(); + CustomCamera.viewportOffset = Vector2.new(px*0.5,0); + CustomCamera.viewportScale = Vector2.new(x,0); + + local right = CurrentCamera.CFrame.RightVector; + local skew = CFrame.new( + 0,0,0, + 1,0,0, + 0,1,0, + x,0,1 + ); + + CurrentCamera.CFrame *= skew; + --for _, billboard in CustomCamera.billboards do + -- if(not billboard.Parent)then + -- continue; + -- end + + -- local cframe = billboard.Parent.CFrame; + -- local origin = cframe*-Vector3.yAxis + Vector3.yAxis*1.5; + -- local screen = CustomCamera:WorldToScreenPoint(origin); + + -- local point = CustomCamera:ViewportToWorldPoint(screen.X, screen.Y); + -- point = point.Origin + point.Direction*screen.Z; + + -- billboard.ExtentsOffsetWorldSpace = point - screen; + --end + +end) \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/Util.lua b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/Util.lua new file mode 100644 index 0000000..ef26daf --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/Util.lua @@ -0,0 +1,89 @@ +--!strict +-- epic util module so scrollbar isnt too lengthy LOLOOLLOLLOLOL + +local Players = game:GetService("Players") + +local LocalPlayer = Players.LocalPlayer +local Mouse = LocalPlayer:GetMouse() + +local Util = {} + +-- attach scrollbar to the scrollingframe +function Util.AttachScrollbarToFrame(bar : ImageLabel, frame : GuiObject, align : Enum.VerticalScrollBarPosition) + if frame.Parent and frame.Parent:IsA("GuiObject") then + local where = frame.AbsolutePosition + (if align == Enum.VerticalScrollBarPosition.Right then + (frame.AbsoluteSize * Vector2.xAxis) + else Vector2.zero + ) + + local XScale = (- frame.AbsolutePosition.X + where.X) / frame.Parent.AbsoluteSize.X + local YScale = (- frame.AbsolutePosition.Y + where.Y) / frame.Parent.AbsoluteSize.Y + bar.Position = UDim2.fromScale(XScale,YScale) + + -- size now + bar.Size = UDim2.new(0, 16, frame.Size.Y.Scale, frame.Size.Y.Offset) + end +end + +-- positions the scrollbar button inside the scrollbar frame from canvas +function Util.AdjustScrollBar(bar : ImageLabel, scrollingFrame : ScrollingFrame, Horizontal : boolean?) + local Scroller = bar:WaitForChild("Scroller") + local Scrollbar = Scroller:WaitForChild("ScrollBar") + + local X = (scrollingFrame.CanvasPosition.X/scrollingFrame.AbsoluteCanvasSize.X) + local Y = (scrollingFrame.CanvasPosition.Y/scrollingFrame.AbsoluteCanvasSize.Y) + + if Scrollbar:IsA("GuiObject") then + Scrollbar.Position = Horizontal==true and UDim2.fromScale(X, 0.5) or UDim2.fromScale(0.5, Y) + end +end + +-- adjust the scrollbar size from scrollingframe canvas +function Util.FixScrollbarSize(bar : ImageLabel, scrollingFrame : ScrollingFrame, Horizontal : boolean?) + local Scroller = bar:WaitForChild("Scroller") + local Scrollbar = Scroller:WaitForChild("ScrollBar") + local Axis = Horizontal == true and "X" or "Y" + + local size = scrollingFrame.AbsoluteWindowSize/scrollingFrame.AbsoluteCanvasSize + + if Scrollbar:IsA("GuiObject") then + Scrollbar.Size = Horizontal==true and UDim2.fromScale(size.X, 1) or UDim2.fromScale(1, size.Y) + end + + Util.AdjustScrollBar(bar, scrollingFrame, Horizontal) + + if Axis == "X" then + bar.Visible = (scrollingFrame.AbsoluteCanvasSize.X > scrollingFrame.AbsoluteSize.X) + else + bar.Visible = (scrollingFrame.AbsoluteCanvasSize.Y > scrollingFrame.AbsoluteSize.Y) + end +end + +function Util.IsMouseInFrame(frame : GuiObject) + local mx, my = Mouse.X, Mouse.Y + + local AbsPosition = frame.AbsolutePosition + local AbsSize = frame.AbsoluteSize + + return( + mx > AbsPosition.X + and my > AbsPosition.Y + and mx < AbsPosition.X + AbsSize.X + and my < AbsPosition.Y + AbsSize.Y + ) +end + +function Util.MousePosition(NoX : boolean, NoY : boolean) : Vector2 + if (NoX == true) and (NoY == true) then + warn("look man u need to like allow atleast 1 axis") + + return Vector2.zero + end + + return Vector2.new( + (NoX ~= true and Mouse.X or 0), + (NoY ~= true and Mouse.Y or 0) + ) +end + +return Util diff --git a/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.lua b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.lua new file mode 100644 index 0000000..d65b08f --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.lua @@ -0,0 +1,249 @@ +--!nonstrict +--[[ + games unite + @author nobonet + @submodule Scrollbar + + epic docs: + function Module.new(ScrollingFrame ScrollingFrame, Enum.VerticalScrollBarPosition VScrollPosition) + | create new scroller for this scrolingframe + Default Value: none this is important step DONT forget the scrollingframe + | VScrollPosition is the equal to a ScrollingFrame's VerticalScrollBarPosition + Default Value: Enum.VerticalScrollBarPosition.Right + + function Module:Destroy() + | byebye + + function Module:init() + | u dont need to execute this + + function Module:Scroll(number offset, number scale) + | scroll the frame by specified offset and/or scale + Default Value: 0, 0 +]] + +local Players = game:GetService("Players") +local UserInputService = game:GetService("UserInputService") + +local LocalPlayer = Players.LocalPlayer +local Mouse = LocalPlayer:GetMouse() + +local ScrollItemsTemplate = script:WaitForChild("ScrollingItems") + +local ScrollDist = 30 +local ButtonScrollDist = 55 + +local Util = require(script:WaitForChild("Util")) + +------------------------------------------------------------------------------------- +-- MODULE !!!!!!!!! + +local Scrollbar = {} +Scrollbar.__index = Scrollbar +Scrollbar.Initiated = false + +---------------------------- +-- the scorllbar things + +-- constructor +function Scrollbar.new(ScrollingFrame : ScrollingFrame, VScrollPosition : Enum.VerticalScrollBarPosition?) + assert(typeof(ScrollingFrame) == "Instance" and ScrollingFrame:IsA("ScrollingFrame"), + "pls put an actual ScrollingFrame" + ) + + local new = setmetatable({ + ["ScrollingFrame"] = ScrollingFrame; + ["VScrollPosition"] = VScrollPosition or Enum.VerticalScrollBarPosition.Right; + ["ScrollItems"] = ScrollItemsTemplate:Clone(); + ["Dragging"] = false; + ["Connections"] = {}; + }, Scrollbar) + + return new:init() +end + +-- initializer +function Scrollbar:init() + if self.Initiated == true then + return + end + + local ScrollingFrame : ScrollingFrame = self.ScrollingFrame + local ScrollingItems = self.ScrollItems + + local function AddScrollBar(Bar : ImageLabel, horizontal : boolean) + local Scroller = Bar:WaitForChild("Scroller") + local Scrollbar = Scroller:WaitForChild("ScrollBar") + local Scroll1Button = Bar:WaitForChild(horizontal and "ScrollLeft" or "ScrollUp") + local Scroll2Button = Bar:WaitForChild(horizontal and "ScrollRight" or "ScrollDown") + + --Util.AttachScrollbarToFrame(Bar, ScrollingFrame, self.VScrollPosition) + Util.FixScrollbarSize(Bar, ScrollingFrame, horizontal) + + if horizontal~=true then + if self.VScrollPosition == Enum.VerticalScrollBarPosition.Right then + Bar.AnchorPoint = Vector2.xAxis + else + Bar.AnchorPoint = Vector2.zero + end + end + + -- listen to size/position change + do + table.insert(self.Connections, ScrollingFrame:GetPropertyChangedSignal("AbsoluteCanvasSize"):Connect(function(): () + Util.FixScrollbarSize(Bar, ScrollingFrame, horizontal) + end)) + + -- sisze of scrll frame + table.insert(self.Connections, ScrollingFrame:GetPropertyChangedSignal("AbsoluteSize"):Connect(function(): () + --Util.AttachScrollbarToFrame(Bar, ScrollingFrame, self.VScrollPosition) + Util.FixScrollbarSize(Bar, ScrollingFrame, horizontal) + end)) + + -- position of scroll frame + table.insert(self.Connections, ScrollingFrame:GetPropertyChangedSignal("CanvasPosition"):Connect(function(): () + Util.AdjustScrollBar(Bar, ScrollingFrame, horizontal) + end)) + end + + ---- interaction + do + -- buttons + table.insert(self.Connections, Scroll1Button.Activated:Connect(function(inputObject: InputObject, clickCount: number): () + self:Scroll(-ButtonScrollDist, nil, horizontal) + end)) + table.insert(self.Connections, Scroll2Button.Activated:Connect(function(inputObject: InputObject, clickCount: number): () + self:Scroll(ButtonScrollDist, nil, horizontal) + end)) + -- scrollwheel + table.insert(self.Connections, UserInputService.InputChanged:Connect(function(input: InputObject, gameProcessedEvent: boolean): () + local Interacting = (Util.IsMouseInFrame(ScrollingFrame) or Util.IsMouseInFrame(Bar)) + if input.UserInputType == Enum.UserInputType.MouseWheel then + if Interacting == true then + local direction = input.Position.Z * ScrollDist + self:Scroll(-direction, 0, false) + end + end + end)) + -- mouse + table.insert(self.Connections, Scrollbar.MouseButton1Down:Connect(function(x: number, y: number): () + self:StartDrag(horizontal) + end)) + end + end + + -- listen to ancestry changed for whether it got destroyed or just a simple parent change + table.insert(self.Connections, ScrollingFrame.AncestryChanged:Connect(function(child: Instance, parent: Instance): () + if ScrollingFrame.Parent == nil then + self:Destroy() + return + end + + ScrollingItems.Parent = ScrollingFrame.Parent + --Util.AttachScrollbarToFrame(Bar, ScrollingFrame, self.VScrollPosition) + end)) + + table.insert(self.Connections, UserInputService.InputEnded:Connect(function(input: InputObject, gameProcessedEvent: boolean): () + if input.UserInputType == Enum.UserInputType.MouseButton1 then + self:EndDrag() + end + end)) + + ---- dumb object value (created by jesus christ) + local DumbObjectValue: ObjectValue = Instance.new("ObjectValue", ScrollingItems) + DumbObjectValue.Name = "TargetFrame" + DumbObjectValue.Value = self.ScrollingFrame + + ---- modify the scrollframe + ScrollingFrame.ScrollingEnabled = false + ScrollingFrame.ScrollBarThickness = 0 + ScrollingFrame.ScrollBarImageTransparency = 1 + + AddScrollBar(ScrollingItems.Bar, false) + AddScrollBar(ScrollingItems.HBar, true) + + self.Initiated = true + return self +end + +-- destructor +function Scrollbar:Destroy() + -- disconnect + for _, v : RBXScriptConnection in self.Connections do + v:Disconnect() + end + + -- delete + pcall(self.ScrollItems.Destroy, self.ScrollItems) + + -- byebye + table.clear(self) + setmetatable(self,nil) +end + +---------------------------- +-- scrollbar functions + +function Scrollbar:Scroll(offset : number, scale : number, horizontal : boolean?): () + local ScrollingFrame : ScrollingFrame = self.ScrollingFrame + + -- adjust + local ScaleDist: number = (ScrollingFrame.AbsoluteCanvasSize.Y * (tonumber(scale) or 0)) + ScaleDist = ScaleDist + (tonumber(offset) or 0) + local Adding: Vector2 = horizontal==true and Vector2.new(ScaleDist, 0) or Vector2.new(0, ScaleDist) + ScrollingFrame.CanvasPosition += Adding + + -- fix scrollbars + local ScrollingItems = self.ScrollItems + local Bar : ImageLabel = ScrollingItems:WaitForChild("Bar") + local HBar : ImageLabel = ScrollingItems.HBar + + if horizontal then + -- horizontal + Util.AdjustScrollBar(HBar, ScrollingFrame, true) + Util.FixScrollbarSize(HBar, ScrollingFrame, true) + else + -- vertical + Util.AdjustScrollBar(Bar, ScrollingFrame, false) + Util.FixScrollbarSize(Bar, ScrollingFrame, false) + end +end + +function Scrollbar:StartDrag(Horizontal : boolean?): () + local ScrollingFrame : ScrollingFrame = self.ScrollingFrame + local Axis = Horizontal == true and "X" or "Y" + + if self.Dragging == false then + self.Dragging = true + local LastMousePos = Util.MousePosition(false, false) + + while self.Dragging do + -- update framerate :3 + local deltaTime = task.wait(1 / 30) + + local ThisMousePos = Util.MousePosition(false, false) + + if Axis == "X" then + local scale = (ScrollingFrame.AbsoluteCanvasSize.X / ScrollingFrame.AbsoluteSize.X) + local delta = ThisMousePos.X - LastMousePos.X + + self:Scroll(delta * scale, 0, Horizontal) + LastMousePos = ThisMousePos + else + local scale = (ScrollingFrame.AbsoluteCanvasSize.Y / ScrollingFrame.AbsoluteSize.Y) + local delta = ThisMousePos.Y - LastMousePos.Y + + self:Scroll(delta * scale, 0, Horizontal) + LastMousePos = ThisMousePos + end + end + end +end + +function Scrollbar:EndDrag(): () + if self.Dragging then + self.Dragging = false + end +end + +return Scrollbar \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.meta.json b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/init.client.lua b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/init.client.lua new file mode 100644 index 0000000..b3ba562 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/init.client.lua @@ -0,0 +1,40 @@ +--[[ + Toolbox client code +]] +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local ScrollbarXP = require(script:WaitForChild("ScrollbarXP")) + +local insertProtocol = ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("InsertContent") + +local Scrollbar = ScrollbarXP.new(script.Parent) + +local toolboxMain = script.Parent +local toolboxControls = toolboxMain:WaitForChild("ToolboxControls", nil) +local toolboxItems = toolboxMain:WaitForChild("ToolboxItems", nil) + +local function insertContent(assetId: number): () + print(assetId) + local model: number = insertProtocol:InvokeServer(assetId) +end + +for _: number, v: Instance in ipairs(toolboxItems:GetChildren()) do + if v:IsA("ImageButton") then + v.MouseButton1Click:Connect(function(): () + print("test") + local assetIdValue: Instance? = v:FindFirstChild("AssetID", false) + + if assetIdValue and assetIdValue:IsA("IntValue") then + insertContent(assetIdValue.Value) + end + end) + + v.MouseEnter:Connect(function() + v.Border.Visible = true + end) + + v.MouseLeave:Connect(function() + v.Border.Visible = false + end) + end +end \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/init.meta.json b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/init.meta.json new file mode 100644 index 0000000..95ad713 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/ToolboxWindow/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ScrollingFrame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/init.meta.json b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/init.meta.json new file mode 100644 index 0000000..118e2ca --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainGui/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ScreenGui", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainResetGui/MainResetGuiHandler.client.lua b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainResetGui/MainResetGuiHandler.client.lua new file mode 100644 index 0000000..741b6e8 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainResetGui/MainResetGuiHandler.client.lua @@ -0,0 +1,616 @@ +--[[ + FWM Official, 2022 + + Main Gui that will reset upon respawn - Roblox_Gamer2030 +]] +local Chat = game:GetService("Chat") +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local RunService = game:GetService("RunService") +local GuiService = game:GetService("GuiService") +local UserInputService = game:GetService("UserInputService") +local TextureGroups = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("TextureGroups", nil)) +local StockSound = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("StockSound")) +local MouseIcon = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("MouseIcon")) +local Protocols = ReplicatedStorage:WaitForChild("Protocols") + +local MainGui = script.Parent +local Templates = ReplicatedStorage:WaitForChild("Templates") +--local Holder = MainGui:WaitForChild("Holder") +local GameSettings = UserSettings().GameSettings +local LocalPlayer = Players.LocalPlayer +local LocalPlayerGui: PlayerGui = LocalPlayer.PlayerGui +local Mouse = LocalPlayer:GetMouse() +local Solo = ReplicatedStorage:WaitForChild("Solo") +local CurrentTimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value +local canGreenDisc: boolean = false +local isMobile = (UserInputService.TouchEnabled and (not UserInputService.MouseEnabled)) +--local Settings = LocalPlayer:WaitForChild("PlayerDataFolder"):WaitForChild("UserDataFolder"):WaitForChild("SettingsFolder") + +local Character: Model? = LocalPlayer.Character +local Humanoid + +local globalGameProcessed: boolean = false + +local MouseConnectedDisc = Templates.Textures.Adornees.GreenDisc:Clone() +Mouse.TargetFilter = MouseConnectedDisc +MouseConnectedDisc.Adornee = workspace.Terrain +MouseConnectedDisc.Parent = workspace.CurrentCamera + +--local ToolCount = 0 +local Tools = {} + +local GamepadSelection = 1 +local currentDiscMoveTo = nil + +local KeyCodes = { + + [Enum.KeyCode.One] = 1, + [Enum.KeyCode.Two] = 2, + [Enum.KeyCode.Three] = 3, + [Enum.KeyCode.Four] = 4, + [Enum.KeyCode.Five] = 5, + [Enum.KeyCode.Six] = 6, + [Enum.KeyCode.Seven] = 7, + [Enum.KeyCode.Eight] = 8, + [Enum.KeyCode.Nine] = 9, + [Enum.KeyCode.Zero] = 10 + +} + +local YellowHover = Color3.new(1, 1, 0) +local GreenHover = Color3.new(0.14902, 1, 0) +local BlueHover = Color3.new(0, 0, 1) +local White = Color3.new(1, 1, 1) +local DefaultColor = Color3.new(0.701961, 0.701961, 0.701961) + +local function findTexture(baseTexture: string, state: string): string + for i, v in ipairs(TextureGroups) do + if string.lower(v.base) == string.lower(baseTexture) then + return v[state] + end + end + + return baseTexture +end + +local function Healthbar(): () + MainGui:WaitForChild("RedHealthbarFill"):WaitForChild("GreenHealthbarFill").Size = UDim2.new(1, 0, LocalPlayer.Character.Humanoid.Health/LocalPlayer.Character.Humanoid.MaxHealth, 0) +end + +local function DisableOtherBorders(): () + for _, v in pairs(script.Parent.Backpack:GetChildren()) do + if v.ClassName == "TextButton" and tonumber(v.Name) then + v.Border.Visible = false + end + end +end + +local function MakeBorderVisible(frame): () + --if Settings.TimePeriod.Value ~= "2006M" then + frame.Border.Visible = (CurrentTimePeriod > 3) + frame.Border.ClipsDescendants = true + frame.Border.ClipsDescendants = false + --end +end + +local function ToolEquipEvent(tool, frame) + if tool.Parent == LocalPlayer.Character then + LocalPlayer.Character.Humanoid:UnequipTools() + DisableOtherBorders() + else + LocalPlayer.Character.Humanoid:EquipTool(tool) + + if tool:GetAttribute("Command") and tool:GetAttribute("Command") ~= "ScriptHopper" then + StockSound:PlaySoundLocal("Ping") + end + + DisableOtherBorders() + MakeBorderVisible(frame) + end +end + +local function RegisterTool(toolobject) + if not table.find(Tools, toolobject) then + table.insert(Tools, toolobject) + --ToolCount = ToolCount + 1 + + local newCell = Templates.GuiInstances.Backpack:Clone() + newCell.Parent = script.Parent.Backpack + newCell.Name = #Tools + newCell.LayoutOrder = newCell.Name + newCell.Tool.Value = toolobject + + if toolobject.TextureId ~= "" then + newCell.ToolName.Text = toolobject.Name + newCell.ToolImage.Image = toolobject.TextureId + newCell.ToolImage.Visible = true + else + newCell.ToolName.Text = toolobject.Name + newCell.ToolImage.Image = toolobject.TextureId + newCell.ToolName.Visible = true + end + + newCell.ToolNumber.Text = newCell.Name + + local conns = {} + + conns = { + newCell:GetPropertyChangedSignal("Name"):Connect(function(): () + newCell.ToolNumber.Text = newCell.Name + end), + + toolobject:GetPropertyChangedSignal("TextureId"):Connect(function(): () + if toolobject.TextureId ~= "" then + newCell.ToolName.Text = toolobject.Name + newCell.ToolImage.Image = toolobject.TextureId + newCell.ToolImage.Visible = true + newCell.ToolName.Visible = false + else + newCell.ToolName.Text = toolobject.Name + newCell.ToolImage.Image = toolobject.TextureId + newCell.ToolName.Visible = true + newCell.ToolImage.Visible = false + end + end), + + toolobject:GetPropertyChangedSignal("Name"):Connect(function(): () + newCell.ToolName.Text = toolobject.Name + end), + + newCell.InputBegan:Connect(function(input: InputObject): () + if input.UserInputType == Enum.UserInputType.MouseMovement then + if toolobject.TextureId ~= "" then + newCell.HoverThing.BackgroundColor3 = YellowHover + newCell.HoverThing.Visible = true + newCell.ToolImage.Image = findTexture(toolobject.TextureId, "over") + else + newCell.FillIn.BackgroundColor3 = DefaultColor + newCell.FillIn.Visible = true + end + end + end), + + newCell.MouseButton1Down:Connect(function(x: number, y: number): () + if toolobject.TextureId ~= "" then + newCell.HoverThing.BackgroundColor3 = BlueHover + newCell.ToolImage.Image = findTexture(toolobject.TextureId, "down") + else + newCell.FillIn.BackgroundColor3 = YellowHover + end + end), + + newCell.InputEnded:Connect(function(input: InputObject): () + if input.UserInputType == Enum.UserInputType.MouseMovement then + if toolobject.TextureId ~= "" then + newCell.HoverThing.BackgroundColor3 = DefaultColor + newCell.HoverThing.Visible = false + newCell.ToolImage.Image = findTexture(toolobject.TextureId, "base") + else + newCell.FillIn.BackgroundColor3 = DefaultColor + newCell.FillIn.Visible = false + end + end + end), + + newCell.MouseButton1Click:Connect(function(): () + if toolobject.TextureId ~= "" then + newCell.HoverThing.BackgroundColor3 = YellowHover + newCell.ToolImage.Image = findTexture(toolobject.TextureId, "over") + ToolEquipEvent(newCell.Tool.Value, newCell) + else + newCell.FillIn.BackgroundColor3 = DefaultColor + ToolEquipEvent(newCell.Tool.Value, newCell) + end + end), + + newCell.AncestryChanged:Connect(function() + if not newCell.Parent then + for _, connections in pairs(conns) do + connections:Disconnect() + end + end + end), + } + + newCell.Visible = true + + if toolobject.Parent == LocalPlayer.Character then + DisableOtherBorders() + MakeBorderVisible(newCell) + end + end +end + +local function ResortInventory() + for _, v in pairs(script.Parent.Backpack:GetChildren()) do + if v:IsA("TextButton") and tonumber(v.Name) then + local GetTool = v:FindFirstChild("Tool") + + if GetTool then + local FindInTable = table.find(Tools, GetTool.Value) + + if FindInTable then + v.Name = FindInTable + v.LayoutOrder = v.Name + end + end + end + end +end + +local function UnregisterTool(toolobject) + local FindTool = table.find(Tools, toolobject) + + if FindTool then + local FindInBackpack = script.Parent.Backpack:FindFirstChild(FindTool) + + if FindInBackpack then + local GrabbedTool = FindInBackpack:FindFirstChild("Tool") + + if GrabbedTool then + local IsTool = Tools[FindTool] + + if GrabbedTool.Value == IsTool then -- :rice_scene:'s the tool, then resorts backpack + FindInBackpack:Destroy() + table.remove(Tools, FindTool) + + ResortInventory() + end + end + end + end +end + +local function ToolChildAdded(child) + if child:IsA("Tool") then + local Find = table.find(Tools, child) + + if not Find then + RegisterTool(child) + end + end +end + +local function ToolChildRemoved(child) + if child:IsA("Tool") then + if child.Parent ~= LocalPlayer.Character and child.Parent ~= LocalPlayer.Backpack then + UnregisterTool(child) + end + end +end + +local function FrameEquipEvent(num) + local Find = script.Parent.Backpack:FindFirstChild(tostring(num)) + + if Find then + ToolEquipEvent(Find.Tool.Value, Find) + end +end + +local function UserInputEquipItem(key, process) + if not process then + local GetKey = KeyCodes[key.KeyCode] + + if GetKey then + FrameEquipEvent(GetKey) + end + + if key.KeyCode == Enum.KeyCode.Backspace then + DisableOtherBorders() + end + end +end + +local function updateMouseIcon(): () + local HasTool = Character and Character:FindFirstChildOfClass("Tool") or false + local GrabbedGuis = LocalPlayerGui:GetGuiObjectsAtPosition(Mouse.X, Mouse.Y) + + if not MouseConnectedDisc.Visible then + if GrabbedGuis and not HasTool then + MouseIcon.Icon("rbxasset://textures\\ArrowFarCursor.png") + + for _, Objects in pairs(GrabbedGuis) do + if Objects:IsA("GuiButton") then + MouseIcon.Icon("rbxasset://textures\\ArrowCursor.png") + + break + end + end + end + else + MouseIcon.Icon("rbxasset://textures\\ArrowCursor.png") + end +end + +local Icons = { + default = { + Image = "rbxassetid://13610996027"; + ImageColor3 = Color3.new(1, 1, 1); + Size = UDim2.new(0, 17, 0, 25); + Priority = 0; + }; + + button = { + Image = "rbxassetid://13610995901"; + ImageColor3 = Color3.new(1, 1, 1); + Size = UDim2.new(0, 22, 0, 26); + Priority = 1; + }; + + beam = { + Image = "rbxassetid://13611975254"; + ImageColor3 = Color3.new(0, 0, 0); + Size = UDim2.new(0, 7, 0, 16); + Priority = 2; + } +}; + +local mouseStates = { + -- KEY IF SOMEONE MAKES A GUI W/ THESE NAMES + -- THEY WILL DEF GO T F??? + + ["ChatBar"] = Icons.beam; + ["ToolboxItem"] = Icons.button; + ["ToolboxWindow"] = Icons.default; +}; + +local currentMouseFlag; +local function CursorUpdate(input, gameProcessed) + globalGameProcessed = gameProcessed + MainGui.Cursor.Position = UDim2.new(0, Mouse.X, 0, Mouse.Y + 36) + MainGui.WinXPCursor.Position = UDim2.new(0, Mouse.X, 0, Mouse.Y + 36) + + local GetGuiObjects = LocalPlayer.PlayerGui:GetGuiObjectsAtPosition(Mouse.X, Mouse.Y) + + if GetGuiObjects then + local flag; + for _, v in GetGuiObjects do + local state = mouseStates[v.Name]; + if(not state)then + continue; + elseif(state and not flag)then + flag = state; + elseif(state.Priority>flag.Priority)then + flag = state; + end + end + + if(flag and flag~=currentMouseFlag)then + currentMouseFlag = flag; + MainGui.Cursor.Visible = false; + MainGui.WinXPCursor.Visible = true; + + local xpCursor = MainGui.WinXPCursor; + for name, value in flag do + if(name == "Priority")then + continue; + end + + xpCursor[name] = value; + end + elseif(not flag and currentMouseFlag)then + currentMouseFlag = nil; + MainGui.Cursor.Visible = true; + MainGui.WinXPCursor.Visible = false; + end + end + + -- thingy to not have this run twice + if (not canGreenDisc) and CurrentTimePeriod >= 6 then + updateMouseIcon() + end + + --if CurrentTimePeriod >= 6 then + -- local GetTool = Character:FindFirstChildOfClass("Tool") + -- local GrabbedGuis = LocalPlayerGui:GetGuiObjectsAtPosition(Mouse.X, Mouse.Y) + + -- if GrabbedGuis and not GetTool then + -- if not MouseConnectedDisc.Visible then + -- MouseIcon.Icon("rbxasset://textures\\ArrowFarCursor.png") + + -- for _, Objects in pairs(GrabbedGuis) do + -- if Objects:IsA("GuiButton") then + -- MouseIcon.Icon("rbxasset://textures\\ArrowCursor.png") + + -- break + -- end + -- end + -- else + -- MouseIcon.Icon("rbxasset://textures\\ArrowCursor.png") + -- end + -- end + --end +end + +--Hookup: + +---- Debug stuff + +function roundNumber(num, numPlaces) + return math.floor(num*(10^numPlaces))/(10^numPlaces) +end + +--function DebugUpdate() +-- if Character:FindFirstChild("Torso") then +-- --MainGui.Debug.DebugText.Text = "-- FWM Debug --\nSTATE: "..Character.Humanoid:GetState().Name.."\nMAG: "..roundNumber(Character.Torso.AssemblyLinearVelocity.Magnitude, 1).."\nTIME: "..roundNumber(workspace.DistributedGameTime, 1).."\nOBJ: "..#workspace:GetDescendants().."\nVER: "..game.PlaceVersion +-- end +--end + +local function DebugToggle(input, gameProcessed) + if not gameProcessed then + if input.KeyCode == Enum.KeyCode.F2 then + MainGui.Debug.Visible = not MainGui.Debug.Visible + end + end +end + +local function checkIfValid(checkIfdisc: boolean): boolean + local currentCamera = workspace.CurrentCamera + local cameraCFrame = currentCamera.CFrame + + if Character then + local hasTool = (not Character:FindFirstChildOfClass("Tool")) + local hasTorso = Character:FindFirstChild("Torso") + local notFullyTransparent = false + local isNotWalking = Humanoid and (Humanoid.MoveDirection == Vector3.zero) + local isAlive = Humanoid and (Humanoid.Health > 0) + local discVisible = true + + if checkIfdisc then + discVisible = MouseConnectedDisc.Visible + end + + if hasTorso then + local transparencyModifier = hasTorso.LocalTransparencyModifier + + notFullyTransparent = (transparencyModifier < 1) + end + + return (hasTool and notFullyTransparent and isNotWalking and discVisible and isAlive) + else + return false + end +end + +local function onMoveToFinished(): () + if Character then + local moveValueInChar = Character:FindFirstChild("isDiscWalking") + if not moveValueInChar then + return + end + + if not currentDiscMoveTo then + return + end + + moveValueInChar.Value = false + Protocols.DiscWalking:FireServer(false) + + currentDiscMoveTo:Destroy() + currentDiscMoveTo = nil + end +end + +local function greenDiskMain(dt: number): () + local mouseHit = Mouse.Hit.Position + local distanceFromChar = LocalPlayer:DistanceFromCharacter(mouseHit) + local canDo = checkIfValid(false) + + if canDo and distanceFromChar < 40 and not globalGameProcessed then + MouseConnectedDisc.Visible = true + MouseConnectedDisc.CFrame = CFrame.new(mouseHit) * CFrame.Angles(math.pi / 2, 0, 0) + else + MouseConnectedDisc.Visible = false + end + + updateMouseIcon() +end + +local function clickToMoveMainInput(input, gameProcessed): () + globalGameProcessed = gameProcessed + + if (input.UserInputType == Enum.UserInputType.MouseButton1 or input.KeyCode == Enum.KeyCode.ButtonR2) and not globalGameProcessed and Character then + local moveValueInChar = Character:FindFirstChild("isDiscWalking") + + local mouseTarget = Mouse.Target + local isValid = checkIfValid(true) + + if not moveValueInChar then + return + end + + if mouseTarget and isValid then + onMoveToFinished() + + local mouseHit = Mouse.Hit.Position + Humanoid:MoveTo(mouseHit) + + moveValueInChar.Value = true + Protocols.DiscWalking:FireServer(true) + + currentDiscMoveTo = Templates.Textures.Adornees.GreenDisc:Clone() + Mouse.TargetFilter = currentDiscMoveTo + + currentDiscMoveTo.Name = "GreenDisc_Copy" + currentDiscMoveTo.Adornee = workspace.Terrain + currentDiscMoveTo.Visible = true + currentDiscMoveTo.CFrame = CFrame.new(mouseHit) * CFrame.Angles(math.pi / 2, 0, 0) + currentDiscMoveTo.Parent = workspace.CurrentCamera + end + end +end + +--RunService.RenderStepped:Connect(DebugUpdate) +UserInputService.InputBegan:Connect(UserInputEquipItem) + +UserInputService.InputBegan:Connect(function(input, gameProcessed) + if not gameProcessed then + if input.KeyCode == Enum.KeyCode.ButtonL1 then + GamepadSelection -= 1 + GamepadSelection = math.clamp(GamepadSelection, 1, #Tools) + + FrameEquipEvent(GamepadSelection) + elseif input.KeyCode == Enum.KeyCode.ButtonR1 then + GamepadSelection += 1 + GamepadSelection = math.clamp(GamepadSelection, 1, #Tools) + + FrameEquipEvent(GamepadSelection) + end + end +end) + +MainGui.RedHealthbarFill.Visible = not Solo.Value + +CursorUpdate() +UserInputService.InputChanged:Connect(CursorUpdate) + +if Solo.Value or (not Chat:CanUserChatAsync(LocalPlayer.UserId)) then + script.Parent.Backpack.Position = UDim2.new(0, 0, 1, 0) +end + +-- A mobile fix since the mouse icon doesn't update properly on a single tap +if isMobile then + UserInputService.InputBegan:Connect(CursorUpdate) +end + +if not Character then + Character = LocalPlayer.CharacterAdded:Wait() +end + +LocalPlayer:WaitForChild("Backpack").ChildAdded:Connect(ToolChildAdded) +LocalPlayer:WaitForChild("Backpack").ChildRemoved:Connect(ToolChildRemoved) + +for _, v in ipairs(LocalPlayer:WaitForChild("Backpack"):GetChildren()) do + if v:IsA("Tool") then + ToolChildAdded(v) + end +end + +if Character then + Character.ChildAdded:Connect(ToolChildAdded) + Character.ChildRemoved:Connect(ToolChildRemoved) + + for _, v in ipairs(Character:GetChildren()) do + if v:IsA("Tool") then + ToolChildAdded(v) + end + end + + if not Humanoid then + Humanoid = Character:WaitForChild("Humanoid") + end + + if CurrentTimePeriod >= 9 and (not isMobile) and Humanoid then + canGreenDisc = true + + RunService.Heartbeat:Connect(greenDiskMain) + UserInputService.InputBegan:Connect(clickToMoveMainInput) + + Humanoid.MoveToFinished:Connect(onMoveToFinished) + Humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(onMoveToFinished) + Humanoid.Died:Connect(onMoveToFinished) + end + + Humanoid.HealthChanged:Connect(Healthbar) +end \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainResetGui/init.meta.json b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainResetGui/init.meta.json new file mode 100644 index 0000000..118e2ca --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/StarterGui/MainResetGui/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ScreenGui", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/StarterGui/init.meta.json b/rojo/MainModule/src/ServerStorage/UI/StarterGui/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/StarterGui/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/UI/init.meta.json b/rojo/MainModule/src/ServerStorage/UI/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/UI/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/ServerStorage/init.meta.json b/rojo/MainModule/src/ServerStorage/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/ServerStorage/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/StarterCharacterScripts/CharacterMainReRewrite.client.lua b/rojo/MainModule/src/StarterCharacterScripts/CharacterMainReRewrite.client.lua new file mode 100644 index 0000000..52c20c8 --- /dev/null +++ b/rojo/MainModule/src/StarterCharacterScripts/CharacterMainReRewrite.client.lua @@ -0,0 +1,629 @@ +local Debris: Debris = game:GetService("Debris") +local GuiService: GuiService = game:GetService("GuiService") +local Players = game:GetService("Players") +local RunService: RunService = game:GetService("RunService") +local TweenService: TweenService = game:GetService("TweenService") +local UserInputService: UserInputService = game:GetService("UserInputService") +local ReplicatedStorage: ReplicatedStorage = game:GetService("ReplicatedStorage") + +---- Objects +local self = Players.LocalPlayer +local Figure = self.Character or self.CharacterAdded:Wait() +local hum = Figure:WaitForChild("Humanoid") +local torso = Figure:WaitForChild("Torso") +local head = Figure:WaitForChild("Head") +local protocols = ReplicatedStorage:WaitForChild("Protocols") +--local animate = Figure:WaitForChild("Animate", 1) + +local paramsIgnore = RaycastParams.new() +paramsIgnore.RespectCanCollide = true + +local ignore = {Figure} + +---- Script variables +local lastJump = 0 +local bounceCooldown = 0 +local currentState = "Running" +local Jumped = false +local Grounded = false + +---- silly things +local wait = task.wait +local spawn = task.spawn +local delay = task.delay + +hum:SetStateEnabled(Enum.HumanoidStateType.Climbing, false) +---- Other +local connections = {} +local climblift : BodyVelocity +local velocityLock : BodyVelocity +local ForceRotation : BodyGyro +local climbcon : RBXScriptConnection? +local movedircon : RBXScriptConnection? +local discwalkingcon : RBXScriptConnection? +local isDiscWalking : BoolValue +local isClimbing : BoolValue + +-- do not look here +local DumbTables = { + NOPESTATES = { + PlatformStanding = true; + FallingDown = true; + Seated = true; + Dead = true; + }; + + cantclimb = { + FallingDown = true; + GettingUp = true; + Seated = true; + Dead = true; + }; + + thenotjump = { + Freefall = true; + Jumping = true; + }; +}; + +local inf = TweenInfo.new(0.27, Enum.EasingStyle.Quad, Enum.EasingDirection.Out) +local infSlow = TweenInfo.new(0.587, Enum.EasingStyle.Quad, Enum.EasingDirection.Out) +local hheight0 = TweenService:Create(hum,infSlow, {HipHeight = 0}) +local hheight0Slow = TweenService:Create(hum, infSlow, {HipHeight = 0}) + +local XZ = Vector3.new(1, 0, 1) + +---- Localized globals (whatever this is for but i think it helps X X DDDD DDD) +local CFAng, CFNew = CFrame.Angles, CFrame.new +local abs, pi = math.abs, math.pi +local tableinsert = table.insert +local Vector3new = Vector3.new +local workspace = workspace +local tick = tick + +---- Some functions +local function SafeUnit(unit: Vector3, CustomReturn: Vector3) : Vector3 + if (unit.Magnitude > 0) then + return unit.Unit; + end + return CustomReturn or Vector3.zero; +end + +local function Lerp(a: number, b: number, t: number): number + return a + (b - a) * t +end + +local function create(class: string, parent: Instance?, props: {[string] : any}) + local success : boolean, instance = pcall(function() + return Instance.new(class) + end) + + if success == true then + if typeof(props) == "table" then + for prop, val in pairs(props) do + pcall(function() + instance[prop] = val + end) + end + end + + if typeof(parent) == "Instance" then + instance.Parent = parent + end + + return instance + else + warn(instance) -- x d + end + + return nil +end + +-- D: +climblift = create("BodyVelocity", nil, {Name = "ClimbLift", Velocity = Vector3.zero, MaxForce = Vector3new(25000, 25000, 25000), P = 100000}) +velocityLock = create("BodyVelocity", nil, {Name = "MovementLock", MaxForce = Vector3new(4e4, 0, 4e4), Velocity = Vector3.zero}) +ForceRotation = create("BodyGyro", nil, {Name = "MovementGyro", MaxTorque = Vector3new(0, 6e6, 0), Parent = torso, D = 200}) + +local function SetJump(enabled : boolean) + if enabled == true then + velocityLock.Parent = torso + velocityLock.Velocity = torso.AssemblyLinearVelocity + else + velocityLock.Parent = nil + end +end + +local function LandTilt() + local anguVel : AngularVelocity = torso:FindFirstChild("TorsoAttach"):FindFirstChild("AngularTilt") + + if anguVel then + local vector = CFNew(head.Position, head.Position + head.AssemblyLinearVelocity * Vector3new(1, 0, 1)).LookVector + local test = head.CFrame:vectorToObjectSpace(vector).Unit + vector = SafeUnit(test*XZ, -Vector3.zAxis) + + anguVel.Enabled = true + anguVel.MaxTorque = 6e6 + anguVel.AngularVelocity = vector * (head.AssemblyLinearVelocity.Magnitude / 14) + for i = 1, 3 do RunService.RenderStepped:Wait() end + repeat wait(0.04) + anguVel.MaxTorque = Lerp(anguVel.MaxTorque, 0, 0.4) + anguVel.AngularVelocity = anguVel.AngularVelocity:Lerp(Vector3.zero, 0.6) + until anguVel.MaxTorque <= 100 or (currentState == "FallingDown") + anguVel.MaxTorque = 0 + anguVel.AngularVelocity = Vector3.zero + anguVel.Enabled = false + end +end + +local lastBounce = 0 +local function Bounce() + bounceCooldown = tick() + local VerticalSpd = torso.AssemblyLinearVelocity.Y + local HorizontalVelocity = torso.AssemblyLinearVelocity * Vector3new(1, 0, 1) + local TargetVelocity = Vector3.zero + + if (VerticalSpd < 0) == false then return end + + if abs(VerticalSpd) >= 70 then + task.spawn(LandTilt) + repeat RunService.RenderStepped:Wait() until Grounded + TargetVelocity = HorizontalVelocity + Vector3new(0, abs(VerticalSpd) / 1.25, 0) + elseif abs(VerticalSpd) >= 44.38 and abs(VerticalSpd) < 70 then + local addToBounce = 0 + if os.clock() - lastBounce <= 1.3 then + hum.HipHeight = -1.3 + wait() + hheight0:Play() + addToBounce = -1 + else + task.spawn(LandTilt) + end + + repeat RunService.RenderStepped:Wait() until Grounded + TargetVelocity = HorizontalVelocity + Vector3new(0, abs(VerticalSpd) / 1.25, 0) + lastBounce = os.clock() + addToBounce + end + task.wait() + hum:ChangeState(Enum.HumanoidStateType.Freefall) + SetJump(false); Jumped = false + + if TargetVelocity ~= Vector3.zero then + torso.AssemblyLinearVelocity = TargetVelocity + end +end + +local function Raycast(origin : Vector3, direction : Vector3, params : RaycastParams) + local RayResults = workspace:Raycast(origin, direction, params) + + if RayResults then + local hit : BasePart? = RayResults.Instance + local pos : Vector3 = RayResults.Position + local normal : Vector3 = RayResults.Normal + + if hit and hit.CanCollide == false then + tableinsert(ignore, hit) + paramsIgnore.FilterDescendantsInstances = ignore + return Raycast(origin, direction, params) -- game is kill + end + + return hit, pos, normal + end + + return nil +end + +local function legfloat() + local leg = (Figure:FindFirstChild("Right Leg") or Figure:FindFirstChild("Left Leg")) or nil + hum.HipHeight = (leg ~= nil and 0 or 2) + + if leg then + hheight0 = TweenService:Create(hum,infSlow, {HipHeight = 0}) + hheight0Slow = TweenService:Create(hum, infSlow, {HipHeight = 0}) + else + hheight0 = TweenService:Create(hum, inf, {HipHeight = 2}) + hheight0Slow = TweenService:Create(hum, infSlow, {HipHeight = 2}) + end +end + +local function TiltAngle(angle) + return (torso.CFrame * CFAng(pi / 2, 0, 0)).LookVector.Y < angle +end + +local function onTouchVelocity(hit : BasePart, touching : BasePart) + local vel = hit.AssemblyLinearVelocity + + if vel.Magnitude >= 0.5 then + touching.AssemblyAngularVelocity = touching.CFrame:VectorToObjectSpace(vel) + end +end + +local function ForceUpwards(speed) + if tonumber(speed) and torso then + for _, v : Instance in pairs(Figure:GetChildren()) do + if v:IsA("BasePart") then + v.AssemblyLinearVelocity = (v.AssemblyLinearVelocity * XZ) + speed + end + end + + local bv = Instance.new("BodyVelocity") + bv.Name = "forcedSpeedUpwards" + bv.Parent = torso + bv.MaxForce = Vector3.yAxis*math.huge + bv.Velocity = speed + + Debris:AddItem(bv, 0.0176715) + end +end + +local function ConnectTouchEvent(part : BasePart, functionToConnect) + if part == nil then return nil end + + local con = part.Touched:Connect(function(hit) + functionToConnect(hit, part) + end) + + tableinsert(connections, con) + return con +end + +local alreadyKilled = false +local function Kill() + if alreadyKilled == true then + return + end + alreadyKilled = true + + -- Clear connections + for i in pairs(connections) do + connections[i]:Disconnect() + connections[i] = nil + end + + if climbcon then climbcon:Disconnect() climbcon = nil end + + -- Sets "climblift" to nil if it is in the player still + climblift.Parent = nil + + -- Disconnect physics update + RunService:UnbindFromRenderStep("StankyPhysics") +end + +local function CheckReflectPoint(where : Part, offset : Vector3?) + local HorizontalVelocity = (where.AssemblyLinearVelocity * Vector3new(1, 0, 1)) + local velocityDot = where.CFrame.LookVector:Dot(HorizontalVelocity.Unit) + local rayLength = 2 - (where.CFrame.LookVector:Dot(HorizontalVelocity.Unit) / 1.3) + local hit, pos, nor = Raycast(where.Position, (HorizontalVelocity.Unit * rayLength) + (offset or Vector3.zero), paramsIgnore) + local reflectedNormal = nil + + if hit then + reflectedNormal = HorizontalVelocity.Unit - (2 * HorizontalVelocity.Unit:Dot(nor) * nor) + end + + return reflectedNormal +end + +-------- Main code +paramsIgnore.FilterDescendantsInstances = ignore + +local gyro = Instance.new("BodyGyro") +gyro.Name = "GyroSlowedDownStanding" +gyro.CFrame = CFrame.new(torso.CFrame.LookVector) +gyro.D = 335 +gyro.P = 2555 +gyro.MaxTorque = Vector3.new(4e4, 0, 4e4) +gyro.Parent = Figure.Head + +--- Create connections +ConnectTouchEvent(torso, onTouchVelocity) +ConnectTouchEvent(head, onTouchVelocity) +ConnectTouchEvent(Figure:FindFirstChild("Right Arm"), onTouchVelocity) +ConnectTouchEvent(Figure:FindFirstChild("Left Arm"), onTouchVelocity) + + +tableinsert(connections, hum.StateChanged:Connect(function(old, new) + old, new = old.Name, new.Name + currentState = new + + if Figure:FindFirstChild("Left Arm") then + Figure["Left Arm"].CanCollide = true + end + + if Figure:FindFirstChild("Right Arm") then + Figure["Right Arm"].CanCollide = true + end + + if new == "Dead" then + Kill() + return + end + + if new == "Landed" then + if tick() - bounceCooldown >= 1 then + spawn(Bounce) + end + return + elseif new == "GettingUp" then + ForceUpwards(Vector3new(0, math.random(30, 50), 0)) + end + + if new == "Jumping" then + lastJump = tick() + Jumped = true + SetJump(true) + return + elseif not DumbTables.thenotjump[new] and Jumped == true then + Jumped = false + SetJump(false) + return + end +end)) + +tableinsert(connections, Figure.ChildAdded:Connect(legfloat)) +tableinsert(connections, Figure.ChildRemoved:Connect(legfloat)) + +tableinsert(connections, UserInputService.InputBegan:Connect(function(i, p) + if p or GuiService.MenuIsOpen or UserInputService:GetFocusedTextBox() then return end + local key = i.KeyCode + + if key == Enum.KeyCode.Space then + if currentState == "Freefall" and Jumped == false and hum:GetStateEnabled(Enum.HumanoidStateType.Jumping) == true then + Jumped = true + SetJump(true) + + --if animate then + -- animate.ForcePose:Fire("Jumping") + --end + end + end +end)) + +--- Loops (and some dumb funcs) + +local function VisualizeRaycast(raypos) + task.spawn(function() + local p = create("Part", nil, {Anchored = true, CanCollide = false, CanTouch = false, CanQuery = false, Position = raypos, BrickColor = BrickColor.Green(), Shape = Enum.PartType.Ball, TopSurface = Enum.SurfaceType.Smooth, BottomSurface = Enum.SurfaceType.Smooth, Size = Vector3new(0.5, 0.5, 0.5), Parent = workspace}) + + task.wait(5) + + p:Destroy() + end) +end + +local function ReflectFromTouch(where) + for i = -0.5, 0.5, 0.1 do + local HorizontalVelocity = velocityLock.Velocity * Vector3new(1,0,1) + local reflectedNormal = CheckReflectPoint(where, (HorizontalVelocity.Unit * 5) + (Vector3.yAxis * i)) + + if reflectedNormal then + velocityLock.Velocity = reflectedNormal * HorizontalVelocity.Magnitude + break + end + end +end +local function ConnectReflectFromTouch(bodypart : BasePart) + if bodypart ~= nil then + bodypart.Touched:Connect(function() + if currentState == "Freefall" and Jumped == true then + ReflectFromTouch(bodypart) + end + end) + end +end + +ConnectReflectFromTouch(Figure:FindFirstChild("Right Arm")) +ConnectReflectFromTouch(Figure:FindFirstChild("Left Arm")) + +ConnectReflectFromTouch(Figure:FindFirstChild("Torso")) +ConnectReflectFromTouch(Figure:FindFirstChild("Head")) + +local ForceRotationLook = CFrame.lookAt(torso.Position, torso.Position + torso.CFrame.LookVector) +local dontforcerotationlook = false + +local function updatePhys(dt : number) + local TorsoP = torso.Position + local HorizontalVelocity = (torso.AssemblyLinearVelocity * XZ) + local VerticalSpeed = torso.AssemblyLinearVelocity.Y + local hasTool = Figure:FindFirstChildOfClass("Tool") + local GroundPart, GroundPosition, GroundNormal = Raycast(torso.Position, Vector3.yAxis*-3.05, paramsIgnore) + local DiscWalking = (isDiscWalking and isDiscWalking.Value) + Grounded = (GroundPart ~= nil) + + if tick() - lastJump >= 1 then + hum:SetStateEnabled(Enum.HumanoidStateType.Jumping, true) + else + hum:SetStateEnabled(Enum.HumanoidStateType.Jumping, false) + end + + if (currentState == "Jumping" or currentState == "Freefall") and Jumped == true then + hum.AutoRotate = false + else + hum.AutoRotate = true + end + + -- Trip when tilted to some angle + if TiltAngle(0.6) and (currentState == "Freefall" or currentState == "Running") then + --if hum:GetState().Name ~= "FallingDown" then + hum:ChangeState(Enum.HumanoidStateType.FallingDown) + --end + end + + -- Physics velocity reflect when jump + if Jumped and currentState ~= "FallingDown" then + local reflectedNormal = CheckReflectPoint(torso) + + if reflectedNormal then + velocityLock.Velocity = reflectedNormal * HorizontalVelocity.Magnitude + end + end + + -- other physics thing + if DumbTables.NOPESTATES[currentState] then + if gyro.MaxTorque ~= Vector3.zero then + gyro.MaxTorque = Vector3.zero + for _, v in pairs(torso:GetConnectedParts()) do + v.AssemblyAngularVelocity = Vector3.zero + end + end + else + gyro.MaxTorque = XZ*4e4 + end + + -- :) + if (currentState == "Running" or currentState == "Freefall") and (not DiscWalking) then + if currentState == "Running" or (currentState == "Freefall" and Jumped == false) then + dontforcerotationlook = false + ForceRotationLook = CFrame.lookAt(torso.Position, torso.Position + (hum.MoveDirection.Magnitude > 0 and hum.MoveDirection or torso.CFrame.LookVector)) + elseif currentState == "Freefall" and Jumped == true then + if dontforcerotationlook == false then + dontforcerotationlook = true + ForceRotationLook = CFrame.lookAt(torso.Position, torso.Position + torso.CFrame.LookVector) + else + torso.AssemblyAngularVelocity = Vector3.zero + end + end + ForceRotation.CFrame = ForceRotationLook + ForceRotation.MaxTorque = Vector3.yAxis*5e5 + else + ForceRotation.MaxTorque = Vector3.zero + end + + --for _, part in region do + -- if (part.CanCollide) then + + -- end + --end + + --if currentState == "Climbing" then + + -- if Figure:FindFirstChild("Left Arm") then + -- Figure["Left Arm"].CanCollide = false + -- end + + -- if Figure:FindFirstChild("Right Arm") then + -- Figure["Right Arm"].CanCollide = false + -- end + + -- local yes = (hum.MoveDirection * hum.WalkSpeed) + -- torso.AssemblyLinearVelocity = Vector3new(yes.X, torso.AssemblyLinearVelocity.Y, yes.Z) + + --end +end + +-- something nobonet couldn't do #roasted +-- ok may b this was kinda heavily inspired by retroblox climb code (dw we were allowed to use by ayray) +local function handleClimbing(dt) + local direction = hum.MoveDirection + local raycount = 0 + local outside = false + + if (not torso) then + if climbcon then + climbcon:Disconnect() + climbcon = nil + end + + climblift.Parent = nil + + return + end + + local angul = torso:FindFirstChild("TorsoAttach"):FindFirstChild("AngularTilt") + + for i = 1, 12 do + local lookVec = torso.CFrame.LookVector + local origin = Vector3.new(torso.Position.X, torso.Position.Y - 0.8, torso.Position.Z) + + local cast, pos = Raycast(origin + Vector3.new(0, -2.25 + (i * 0.255), 0), lookVec, paramsIgnore) + + if cast then + if not outside then + outside = true + raycount += 1 + end + elseif outside then + outside = false + raycount += 1 + end + end + + if raycount > 1 and (not angul.Enabled) and (not DumbTables.cantclimb[currentState]) and (not Jumped) then + local velocityBy = (isDiscWalking and isDiscWalking.Value) + and Vector3.new(torso.AssemblyLinearVelocity.X, hum.WalkSpeed * 0.7, torso.AssemblyLinearVelocity.Z) + or Vector3.new(direction.X * hum.WalkSpeed, hum.WalkSpeed * 0.7, direction.Z * hum.WalkSpeed) + + if not climblift.Parent then + climblift.Parent = torso + + if isClimbing then + isClimbing.Value = true + protocols.Climbing:FireServer(true) + end + end + + climblift.Velocity = velocityBy + elseif climblift.Parent then + climblift.Parent = nil + + if isClimbing then + isClimbing.Value = false + protocols.Climbing:FireServer(false) + end + end +end + +local function moveDirectionChanged() + if ((isDiscWalking and isDiscWalking.Value) or hum.MoveDirection ~= Vector3.zero) and torso then + if climbcon then + return + end + + climbcon = RunService.RenderStepped:Connect(handleClimbing) + else + if climbcon then + climbcon:Disconnect() + climbcon = nil + end + + if climblift.Parent and isClimbing then + isClimbing.Value = false + protocols.Climbing:FireServer(false) + end + + climblift.Parent = nil + end +end + +-- I am aware of the other ChildAdded call for the Figure, but I don't give a fart +local function childAddedToChar(child) + local isDiscWalk = child:GetAttribute("FWMDiscWalk") + local isClimb = child:GetAttribute("FWMClimb") + + if child:IsA("BoolValue") then + if isDiscWalk then + isDiscWalking = child + tableinsert(connections, isDiscWalking:GetPropertyChangedSignal("Value"):Connect(moveDirectionChanged)) + elseif isClimb then + isClimbing = child + end + + if (isDiscWalking and isClimbing) and discwalkingcon then + discwalkingcon:Disconnect() + discwalkingcon = nil + end + end +end + +RunService:BindToRenderStep("StankyPhysics", Enum.RenderPriority.Character.Value + 1, updatePhys) +tableinsert(connections, hum:GetPropertyChangedSignal("MoveDirection"):Connect(moveDirectionChanged)) + +discwalkingcon = Figure.ChildAdded:Connect(childAddedToChar) +tableinsert(connections, discwalkingcon) + +--Hat system prototype: +game:GetService("UserInputService").InputBegan:connect(function(inputObject, gameProcessedEvent) + if not gameProcessedEvent then + if inputObject.KeyCode == Enum.KeyCode.Equals then + protocols:WaitForChild("Drop"):FireServer() + end + end +end) \ No newline at end of file diff --git a/rojo/MainModule/src/StarterCharacterScripts/RobloxTeam.server.lua b/rojo/MainModule/src/StarterCharacterScripts/RobloxTeam.server.lua new file mode 100644 index 0000000..b6f3195 --- /dev/null +++ b/rojo/MainModule/src/StarterCharacterScripts/RobloxTeam.server.lua @@ -0,0 +1,55 @@ +local Player = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local TimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value +local CurrentPlayer = Player:GetPlayerFromCharacter(script.Parent) + +local bodyPartColors = { + ["Head"] = BrickColor.new(24), + ["Left Arm"] = BrickColor.new(26), + ["Right Arm"] = BrickColor.new(26), + ["Left Leg"] = BrickColor.new(26), + ["Right Leg"] = BrickColor.new(26) +} + +if TimePeriod < 8 then + task.defer(function() + script:Destroy() + end) +end + +local function onTeamChanged() + if not CurrentPlayer then + return + end + + task.wait(1) + + local character = script.Parent + + if CurrentPlayer.Neutral then + local oldBodyColors = character:FindFirstChild("Body Colors") + + if oldBodyColors then + oldBodyColors:Clone().Parent = character + oldBodyColors:Destroy() + end + else + for i, v in pairs(character:GetChildren()) do + if v:IsA("Part") and bodyPartColors[v.Name] then + v.BrickColor = bodyPartColors[v.Name] + end + end + + local hasTorso = character:FindFirstChild("Torso") + + if hasTorso then + hasTorso.BrickColor = CurrentPlayer.Team.TeamColor + end + end +end + +CurrentPlayer:GetPropertyChangedSignal("Neutral"):Connect(onTeamChanged) +CurrentPlayer:GetPropertyChangedSignal("TeamColor"):Connect(onTeamChanged) + +onTeamChanged() \ No newline at end of file diff --git a/rojo/MainModule/src/StarterCharacterScripts/init.meta.json b/rojo/MainModule/src/StarterCharacterScripts/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/StarterCharacterScripts/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/StarterGui/ControllerFlagHandler.client.lua b/rojo/MainModule/src/StarterGui/ControllerFlagHandler.client.lua new file mode 100644 index 0000000..6c7d2b7 --- /dev/null +++ b/rojo/MainModule/src/StarterGui/ControllerFlagHandler.client.lua @@ -0,0 +1,196 @@ +--[[ + FWM Official, 2022 + + Handles Controller Flags +]] + +--Init: +local UserInputService = game:GetService("UserInputService") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local CollectionService = game:GetService("CollectionService") + +local ControllerFlags = script.Parent:WaitForChild("MainGui"):WaitForChild("ControllerFlags") + +local BlueController = false +local RedController = false + +local Steer = 0 +local Throttle = 0 + +local Steer2 = 0 +local Throttle2 = 0 + +local ControllerFlagVehicleSeats = CollectionService:GetTagged("ControllerSeat") + +local ControllerKeys = { + [Enum.KeyCode.U] = { + Throttle = 1, + }, + + [Enum.KeyCode.H] = { + Steer = -1, + }, + + [Enum.KeyCode.J] = { + Throttle = -1, + }, + + [Enum.KeyCode.K] = { + Steer = 1, + }, + + [Enum.KeyCode.W] = { + Throttle2 = 1, + }, + + [Enum.KeyCode.A] = { + Steer2 = -1, + }, + + [Enum.KeyCode.S] = { + Throttle2 = -1, + }, + + [Enum.KeyCode.D] = { + Steer2 = 1, + }, +} + +local function ControllerInit() + if ReplicatedStorage:WaitForChild("Solo").Value == false then + for _, v in pairs(ControllerFlags:GetDescendants()) do + if v:IsA("ImageLabel") and v.Name ~= "Flag" then + v.ImageTransparency = 0.6 + v.BackgroundTransparency = 0 + end + end + end +end + +local function IsKeyDown(keycode) + return UserInputService:IsKeyDown(keycode) +end + +local function FindControllers() + for _, obj in pairs(workspace:GetDescendants()) do + if obj:IsA("Model") then + if obj:GetAttribute("Controller") == "KeyboardRight" then + BlueController = true + elseif obj:GetAttribute("Controller") == "KeyboardLeft" then + RedController = true + end + end + end + + ControllerFlags.KeyboardRight.Visible = BlueController + ControllerFlags.KeyboardLeft.Visible = RedController +end + +-- sucks but whatever - Vibin +local function Drive(keycode) + if ReplicatedStorage:WaitForChild("Solo").Value == true and (BlueController or RedController) == true then + if ControllerKeys[keycode]["Steer"] then + if not IsKeyDown(keycode) then + Steer = 0 + else + Steer = ControllerKeys[keycode]["Steer"] + end + end + + if ControllerKeys[keycode]["Steer2"] then + if not IsKeyDown(keycode) then + Steer2 = 0 + else + Steer2 = ControllerKeys[keycode]["Steer2"] + end + end + + if ControllerKeys[keycode]["Throttle"] then + if not IsKeyDown(keycode) then + Throttle = 0 + else + Throttle = ControllerKeys[keycode]["Throttle"] + end + end + + if ControllerKeys[keycode]["Throttle2"] then + if not IsKeyDown(keycode) then + Throttle2 = 0 + else + Throttle2 = ControllerKeys[keycode]["Throttle2"] + end + end + + for _, v in pairs(ControllerFlagVehicleSeats) do + if v.Parent then + if v.Parent:GetAttribute("Controller") == "KeyboardRight" then + v.Steer = Steer + v.Throttle = Throttle + elseif v.Parent:GetAttribute("Controller") == "KeyboardLeft" then + v.Steer = Steer2 + v.Throttle = Throttle2 + end + end + end + end +end + +local function ControllerMainDown(input) + if ReplicatedStorage:WaitForChild("Solo").Value == true and (BlueController or RedController) == true then + if input.UserInputType == Enum.UserInputType.Keyboard then + local CurrentlyHolding = ControllerKeys[input.KeyCode] + + if CurrentlyHolding ~= nil then + local ControllerKey = input.KeyCode + local KeyName = ControllerKey.Name + + --KeyboardLeft: + if ControllerFlags.KeyboardLeft:FindFirstChild(KeyName) then + local CurrentKey = ControllerFlags.KeyboardLeft:FindFirstChild(KeyName) + CurrentKey.Image = CurrentKey:GetAttribute("KeyDown") + end + + --KeyboardRight: + if ControllerFlags.KeyboardRight:FindFirstChild(KeyName) then + local CurrentKey = ControllerFlags.KeyboardRight:FindFirstChild(KeyName) + CurrentKey.Image = CurrentKey:GetAttribute("KeyDown") + end + + Drive(ControllerKey) + end + end + end +end + +local function ControllerMainUp(input) + if ReplicatedStorage:WaitForChild("Solo").Value == true and (BlueController or RedController) == true then + if input.UserInputType == Enum.UserInputType.Keyboard and ControllerKeys[input.KeyCode] then + local CurrentlyHolding = ControllerKeys[input.KeyCode] + + if CurrentlyHolding ~= nil then + local ControllerKey = input.KeyCode + local KeyName = ControllerKey.Name + + --KeyboardLeft: + if ControllerFlags.KeyboardLeft:FindFirstChild(KeyName) then + local CurrentKey = ControllerFlags.KeyboardLeft:FindFirstChild(KeyName) + CurrentKey.Image = CurrentKey:GetAttribute("KeyUp") + end + + --KeyboardRight: + if ControllerFlags.KeyboardRight:FindFirstChild(KeyName) then + local CurrentKey = ControllerFlags.KeyboardRight:FindFirstChild(KeyName) + CurrentKey.Image = CurrentKey:GetAttribute("KeyUp") + end + + Drive(ControllerKey) + end + end + end +end + +FindControllers() + +ControllerInit() +UserInputService.InputBegan:Connect(ControllerMainDown) +UserInputService.InputEnded:Connect(ControllerMainUp) \ No newline at end of file diff --git a/rojo/MainModule/src/StarterGui/MainGui/MainGuiHandler.client.lua b/rojo/MainModule/src/StarterGui/MainGui/MainGuiHandler.client.lua new file mode 100644 index 0000000..ad2b2a4 --- /dev/null +++ b/rojo/MainModule/src/StarterGui/MainGui/MainGuiHandler.client.lua @@ -0,0 +1,1344 @@ +--!strict +--[[ + FWM Official, 2022 + + The main gui handler for FWM, does not reset +]] + +local Chat: Chat = game:GetService("Chat") +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local RunService: RunService = game:GetService("RunService") +local ScriptContext: ScriptContext = game:GetService("ScriptContext") +local StarterGui = game:GetService("StarterGui") +local TeleportService: TeleportService = game:GetService("TeleportService") +local TextChatService: TextChatService = game:GetService("TextChatService") +local UserInputService: UserInputService = game:GetService("UserInputService") +local Teams: Teams = game:GetService("Teams") +local HttpService: HttpService = game:GetService("HttpService") + +local DraggableObject = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("DraggableObject")) +local StockSound = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("StockSound")) +local SuperSafeChat = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("SuperSafeChat")) + +local DecodedSuperSafeChat = HttpService:JSONDecode(SuperSafeChat) +local FullDecoded = DecodedSuperSafeChat["roblox"]["utterance"] +local MainGui = script.Parent +local Templates = ReplicatedStorage:WaitForChild("Templates") +local GameSettings = UserSettings().GameSettings +local LocalPlayer = Players.LocalPlayer +local Mouse = LocalPlayer:GetMouse() +local Camera = workspace.CurrentCamera +local Solo = ReplicatedStorage:WaitForChild("Solo") + +local ErrorsInChat = ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("GetSetting"):InvokeServer("ErrorsInChat") +local DisplayNames = ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("GetSetting"):InvokeServer("DisplayNames") + +local CurrentTimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value +local HintFolder = ReplicatedStorage:WaitForChild("HintFolder") + +local chats = {} +local chatTasks = {} + +local registeredVisualInstances = {} + +local playerlistdata: any = { + players = {}, + teams = {}, +} + +local teamCount = 0 + +local canShowTeams = false +local safeChatOpened = false +local clickedExit = false +local color3Teams = CurrentTimePeriod < 8 + +local lb_big = UDim2.new(0.33, 0, 0.018, 0) +local lb_small = UDim2.new(0.162, 0, 0.018, 0) + +local NAME_COLORS: {Color3} = { + --BrickColor.new("Crimson"), --r + --BrickColor.new("Deep blue"), --g + --BrickColor.new("Earth green"), --b + --BrickColor.new("Bright violet"), + --BrickColor.new("Bright orange"), + --BrickColor.new("Bright yellow"), + --BrickColor.new("Light reddish violet"), + --BrickColor.new("Brick yellow"), + Color3.fromRGB(173, 35, 35), + Color3.fromRGB(42, 75, 215), + Color3.fromRGB(29, 105, 20), + Color3.fromRGB(129, 38, 192), + Color3.fromRGB(255, 146, 51), + Color3.fromRGB(255, 238, 51), + Color3.fromRGB(255, 205, 243), + Color3.fromRGB(233, 222, 187), +} + +local twoExtraButtons = { + MainGui.Topbar["Edit Mode"], + MainGui.Topbar.Toolbox +} + +local whitelistedStringsTalk: any = { + ["[ERROR!]"] = { + Username = { + TextColor3 = Color3.fromRGB(255, 0, 0), + TextStrokeTransparency = 0, + }, + + Text = { + TextColor3 = Color3.fromRGB(255, 0, 0), + } + }, +} + +local function toolboxShouldBeEnabled(): boolean + return Solo.Value or RunService:IsStudio(); +end + +local function GetNameValue(pName: string): number + local value = 0 + for index = 1, #pName do + local cValue = string.byte(string.sub(pName, index, index)) + local reverseIndex = #pName - index + 1 + if #pName%2 == 1 then + reverseIndex = reverseIndex - 1 + end + if reverseIndex%4 >= 2 then + cValue = -cValue + end + value = value + cValue + end + return value +end + +local color_offset = 0 + +local function ComputeNameColor(pName: string): Color3 + return NAME_COLORS[((GetNameValue(pName) + color_offset) % #NAME_COLORS) + 1] +end + +StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, false) +StarterGui:SetCore("ChatActive", false) +UserInputService.MouseIconEnabled = false + +--Functions: +local function ObjectAdded(obj): () + if (obj:IsA("Message") or obj:IsA("Hint")) and not registeredVisualInstances[obj] then + registeredVisualInstances[obj] = true + + local connections = {} + local parentChanging = false + local objectClass = obj.ClassName -- :IsA doesn't work but this does?? + + local grabbedInstanceGui = Templates.GuiInstances["FWM_"..tostring(objectClass).."_Instance"]:Clone() + grabbedInstanceGui.Name = "LEGACY_INSTANCE" + grabbedInstanceGui.Text = obj.Text + grabbedInstanceGui.Parent = MainGui + + if objectClass == "Message" then + grabbedInstanceGui.Visible = #obj.Text > 0 + obj.Text = "" + + if obj.Parent == LocalPlayer and CurrentTimePeriod >= 7 then + grabbedInstanceGui.Position = UDim2.new(0, 30, 0, 30) + grabbedInstanceGui.Size = UDim2.new(0.3, 0, 0.25, 0) + end + elseif objectClass == "Hint" then + task.defer(function() + obj.Parent = HintFolder + end) + + if not MainGui.ChatBar.Visible then + grabbedInstanceGui.AnchorPoint = Vector2.new(1, 0) + else + grabbedInstanceGui.AnchorPoint = Vector2.new(1, 1) + end + end + + table.insert(connections, obj:GetPropertyChangedSignal("Text"):Connect(function() + if objectClass == "Message" then + if obj.Text ~= "" then + grabbedInstanceGui.Text = obj.Text + grabbedInstanceGui.Visible = true + obj.Text = "" + end + elseif objectClass == "Hint" then + grabbedInstanceGui.Text = obj.Text + end + end)) + + table.insert(connections, MainGui.ChatBar:GetPropertyChangedSignal("Visible"):Connect(function() + if objectClass == "Hint" then + if not MainGui.ChatBar.Visible then + grabbedInstanceGui.AnchorPoint = Vector2.new(1, 0) + else + grabbedInstanceGui.AnchorPoint = Vector2.new(1, 1) + end + end + end)) + + table.insert(connections, obj.AncestryChanged:Connect(function(child, parent) + local canDestroy = false + + if objectClass == "Message" then + if obj:IsDescendantOf(workspace) then + grabbedInstanceGui.Position = UDim2.new(0, 0, 0, 0) + grabbedInstanceGui.Size = UDim2.new(1, 0, 1, 0) + elseif obj.Parent == LocalPlayer then + if CurrentTimePeriod >= 7 then + grabbedInstanceGui.Position = UDim2.new(0, 30, 0, 30) + grabbedInstanceGui.Size = UDim2.new(0.3, 0, 0.25, 0) + end + else + canDestroy = true + end + elseif objectClass == "Hint" then + if obj:IsDescendantOf(workspace) then + if parentChanging then + return + end + + parentChanging = true + + task.defer(function() + obj.Parent = HintFolder + end) + + parentChanging = false + elseif obj.Parent ~= HintFolder then + canDestroy = true + end + end + + if canDestroy then + for i, v in pairs(connections) do + v:Disconnect() + end + + grabbedInstanceGui:Destroy() + registeredVisualInstances[obj] = nil + end + end)) + end +end + +local function FullscreenMain(): () + local Topbar = MainGui:WaitForChild("Topbar") + if GameSettings:InFullScreen() then + Topbar.Fullscreen.ButtonText.Text = "x Fullscreen" + else + Topbar.Fullscreen.ButtonText.Text = "Fullscreen" + end +end + +local function getTeamCount(Team: Instance, StatName: string): number + if Team:IsA("Team") then + local Count = 0 + + for i, v in pairs(Team:GetPlayers()) do + local hasData = playerlistdata.players[v] + + if hasData then + local statFocusing = hasData.statFocusing + + if statFocusing then + local findValue = statFocusing:FindFirstChild(StatName) + + if findValue then + Count += findValue.Value + end + end + end + end + + return Count + end + + return 0 +end + +local function refreshTeamStats(Team: Instance): () + if Team:IsA("Team") then + local teamData = playerlistdata.teams[Team] + local localData = playerlistdata.players[LocalPlayer] + + if teamData and localData then + local isUI = localData.statsUI + + local statLabelConnections = localData.statLabelConnections + local statFocusing = localData.statFocusing + + if statFocusing then + local statAmount = #localData.statFocusing:GetChildren() + + if isUI then + local isColor3 = color3Teams and Team:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and Team:GetAttribute("Color3") or Team.TeamColor.Color + + for StatName, StatLabel in pairs(isUI) do + local getTeamUI = teamData.teamStats[StatName] + + if not getTeamUI then + local newStat = Templates.GuiInstances.Leaderstat:Clone() + newStat.Name = StatName + newStat.Text = getTeamCount(Team, StatName) + newStat.TextColor3 = TeamColor + newStat.TextStrokeTransparency = 0 + newStat.LayoutOrder = StatLabel.LayoutOrder + newStat.Parent = teamData.teamFrames.mainFrame.TeamPoints + + teamData.teamStats[StatName] = newStat + else + getTeamUI.Text = getTeamCount(Team, StatName) + end + end + + for i, v in pairs(teamData.teamFrames.mainFrame.TeamPoints:GetChildren()) do + if v:IsA("TextLabel") then + if not localData.statsUI[v.Name] then + v:Destroy() + end + end + end + end + + local getUIGrid = teamData.teamFrames.mainFrame.TeamPoints:FindFirstChildOfClass("UIGridLayout") + getUIGrid.CellSize = UDim2.new(1 / statAmount, 0, 1, 0) + end + end + end +end + +local function onTeamUpdate(Team: Instance): () + if Team:IsA("Team") and playerlistdata.teams[Team] then + local teamData = playerlistdata.teams[Team] + local mainFrame = teamData.teamFrames.mainFrame + local isColor3 = color3Teams and Team:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and Team:GetAttribute("Color3") or Team.TeamColor.Color + + --local TeamColor = Team.TeamColor.Color + + mainFrame.Name = "Team_"..Team.Name + mainFrame.TeamNameLabel.Text = Team.Name + mainFrame.TeamNameLabel.TextColor3 = TeamColor + mainFrame.TeamBar.BorderColor3 = TeamColor + + for i, v in pairs(teamData.teamStats) do + teamData.teamStats[i].TextColor3 = TeamColor + end + + for i, v in pairs(Team:GetPlayers()) do + local getData = playerlistdata.players[v] + + if getData then + local playerFrame = getData.playerFrame + + local isColor3 = color3Teams and Team:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and Team:GetAttribute("Color3") or Team.TeamColor.Color + --local TeamColor = Team.TeamColor.Color + + playerFrame.NameLabel.TextColor3 = TeamColor + + for i, v in pairs(getData.statsUI) do + getData.statsUI[i].TextColor3 = TeamColor + end + end + end + end +end + +local function TeamAdded(Team: Instance): () + if Team:IsA("Team") and not playerlistdata.teams[Team] and canShowTeams then + playerlistdata.teams[Team] = { + teamFrames = { + splitFrames = { + topFrame = nil, + bottomFrame = nil + }, + mainFrame = nil, + }, + + teamStats = {}, + teamConnections = {}, + teamPriority = 0 + } + + teamCount += 1 + + local teamData = playerlistdata.teams[Team] + teamData.teamPriority = teamCount + teamData.teamFrames.mainFrame = Templates.GuiInstances.Team:Clone() + teamData.teamFrames.splitFrames.topFrame = Templates.GuiInstances.TeamSplit_Top:Clone() + teamData.teamFrames.splitFrames.bottomFrame = Templates.GuiInstances.TeamSplit_Bottom:Clone() + + local mainFrame = teamData.teamFrames.mainFrame + local splitBottom = teamData.teamFrames.splitFrames.bottomFrame + local splitTop = teamData.teamFrames.splitFrames.topFrame + + local isColor3 = color3Teams and Team:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and Team:GetAttribute("Color3") or Team.TeamColor.Color + --local TeamColor = Team.TeamColor.Color + + mainFrame.Name = "Team_"..Team.Name + mainFrame.TeamNameLabel.Text = Team.Name + mainFrame.TeamNameLabel.TextColor3 = TeamColor + mainFrame.TeamBar.BorderColor3 = TeamColor + mainFrame.LayoutOrder = teamData.teamPriority * 100 + + splitBottom.LayoutOrder = mainFrame.LayoutOrder + 2 + splitTop.LayoutOrder = mainFrame.LayoutOrder + 1 + + mainFrame.Parent = MainGui.Leaderboard + splitBottom.Parent = MainGui.Leaderboard + splitTop.Parent = MainGui.Leaderboard + + MainGui.Leaderboard.TeamSplit_VeryBottom.Visible = true + + table.insert(teamData.teamConnections, Team:GetPropertyChangedSignal("TeamColor"):Connect(function() + onTeamUpdate(Team) + end)) + + table.insert(teamData.teamConnections, Team:GetPropertyChangedSignal("Name"):Connect(function() + onTeamUpdate(Team) + end)) + + if color3Teams then + Team:GetAttributeChangedSignal("Color3"):Connect(function() + onTeamUpdate(Team) + end) + end + + updatePlayerList() + end +end + +local function TeamRemoving(Team: Instance): () + if Team:IsA("Team") and playerlistdata.teams[Team] and teamCount > 0 then + --teamCount -= 1 + + local teamData = playerlistdata.teams[Team] + + for i, v in pairs(teamData.teamConnections) do + v:Disconnect() + end + teamData.teamConnections = {} + + teamData.teamFrames.mainFrame:Destroy() + + for i, v in pairs(teamData.teamFrames.splitFrames) do + teamData.teamFrames.splitFrames[i]:Destroy() + teamData.teamFrames.splitFrames[i] = nil + end + teamData.teamFrames.splitFrames = {} + + for i, v in pairs(teamData.teamStats) do + teamData.teamStats[i]:Destroy() + teamData.teamStats[i] = nil + end + teamData.teamStats = {} + + playerlistdata.teams[Team] = nil + + updatePlayerList() + end +end + +local function fixStatsLayout(statName: string, newOrder: number): () + local localData = playerlistdata.players[LocalPlayer] + + if localData then + for i, v in pairs(Players:GetPlayers()) do + local playerData = playerlistdata.players[v] + + if playerData then + local playerFrame = playerData.playerFrame + local findStat = playerFrame.Leaderstats:FindFirstChild(statName) + + if findStat then + findStat.LayoutOrder = newOrder + end + end + end + end +end + +-- TODO: separate for less usage +local function updateBoard(): () + local localData = playerlistdata.players[LocalPlayer] + + if localData then + local isFocusing = localData.statFocusing + local trueStatAmount = localData.statAmount + local statAmount = 1 + + if isFocusing then + statAmount = #isFocusing:GetChildren() + + MainGui.Leaderboard.TopBar.Player.Text = "Players" + canShowTeams = true + + if MainGui.Leaderboard.Size ~= lb_big then + MainGui.Leaderboard.Size = lb_big + end + + if CurrentTimePeriod >= 6 and #Teams:GetTeams() > 0 then + MainGui.Leaderboard.TopBar.Player.Text = "Team" + MainGui.Leaderboard.TopSplit.Visible = false + MainGui.Leaderboard.TeamSplit_VeryBottom.Visible = true + else + MainGui.Leaderboard.TopSplit.Visible = true + MainGui.Leaderboard.TeamSplit_VeryBottom.Visible = false + end + else + MainGui.Leaderboard.TopBar.Player.Text = "Player List" + canShowTeams = false + + if MainGui.Leaderboard.Size ~= lb_small then + MainGui.Leaderboard.Size = lb_small + end + + MainGui.Leaderboard.TopSplit.Visible = true + MainGui.Leaderboard.TeamSplit_VeryBottom.Visible = false + end + + -- update top bar + local getStatUI = localData.statsUI + + for StatObject, StatLabel in pairs(localData.statsUI) do + local getLocal = localData.statsUI[StatObject] + local findStat = MainGui.Leaderboard.TopBar.Leaderstats:FindFirstChild(StatObject) + + if not findStat then + localData.statAmount += 1 + + local newStat = Templates.GuiInstances.Leaderstat:Clone() + newStat.Name = StatObject + newStat.Text = StatObject + newStat.LayoutOrder = localData.statAmount + newStat.Parent = MainGui.Leaderboard.TopBar.Leaderstats + + fixStatsLayout(StatObject, localData.statAmount) + end + end + + for i, v in pairs(MainGui.Leaderboard.TopBar.Leaderstats:GetChildren()) do + if v:IsA("TextLabel") then + if not localData.statsUI[v.Name] then + localData.statAmount -= 1 + v:Destroy() + end + end + end + + local getUIGrid = MainGui.Leaderboard.TopBar.Leaderstats:FindFirstChildOfClass("UIGridLayout") + getUIGrid.CellSize = UDim2.new(1 / statAmount, 0, 1, 0) + end + + if CurrentTimePeriod >= 6 then + for i, v in pairs(Players:GetPlayers()) do + onTeamChange(v) + end + + if canShowTeams then + for i, v in ipairs(Teams:GetTeams()) do + TeamAdded(v) + refreshTeamStats(v) + end + else + for i, v in ipairs(Teams:GetTeams()) do + if v:IsA("Team") then + TeamRemoving(v) + + for i2, v2 in pairs(v:GetPlayers()) do + onTeamChange(v2) + end + end + end + end + end +end + +local function globalTeamRemoving(Team: Instance): () + TeamRemoving(Team) +end + +local function globalTeamAdded(Team: Instance): () + TeamAdded(Team) +end + +function updatePlayerList() + updateBoard() +end + +local function onStatRemoved(Stat: Instance, statName: string?, Player: Instance): () + if Stat:IsA("IntValue") then + local grabbedPlayer = Player + + if grabbedPlayer and grabbedPlayer:IsA("Player") and playerlistdata.players[grabbedPlayer] then + local data = playerlistdata.players[grabbedPlayer] + + local statFocusing = data.statFocusing + local statAmount = 1 + + local trueStatAmount = data.statAmount + + if statFocusing then + statAmount = #data.statFocusing:GetChildren() + end + + local dataFrame = data.playerFrame + + local grabbedName = statName or Stat.Name + + if data.statsUI[grabbedName] then + local getStatUI = data.statsUI[grabbedName] + getStatUI:Destroy() + + local getUIGrid = dataFrame.Leaderstats:FindFirstChildOfClass("UIGridLayout") + getUIGrid.CellSize = UDim2.new(1 / statAmount, 0, 1, 0) + + local objectConnections = data.statLabelConnections[grabbedName] + + for i, v in pairs(objectConnections) do + v:Disconnect() + end + data.statLabelConnections[grabbedName] = nil + data.statsUI[grabbedName] = nil + + --data.statAmount -= 1 + end + + updatePlayerList() + end + end +end + +local function onStatAdded(Stat: Instance): () + if Stat:IsA("IntValue") and Stat.Parent then + local grabbedPlayer = Stat.Parent.Parent + + if grabbedPlayer and grabbedPlayer:IsA("Player") and playerlistdata.players[grabbedPlayer] then + local data = playerlistdata.players[grabbedPlayer] + local statLabelConnections = data.statLabelConnections + local statFocusing = data.statFocusing + local statAmount = #statFocusing:GetChildren() + local dataFrame = data.playerFrame + + statLabelConnections[Stat.Name] = {} + + local focusedStatLabelConnection = statLabelConnections[Stat.Name] + + if not data.statsUI[Stat.Name] then + local newStat = Templates.GuiInstances.Leaderstat:Clone() + newStat.Name = Stat.Name + newStat.Text = tostring(Stat.Value) + newStat.LayoutOrder = statAmount + + if CurrentTimePeriod >= 6 and (not grabbedPlayer.Neutral) and grabbedPlayer.Team and playerlistdata.teams[grabbedPlayer.Team] then + newStat.TextColor3 = grabbedPlayer.Team.TeamColor.Color + end + + local currentName = Stat.Name + + table.insert(focusedStatLabelConnection, Stat:GetPropertyChangedSignal("Value"):Connect(function() + newStat.Text = tostring(Stat.Value) + + if CurrentTimePeriod >= 6 and canShowTeams and playerlistdata.teams[grabbedPlayer.Team] and grabbedPlayer.Team then + refreshTeamStats(grabbedPlayer.Team) + end + end)) + + -- TODO: make this NOT use onStatRemoved + --table.insert(focusedStatLabelConnection, Stat:GetPropertyChangedSignal("Name"):Connect(function() + -- onStatRemoved(Stat, currentName, grabbedPlayer) + -- onStatAdded(Stat) + --end)) + + newStat.Parent = dataFrame.Leaderstats + + local getUIGrid = dataFrame.Leaderstats:FindFirstChildOfClass("UIGridLayout") + getUIGrid.CellSize = UDim2.new(1 / statAmount, 0, 1, 0) + + data.statsUI[Stat.Name] = newStat + end + + updatePlayerList() + end + end +end + +local function HandleLeaderstats(Stat: Instance): () + if Stat:IsA("IntValue") and Stat.Name == "leaderstats" and Stat.Parent then + local grabbedPlayer = Stat.Parent + + if grabbedPlayer and grabbedPlayer:IsA("Player") and playerlistdata.players[grabbedPlayer] then + local playerData = playerlistdata.players[grabbedPlayer] + playerData.statFocusing = Stat + + local statFocusing = playerData.statFocusing + local statConnections = playerData.statConnections + + for i, v in ipairs(statFocusing:GetChildren()) do + onStatAdded(v) + end + + table.insert(statConnections, statFocusing.ChildAdded:Connect(onStatAdded)) + table.insert(statConnections, statFocusing.ChildRemoved:Connect(function(stat) + onStatRemoved(stat, stat.Name, grabbedPlayer) + end)) + + updatePlayerList() + end + end +end + +local function HandleLeaderstatsRemoval(Stat: Instance, Player: Instance): () + if Stat:IsA("IntValue") and Stat.Name == "leaderstats" then + local grabbedPlayer = Player + + if grabbedPlayer and grabbedPlayer:IsA("Player") and playerlistdata.players[grabbedPlayer] then + local playerData = playerlistdata.players[grabbedPlayer] + local statFocusing = playerData.statFocusing + + if statFocusing == Stat then + playerData.statFocusing = nil + + for i, v in pairs(playerData.statConnections) do + v:Disconnect() + end + playerData.statConnections = {} + + for i, v in pairs(playerData.statsUI) do + playerData.statsUI[i]:Destroy() + playerData.statsUI[i] = nil + end + playerData.statsUI = {} + + for i, v in pairs(Stat:GetChildren()) do + onStatRemoved(v, Stat.Name, grabbedPlayer) + end + end + + updatePlayerList() + end + end +end + +local function neutralizePlayer(Player: Instance): () + if Player:IsA("Player") and playerlistdata.players[Player] then + local playerData = playerlistdata.players[Player] + + if (#Teams:GetTeams() > 0) and canShowTeams then + playerData.playerFrame.LayoutOrder = 0 + playerData.playerFrame.Visible = false + + for i, v in pairs(Teams:GetTeams()) do + refreshTeamStats(v) + end + else + playerData.playerFrame.LayoutOrder = 0 + playerData.playerFrame.NameLabel.TextColor3 = ComputeNameColor(playerData.playerFrame.NameLabel.Text) + playerData.playerFrame.Visible = true + + for i, v in pairs(playerData.statsUI) do + playerData.statsUI[i].TextColor3 = Color3.fromRGB(242, 243, 243) + end + end + end +end + +local function changeTeam(Player: Instance): () + if Player:IsA("Player") then + local getData = playerlistdata.players[Player] + + if getData and Player.Team then + local acceptableTeam = playerlistdata.teams[Player.Team] + + if not acceptableTeam then + neutralizePlayer(Player) + else + local playerFrame = getData.playerFrame + + local isColor3 = color3Teams and Player.Team:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and Player.Team:GetAttribute("Color3") or Player.Team.TeamColor.Color + --local TeamColor = Player.Team.TeamColor.Color + + playerFrame.NameLabel.TextColor3 = TeamColor + + for i, v in pairs(getData.statsUI) do + getData.statsUI[i].TextColor3 = TeamColor + end + + if not playerFrame.Visible then + playerFrame.Visible = true + end + + if playerFrame.LayoutOrder ~= acceptableTeam.teamFrames.mainFrame.LayoutOrder + 1 then + playerFrame.LayoutOrder = acceptableTeam.teamFrames.mainFrame.LayoutOrder + 1 + end + end + end + + for i, v in pairs(Teams:GetTeams()) do + refreshTeamStats(v) + end + end +end + +function onTeamChange(Player: Instance): () + if Player:IsA("Player") and playerlistdata.players[Player] then + if (playerlistdata.teams[Player.Team] and not Player.Neutral) then + changeTeam(Player) + else + neutralizePlayer(Player) + end + end +end + +local function PlayerAdded(Player: Instance): () + if Player:IsA("Player") and not playerlistdata.players[Player] then + playerlistdata.players[Player] = { + playerFrame = nil, + statFocusing = nil, + statConnections = {}, + statLabelConnections = {}, + playerConnections = {}, + statsUI = {}, + statAmount = 0 + } + + local playerInData = playerlistdata.players[Player] + local playerConnections = playerInData.playerConnections + + playerInData.playerFrame = Templates.GuiInstances.Player:Clone() + + local newPlayerFrame = playerInData.playerFrame + newPlayerFrame.Name = Player.UserId + + if not Solo.Value then + if DisplayNames then + newPlayerFrame.NameLabel.Text = string.sub(Player.DisplayName, 1, 16) + else + newPlayerFrame.NameLabel.Text = string.sub(Player.Name, 1, 16) + end + + newPlayerFrame.NameLabel.TextColor3 = ComputeNameColor(newPlayerFrame.NameLabel.Text) + else + newPlayerFrame.NameLabel.Text = "Player" + newPlayerFrame.NameLabel.TextColor3 = Color3.fromRGB(42, 75, 215) + end + + newPlayerFrame.Visible = true + newPlayerFrame.Parent = MainGui.Leaderboard + + if CurrentTimePeriod >= 6 then + neutralizePlayer(Player) + end + + local foundStats = Player:FindFirstChild("leaderstats") + + if foundStats then + HandleLeaderstats(foundStats) + end + + table.insert(playerConnections, Player.ChildAdded:Connect(HandleLeaderstats)) + table.insert(playerConnections, Player.ChildRemoved:Connect(function(child) + HandleLeaderstatsRemoval(child, Player) + end)) + + if CurrentTimePeriod >= 6 then + table.insert(playerConnections, Player:GetPropertyChangedSignal("Neutral"):Connect(function() + onTeamChange(Player) + end)) + + table.insert(playerConnections, Player:GetPropertyChangedSignal("Team"):Connect(function() + onTeamChange(Player) + end)) + + onTeamChange(Player) + end + end +end + +local function PlayerRemoving(Player: Instance): () + if Player:IsA("Player") then + local getData = playerlistdata.players[Player] + + if getData then + for i, v in pairs(getData.statLabelConnections) do + for i2, v2 in pairs(getData.statLabelConnections[i]) do + v2:Disconnect() + end + + getData.statLabelConnections[i] = nil + end + table.clear(getData.statLabelConnections) + + for i, v in pairs(getData.playerConnections) do + v:Disconnect() + end + table.clear(getData.playerConnections) + + getData.statFocusing = nil + + for i, v in pairs(getData.statsUI) do + getData.statsUI[i]:Destroy() + getData.statsUI[i] = nil + end + getData.statsUI = {} + getData.playerFrame:Destroy() + + playerlistdata.players[Player] = nil + end + + updatePlayerList() + end +end + +local function CameraButtonMain(): () + StockSound:PlaySoundLocal("Step") +end + +local function DisplayChatMessage(Chatter: any, Message, gotFiltered: boolean?): () + local ChatterType = typeof(Chatter) + local IsWhitelisted = whitelistedStringsTalk[Chatter] + + local PlayerObject = ((ChatterType == "Instance") and Chatter:IsA("Player")) and Chatter + local PlayerName + + if PlayerObject then + PlayerName = DisplayNames and PlayerObject.DisplayName or PlayerObject.Name + else + PlayerName = tostring(Chatter) + end + + if PlayerObject or IsWhitelisted then + local ChatTemplate = ReplicatedStorage.Templates.GuiInstances.Message:Clone() + + table.insert(chats, ChatTemplate) + + if #chats >= 7 then + local firstChat = chats[1] + + task.cancel(chatTasks[firstChat]) + chatTasks[firstChat] = nil + + firstChat:Destroy() + table.remove(chats, 1) + end + + ChatTemplate.Username.Text = PlayerName.."; " + ChatTemplate.Username.TextColor3 = ComputeNameColor(PlayerName) + + if CurrentTimePeriod >= 6 and PlayerObject and PlayerObject.Team and (not PlayerObject.Neutral) then + local TeamOfPlayer = PlayerObject.Team + + local isColor3 = color3Teams and TeamOfPlayer:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and TeamOfPlayer:GetAttribute("Color3") or TeamOfPlayer.TeamColor.Color + + ChatTemplate.Username.TextColor3 = TeamColor + end + + -- Custom chats, refer to the "whiteListedStringsTalk" table for documentation + if IsWhitelisted then + local hasUserChange = whitelistedStringsTalk[Chatter].Username + local hasTextChange = whitelistedStringsTalk[Chatter].Text + + if hasUserChange then + for changing, value in pairs(hasUserChange) do + ChatTemplate.Username[changing] = value + end + end + + if hasTextChange then + for changing, value in pairs(hasTextChange) do + ChatTemplate.Username.Message[changing] = value + end + end + end + + ChatTemplate.Username.Message.Text = Message + ChatTemplate.Username.Message.TextColor3 = gotFiltered and Color3.fromRGB(255, 0, 0) or ChatTemplate.Username.Message.TextColor3 + + ChatTemplate.Parent = MainGui.ChatWindow + + ChatTemplate.Username.Size = UDim2.new(0,ChatTemplate.Username.TextBounds.X,1,0) + ChatTemplate.Username.Message.Size = UDim2.new(0,ChatTemplate.Username.Message.TextBounds.X + 12,1,0) + ChatTemplate.Size = UDim2.new(0,ChatTemplate.Username.TextBounds.X + ChatTemplate.Username.Message.TextBounds.X + 12,0,16) + + chatTasks[ChatTemplate] = task.delay(64, function() + local isStillInChat = table.find(chats, ChatTemplate) + + if isStillInChat then + ChatTemplate:Destroy() + chatTasks[ChatTemplate] = nil + + table.remove(chats, isStillInChat) + end + end) + end +end + +local function destroyFocusedSuperSafeChats(focusedElement): () + local buttonStyle = focusedElement:FindFirstChild("ButtonStyle") + + if buttonStyle then + buttonStyle.BackgroundColor3 = Color3.fromRGB(255, 255, 255) + end + + focusedElement.BackgroundColor3 = Color3.fromRGB(255, 255, 255) + + for i, v in pairs(focusedElement:GetDescendants()) do + if v.Name == "List" then + v.Visible = false + elseif v.Name == "ButtonStyle" and v.BackgroundColor3 ~= Color3.fromRGB(255, 255, 255) then + v.BackgroundColor3 = Color3.fromRGB(255, 255, 255) + end + end +end + +local function makeSuperSafeChatElementsVisible(optionElement: TextButton): () + local buttonStyle = optionElement:FindFirstChild("ButtonStyle") + + if buttonStyle and buttonStyle:IsA("Frame") then + buttonStyle.BackgroundColor3 = Color3.fromRGB(178, 178, 178) + end + + optionElement.BackgroundColor3 = Color3.fromRGB(178, 178, 178) + + local grabbedList: Instance? = optionElement:FindFirstChild("List") + + if grabbedList and grabbedList:IsA("Frame") then + grabbedList.Visible = true + end +end + +local function superSafeChatBubbleClicked(): () + if not safeChatOpened then + safeChatOpened = true + + MainGui.SuperSafeChatBubble.Image = "rbxassetid://12483705914" + MainGui.SuperSafeChatBubble.List.Visible = true + else + safeChatOpened = false + + MainGui.SuperSafeChatBubble.Image = "rbxassetid://12483706070" + MainGui.SuperSafeChatBubble.List.Visible = false + end +end + +local function createSuperSafeChatButton(indexTable, buttonParent): TextButton + local Option: TextButton = Templates:WaitForChild("GuiInstances"):WaitForChild("SafeChatOption"):Clone() + local buttonStyle = Option:FindFirstChild("ButtonStyle") + + if buttonStyle then + local textLabel = buttonStyle:FindFirstChild("TextLabel") + + if textLabel and textLabel:IsA("TextLabel") then + textLabel.Text = tostring(indexTable["#text"] or indexTable) + end + end + + Option.Parent = buttonParent:WaitForChild("List") + + return Option +end + +local function onSuperSafeChatOptionClicked(button: TextButton): () + StockSound:PlaySoundLocal("Click") + destroyFocusedSuperSafeChats(MainGui.SuperSafeChatBubble) + superSafeChatBubbleClicked() + + local ChatMain = require(LocalPlayer.PlayerScripts:WaitForChild("ChatScript", nil):WaitForChild("ChatMain", nil)) + local ButtonStyle = button:FindFirstChild("ButtonStyle") + + if ButtonStyle then + local TextLabel = ButtonStyle:FindFirstChild("TextLabel") + + if TextLabel and TextLabel:IsA("TextLabel") then + ChatMain.MessagePosted:fire(TextLabel.Text) + end + end +end + +local function HandleInputBegan(input: InputObject, gameProcessedEvent: boolean): () + if input.KeyCode == Enum.KeyCode.Slash and UserInputService:GetFocusedTextBox() == nil then + MainGui.ChatBar.TextBox:CaptureFocus() + + RunService.RenderStepped:Wait() + + MainGui.ChatBar.TextBox.Text = "" + elseif safeChatOpened and input.UserInputType ~= Enum.UserInputType.MouseMovement and not gameProcessedEvent then + superSafeChatBubbleClicked() + destroyFocusedSuperSafeChats(MainGui.SuperSafeChatBubble) + end +end + +local function OnChatBarFocusLost(enterPressed): () + if enterPressed then + if MainGui.ChatBar.TextBox.Text ~= "" then + local ChatMain = require(LocalPlayer.PlayerScripts:WaitForChild("ChatScript", nil):WaitForChild("ChatMain", nil)) + + ChatMain.MessagePosted:fire(MainGui.ChatBar.TextBox.Text) + + MainGui.ChatBar.TextBox:ReleaseFocus() + MainGui.ChatBar.TextBox.Text = "" + end + end +end + +local function OnExit(): () + if clickedExit then + return + end + + clickedExit = true + + local IsStudio = RunService:IsStudio() + local MessageDecided = IsStudio and "Cannot Teleport in the Studio." or "Teleporting to the Menu. Please wait..." + + local ExitMessage = Instance.new("Message") + ExitMessage.Name = "ExitMessage" + ExitMessage.Text = MessageDecided + ExitMessage.Parent = workspace + + if not IsStudio then + TeleportService:Teleport(10789607669, Players.LocalPlayer, nil, nil) + end +end + +local function HelpInit(): () + local FrameDrag = DraggableObject.new(MainGui.HelpWindow.WindowStyle.FrameTop) + FrameDrag:Enable() + + MainGui.HelpWindow.WindowStyle.FrameTop.X.MouseButton1Click:Connect(function() + MainGui.HelpWindow.Visible = false + end) +end + +local function OnHelp(): () + MainGui.HelpWindow.Visible = true +end + +local function AdditionalButtons(): () + for i, v in pairs(twoExtraButtons) do + v.Visible = (CurrentTimePeriod > 7) + + if toolboxShouldBeEnabled() then + v.ButtonText.TextColor3 = Color3.fromRGB(76, 76, 76) + v.HoverImage = "rbxassetid://8090188810" + v.Visible = true + end + end +end + +local function Errored(msg, trace, err) + DisplayChatMessage("[ERROR!]", tostring(msg)) +end + +local function superSafeChatParser(list, rootButton: GuiButton) + local focusedElement: any = nil + for i, v in pairs(list) do + local Option = createSuperSafeChatButton(v, rootButton) + + Option.MouseEnter:Connect(function() + if focusedElement then + destroyFocusedSuperSafeChats(focusedElement) + end + + focusedElement = Option + makeSuperSafeChatElementsVisible(focusedElement) + end) + + Option.MouseButton1Click:Connect(function() + onSuperSafeChatOptionClicked(Option) + focusedElement = nil + end) + + if v["utterance"] ~= nil then + local utteranceTable = v["utterance"] + local utteranceType = typeof(utteranceTable) + + local NewList = Templates:WaitForChild("GuiInstances"):WaitForChild("List"):Clone() + NewList:WaitForChild("UIListLayout").VerticalAlignment = Enum.VerticalAlignment.Center + + NewList.Parent = Option + + if utteranceType == "table" then + superSafeChatParser(utteranceTable, Option) + + NewList:WaitForChild("UIPadding").PaddingBottom = UDim.new(0, 24) + else + local newButton = createSuperSafeChatButton(utteranceTable, Option) + + newButton.MouseButton1Click:Connect(function() + onSuperSafeChatOptionClicked(newButton) + focusedElement = nil + end) + + newButton.MouseEnter:Connect(function() + focusedElement = newButton + makeSuperSafeChatElementsVisible(newButton) + end) + end + end + end +end + +local ToolboxConnections +local function DestroyToolboxConnections() + if not ToolboxConnections then + return + end + + local character = LocalPlayer.Character + if character then + character.Humanoid.CameraOffset = Vector3.zero + end + + for _, connection in ipairs(ToolboxConnections) do + connection:Disconnect() + end + + ToolboxConnections = nil +end + +local toolboxRightPadding = 225; +local function MakeToolboxConnections() + DestroyToolboxConnections() + + local character = LocalPlayer.Character + local function update() + if character then + + end + end + + if character then + update() + end + + ToolboxConnections = { + LocalPlayer.CharacterAdded:Connect(function() + character = LocalPlayer.Character + update() + end), + + Camera:GetPropertyChangedSignal("ViewportSize"):Connect(function() + update() + end) + } + + return ToolboxConnections +end + +local function OnToolbox() + if toolboxShouldBeEnabled() then + MainGui.ToolboxWindow.Visible = not MainGui.ToolboxWindow.Visible + + local isEnabled = MainGui.ToolboxWindow.Visible + MainGui.Topbar.Toolbox.ButtonText.Text = isEnabled and "x Toolbox" or "Toolbox" + MainGui.UIPadding.PaddingRight = UDim.new(0, isEnabled and toolboxRightPadding or 0) + + -- IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE + MainGui.Parent.MainResetGui.UIPadding.PaddingRight = MainGui.UIPadding.PaddingRight; + -- IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE IGNORE + + -- who the hell made this code + -- KEY U R STUPID 4 THIS + return isEnabled and MakeToolboxConnections() or DestroyToolboxConnections() + end +end + +--Hookup: + +if (not ErrorsInChat) then + whitelistedStringsTalk["[ERROR!]"] = nil +end + +UserInputService.InputBegan:Connect(HandleInputBegan) + +MainGui.ChatBar.TextBox.FocusLost:Connect(OnChatBarFocusLost) +ReplicatedStorage.Protocols.Chat.OnClientEvent:Connect(function(player, message, gotFiltered) + local getType = typeof(player) + local isWhitelistedString = whitelistedStringsTalk[player] + + if player and (getType == "string" and isWhitelistedString) or (getType == "Instance" and player:IsA("Player")) then + DisplayChatMessage(player, message, gotFiltered) + end +end) + +MainGui.Topbar.Exit.MouseButton1Click:Connect(OnExit) +HelpInit() +MainGui.Topbar.Help.MouseButton1Click:Connect(OnHelp) +MainGui.Topbar.Toolbox.MouseButton1Click:Connect(OnToolbox) + +for _, v in pairs(workspace:GetDescendants()) do + ObjectAdded(v) +end + +FullscreenMain() +AdditionalButtons() + +workspace.DescendantAdded:Connect(ObjectAdded) +LocalPlayer.ChildAdded:Connect(ObjectAdded) +GameSettings.FullscreenChanged:Connect(FullscreenMain) + +for _, v in pairs(Players:GetPlayers()) do + PlayerAdded(v) +end + +Players.PlayerAdded:Connect(PlayerAdded) +Players.PlayerRemoving:Connect(PlayerRemoving) + +for _, v in pairs(LocalPlayer:GetChildren()) do + ObjectAdded(v) +end + +for _, v in pairs(MainGui:WaitForChild("CameraControl"):WaitForChild("CameraButtons"):GetChildren()) do + if v:IsA("ImageButton") then + v.MouseButton1Click:Connect(CameraButtonMain) + end +end + +if CurrentTimePeriod >= 6 then + Teams.ChildAdded:Connect(TeamAdded) + Teams.ChildRemoved:Connect(TeamRemoving) +end + +ScriptContext.Error:Connect(Errored) + +if CurrentTimePeriod >= 8 then + superSafeChatParser(FullDecoded, MainGui.SuperSafeChatBubble) + MainGui.SuperSafeChatBubble.Visible = true + MainGui.SuperSafeChatBubble.MouseButton1Click:Connect(superSafeChatBubbleClicked) + MainGui.HelpWindow.Size = UDim2.new(0, 803, 0, 236) + MainGui.HelpWindow.MainContent.Image = "rbxassetid://12761386129" + --MainGui.HelpWindow.Size.Y.Offset = 236 +end + +if CurrentTimePeriod >= 7 then + MainGui.CameraControl.Position = UDim2.new(1, 5, 1, -15) + MainGui.CameraControl.ReportButton.Visible = true +end + +-- disables camera buttons for mobile, since we kept getting complaints about that +if (UserInputService.TouchEnabled and not UserInputService.MouseEnabled) then + MainGui.CameraControl.Visible = false +end + +-- disable chat if privacy settings say so +if Solo.Value == false and Chat:CanUserChatAsync(LocalPlayer.UserId) then + return +else + MainGui.ChatBar.Visible = false + MainGui.ChatWindow.Visible = false + MainGui.SuperSafeChatBubble.Visible = false + MainGui.CameraControl.ReportButton.Visible = false + MainGui.CameraControl.Position = UDim2.new(1, MainGui.CameraControl.Position.X.Offset, 1, 6) +end + +-- make a house diff --git a/rojo/MainModule/src/StarterGui/MainGui/MainGuiOffset.client.lua b/rojo/MainModule/src/StarterGui/MainGui/MainGuiOffset.client.lua new file mode 100644 index 0000000..d56d519 --- /dev/null +++ b/rojo/MainModule/src/StarterGui/MainGui/MainGuiOffset.client.lua @@ -0,0 +1,53 @@ +local CurrentCamera = workspace.CurrentCamera; +local ReplicatedStorage = game:GetService("ReplicatedStorage"); + +local CustomCamera = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("CustomCamera")); +local RunService = game:GetService("RunService"); + +local UIPadding = script.Parent:WaitForChild("UIPadding"); + +local ViewportSize; +local function getPositionMatrix() + local offset = -UIPadding.PaddingRight.Offset; + local position = offset/ViewportSize; + + local r = ViewportSize.X/ViewportSize.Y; + local h = math.tan(math.rad(CurrentCamera.FieldOfView)*0.5); + local w = h*r; + + return -position.X*w, -offset; +end + +RunService:BindToRenderStep("cameraOffsetMatrix", Enum.RenderPriority.Camera.Value+1, function() + local vp = CurrentCamera.ViewportSize; + ViewportSize = Vector2.new(vp.X, vp.Y); + + local x, px = getPositionMatrix(); + CustomCamera.viewportOffset = Vector2.new(px*0.5,0); + CustomCamera.viewportScale = Vector2.new(x,0); + + local right = CurrentCamera.CFrame.RightVector; + local skew = CFrame.new( + 0,0,0, + 1,0,0, + 0,1,0, + x,0,1 + ); + + CurrentCamera.CFrame *= skew; + --for _, billboard in CustomCamera.billboards do + -- if(not billboard.Parent)then + -- continue; + -- end + + -- local cframe = billboard.Parent.CFrame; + -- local origin = cframe*-Vector3.yAxis + Vector3.yAxis*1.5; + -- local screen = CustomCamera:WorldToScreenPoint(origin); + + -- local point = CustomCamera:ViewportToWorldPoint(screen.X, screen.Y); + -- point = point.Origin + point.Direction*screen.Z; + + -- billboard.ExtentsOffsetWorldSpace = point - screen; + --end + +end) \ No newline at end of file diff --git a/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/Util.lua b/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/Util.lua new file mode 100644 index 0000000..ef26daf --- /dev/null +++ b/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/Util.lua @@ -0,0 +1,89 @@ +--!strict +-- epic util module so scrollbar isnt too lengthy LOLOOLLOLLOLOL + +local Players = game:GetService("Players") + +local LocalPlayer = Players.LocalPlayer +local Mouse = LocalPlayer:GetMouse() + +local Util = {} + +-- attach scrollbar to the scrollingframe +function Util.AttachScrollbarToFrame(bar : ImageLabel, frame : GuiObject, align : Enum.VerticalScrollBarPosition) + if frame.Parent and frame.Parent:IsA("GuiObject") then + local where = frame.AbsolutePosition + (if align == Enum.VerticalScrollBarPosition.Right then + (frame.AbsoluteSize * Vector2.xAxis) + else Vector2.zero + ) + + local XScale = (- frame.AbsolutePosition.X + where.X) / frame.Parent.AbsoluteSize.X + local YScale = (- frame.AbsolutePosition.Y + where.Y) / frame.Parent.AbsoluteSize.Y + bar.Position = UDim2.fromScale(XScale,YScale) + + -- size now + bar.Size = UDim2.new(0, 16, frame.Size.Y.Scale, frame.Size.Y.Offset) + end +end + +-- positions the scrollbar button inside the scrollbar frame from canvas +function Util.AdjustScrollBar(bar : ImageLabel, scrollingFrame : ScrollingFrame, Horizontal : boolean?) + local Scroller = bar:WaitForChild("Scroller") + local Scrollbar = Scroller:WaitForChild("ScrollBar") + + local X = (scrollingFrame.CanvasPosition.X/scrollingFrame.AbsoluteCanvasSize.X) + local Y = (scrollingFrame.CanvasPosition.Y/scrollingFrame.AbsoluteCanvasSize.Y) + + if Scrollbar:IsA("GuiObject") then + Scrollbar.Position = Horizontal==true and UDim2.fromScale(X, 0.5) or UDim2.fromScale(0.5, Y) + end +end + +-- adjust the scrollbar size from scrollingframe canvas +function Util.FixScrollbarSize(bar : ImageLabel, scrollingFrame : ScrollingFrame, Horizontal : boolean?) + local Scroller = bar:WaitForChild("Scroller") + local Scrollbar = Scroller:WaitForChild("ScrollBar") + local Axis = Horizontal == true and "X" or "Y" + + local size = scrollingFrame.AbsoluteWindowSize/scrollingFrame.AbsoluteCanvasSize + + if Scrollbar:IsA("GuiObject") then + Scrollbar.Size = Horizontal==true and UDim2.fromScale(size.X, 1) or UDim2.fromScale(1, size.Y) + end + + Util.AdjustScrollBar(bar, scrollingFrame, Horizontal) + + if Axis == "X" then + bar.Visible = (scrollingFrame.AbsoluteCanvasSize.X > scrollingFrame.AbsoluteSize.X) + else + bar.Visible = (scrollingFrame.AbsoluteCanvasSize.Y > scrollingFrame.AbsoluteSize.Y) + end +end + +function Util.IsMouseInFrame(frame : GuiObject) + local mx, my = Mouse.X, Mouse.Y + + local AbsPosition = frame.AbsolutePosition + local AbsSize = frame.AbsoluteSize + + return( + mx > AbsPosition.X + and my > AbsPosition.Y + and mx < AbsPosition.X + AbsSize.X + and my < AbsPosition.Y + AbsSize.Y + ) +end + +function Util.MousePosition(NoX : boolean, NoY : boolean) : Vector2 + if (NoX == true) and (NoY == true) then + warn("look man u need to like allow atleast 1 axis") + + return Vector2.zero + end + + return Vector2.new( + (NoX ~= true and Mouse.X or 0), + (NoY ~= true and Mouse.Y or 0) + ) +end + +return Util diff --git a/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.lua b/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.lua new file mode 100644 index 0000000..d65b08f --- /dev/null +++ b/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.lua @@ -0,0 +1,249 @@ +--!nonstrict +--[[ + games unite + @author nobonet + @submodule Scrollbar + + epic docs: + function Module.new(ScrollingFrame ScrollingFrame, Enum.VerticalScrollBarPosition VScrollPosition) + | create new scroller for this scrolingframe + Default Value: none this is important step DONT forget the scrollingframe + | VScrollPosition is the equal to a ScrollingFrame's VerticalScrollBarPosition + Default Value: Enum.VerticalScrollBarPosition.Right + + function Module:Destroy() + | byebye + + function Module:init() + | u dont need to execute this + + function Module:Scroll(number offset, number scale) + | scroll the frame by specified offset and/or scale + Default Value: 0, 0 +]] + +local Players = game:GetService("Players") +local UserInputService = game:GetService("UserInputService") + +local LocalPlayer = Players.LocalPlayer +local Mouse = LocalPlayer:GetMouse() + +local ScrollItemsTemplate = script:WaitForChild("ScrollingItems") + +local ScrollDist = 30 +local ButtonScrollDist = 55 + +local Util = require(script:WaitForChild("Util")) + +------------------------------------------------------------------------------------- +-- MODULE !!!!!!!!! + +local Scrollbar = {} +Scrollbar.__index = Scrollbar +Scrollbar.Initiated = false + +---------------------------- +-- the scorllbar things + +-- constructor +function Scrollbar.new(ScrollingFrame : ScrollingFrame, VScrollPosition : Enum.VerticalScrollBarPosition?) + assert(typeof(ScrollingFrame) == "Instance" and ScrollingFrame:IsA("ScrollingFrame"), + "pls put an actual ScrollingFrame" + ) + + local new = setmetatable({ + ["ScrollingFrame"] = ScrollingFrame; + ["VScrollPosition"] = VScrollPosition or Enum.VerticalScrollBarPosition.Right; + ["ScrollItems"] = ScrollItemsTemplate:Clone(); + ["Dragging"] = false; + ["Connections"] = {}; + }, Scrollbar) + + return new:init() +end + +-- initializer +function Scrollbar:init() + if self.Initiated == true then + return + end + + local ScrollingFrame : ScrollingFrame = self.ScrollingFrame + local ScrollingItems = self.ScrollItems + + local function AddScrollBar(Bar : ImageLabel, horizontal : boolean) + local Scroller = Bar:WaitForChild("Scroller") + local Scrollbar = Scroller:WaitForChild("ScrollBar") + local Scroll1Button = Bar:WaitForChild(horizontal and "ScrollLeft" or "ScrollUp") + local Scroll2Button = Bar:WaitForChild(horizontal and "ScrollRight" or "ScrollDown") + + --Util.AttachScrollbarToFrame(Bar, ScrollingFrame, self.VScrollPosition) + Util.FixScrollbarSize(Bar, ScrollingFrame, horizontal) + + if horizontal~=true then + if self.VScrollPosition == Enum.VerticalScrollBarPosition.Right then + Bar.AnchorPoint = Vector2.xAxis + else + Bar.AnchorPoint = Vector2.zero + end + end + + -- listen to size/position change + do + table.insert(self.Connections, ScrollingFrame:GetPropertyChangedSignal("AbsoluteCanvasSize"):Connect(function(): () + Util.FixScrollbarSize(Bar, ScrollingFrame, horizontal) + end)) + + -- sisze of scrll frame + table.insert(self.Connections, ScrollingFrame:GetPropertyChangedSignal("AbsoluteSize"):Connect(function(): () + --Util.AttachScrollbarToFrame(Bar, ScrollingFrame, self.VScrollPosition) + Util.FixScrollbarSize(Bar, ScrollingFrame, horizontal) + end)) + + -- position of scroll frame + table.insert(self.Connections, ScrollingFrame:GetPropertyChangedSignal("CanvasPosition"):Connect(function(): () + Util.AdjustScrollBar(Bar, ScrollingFrame, horizontal) + end)) + end + + ---- interaction + do + -- buttons + table.insert(self.Connections, Scroll1Button.Activated:Connect(function(inputObject: InputObject, clickCount: number): () + self:Scroll(-ButtonScrollDist, nil, horizontal) + end)) + table.insert(self.Connections, Scroll2Button.Activated:Connect(function(inputObject: InputObject, clickCount: number): () + self:Scroll(ButtonScrollDist, nil, horizontal) + end)) + -- scrollwheel + table.insert(self.Connections, UserInputService.InputChanged:Connect(function(input: InputObject, gameProcessedEvent: boolean): () + local Interacting = (Util.IsMouseInFrame(ScrollingFrame) or Util.IsMouseInFrame(Bar)) + if input.UserInputType == Enum.UserInputType.MouseWheel then + if Interacting == true then + local direction = input.Position.Z * ScrollDist + self:Scroll(-direction, 0, false) + end + end + end)) + -- mouse + table.insert(self.Connections, Scrollbar.MouseButton1Down:Connect(function(x: number, y: number): () + self:StartDrag(horizontal) + end)) + end + end + + -- listen to ancestry changed for whether it got destroyed or just a simple parent change + table.insert(self.Connections, ScrollingFrame.AncestryChanged:Connect(function(child: Instance, parent: Instance): () + if ScrollingFrame.Parent == nil then + self:Destroy() + return + end + + ScrollingItems.Parent = ScrollingFrame.Parent + --Util.AttachScrollbarToFrame(Bar, ScrollingFrame, self.VScrollPosition) + end)) + + table.insert(self.Connections, UserInputService.InputEnded:Connect(function(input: InputObject, gameProcessedEvent: boolean): () + if input.UserInputType == Enum.UserInputType.MouseButton1 then + self:EndDrag() + end + end)) + + ---- dumb object value (created by jesus christ) + local DumbObjectValue: ObjectValue = Instance.new("ObjectValue", ScrollingItems) + DumbObjectValue.Name = "TargetFrame" + DumbObjectValue.Value = self.ScrollingFrame + + ---- modify the scrollframe + ScrollingFrame.ScrollingEnabled = false + ScrollingFrame.ScrollBarThickness = 0 + ScrollingFrame.ScrollBarImageTransparency = 1 + + AddScrollBar(ScrollingItems.Bar, false) + AddScrollBar(ScrollingItems.HBar, true) + + self.Initiated = true + return self +end + +-- destructor +function Scrollbar:Destroy() + -- disconnect + for _, v : RBXScriptConnection in self.Connections do + v:Disconnect() + end + + -- delete + pcall(self.ScrollItems.Destroy, self.ScrollItems) + + -- byebye + table.clear(self) + setmetatable(self,nil) +end + +---------------------------- +-- scrollbar functions + +function Scrollbar:Scroll(offset : number, scale : number, horizontal : boolean?): () + local ScrollingFrame : ScrollingFrame = self.ScrollingFrame + + -- adjust + local ScaleDist: number = (ScrollingFrame.AbsoluteCanvasSize.Y * (tonumber(scale) or 0)) + ScaleDist = ScaleDist + (tonumber(offset) or 0) + local Adding: Vector2 = horizontal==true and Vector2.new(ScaleDist, 0) or Vector2.new(0, ScaleDist) + ScrollingFrame.CanvasPosition += Adding + + -- fix scrollbars + local ScrollingItems = self.ScrollItems + local Bar : ImageLabel = ScrollingItems:WaitForChild("Bar") + local HBar : ImageLabel = ScrollingItems.HBar + + if horizontal then + -- horizontal + Util.AdjustScrollBar(HBar, ScrollingFrame, true) + Util.FixScrollbarSize(HBar, ScrollingFrame, true) + else + -- vertical + Util.AdjustScrollBar(Bar, ScrollingFrame, false) + Util.FixScrollbarSize(Bar, ScrollingFrame, false) + end +end + +function Scrollbar:StartDrag(Horizontal : boolean?): () + local ScrollingFrame : ScrollingFrame = self.ScrollingFrame + local Axis = Horizontal == true and "X" or "Y" + + if self.Dragging == false then + self.Dragging = true + local LastMousePos = Util.MousePosition(false, false) + + while self.Dragging do + -- update framerate :3 + local deltaTime = task.wait(1 / 30) + + local ThisMousePos = Util.MousePosition(false, false) + + if Axis == "X" then + local scale = (ScrollingFrame.AbsoluteCanvasSize.X / ScrollingFrame.AbsoluteSize.X) + local delta = ThisMousePos.X - LastMousePos.X + + self:Scroll(delta * scale, 0, Horizontal) + LastMousePos = ThisMousePos + else + local scale = (ScrollingFrame.AbsoluteCanvasSize.Y / ScrollingFrame.AbsoluteSize.Y) + local delta = ThisMousePos.Y - LastMousePos.Y + + self:Scroll(delta * scale, 0, Horizontal) + LastMousePos = ThisMousePos + end + end + end +end + +function Scrollbar:EndDrag(): () + if self.Dragging then + self.Dragging = false + end +end + +return Scrollbar \ No newline at end of file diff --git a/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.meta.json b/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/ScrollbarXP/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/init.client.lua b/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/init.client.lua new file mode 100644 index 0000000..b3ba562 --- /dev/null +++ b/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/ToolboxHandler/init.client.lua @@ -0,0 +1,40 @@ +--[[ + Toolbox client code +]] +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local ScrollbarXP = require(script:WaitForChild("ScrollbarXP")) + +local insertProtocol = ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("InsertContent") + +local Scrollbar = ScrollbarXP.new(script.Parent) + +local toolboxMain = script.Parent +local toolboxControls = toolboxMain:WaitForChild("ToolboxControls", nil) +local toolboxItems = toolboxMain:WaitForChild("ToolboxItems", nil) + +local function insertContent(assetId: number): () + print(assetId) + local model: number = insertProtocol:InvokeServer(assetId) +end + +for _: number, v: Instance in ipairs(toolboxItems:GetChildren()) do + if v:IsA("ImageButton") then + v.MouseButton1Click:Connect(function(): () + print("test") + local assetIdValue: Instance? = v:FindFirstChild("AssetID", false) + + if assetIdValue and assetIdValue:IsA("IntValue") then + insertContent(assetIdValue.Value) + end + end) + + v.MouseEnter:Connect(function() + v.Border.Visible = true + end) + + v.MouseLeave:Connect(function() + v.Border.Visible = false + end) + end +end \ No newline at end of file diff --git a/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/init.meta.json b/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/init.meta.json new file mode 100644 index 0000000..95ad713 --- /dev/null +++ b/rojo/MainModule/src/StarterGui/MainGui/ToolboxWindow/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ScrollingFrame", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/StarterGui/MainGui/init.meta.json b/rojo/MainModule/src/StarterGui/MainGui/init.meta.json new file mode 100644 index 0000000..118e2ca --- /dev/null +++ b/rojo/MainModule/src/StarterGui/MainGui/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ScreenGui", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/StarterGui/MainResetGui/MainResetGuiHandler.client.lua b/rojo/MainModule/src/StarterGui/MainResetGui/MainResetGuiHandler.client.lua new file mode 100644 index 0000000..741b6e8 --- /dev/null +++ b/rojo/MainModule/src/StarterGui/MainResetGui/MainResetGuiHandler.client.lua @@ -0,0 +1,616 @@ +--[[ + FWM Official, 2022 + + Main Gui that will reset upon respawn - Roblox_Gamer2030 +]] +local Chat = game:GetService("Chat") +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local RunService = game:GetService("RunService") +local GuiService = game:GetService("GuiService") +local UserInputService = game:GetService("UserInputService") +local TextureGroups = require(ReplicatedStorage:WaitForChild("Modules", nil):WaitForChild("TextureGroups", nil)) +local StockSound = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("StockSound")) +local MouseIcon = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("MouseIcon")) +local Protocols = ReplicatedStorage:WaitForChild("Protocols") + +local MainGui = script.Parent +local Templates = ReplicatedStorage:WaitForChild("Templates") +--local Holder = MainGui:WaitForChild("Holder") +local GameSettings = UserSettings().GameSettings +local LocalPlayer = Players.LocalPlayer +local LocalPlayerGui: PlayerGui = LocalPlayer.PlayerGui +local Mouse = LocalPlayer:GetMouse() +local Solo = ReplicatedStorage:WaitForChild("Solo") +local CurrentTimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value +local canGreenDisc: boolean = false +local isMobile = (UserInputService.TouchEnabled and (not UserInputService.MouseEnabled)) +--local Settings = LocalPlayer:WaitForChild("PlayerDataFolder"):WaitForChild("UserDataFolder"):WaitForChild("SettingsFolder") + +local Character: Model? = LocalPlayer.Character +local Humanoid + +local globalGameProcessed: boolean = false + +local MouseConnectedDisc = Templates.Textures.Adornees.GreenDisc:Clone() +Mouse.TargetFilter = MouseConnectedDisc +MouseConnectedDisc.Adornee = workspace.Terrain +MouseConnectedDisc.Parent = workspace.CurrentCamera + +--local ToolCount = 0 +local Tools = {} + +local GamepadSelection = 1 +local currentDiscMoveTo = nil + +local KeyCodes = { + + [Enum.KeyCode.One] = 1, + [Enum.KeyCode.Two] = 2, + [Enum.KeyCode.Three] = 3, + [Enum.KeyCode.Four] = 4, + [Enum.KeyCode.Five] = 5, + [Enum.KeyCode.Six] = 6, + [Enum.KeyCode.Seven] = 7, + [Enum.KeyCode.Eight] = 8, + [Enum.KeyCode.Nine] = 9, + [Enum.KeyCode.Zero] = 10 + +} + +local YellowHover = Color3.new(1, 1, 0) +local GreenHover = Color3.new(0.14902, 1, 0) +local BlueHover = Color3.new(0, 0, 1) +local White = Color3.new(1, 1, 1) +local DefaultColor = Color3.new(0.701961, 0.701961, 0.701961) + +local function findTexture(baseTexture: string, state: string): string + for i, v in ipairs(TextureGroups) do + if string.lower(v.base) == string.lower(baseTexture) then + return v[state] + end + end + + return baseTexture +end + +local function Healthbar(): () + MainGui:WaitForChild("RedHealthbarFill"):WaitForChild("GreenHealthbarFill").Size = UDim2.new(1, 0, LocalPlayer.Character.Humanoid.Health/LocalPlayer.Character.Humanoid.MaxHealth, 0) +end + +local function DisableOtherBorders(): () + for _, v in pairs(script.Parent.Backpack:GetChildren()) do + if v.ClassName == "TextButton" and tonumber(v.Name) then + v.Border.Visible = false + end + end +end + +local function MakeBorderVisible(frame): () + --if Settings.TimePeriod.Value ~= "2006M" then + frame.Border.Visible = (CurrentTimePeriod > 3) + frame.Border.ClipsDescendants = true + frame.Border.ClipsDescendants = false + --end +end + +local function ToolEquipEvent(tool, frame) + if tool.Parent == LocalPlayer.Character then + LocalPlayer.Character.Humanoid:UnequipTools() + DisableOtherBorders() + else + LocalPlayer.Character.Humanoid:EquipTool(tool) + + if tool:GetAttribute("Command") and tool:GetAttribute("Command") ~= "ScriptHopper" then + StockSound:PlaySoundLocal("Ping") + end + + DisableOtherBorders() + MakeBorderVisible(frame) + end +end + +local function RegisterTool(toolobject) + if not table.find(Tools, toolobject) then + table.insert(Tools, toolobject) + --ToolCount = ToolCount + 1 + + local newCell = Templates.GuiInstances.Backpack:Clone() + newCell.Parent = script.Parent.Backpack + newCell.Name = #Tools + newCell.LayoutOrder = newCell.Name + newCell.Tool.Value = toolobject + + if toolobject.TextureId ~= "" then + newCell.ToolName.Text = toolobject.Name + newCell.ToolImage.Image = toolobject.TextureId + newCell.ToolImage.Visible = true + else + newCell.ToolName.Text = toolobject.Name + newCell.ToolImage.Image = toolobject.TextureId + newCell.ToolName.Visible = true + end + + newCell.ToolNumber.Text = newCell.Name + + local conns = {} + + conns = { + newCell:GetPropertyChangedSignal("Name"):Connect(function(): () + newCell.ToolNumber.Text = newCell.Name + end), + + toolobject:GetPropertyChangedSignal("TextureId"):Connect(function(): () + if toolobject.TextureId ~= "" then + newCell.ToolName.Text = toolobject.Name + newCell.ToolImage.Image = toolobject.TextureId + newCell.ToolImage.Visible = true + newCell.ToolName.Visible = false + else + newCell.ToolName.Text = toolobject.Name + newCell.ToolImage.Image = toolobject.TextureId + newCell.ToolName.Visible = true + newCell.ToolImage.Visible = false + end + end), + + toolobject:GetPropertyChangedSignal("Name"):Connect(function(): () + newCell.ToolName.Text = toolobject.Name + end), + + newCell.InputBegan:Connect(function(input: InputObject): () + if input.UserInputType == Enum.UserInputType.MouseMovement then + if toolobject.TextureId ~= "" then + newCell.HoverThing.BackgroundColor3 = YellowHover + newCell.HoverThing.Visible = true + newCell.ToolImage.Image = findTexture(toolobject.TextureId, "over") + else + newCell.FillIn.BackgroundColor3 = DefaultColor + newCell.FillIn.Visible = true + end + end + end), + + newCell.MouseButton1Down:Connect(function(x: number, y: number): () + if toolobject.TextureId ~= "" then + newCell.HoverThing.BackgroundColor3 = BlueHover + newCell.ToolImage.Image = findTexture(toolobject.TextureId, "down") + else + newCell.FillIn.BackgroundColor3 = YellowHover + end + end), + + newCell.InputEnded:Connect(function(input: InputObject): () + if input.UserInputType == Enum.UserInputType.MouseMovement then + if toolobject.TextureId ~= "" then + newCell.HoverThing.BackgroundColor3 = DefaultColor + newCell.HoverThing.Visible = false + newCell.ToolImage.Image = findTexture(toolobject.TextureId, "base") + else + newCell.FillIn.BackgroundColor3 = DefaultColor + newCell.FillIn.Visible = false + end + end + end), + + newCell.MouseButton1Click:Connect(function(): () + if toolobject.TextureId ~= "" then + newCell.HoverThing.BackgroundColor3 = YellowHover + newCell.ToolImage.Image = findTexture(toolobject.TextureId, "over") + ToolEquipEvent(newCell.Tool.Value, newCell) + else + newCell.FillIn.BackgroundColor3 = DefaultColor + ToolEquipEvent(newCell.Tool.Value, newCell) + end + end), + + newCell.AncestryChanged:Connect(function() + if not newCell.Parent then + for _, connections in pairs(conns) do + connections:Disconnect() + end + end + end), + } + + newCell.Visible = true + + if toolobject.Parent == LocalPlayer.Character then + DisableOtherBorders() + MakeBorderVisible(newCell) + end + end +end + +local function ResortInventory() + for _, v in pairs(script.Parent.Backpack:GetChildren()) do + if v:IsA("TextButton") and tonumber(v.Name) then + local GetTool = v:FindFirstChild("Tool") + + if GetTool then + local FindInTable = table.find(Tools, GetTool.Value) + + if FindInTable then + v.Name = FindInTable + v.LayoutOrder = v.Name + end + end + end + end +end + +local function UnregisterTool(toolobject) + local FindTool = table.find(Tools, toolobject) + + if FindTool then + local FindInBackpack = script.Parent.Backpack:FindFirstChild(FindTool) + + if FindInBackpack then + local GrabbedTool = FindInBackpack:FindFirstChild("Tool") + + if GrabbedTool then + local IsTool = Tools[FindTool] + + if GrabbedTool.Value == IsTool then -- :rice_scene:'s the tool, then resorts backpack + FindInBackpack:Destroy() + table.remove(Tools, FindTool) + + ResortInventory() + end + end + end + end +end + +local function ToolChildAdded(child) + if child:IsA("Tool") then + local Find = table.find(Tools, child) + + if not Find then + RegisterTool(child) + end + end +end + +local function ToolChildRemoved(child) + if child:IsA("Tool") then + if child.Parent ~= LocalPlayer.Character and child.Parent ~= LocalPlayer.Backpack then + UnregisterTool(child) + end + end +end + +local function FrameEquipEvent(num) + local Find = script.Parent.Backpack:FindFirstChild(tostring(num)) + + if Find then + ToolEquipEvent(Find.Tool.Value, Find) + end +end + +local function UserInputEquipItem(key, process) + if not process then + local GetKey = KeyCodes[key.KeyCode] + + if GetKey then + FrameEquipEvent(GetKey) + end + + if key.KeyCode == Enum.KeyCode.Backspace then + DisableOtherBorders() + end + end +end + +local function updateMouseIcon(): () + local HasTool = Character and Character:FindFirstChildOfClass("Tool") or false + local GrabbedGuis = LocalPlayerGui:GetGuiObjectsAtPosition(Mouse.X, Mouse.Y) + + if not MouseConnectedDisc.Visible then + if GrabbedGuis and not HasTool then + MouseIcon.Icon("rbxasset://textures\\ArrowFarCursor.png") + + for _, Objects in pairs(GrabbedGuis) do + if Objects:IsA("GuiButton") then + MouseIcon.Icon("rbxasset://textures\\ArrowCursor.png") + + break + end + end + end + else + MouseIcon.Icon("rbxasset://textures\\ArrowCursor.png") + end +end + +local Icons = { + default = { + Image = "rbxassetid://13610996027"; + ImageColor3 = Color3.new(1, 1, 1); + Size = UDim2.new(0, 17, 0, 25); + Priority = 0; + }; + + button = { + Image = "rbxassetid://13610995901"; + ImageColor3 = Color3.new(1, 1, 1); + Size = UDim2.new(0, 22, 0, 26); + Priority = 1; + }; + + beam = { + Image = "rbxassetid://13611975254"; + ImageColor3 = Color3.new(0, 0, 0); + Size = UDim2.new(0, 7, 0, 16); + Priority = 2; + } +}; + +local mouseStates = { + -- KEY IF SOMEONE MAKES A GUI W/ THESE NAMES + -- THEY WILL DEF GO T F??? + + ["ChatBar"] = Icons.beam; + ["ToolboxItem"] = Icons.button; + ["ToolboxWindow"] = Icons.default; +}; + +local currentMouseFlag; +local function CursorUpdate(input, gameProcessed) + globalGameProcessed = gameProcessed + MainGui.Cursor.Position = UDim2.new(0, Mouse.X, 0, Mouse.Y + 36) + MainGui.WinXPCursor.Position = UDim2.new(0, Mouse.X, 0, Mouse.Y + 36) + + local GetGuiObjects = LocalPlayer.PlayerGui:GetGuiObjectsAtPosition(Mouse.X, Mouse.Y) + + if GetGuiObjects then + local flag; + for _, v in GetGuiObjects do + local state = mouseStates[v.Name]; + if(not state)then + continue; + elseif(state and not flag)then + flag = state; + elseif(state.Priority>flag.Priority)then + flag = state; + end + end + + if(flag and flag~=currentMouseFlag)then + currentMouseFlag = flag; + MainGui.Cursor.Visible = false; + MainGui.WinXPCursor.Visible = true; + + local xpCursor = MainGui.WinXPCursor; + for name, value in flag do + if(name == "Priority")then + continue; + end + + xpCursor[name] = value; + end + elseif(not flag and currentMouseFlag)then + currentMouseFlag = nil; + MainGui.Cursor.Visible = true; + MainGui.WinXPCursor.Visible = false; + end + end + + -- thingy to not have this run twice + if (not canGreenDisc) and CurrentTimePeriod >= 6 then + updateMouseIcon() + end + + --if CurrentTimePeriod >= 6 then + -- local GetTool = Character:FindFirstChildOfClass("Tool") + -- local GrabbedGuis = LocalPlayerGui:GetGuiObjectsAtPosition(Mouse.X, Mouse.Y) + + -- if GrabbedGuis and not GetTool then + -- if not MouseConnectedDisc.Visible then + -- MouseIcon.Icon("rbxasset://textures\\ArrowFarCursor.png") + + -- for _, Objects in pairs(GrabbedGuis) do + -- if Objects:IsA("GuiButton") then + -- MouseIcon.Icon("rbxasset://textures\\ArrowCursor.png") + + -- break + -- end + -- end + -- else + -- MouseIcon.Icon("rbxasset://textures\\ArrowCursor.png") + -- end + -- end + --end +end + +--Hookup: + +---- Debug stuff + +function roundNumber(num, numPlaces) + return math.floor(num*(10^numPlaces))/(10^numPlaces) +end + +--function DebugUpdate() +-- if Character:FindFirstChild("Torso") then +-- --MainGui.Debug.DebugText.Text = "-- FWM Debug --\nSTATE: "..Character.Humanoid:GetState().Name.."\nMAG: "..roundNumber(Character.Torso.AssemblyLinearVelocity.Magnitude, 1).."\nTIME: "..roundNumber(workspace.DistributedGameTime, 1).."\nOBJ: "..#workspace:GetDescendants().."\nVER: "..game.PlaceVersion +-- end +--end + +local function DebugToggle(input, gameProcessed) + if not gameProcessed then + if input.KeyCode == Enum.KeyCode.F2 then + MainGui.Debug.Visible = not MainGui.Debug.Visible + end + end +end + +local function checkIfValid(checkIfdisc: boolean): boolean + local currentCamera = workspace.CurrentCamera + local cameraCFrame = currentCamera.CFrame + + if Character then + local hasTool = (not Character:FindFirstChildOfClass("Tool")) + local hasTorso = Character:FindFirstChild("Torso") + local notFullyTransparent = false + local isNotWalking = Humanoid and (Humanoid.MoveDirection == Vector3.zero) + local isAlive = Humanoid and (Humanoid.Health > 0) + local discVisible = true + + if checkIfdisc then + discVisible = MouseConnectedDisc.Visible + end + + if hasTorso then + local transparencyModifier = hasTorso.LocalTransparencyModifier + + notFullyTransparent = (transparencyModifier < 1) + end + + return (hasTool and notFullyTransparent and isNotWalking and discVisible and isAlive) + else + return false + end +end + +local function onMoveToFinished(): () + if Character then + local moveValueInChar = Character:FindFirstChild("isDiscWalking") + if not moveValueInChar then + return + end + + if not currentDiscMoveTo then + return + end + + moveValueInChar.Value = false + Protocols.DiscWalking:FireServer(false) + + currentDiscMoveTo:Destroy() + currentDiscMoveTo = nil + end +end + +local function greenDiskMain(dt: number): () + local mouseHit = Mouse.Hit.Position + local distanceFromChar = LocalPlayer:DistanceFromCharacter(mouseHit) + local canDo = checkIfValid(false) + + if canDo and distanceFromChar < 40 and not globalGameProcessed then + MouseConnectedDisc.Visible = true + MouseConnectedDisc.CFrame = CFrame.new(mouseHit) * CFrame.Angles(math.pi / 2, 0, 0) + else + MouseConnectedDisc.Visible = false + end + + updateMouseIcon() +end + +local function clickToMoveMainInput(input, gameProcessed): () + globalGameProcessed = gameProcessed + + if (input.UserInputType == Enum.UserInputType.MouseButton1 or input.KeyCode == Enum.KeyCode.ButtonR2) and not globalGameProcessed and Character then + local moveValueInChar = Character:FindFirstChild("isDiscWalking") + + local mouseTarget = Mouse.Target + local isValid = checkIfValid(true) + + if not moveValueInChar then + return + end + + if mouseTarget and isValid then + onMoveToFinished() + + local mouseHit = Mouse.Hit.Position + Humanoid:MoveTo(mouseHit) + + moveValueInChar.Value = true + Protocols.DiscWalking:FireServer(true) + + currentDiscMoveTo = Templates.Textures.Adornees.GreenDisc:Clone() + Mouse.TargetFilter = currentDiscMoveTo + + currentDiscMoveTo.Name = "GreenDisc_Copy" + currentDiscMoveTo.Adornee = workspace.Terrain + currentDiscMoveTo.Visible = true + currentDiscMoveTo.CFrame = CFrame.new(mouseHit) * CFrame.Angles(math.pi / 2, 0, 0) + currentDiscMoveTo.Parent = workspace.CurrentCamera + end + end +end + +--RunService.RenderStepped:Connect(DebugUpdate) +UserInputService.InputBegan:Connect(UserInputEquipItem) + +UserInputService.InputBegan:Connect(function(input, gameProcessed) + if not gameProcessed then + if input.KeyCode == Enum.KeyCode.ButtonL1 then + GamepadSelection -= 1 + GamepadSelection = math.clamp(GamepadSelection, 1, #Tools) + + FrameEquipEvent(GamepadSelection) + elseif input.KeyCode == Enum.KeyCode.ButtonR1 then + GamepadSelection += 1 + GamepadSelection = math.clamp(GamepadSelection, 1, #Tools) + + FrameEquipEvent(GamepadSelection) + end + end +end) + +MainGui.RedHealthbarFill.Visible = not Solo.Value + +CursorUpdate() +UserInputService.InputChanged:Connect(CursorUpdate) + +if Solo.Value or (not Chat:CanUserChatAsync(LocalPlayer.UserId)) then + script.Parent.Backpack.Position = UDim2.new(0, 0, 1, 0) +end + +-- A mobile fix since the mouse icon doesn't update properly on a single tap +if isMobile then + UserInputService.InputBegan:Connect(CursorUpdate) +end + +if not Character then + Character = LocalPlayer.CharacterAdded:Wait() +end + +LocalPlayer:WaitForChild("Backpack").ChildAdded:Connect(ToolChildAdded) +LocalPlayer:WaitForChild("Backpack").ChildRemoved:Connect(ToolChildRemoved) + +for _, v in ipairs(LocalPlayer:WaitForChild("Backpack"):GetChildren()) do + if v:IsA("Tool") then + ToolChildAdded(v) + end +end + +if Character then + Character.ChildAdded:Connect(ToolChildAdded) + Character.ChildRemoved:Connect(ToolChildRemoved) + + for _, v in ipairs(Character:GetChildren()) do + if v:IsA("Tool") then + ToolChildAdded(v) + end + end + + if not Humanoid then + Humanoid = Character:WaitForChild("Humanoid") + end + + if CurrentTimePeriod >= 9 and (not isMobile) and Humanoid then + canGreenDisc = true + + RunService.Heartbeat:Connect(greenDiskMain) + UserInputService.InputBegan:Connect(clickToMoveMainInput) + + Humanoid.MoveToFinished:Connect(onMoveToFinished) + Humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(onMoveToFinished) + Humanoid.Died:Connect(onMoveToFinished) + end + + Humanoid.HealthChanged:Connect(Healthbar) +end \ No newline at end of file diff --git a/rojo/MainModule/src/StarterGui/MainResetGui/init.meta.json b/rojo/MainModule/src/StarterGui/MainResetGui/init.meta.json new file mode 100644 index 0000000..118e2ca --- /dev/null +++ b/rojo/MainModule/src/StarterGui/MainResetGui/init.meta.json @@ -0,0 +1,4 @@ +{ + "className": "ScreenGui", + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/StarterGui/init.meta.json b/rojo/MainModule/src/StarterGui/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/StarterGui/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/StarterPlayerScripts/CameraScript/Invisicam.lua b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/Invisicam.lua new file mode 100644 index 0000000..17eb8a0 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/Invisicam.lua @@ -0,0 +1,584 @@ +--[[ + Invisicam + + Modified 5.16.2017 by AllYourBlox to consider combined transparency when looking through multiple parts, and to add + a mode that takes advantage of the reduced cost of ray casts from re-implementing GetPartsObscuringTarget + on the C++ side to be O(N) for N parts hit, rather than O(N^2), and to have optimizations specifically + improving performance of closely bundled rays. Fading is also removed, since it is a frame rate killer with high-poly models, + and on mobile. + + Based on Invisicam Version 2.5 by OnlyTwentyCharacters +--]] + +local Invisicam = {} +--------------- +-- Constants -- +--------------- +local USE_STACKING_TRANSPARENCY = true -- Multiple items between the subject and camera get transparency values that add up to TARGET_TRANSPARENCY +local TARGET_TRANSPARENCY = 0.75 -- Classic Invisicam's Value, also used by new invisicam for parts hit by head and torso rays +local TARGET_TRANSPARENCY_PERIPHERAL = 0.5 -- Used by new SMART_CIRCLE mode for items not hit by head and torso rays + +local MODE = { + CUSTOM = 1, -- Whatever you want! + LIMBS = 2, -- Track limbs + MOVEMENT = 3, -- Track movement + CORNERS = 4, -- Char model corners + CIRCLE1 = 5, -- Circle of casts around character + CIRCLE2 = 6, -- Circle of casts around character, camera relative + LIMBMOVE = 7, -- LIMBS mode + MOVEMENT mode + SMART_CIRCLE = 8, -- More sample points on and around character + CHAR_OUTLINE = 9, +} + +Invisicam.MODE = MODE +local STARTING_MODE = MODE.SMART_CIRCLE + +local LIMB_TRACKING_SET = { + -- Common to R6, R15 + ['Head'] = true, + + -- R6 Only + ['Left Arm'] = true, + ['Right Arm'] = true, + ['Left Leg'] = true, + ['Right Leg'] = true, + + -- R15 Only + ['LeftLowerArm'] = true, + ['RightLowerArm'] = true, + ['LeftUpperLeg'] = true, + ['RightUpperLeg'] = true +} + +local CORNER_FACTORS = { + Vector3.new(1,1,-1), + Vector3.new(1,-1,-1), + Vector3.new(-1,-1,-1), + Vector3.new(-1,1,-1) +} + +local CIRCLE_CASTS = 10 +local MOVE_CASTS = 3 +local SMART_CIRCLE_CASTS = 24 +local SMART_CIRCLE_INCREMENT = 2.0 * math.pi / SMART_CIRCLE_CASTS +local CHAR_OUTLINE_CASTS = 24 + +--------------- +-- Variables -- +--------------- + +local RunService = game:GetService('RunService') +local PlayersService = game:GetService('Players') +local Player = PlayersService.LocalPlayer + +local Camera = nil +local Character = nil +local HumanoidRootPart = nil +local TorsoPart = nil +local HeadPart = nil + +local Mode = nil +local BehaviorFunction = nil + +local childAddedConn = nil +local childRemovedConn = nil + +local Behaviors = {} -- Map of modes to behavior fns +local SavedHits = {} -- Objects currently being faded in/out +local TrackedLimbs = {} -- Used in limb-tracking casting modes + +--------------- +--| Utility |-- +--------------- + +local math_min = math.min +local math_max = math.max +local math_cos = math.cos +local math_sin = math.sin +local math_pi = math.pi + +local Vector3_new = Vector3.new +local ZERO_VECTOR3 = Vector3_new(0,0,0) + +local function AssertTypes(param, ...) + local allowedTypes = {} + local typeString = '' + for _, typeName in pairs({...}) do + allowedTypes[typeName] = true + typeString = typeString .. (typeString == '' and '' or ' or ') .. typeName + end + local theType = type(param) + assert(allowedTypes[theType], typeString .. " type expected, got: " .. theType) +end + +----------------------- +--| Local Functions |-- +----------------------- + +local function LimbBehavior(castPoints) + for limb, _ in pairs(TrackedLimbs) do + castPoints[#castPoints + 1] = limb.Position + end +end + +local function MoveBehavior(castPoints) + for i = 1, MOVE_CASTS do + local position, velocity = HumanoidRootPart.Position, HumanoidRootPart.Velocity + local horizontalSpeed = Vector3_new(velocity.X, 0, velocity.Z).Magnitude / 2 + local offsetVector = (i - 1) * HumanoidRootPart.CFrame.lookVector * horizontalSpeed + castPoints[#castPoints + 1] = position + offsetVector + end +end + +local function CornerBehavior(castPoints) + local cframe = HumanoidRootPart.CFrame + local centerPoint = cframe.p + local rotation = cframe - centerPoint + local halfSize = Character:GetExtentsSize() / 2 --NOTE: Doesn't update w/ limb animations + castPoints[#castPoints + 1] = centerPoint + for i = 1, #CORNER_FACTORS do + castPoints[#castPoints + 1] = centerPoint + (rotation * (halfSize * CORNER_FACTORS[i])) + end +end + +local function CircleBehavior(castPoints) + local cframe = nil + if Mode == MODE.CIRCLE1 then + cframe = HumanoidRootPart.CFrame + else + local camCFrame = Camera.CoordinateFrame + cframe = camCFrame - camCFrame.p + HumanoidRootPart.Position + end + castPoints[#castPoints + 1] = cframe.p + for i = 0, CIRCLE_CASTS - 1 do + local angle = (2 * math_pi / CIRCLE_CASTS) * i + local offset = 3 * Vector3_new(math_cos(angle), math_sin(angle), 0) + castPoints[#castPoints + 1] = cframe * offset + end +end + +local function LimbMoveBehavior(castPoints) + LimbBehavior(castPoints) + MoveBehavior(castPoints) +end + +local function CharacterOutlineBehavior(castPoints) + local torsoUp = TorsoPart.CFrame.upVector.unit + local torsoRight = TorsoPart.CFrame.rightVector.unit + + -- Torso cross of points for interior coverage + castPoints[#castPoints + 1] = TorsoPart.CFrame.p + castPoints[#castPoints + 1] = TorsoPart.CFrame.p + torsoUp + castPoints[#castPoints + 1] = TorsoPart.CFrame.p - torsoUp + castPoints[#castPoints + 1] = TorsoPart.CFrame.p + torsoRight + castPoints[#castPoints + 1] = TorsoPart.CFrame.p - torsoRight + if HeadPart then + castPoints[#castPoints + 1] = HeadPart.CFrame.p + end + + local cframe = CFrame.new(ZERO_VECTOR3,Vector3_new(Camera.CoordinateFrame.lookVector.X,0,Camera.CoordinateFrame.lookVector.Z)) + local centerPoint = (TorsoPart and TorsoPart.Position or HumanoidRootPart.Position) + + local partsWhitelist = {TorsoPart} + if HeadPart then + partsWhitelist[#partsWhitelist + 1] = HeadPart + end + + for i = 1, CHAR_OUTLINE_CASTS do + local angle = (2 * math_pi * i / CHAR_OUTLINE_CASTS) + local offset = cframe * (3 * Vector3_new(math_cos(angle), math_sin(angle), 0)) + + offset = Vector3_new(offset.X, math_max(offset.Y, -2.25), offset.Z) + + local ray = Ray.new(centerPoint + offset, -3 * offset) + local hit, hitPoint = workspace:FindPartOnRayWithWhitelist(ray, partsWhitelist, false, false) + + if hit then + -- Use hit point as the cast point, but nudge it slightly inside the character so that bumping up against + -- walls is less likely to cause a transparency glitch + castPoints[#castPoints + 1] = hitPoint + 0.2 * (centerPoint - hitPoint).unit + end + end +end + +-- Helper function for Determinant of 3x3 +local function Det3x3(a,b,c,d,e,f,g,h,i) + return (a*(e*i-f*h)-b*(d*i-f*g)+c*(d*h-e*g)) +end + +-- Smart Circle mode needs the intersection of 2 rays that are known to be in the same plane +-- because they are generated from cross products with a common vector. This function is computing +-- that intersection, but it's actually the general solution for the point halfway between where +-- two skew lines come nearest to each other, which is more forgiving. +local function RayIntersection(p0, v0, p1, v1) + local v2 = v0:Cross(v1) + local d1 = p1.x - p0.x + local d2 = p1.y - p0.y + local d3 = p1.z - p0.z + local denom = Det3x3(v0.x,-v1.x,v2.x,v0.y,-v1.y,v2.y,v0.z,-v1.z,v2.z) + + if (denom == 0) then + return ZERO_VECTOR3 -- No solution (rays are parallel) + end + + local t0 = Det3x3(d1,-v1.x,v2.x,d2,-v1.y,v2.y,d3,-v1.z,v2.z) / denom + local t1 = Det3x3(v0.x,d1,v2.x,v0.y,d2,v2.y,v0.z,d3,v2.z) / denom + local s0 = p0 + t0 * v0 + local s1 = p1 + t1 * v1 + local s = s0 + 0.5 * ( s1 - s0 ) + + -- 0.25 studs is a threshold for deciding if the rays are + -- close enough to be considered intersecting, found through testing + if (s1-s0).Magnitude < 0.25 then + return s + else + return ZERO_VECTOR3 + end +end + +local function SmartCircleBehavior(castPoints) + local torsoUp = TorsoPart.CFrame.upVector.unit + local torsoRight = TorsoPart.CFrame.rightVector.unit + + -- SMART_CIRCLE mode includes rays to head and 5 to the torso. + -- Hands, arms, legs and feet are not included since they + -- are not canCollide and can therefore go inside of parts + castPoints[#castPoints + 1] = TorsoPart.CFrame.p + castPoints[#castPoints + 1] = TorsoPart.CFrame.p + torsoUp + castPoints[#castPoints + 1] = TorsoPart.CFrame.p - torsoUp + castPoints[#castPoints + 1] = TorsoPart.CFrame.p + torsoRight + castPoints[#castPoints + 1] = TorsoPart.CFrame.p - torsoRight + if HeadPart then + castPoints[#castPoints + 1] = HeadPart.CFrame.p + end + + local cameraOrientation = Camera.CFrame - Camera.CFrame.p + local torsoPoint = Vector3_new(0,0.5,0) + (TorsoPart and TorsoPart.Position or HumanoidRootPart.Position) + local radius = 2.5 + + -- This loop first calculates points in a circle of radius 2.5 around the torso of the character, in the + -- plane orthogonal to the camera's lookVector. Each point is then raycast to, to determine if it is within + -- the free space surrounding the player (not inside anything). Two iterations are done to adjust points that + -- are inside parts, to try to move them to valid locations that are still on their camera ray, so that the + -- circle remains circular from the camera's perspective, but does not cast rays into walls or parts that are + -- behind, below or beside the character and not really obstructing view of the character. This minimizes + -- the undesirable situation where the character walks up to an exterior wall and it is made invisible even + -- though it is behind the character. + for i = 1, SMART_CIRCLE_CASTS do + local angle = SMART_CIRCLE_INCREMENT * i - 0.5 * math.pi + local offset = radius * Vector3_new(math_cos(angle), math_sin(angle), 0) + local circlePoint = torsoPoint + cameraOrientation * offset + + -- Vector from camera to point on the circle being tested + local vp = circlePoint - Camera.CFrame.p + + local ray = Ray.new(torsoPoint, circlePoint - torsoPoint) + local hit, hp, hitNormal = workspace:FindPartOnRayWithIgnoreList(ray, {Character}, false, false ) + local castPoint = circlePoint + + if hit then + local hprime = hp + 0.1 * hitNormal.unit -- Slightly offset hit point from the hit surface + local v0 = hprime - torsoPoint -- Vector from torso to offset hit point + local d0 = v0.magnitude + + local perp = (v0:Cross(vp)).unit + + -- Vector from the offset hit point, along the hit surface + local v1 = (perp:Cross(hitNormal)).unit + + -- Vector from camera to offset hit + local vprime = (hprime - Camera.CFrame.p).unit + + -- This dot product checks to see if the vector along the hit surface would hit the correct + -- side of the invisicam cone, or if it would cross the camera look vector and hit the wrong side + if ( v0.unit:Dot(-v1) < v0.unit:Dot(vprime)) then + castPoint = RayIntersection(hprime, v1, circlePoint, vp) + + if castPoint.Magnitude > 0 then + local ray = Ray.new(hprime, castPoint - hprime) + local hit, hitPoint, hitNormal = workspace:FindPartOnRayWithIgnoreList(ray, {Character}, false, false ) + + if hit then + local hprime2 = hitPoint + 0.1 * hitNormal.unit + castPoint = hprime2 + end + else + castPoint = hprime + end + else + castPoint = hprime + end + + local ray = Ray.new(torsoPoint, (castPoint - torsoPoint)) + local hit, hitPoint, hitNormal = workspace:FindPartOnRayWithIgnoreList(ray, {Character}, false, false ) + + if hit then + local castPoint2 = hitPoint - 0.1 * (castPoint - torsoPoint).unit + castPoint = castPoint2 + end + end + + castPoints[#castPoints + 1] = castPoint + end +end + +local function CheckTorsoReference() + if Character then + TorsoPart = Character:FindFirstChild("Torso") + if not TorsoPart then + TorsoPart = Character:FindFirstChild("UpperTorso") + if not TorsoPart then + TorsoPart = Character:FindFirstChild("HumanoidRootPart") + end + end + + HeadPart = Character:FindFirstChild("Head") + end +end + +local function OnCharacterAdded(character) + if childAddedConn then + childAddedConn:disconnect() + childAddedConn = nil + end + if childRemovedConn then + childRemovedConn:disconnect() + childRemovedConn = nil + end + + Character = character + + TrackedLimbs = {} + local function childAdded(child) + if child:IsA('BasePart') then + if LIMB_TRACKING_SET[child.Name] then + TrackedLimbs[child] = true + end + + if (child.Name == 'Torso' or child.Name == 'UpperTorso') then + TorsoPart = child + end + + if (child.Name == 'Head') then + HeadPart = child + end + end + end + + local function childRemoved(child) + TrackedLimbs[child] = nil + + -- If removed/replaced part is 'Torso' or 'UpperTorso' double check that we still have a TorsoPart to use + CheckTorsoReference() + end + + childAddedConn = character.ChildAdded:connect(childAdded) + childRemovedConn = character.ChildRemoved:connect(childRemoved) + + for _, child in pairs(Character:GetChildren()) do + childAdded(child) + end +end + +local function OnCurrentCameraChanged() + local newCamera = workspace.CurrentCamera + if newCamera then + Camera = newCamera + end +end + +----------------------- +-- Exposed Functions -- +----------------------- + +-- Update. Called every frame after the camera movement step +function Invisicam:Update() + + -- Bail if there is no Character + if not Character then return end + + -- Make sure we still have a HumanoidRootPart + if not HumanoidRootPart then + local humanoid = Character:FindFirstChildOfClass("Humanoid") + if humanoid and humanoid.Torso then + HumanoidRootPart = humanoid.Torso + else + -- Not set up with Humanoid? Try and see if there's one in the Character at all: + HumanoidRootPart = Character:FindFirstChild("HumanoidRootPart") + if not HumanoidRootPart then + -- Bail out, since we're relying on HumanoidRootPart existing + return + end + end + local ancestryChangedConn; + ancestryChangedConn = HumanoidRootPart.AncestryChanged:connect(function(child, parent) + if child == HumanoidRootPart and not parent then + HumanoidRootPart = nil + if ancestryChangedConn and ancestryChangedConn.Connected then + ancestryChangedConn:Disconnect() + ancestryChangedConn = nil + end + end + end) + end + + if not TorsoPart then + CheckTorsoReference() + if not TorsoPart then + -- Bail out, since we're relying on Torso existing, should never happen since we fall back to using HumanoidRootPart as torso + return + end + end + + -- Make a list of world points to raycast to + local castPoints = {} + BehaviorFunction(castPoints) + + -- Cast to get a list of objects between the camera and the cast points + local currentHits = {} + local ignoreList = {Character} + local function add(hit) + currentHits[hit] = true + if not SavedHits[hit] then + SavedHits[hit] = hit.LocalTransparencyModifier + end + end + + local hitParts + local hitPartCount = 0 + + -- Hash table to treat head-ray-hit parts differently than the rest of the hit parts hit by other rays + -- head/torso ray hit parts will be more transparent than peripheral parts when USE_STACKING_TRANSPARENCY is enabled + local headTorsoRayHitParts = {} + local partIsTouchingCamera = {} + + local perPartTransparencyHeadTorsoHits = TARGET_TRANSPARENCY + local perPartTransparencyOtherHits = TARGET_TRANSPARENCY + + if USE_STACKING_TRANSPARENCY then + + -- This first call uses head and torso rays to find out how many parts are stacked up + -- for the purpose of calculating required per-part transparency + local headPoint = HeadPart and HeadPart.CFrame.p or castPoints[1] + local torsoPoint = TorsoPart and TorsoPart.CFrame.p or castPoints[2] + hitParts = Camera:GetPartsObscuringTarget({headPoint, torsoPoint}, ignoreList) + + -- Count how many things the sample rays passed through, including decals. This should only + -- count decals facing the camera, but GetPartsObscuringTarget does not return surface normals, + -- so my compromise for now is to just let any decal increase the part count by 1. Only one + -- decal per part will be considered. + for i = 1, #hitParts do + local hitPart = hitParts[i] + hitPartCount = hitPartCount + 1 -- count the part itself + headTorsoRayHitParts[hitPart] = true + for _, child in pairs(hitPart:GetChildren()) do + if child:IsA('Decal') or child:IsA('Texture') then + hitPartCount = hitPartCount + 1 -- count first decal hit, then break + break + end + end + end + + if (hitPartCount > 0) then + perPartTransparencyHeadTorsoHits = math.pow( ((0.5 * TARGET_TRANSPARENCY) + (0.5 * TARGET_TRANSPARENCY / hitPartCount)), 1 / hitPartCount ) + perPartTransparencyOtherHits = math.pow( ((0.5 * TARGET_TRANSPARENCY_PERIPHERAL) + (0.5 * TARGET_TRANSPARENCY_PERIPHERAL / hitPartCount)), 1 / hitPartCount ) + end + end + + -- Now get all the parts hit by all the rays + hitParts = Camera:GetPartsObscuringTarget(castPoints, ignoreList) + + local partTargetTransparency = {} + + -- Include decals and textures + for i = 1, #hitParts do + local hitPart = hitParts[i] + + partTargetTransparency[hitPart] =headTorsoRayHitParts[hitPart] and perPartTransparencyHeadTorsoHits or perPartTransparencyOtherHits + + -- If the part is not already as transparent or more transparent than what invisicam requires, add it to the list of + -- parts to be modified by invisicam + if hitPart.Transparency < partTargetTransparency[hitPart] then + add(hitPart) + end + + -- Check all decals and textures on the part + for _, child in pairs(hitPart:GetChildren()) do + if child:IsA('Decal') or child:IsA('Texture') then + if (child.Transparency < partTargetTransparency[hitPart]) then + partTargetTransparency[child] = partTargetTransparency[hitPart] + add(child) + end + end + end + end + + -- Invisibilize objects that are in the way, restore those that aren't anymore + for hitPart, originalLTM in pairs(SavedHits) do + if currentHits[hitPart] then + -- LocalTransparencyModifier gets whatever value is required to print the part's total transparency to equal perPartTransparency + hitPart.LocalTransparencyModifier = (hitPart.Transparency < 1) and ((partTargetTransparency[hitPart] - hitPart.Transparency) / (1.0 - hitPart.Transparency)) or 0 + else -- Restore original pre-invisicam value of LTM + hitPart.LocalTransparencyModifier = originalLTM + SavedHits[hitPart] = nil + end + end +end + +function Invisicam:SetMode(newMode) + AssertTypes(newMode, 'number') + for modeName, modeNum in pairs(MODE) do + if modeNum == newMode then + Mode = newMode + BehaviorFunction = Behaviors[Mode] + return + end + end + error("Invalid mode number") +end + +function Invisicam:SetCustomBehavior(func) + AssertTypes(func, 'function') + Behaviors[MODE.CUSTOM] = func + if Mode == MODE.CUSTOM then + BehaviorFunction = func + end +end + +function Invisicam:GetObscuredParts() + return SavedHits +end + +-- Want to turn off Invisicam? Be sure to call this after. +function Invisicam:Cleanup() + for hit, originalFade in pairs(SavedHits) do + hit.LocalTransparencyModifier = originalFade + end +end + +--------------------- +--| Running Logic |-- +--------------------- + +-- Connect to the current and all future cameras +workspace:GetPropertyChangedSignal("CurrentCamera"):connect(OnCurrentCameraChanged) +OnCurrentCameraChanged() + +Player.CharacterAdded:connect(OnCharacterAdded) +if Player.Character then + OnCharacterAdded(Player.Character) +end + +Behaviors[MODE.CUSTOM] = function() end -- (Does nothing until SetCustomBehavior) +Behaviors[MODE.LIMBS] = LimbBehavior +Behaviors[MODE.MOVEMENT] = MoveBehavior +Behaviors[MODE.CORNERS] = CornerBehavior +Behaviors[MODE.CIRCLE1] = CircleBehavior +Behaviors[MODE.CIRCLE2] = CircleBehavior +Behaviors[MODE.LIMBMOVE] = LimbMoveBehavior +Behaviors[MODE.SMART_CIRCLE] = SmartCircleBehavior +Behaviors[MODE.CHAR_OUTLINE] = CharacterOutlineBehavior + +Invisicam:SetMode(STARTING_MODE) + +return Invisicam diff --git a/rojo/MainModule/src/StarterPlayerScripts/CameraScript/PopperCam.lua b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/PopperCam.lua new file mode 100644 index 0000000..f7c36cc --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/PopperCam.lua @@ -0,0 +1,243 @@ +-- PopperCam Version 16 +-- OnlyTwentyCharacters +local Players = game:GetService("Players") +local GuiRoot = Players.LocalPlayer.PlayerGui:WaitForChild("MainGui") + +local LocalPlayer = Players.LocalPlayer +local PlayerGui = nil + +if LocalPlayer then + PlayerGui = Players.LocalPlayer:WaitForChild("PlayerGui") +end + +local PopperCam = {} -- Guarantees your players won't see outside the bounds of your map! + +----------------- +--| Constants |-- +----------------- + +local POP_RESTORE_RATE = 0.3 +local MIN_CAMERA_ZOOM = 0.5 + +local VALID_SUBJECTS = { + 'Humanoid', + 'VehicleSeat', + 'SkateboardPlatform', +} + +local portraitPopperFixFlagExists, portraitPopperFixFlagEnabled = pcall(function() + return UserSettings():IsUserFeatureEnabled("UserPortraitPopperFix") +end) +local FFlagUserPortraitPopperFix = portraitPopperFixFlagExists and portraitPopperFixFlagEnabled + +----------------- +--| Variables |-- +----------------- + +local PlayersService = game:GetService('Players') + +local Camera = nil +local CameraSubjectChangeConn = nil + +local SubjectPart = nil + +local PlayerCharacters = {} -- For ignoring in raycasts +local VehicleParts = {} -- Also just for ignoring + +local LastPopAmount = 0 +local LastZoomLevel = 0 +local PopperEnabled = false + +local CFrame_new = CFrame.new + +----------------------- +--| Local Functions |-- +----------------------- + +local math_abs = math.abs + +local function OnCameraSubjectChanged() + VehicleParts = {} + + local newSubject = Camera.CameraSubject + if newSubject then + -- Determine if we should be popping at all + PopperEnabled = false + for _, subjectType in pairs(VALID_SUBJECTS) do + if newSubject:IsA(subjectType) then + PopperEnabled = true + break + end + end + + -- Get all parts of the vehicle the player is controlling + if newSubject:IsA('VehicleSeat') then + VehicleParts = newSubject:GetConnectedParts(true) + end + + --if FFlagUserPortraitPopperFix then + if newSubject:IsA("BasePart") then + SubjectPart = newSubject + elseif newSubject:IsA("Model") then + SubjectPart = newSubject.PrimaryPart + elseif newSubject:IsA("Humanoid") then + --SubjectPart = newSubject.Torso + SubjectPart = newSubject.Parent:FindFirstChild("Head") or newSubject.Torso + end + --end + end +end + +local function OnCharacterAdded(player, character) + PlayerCharacters[player] = character +end + +local function OnPlayersChildAdded(child) + if child:IsA('Player') then + child.CharacterAdded:connect(function(character) + OnCharacterAdded(child, character) + end) + if child.Character then + OnCharacterAdded(child, child.Character) + end + end +end + +local function OnPlayersChildRemoved(child) + if child:IsA('Player') then + PlayerCharacters[child] = nil + end +end + + local function OnWorkspaceChanged(property) + if property == 'CurrentCamera' then + local newCamera = workspace.CurrentCamera + if newCamera then + Camera = newCamera + + if CameraSubjectChangeConn then + CameraSubjectChangeConn:disconnect() + end + + CameraSubjectChangeConn = Camera:GetPropertyChangedSignal("CameraSubject"):connect(OnCameraSubjectChanged) + OnCameraSubjectChanged() + end + end +end + +------------------------- +--| Exposed Functions |-- +------------------------- + +function PopperCam:Update(EnabledCamera) + if PopperEnabled then + -- First, prep some intermediate vars + local cameraCFrame = Camera.CFrame + local cameraSubject = Camera.CameraSubject + local focusPoint = Camera.Focus.p + local subjectObject = nil + + --if FFlagUserPortraitPopperFix and SubjectPart then + if SubjectPart then + subjectObject = SubjectPart + focusPoint = SubjectPart.CFrame.p + end + + local ignoreList = {} + for _, character in pairs(PlayerCharacters) do + ignoreList[#ignoreList + 1] = character + end + for i = 1, #VehicleParts do + ignoreList[#ignoreList + 1] = VehicleParts[i] + end + + -- Get largest cutoff distance + local largest = Camera:GetLargestCutoffDistance(ignoreList) + + -- Then check if the player zoomed since the last frame, + -- and if so, reset our pop history so we stop tweening + local zoomLevel = (cameraCFrame.p - focusPoint).Magnitude + if math_abs(zoomLevel - LastZoomLevel) > 0.001 then + LastPopAmount = 0 + end + + -- Finally, zoom the camera in (pop) by that most-cut-off amount, or the last pop amount if that's more + local popAmount = largest + if LastPopAmount > popAmount then + popAmount = LastPopAmount + end + + if popAmount > 0 then + Camera.CFrame = cameraCFrame + (cameraCFrame.lookVector * popAmount) + LastPopAmount = popAmount - POP_RESTORE_RATE -- Shrink it for the next frame + if LastPopAmount < 0 then + LastPopAmount = 0 + end + end + + LastZoomLevel = zoomLevel + + if subjectObject then + local realZoomLevel = (subjectObject.CFrame.Position - Camera.CFrame.Position).Magnitude + + GuiRoot.CameraControl.ZoomedIn.Visible = (realZoomLevel <= LocalPlayer.CameraMinZoomDistance + 0.05) + GuiRoot.CameraControl.ZoomedOut.Visible = (realZoomLevel == LocalPlayer.CameraMaxZoomDistance) + end + + if Players.LocalPlayer.Character:FindFirstChild("Head") then --this code is always crap + --lol bruh moving transparency code here loooool: + local transparency = 0 + local TextureTransparency = 0.2 + + local distance = (Players.LocalPlayer.Character.Head.Position - Camera.CFrame.Position).magnitude + + if distance <= 5 then + transparency = 0.5 + TextureTransparency = 0.7 + end + + if distance <= 2.5 then --make this better later + transparency = 1 + TextureTransparency = 1 + end + + for i,v in pairs(Players.LocalPlayer.Character:GetChildren()) do + if v:IsA("BasePart") and v.Parent.Name == Players.LocalPlayer.Name then + v.LocalTransparencyModifier = transparency -- you absolute goofball + end + end + + --Players.LocalPlayer.Character.Head.HeadMesh.Transparency = transparency + elseif not Players.LocalPlayer.Character:FindFirstChild("Head") and not Players.LocalPlayer.Character:FindFirstChild("Torso") then + workspace.CurrentCamera.CameraSubject = workspace.Camera:FindFirstChild("LensFlareNode") + end + + -- Stop shift lock being able to see through walls by manipulating Camera focus inside the wall + if EnabledCamera and EnabledCamera:GetShiftLock() and not EnabledCamera:IsInFirstPerson() then + if EnabledCamera:GetCameraActualZoom() < 1 then + local subjectPosition = EnabledCamera.lastSubjectPosition + if subjectPosition then + Camera.Focus = CFrame_new(subjectPosition) + Camera.CFrame = CFrame_new(subjectPosition - MIN_CAMERA_ZOOM*EnabledCamera:GetCameraLook(), subjectPosition) + end + end + end + end +end + +-------------------- +--| Script Logic |-- +-------------------- + +-- Connect to the current and all future cameras +workspace.Changed:connect(OnWorkspaceChanged) +OnWorkspaceChanged('CurrentCamera') + +-- Connect to all Players so we can ignore their Characters +PlayersService.ChildRemoved:connect(OnPlayersChildRemoved) +PlayersService.ChildAdded:connect(OnPlayersChildAdded) +for _, player in pairs(PlayersService:GetPlayers()) do + OnPlayersChildAdded(player) +end + +return PopperCam diff --git a/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/AttachCamera.lua b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/AttachCamera.lua new file mode 100644 index 0000000..f88837e --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/AttachCamera.lua @@ -0,0 +1,75 @@ +local PlayersService = game:GetService('Players') +local RootCameraCreator = require(script.Parent) + +local ZERO_VECTOR2 = Vector2.new(0, 0) +local XZ_VECTOR = Vector3.new(1,0,1) + +local Vector2_new = Vector2.new +local CFrame_new = CFrame.new +local math_atan2 = math.atan2 +local math_min = math.min + +local function IsFinite(num) + return num == num and num ~= 1/0 and num ~= -1/0 +end + +-- May return NaN or inf or -inf +-- This is a way of finding the angle between the two vectors: +local function findAngleBetweenXZVectors(vec2, vec1) + return math_atan2(vec1.X*vec2.Z-vec1.Z*vec2.X, vec1.X*vec2.X + vec1.Z*vec2.Z) +end + +local function CreateAttachCamera() + local module = RootCameraCreator() + + local lastUpdate = tick() + function module:Update() + local now = tick() + + local camera = workspace.CurrentCamera + + if lastUpdate == nil or now - lastUpdate > 1 then + module:ResetCameraLook() + self.LastCameraTransform = nil + end + + local subjectPosition = self:GetSubjectPosition() + if subjectPosition and camera then + local zoom = self:GetCameraZoom() + if zoom <= 0 then + zoom = 0.1 + end + + + local humanoid = self:GetHumanoid() + if lastUpdate and humanoid and humanoid.Torso then + + -- Cap out the delta to 0.1 so we don't get some crazy things when we re-resume from + local delta = math_min(0.1, now - lastUpdate) + local gamepadRotation = self:UpdateGamepad() + self.RotateInput = self.RotateInput + (gamepadRotation * delta) + + local forwardVector = humanoid.Torso.CFrame.lookVector + + local y = findAngleBetweenXZVectors(forwardVector, self:GetCameraLook()) + if IsFinite(y) then + -- Preserve vertical rotation from user input + self.RotateInput = Vector2_new(y, self.RotateInput.Y) + end + end + + local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput) + self.RotateInput = ZERO_VECTOR2 + + camera.Focus = CFrame_new(subjectPosition) + local newCFrame = CFrame_new(subjectPosition - (zoom * newLookVector), subjectPosition) + camera.CFrame = newCFrame + self.LastCameraTransform = newCFrame + end + lastUpdate = now + end + + return module +end + +return CreateAttachCamera diff --git a/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/ClassicCamera.lua b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/ClassicCamera.lua new file mode 100644 index 0000000..5a54d96 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/ClassicCamera.lua @@ -0,0 +1,261 @@ + +local Players = game:GetService('Players') +local VRService = game:GetService("VRService") + +local RootCameraCreator = require(script.Parent) + +local UP_VECTOR = Vector3.new(0, 1, 0) +local XZ_VECTOR = Vector3.new(1, 0, 1) +local ZERO_VECTOR2 = Vector2.new(0, 0) + +local VR_PITCH_FRACTION = 0.25 + +local Vector3_new = Vector3.new +local CFrame_new = CFrame.new +local math_min = math.min +local math_max = math.max +local math_atan2 = math.atan2 +local math_rad = math.rad +local math_abs = math.abs + +local function clamp(low, high, num) + return (num > high and high or num < low and low or num) +end + +local function IsFinite(num) + return num == num and num ~= 1/0 and num ~= -1/0 +end + +local function IsFiniteVector3(vec3) + return IsFinite(vec3.x) and IsFinite(vec3.y) and IsFinite(vec3.z) +end + +-- May return NaN or inf or -inf +-- This is a way of finding the angle between the two vectors: +local function findAngleBetweenXZVectors(vec2, vec1) + return math_atan2(vec1.X*vec2.Z-vec1.Z*vec2.X, vec1.X*vec2.X + vec1.Z*vec2.Z) +end + +local function CreateClassicCamera() + local module = RootCameraCreator() + + local tweenAcceleration = math_rad(220) + local tweenSpeed = math_rad(0) + local tweenMaxSpeed = math_rad(250) + local timeBeforeAutoRotate = 2 + + local lastUpdate = tick() + module.LastUserPanCamera = tick() + + local lastZoom = 0 + function module:Update() + module:ProcessTweens() + local now = tick() + local timeDelta = (now - lastUpdate) + + local userPanningTheCamera = (self.UserPanningTheCamera == true) + local camera = workspace.CurrentCamera + local player = Players.LocalPlayer + local humanoid = self:GetHumanoid() + local cameraSubject = camera and camera.CameraSubject + local isInVehicle = cameraSubject and cameraSubject:IsA('VehicleSeat') + local isOnASkateboard = cameraSubject and cameraSubject:IsA('SkateboardPlatform') + + if lastUpdate == nil or now - lastUpdate > 1 then + module:ResetCameraLook() + self.LastCameraTransform = nil + end + + if lastUpdate then + local gamepadRotation = self:UpdateGamepad() + + if self:ShouldUseVRRotation() then + self.RotateInput = self.RotateInput + self:GetVRRotationInput() + else + -- Cap out the delta to 0.1 so we don't get some crazy things when we re-resume from + local delta = math_min(0.1, now - lastUpdate) + + if gamepadRotation ~= ZERO_VECTOR2 then + userPanningTheCamera = true + self.RotateInput = self.RotateInput + (gamepadRotation * delta) + end + + local angle = 0 + if not (isInVehicle or isOnASkateboard) then + angle = angle + (self.TurningLeft and -120 or 0) + angle = angle + (self.TurningRight and 120 or 0) + end + + if angle ~= 0 then + self.RotateInput = self.RotateInput + Vector2.new(math_rad(angle * delta), 0) + userPanningTheCamera = true + end + end + end + + -- Reset tween speed if user is panning + if userPanningTheCamera then + tweenSpeed = 0 + module.LastUserPanCamera = tick() + end + + local userRecentlyPannedCamera = now - module.LastUserPanCamera < timeBeforeAutoRotate + local subjectPosition = self:GetSubjectPosition() + + if subjectPosition and player and camera then + local zoom = self:GetCameraZoom() + if zoom < 0.5 then + zoom = 0.5 + end + + if self:GetShiftLock() and not self:IsInFirstPerson() then + -- We need to use the right vector of the camera after rotation, not before + local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput) + local offset = ((newLookVector * XZ_VECTOR):Cross(UP_VECTOR).unit * 1.75) + + if IsFiniteVector3(offset) then + subjectPosition = subjectPosition + offset + end + else + if not userPanningTheCamera and self.LastCameraTransform then + local isInFirstPerson = self:IsInFirstPerson() + if (isInVehicle or isOnASkateboard) and lastUpdate and humanoid and humanoid.Torso then + if isInFirstPerson then + if self.LastSubjectCFrame and (isInVehicle or isOnASkateboard) and cameraSubject:IsA('BasePart') then + local y = -findAngleBetweenXZVectors(self.LastSubjectCFrame.lookVector, cameraSubject.CFrame.lookVector) + if IsFinite(y) then + self.RotateInput = self.RotateInput + Vector2.new(y, 0) + end + tweenSpeed = 0 + end + elseif not userRecentlyPannedCamera then + local forwardVector = humanoid.Torso.CFrame.lookVector + if isOnASkateboard then + forwardVector = cameraSubject.CFrame.lookVector + end + + tweenSpeed = clamp(0, tweenMaxSpeed, tweenSpeed + tweenAcceleration * timeDelta) + + local percent = clamp(0, 1, tweenSpeed * timeDelta) + if self:IsInFirstPerson() then + percent = 1 + end + + local y = findAngleBetweenXZVectors(forwardVector, self:GetCameraLook()) + if IsFinite(y) and math_abs(y) > 0.0001 then + self.RotateInput = self.RotateInput + Vector2.new(y * percent, 0) + end + elseif not (isInFirstPerson or userRecentlyPannedCamera) and not VRService.VREnabled then + local lastVec = -(self.LastCameraTransform.p - subjectPosition) + + local y = findAngleBetweenXZVectors(lastVec, self:GetCameraLook()) + + -- This cutoff is to decide if the humanoid's angle of movement, + -- relative to the camera's look vector, is enough that + -- we want the camera to be following them. The point is to provide + -- a sizable deadzone to allow more precise forward movements. + local thetaCutoff = 0.4 + + -- Check for NaNs + if IsFinite(y) and math.abs(y) > 0.0001 and math_abs(y) > thetaCutoff*timeDelta then + self.RotateInput = self.RotateInput + Vector2.new(y, 0) + end + end + end + end + end + + local VREnabled = VRService.VREnabled + camera.Focus = VREnabled and self:GetVRFocus(subjectPosition, timeDelta) or CFrame_new(subjectPosition) + + local cameraFocusP = camera.Focus.p + if VREnabled and not self:IsInFirstPerson() then + local cameraHeight = self:GetCameraHeight() + local vecToSubject = (subjectPosition - camera.CFrame.p) + local distToSubject = vecToSubject.magnitude + + -- Only move the camera if it exceeded a maximum distance to the subject in VR + if distToSubject > zoom or self.RotateInput.x ~= 0 then + local desiredDist = math_min(distToSubject, zoom) + vecToSubject = self:RotateCamera(vecToSubject.unit * XZ_VECTOR, Vector2.new(self.RotateInput.x, 0)) * desiredDist + local newPos = cameraFocusP - vecToSubject + local desiredLookDir = camera.CFrame.lookVector + if self.RotateInput.x ~= 0 then + desiredLookDir = vecToSubject + end + local lookAt = Vector3.new(newPos.x + desiredLookDir.x, newPos.y, newPos.z + desiredLookDir.z) + self.RotateInput = ZERO_VECTOR2 + + local lastVec = -(self.LastCameraTransform.p - subjectPosition) + end + else + local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput) + + if lastZoom ~= zoom then + lastZoom = zoom + + newLookVector = (newLookVector * XZ_VECTOR).unit + + local upY = -math.min(6,zoom * .025) + newLookVector = (newLookVector + (UP_VECTOR * upY)).unit + end + + --follower camera(?): + + + self.RotateInput = ZERO_VECTOR2 + + if VRService.VREnabled then + camera.Focus = self:GetVRFocus(subjectPosition, timeDelta) + else + camera.Focus = CFrame_new(subjectPosition) + end + + print(timeDelta) + + camera.CFrame = camera.CFrame:lerp(CFrame_new(cameraFocusP - (zoom * newLookVector), cameraFocusP), 1 - 0.9 ^ timeDelta) + + --transparency stuff: + local CameraCFrame = CFrame_new(cameraFocusP - (zoom * newLookVector), cameraFocusP) + + local transparency = 0 + local TextureTransparency = 0.5 + --local distance = (Players.LocalPlayer.Character.Head.Position - CameraCFrame.Position).magnitude + --local distance = (Players.LocalPlayer.Character.Head.Position - workspace.Camera.CFrame.Position).magnitude + local distance = zoom + + if distance <= 5 then + transparency = 0.5 + TextureTransparency = 0.75 + end + + if distance <= 2.5 then --make this better later + transparency = 1 + TextureTransparency = 1 + end + + for i,v in pairs(Players.LocalPlayer.Character:GetDescendants()) do + if v:IsA("BasePart") then + v.Transparency = transparency + elseif v:IsA("Texture") then + v.Transparency = TextureTransparency + end + end + end + + self.LastCameraTransform = camera.CFrame + self.LastCameraFocus = camera.Focus + if (isInVehicle or isOnASkateboard) and cameraSubject:IsA('BasePart') then + self.LastSubjectCFrame = cameraSubject.CFrame + else + self.LastSubjectCFrame = nil + end + end + + lastUpdate = now + end + + return module +end + +return CreateClassicCamera diff --git a/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/FixedCamera.lua b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/FixedCamera.lua new file mode 100644 index 0000000..17711d9 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/FixedCamera.lua @@ -0,0 +1,48 @@ +local PlayersService = game:GetService('Players') +local RootCameraCreator = require(script.Parent) + +local ZERO_VECTOR2 = Vector2.new(0, 0) + +local CFrame_new = CFrame.new +local math_min = math.min + +local function CreateFixedCamera() + local module = RootCameraCreator() + + local lastUpdate = tick() + function module:Update() + local now = tick() + + local camera = workspace.CurrentCamera + local player = PlayersService.LocalPlayer + if lastUpdate == nil or now - lastUpdate > 1 then + module:ResetCameraLook() + self.LastCameraTransform = nil + end + + if lastUpdate then + -- Cap out the delta to 0.1 so we don't get some crazy things when we re-resume from + local delta = math_min(0.1, now - lastUpdate) + local gamepadRotation = self:UpdateGamepad() + self.RotateInput = self.RotateInput + (gamepadRotation * delta) + end + + local subjectPosition = self:GetSubjectPosition() + if subjectPosition and player and camera then + local zoom = self:GetCameraZoom() + if zoom <= 0 then + zoom = 0.1 + end + local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput) + self.RotateInput = ZERO_VECTOR2 + + camera.CFrame = CFrame_new(camera.CFrame.p, camera.CFrame.p + (zoom * newLookVector)) + self.LastCameraTransform = camera.CFrame + end + lastUpdate = now + end + + return module +end + +return CreateFixedCamera diff --git a/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/FollowCamera.lua b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/FollowCamera.lua new file mode 100644 index 0000000..422e14d --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/FollowCamera.lua @@ -0,0 +1,230 @@ +local PlayersService = game:GetService('Players') +local VRService = game:GetService("VRService") + +local RootCameraCreator = require(script.Parent) + +local CFrame_new = CFrame.new +local Vector2_new = Vector2.new +local Vector3_new = Vector3.new +local math_min = math.min +local math_max = math.max +local math_atan2 = math.atan2 +local math_rad = math.rad +local math_abs = math.abs + +local HUMANOIDSTATE_CLIMBING = Enum.HumanoidStateType.Climbing +local ZERO_VECTOR2 = Vector2.new(0, 0) +local UP_VECTOR = Vector3.new(0, 1, 0) +local XZ_VECTOR = Vector3.new(1, 0, 1) +local ZERO_VECTOR3 = Vector3.new(0, 0, 0) +local PORTRAIT_OFFSET = Vector3.new(0, -3, 0) + +local GetLerp = game:GetService("ReplicatedStorage"):WaitForChild("Protocols"):WaitForChild("GetSetting"):InvokeServer("CameraLerp") +local CameraLerp = GetLerp or .9 + +--very good place to put your code -key +--Players.LocalPlayer.PlayerScripts.ChildAdded:Connect(function(child) +-- if child.Name == "FPSCap" then +-- CameraLerp = 0.9 +-- end +--end) + +--Players.LocalPlayer.PlayerScripts.ChildRemoved:Connect(function(child) +-- if child.Name == "FPSCap" then +-- CameraLerp = 0.85 +-- end +--end) + + +local function clamp(low, high, num) + return num > high and high or num < low and low or num +end + +local function IsFinite(num) + return num == num and num ~= 1/0 and num ~= -1/0 +end + +local function IsFiniteVector3(vec3) + return IsFinite(vec3.x) and IsFinite(vec3.y) and IsFinite(vec3.z) +end + +-- May return NaN or inf or -inf +local function findAngleBetweenXZVectors(vec2, vec1) + -- This is a way of finding the angle between the two vectors: + return math_atan2(vec1.X*vec2.Z-vec1.Z*vec2.X, vec1.X*vec2.X + vec1.Z*vec2.Z) +end + +local function CreateFollowCamera() + local module = RootCameraCreator() + + local tweenAcceleration = math_rad(220) + local tweenSpeed = math_rad(0) + local tweenMaxSpeed = math_rad(250) + local timeBeforeAutoRotate = 0 + + local lastUpdate = tick() + module.LastUserPanCamera = tick() + module.Offset = Vector3.zero + module.LastCameraTransform = CFrame.identity; + local lastZoom = 0 + + + function module:Update() + module:ProcessTweens() + local now = tick() + local timeDelta = (now - lastUpdate) + + local userPanningTheCamera = (self.UserPanningTheCamera == true) + local camera = workspace.CurrentCamera + local player = PlayersService.LocalPlayer + local humanoid = self:GetHumanoid() + local cameraSubject = camera and camera.CameraSubject + local isClimbing = humanoid and humanoid:GetState() == HUMANOIDSTATE_CLIMBING + local isInVehicle = cameraSubject and cameraSubject:IsA('VehicleSeat') + local isOnASkateboard = cameraSubject and cameraSubject:IsA('SkateboardPlatform') + + if lastUpdate == nil or now - lastUpdate > 1 then + module:ResetCameraLook() + --self.LastCameraTransform = nil + end + + if lastUpdate then + + if self:ShouldUseVRRotation() then + self.RotateInput = self.RotateInput + self:GetVRRotationInput() + else + -- Cap out the delta to 0.1 so we don't get some crazy things when we re-resume from + local delta = math_min(0.1, now - lastUpdate) + local angle = 0 + -- NOTE: Traditional follow camera does not rotate with arrow keys + if not (isInVehicle or isOnASkateboard) then + angle = angle + (-120 or 0) + angle = angle + (120 or 0) + end + + local gamepadRotation = self:UpdateGamepad() + if gamepadRotation ~= Vector2.new(0,0) then + userPanningTheCamera = true + self.RotateInput = self.RotateInput + (gamepadRotation * delta) + end + + if angle ~= 0 then + userPanningTheCamera = true + self.RotateInput = self.RotateInput + Vector2_new(math_rad(angle * delta), 0) + end + end + end + + -- Reset tween speed if user is panning (not anymore!) + if userPanningTheCamera then + tweenSpeed = 0 + module.LastUserPanCamera = tick() + end + + local userRecentlyPannedCamera = now - module.LastUserPanCamera < timeBeforeAutoRotate + + local look = CFrame.lookAt(Vector3.zero, self:GetCameraLook()); + local subjectPosition = self:GetSubjectPosition(); + if subjectPosition and player and camera then + local zoom = self:GetCameraZoom() + if zoom < 0.5 then + zoom = 0.5 + end + + if self:GetShiftLock() and not self:IsInFirstPerson() then + local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput) + local offset = ((newLookVector * XZ_VECTOR):Cross(UP_VECTOR).unit * 1.75) + if IsFiniteVector3(offset) then + subjectPosition = subjectPosition + offset + end + else + if self.LastCameraTransform then --and not userPanningTheCamera + local isInFirstPerson = self:IsInFirstPerson() + if (isClimbing or isInVehicle or isOnASkateboard) and lastUpdate and humanoid and humanoid.Torso then + if isInFirstPerson then + if self.LastSubjectCFrame and (isInVehicle or isOnASkateboard) and cameraSubject:IsA('BasePart') then + local y = -findAngleBetweenXZVectors(self.LastSubjectCFrame.lookVector, cameraSubject.CFrame.lookVector) + if IsFinite(y) then + self.RotateInput = self.RotateInput + Vector2.new(y, 0) + end + tweenSpeed = 0 + end + elseif not userRecentlyPannedCamera then + local forwardVector = humanoid.Torso.CFrame.lookVector + if isOnASkateboard then + forwardVector = cameraSubject.CFrame.lookVector + end + + tweenSpeed = clamp(0, tweenMaxSpeed, tweenSpeed + tweenAcceleration * timeDelta) + + local percent = clamp(0, 1, tweenSpeed*timeDelta) + if not isClimbing and self:IsInFirstPerson() then + percent = 1 + end + local y = findAngleBetweenXZVectors(forwardVector, self:GetCameraLook()) + -- Check for NaN + if IsFinite(y) and math_abs(y) > 0.0001 then + self.RotateInput = self.RotateInput + Vector2.new(y * percent, 0) + end + end + elseif not (isInFirstPerson) and not VRService.VREnabled then + local lastVec = -(self.LastCameraTransform.p - subjectPosition) + + local y = findAngleBetweenXZVectors(lastVec, self:GetCameraLook()) + + -- This cutoff is to decide if the humanoid's angle of movement, + -- relative to the camera's look vector, is enough that + -- we want the camera to be following them. The point is to provide + -- a sizable deadzone to allow more precise forward movements. + local thetaCutoff = 0.4 + + -- Check for NaNs + if IsFinite(y) and math.abs(y) > 0.0001 and math_abs(y) > thetaCutoff*timeDelta then + self.RotateInput = self.RotateInput + Vector2.new(y, 0) + end + end + end + end + + local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput) + self.RotateInput = ZERO_VECTOR2 + + if lastZoom ~= zoom then + lastZoom = zoom + newLookVector = (newLookVector * XZ_VECTOR).unit + + local upY = -math.min(6, zoom * .025) + newLookVector = (newLookVector + (UP_VECTOR * upY)).unit + end + + if VRService.VREnabled then + camera.Focus = self:GetVRFocus(subjectPosition, timeDelta) + elseif self:IsPortraitMode() then + camera.Focus = CFrame_new(subjectPosition + PORTRAIT_OFFSET) + else + camera.Focus = CFrame_new(subjectPosition) + end + + local CameraCFrame = (self.LastCameraTransform or CFrame.identity):lerp( + CFrame_new(camera.Focus.p - (zoom * newLookVector), camera.Focus.p), + CameraLerp + ); + + camera.CFrame = CameraCFrame; + + self.LastCameraTransform = CameraCFrame + self.LastCameraFocus = camera.Focus + if isInVehicle or isOnASkateboard and cameraSubject:IsA('BasePart') then + self.LastSubjectCFrame = cameraSubject.CFrame + else + self.LastSubjectCFrame = nil + end + end + + lastUpdate = now + end + + return module +end + +return CreateFollowCamera diff --git a/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/OrbitalCamera.lua b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/OrbitalCamera.lua new file mode 100644 index 0000000..1ff6313 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/OrbitalCamera.lua @@ -0,0 +1,450 @@ +--[[ + Orbital Camera 1.0.0 + AllYourBlox + + Derived from ClassicCamera, adds camera angle constraints, and represents position values in spherical + coordinates (azimuth, elevation, radius), instead of Cartesian coordinates (x, y, z). Azimuth is the + angle of rotation about the Y axis, with the zero-angle reference point corresponding to offsetting + the camera in the +Z direction, from where it will be looking in the -Z direction by default. Elevation + is the angle up from the XZ plane, where zero degrees is on the plane, and +90 degrees is on the +Y + axis. Distance is the camera-to-subject distance, the spherical coordinates radius, specified in studs. +--]] + +-- Do not edit these values, they are not the developer-set limits, they are limits +-- to the values the camera system equations can correctly handle +local MIN_ALLOWED_ELEVATION_DEG = -80 +local MAX_ALLOWED_ELEVATION_DEG = 80 + +local externalProperties = {} +externalProperties["InitialDistance"] = 25 +externalProperties["MinDistance"] = 10 +externalProperties["MaxDistance"] = 100 +externalProperties["InitialElevation"] = 35 +externalProperties["MinElevation"] = 35 +externalProperties["MaxElevation"] = 35 +externalProperties["ReferenceAzimuth"] = -45 -- Angle around the Y axis where the camera starts. -45 offsets the camera in the -X and +Z directions equally +externalProperties["CWAzimuthTravel"] = 90 -- How many degrees the camera is allowed to rotate from the reference position, CW as seen from above +externalProperties["CCWAzimuthTravel"] = 90 -- How many degrees the camera is allowed to rotate from the reference position, CCW as seen from above +externalProperties["UseAzimuthLimits"] = false -- Full rotation around Y axis available by default + +local refAzimuthRad +local curAzimuthRad +local minAzimuthAbsoluteRad +local maxAzimuthAbsoluteRad +local useAzimuthLimits +local curElevationRad +local minElevationRad +local maxElevationRad +local curDistance +local minDistance +local maxDistance + +local UNIT_Z = Vector3.new(0,0,1) +local TAU = 2 * math.pi + +local changedSignalConnections = {} + +-- End of OrbitalCamera additions +local PlayersService = game:GetService('Players') +local VRService = game:GetService("VRService") + +local RootCameraCreator = require(script.Parent) + +local UP_VECTOR = Vector3.new(0, 1, 0) +local XZ_VECTOR = Vector3.new(1, 0, 1) +local ZERO_VECTOR2 = Vector2.new(0, 0) + +local VR_PITCH_FRACTION = 0.25 + +local Vector3_new = Vector3.new +local CFrame_new = CFrame.new +local math_min = math.min +local math_max = math.max +local math_atan2 = math.atan2 +local math_rad = math.rad +local math_abs = math.abs + +--[[ Gamepad Support ]]-- +local THUMBSTICK_DEADZONE = 0.2 +local r3ButtonDown = false +local l3ButtonDown = false +local currentZoomSpeed = 1 -- Multiplier, so 1 == no zooming + +local function clamp(value, minValue, maxValue) + if maxValue < minValue then + maxValue = minValue + end + return math.clamp(value, minValue, maxValue) +end + +local function IsFinite(num) + return num == num and num ~= 1/0 and num ~= -1/0 +end + +local function IsFiniteVector3(vec3) + return IsFinite(vec3.x) and IsFinite(vec3.y) and IsFinite(vec3.z) +end + +-- May return NaN or inf or -inf +-- This is a way of finding the angle between the two vectors: +local function findAngleBetweenXZVectors(vec2, vec1) + return math_atan2(vec1.X*vec2.Z-vec1.Z*vec2.X, vec1.X*vec2.X + vec1.Z*vec2.Z) +end + +local function GetValueObject(name, defaultValue) + local valueObj = script:FindFirstChild(name) + if valueObj then + return valueObj.Value + end + return defaultValue +end + +local function LoadOrCreateNumberValueParameter(name, valueType, updateFunction) + local valueObj = script:FindFirstChild(name) + + if valueObj and valueObj:isA(valueType) then + -- Value object exists and is the correct type, use its value + externalProperties[name] = valueObj.Value + elseif externalProperties[name] ~= nil then + -- Create missing (or replace incorrectly-typed) valueObject with default value + valueObj = Instance.new(valueType) + valueObj.Name = name + valueObj.Parent = script + valueObj.Value = externalProperties[name] + else + print("externalProperties table has no entry for ",name) + return + end + + if updateFunction then + if changedSignalConnections[name] then + changedSignalConnections[name]:disconnect() + end + changedSignalConnections[name] = valueObj.Changed:connect(function(newValue) + externalProperties[name] = newValue + updateFunction() + end) + end +end + +local function SetAndBoundsCheckAzimuthValues() + minAzimuthAbsoluteRad = math.rad(externalProperties["ReferenceAzimuth"]) - math.abs(math.rad(externalProperties["CWAzimuthTravel"])) + maxAzimuthAbsoluteRad = math.rad(externalProperties["ReferenceAzimuth"]) + math.abs(math.rad(externalProperties["CCWAzimuthTravel"])) + useAzimuthLimits = externalProperties["UseAzimuthLimits"] + if useAzimuthLimits then + curAzimuthRad = math.max(curAzimuthRad, minAzimuthAbsoluteRad) + curAzimuthRad = math.min(curAzimuthRad, maxAzimuthAbsoluteRad) + end +end + +local function SetAndBoundsCheckElevationValues() + -- These degree values are the direct user input values. It is deliberate that they are + -- ranged checked only against the extremes, and not against each other. Any time one + -- is changed, both of the internal values in radians are recalculated. This allows for + -- A developer to change the values in any order and for the end results to be that the + -- internal values adjust to match intent as best as possible. + local minElevationDeg = math.max(externalProperties["MinElevation"], MIN_ALLOWED_ELEVATION_DEG) + local maxElevationDeg = math.min(externalProperties["MaxElevation"], MAX_ALLOWED_ELEVATION_DEG) + + -- Set internal values in radians + minElevationRad = math.rad(math.min(minElevationDeg, maxElevationDeg)) + maxElevationRad = math.rad(math.max(minElevationDeg, maxElevationDeg)) + curElevationRad = math.max(curElevationRad, minElevationRad) + curElevationRad = math.min(curElevationRad, maxElevationRad) +end + +local function SetAndBoundsCheckDistanceValues() + minDistance = externalProperties["MinDistance"] + maxDistance = externalProperties["MaxDistance"] + curDistance = math.max(curDistance, minDistance) + curDistance = math.min(curDistance, maxDistance) +end + +-- This loads from, or lazily creates, NumberValue objects for exposed parameters +local function LoadNumberValueParameters() + -- These initial values do not require change listeners since they are read only once + LoadOrCreateNumberValueParameter("InitialElevation", "NumberValue", nil) + LoadOrCreateNumberValueParameter("InitialDistance", "NumberValue", nil) + + -- Note: ReferenceAzimuth is also used as an initial value, but needs a change listener because it is used in the calculation of the limits + LoadOrCreateNumberValueParameter("ReferenceAzimuth", "NumberValue", SetAndBoundsCheckAzimuthValues) + LoadOrCreateNumberValueParameter("CWAzimuthTravel", "NumberValue", SetAndBoundsCheckAzimuthValues) + LoadOrCreateNumberValueParameter("CCWAzimuthTravel", "NumberValue", SetAndBoundsCheckAzimuthValues) + LoadOrCreateNumberValueParameter("MinElevation", "NumberValue", SetAndBoundsCheckElevationValues) + LoadOrCreateNumberValueParameter("MaxElevation", "NumberValue", SetAndBoundsCheckElevationValues) + LoadOrCreateNumberValueParameter("MinDistance", "NumberValue", SetAndBoundsCheckDistanceValues) + LoadOrCreateNumberValueParameter("MaxDistance", "NumberValue", SetAndBoundsCheckDistanceValues) + LoadOrCreateNumberValueParameter("UseAzimuthLimits", "BoolValue", SetAndBoundsCheckAzimuthValues) + + -- Internal values set (in radians, from degrees), plus sanitization + curAzimuthRad = math.rad(externalProperties["ReferenceAzimuth"]) + curElevationRad = math.rad(externalProperties["InitialElevation"]) + curDistance = externalProperties["InitialDistance"] + + SetAndBoundsCheckAzimuthValues() + SetAndBoundsCheckElevationValues() + SetAndBoundsCheckDistanceValues() +end + +local function CreateOrbitalCamera() + local module = RootCameraCreator() + + LoadNumberValueParameters() + + module.DefaultZoom = curDistance + + local tweenAcceleration = math_rad(220) + local tweenSpeed = math_rad(0) + local tweenMaxSpeed = math_rad(250) + local timeBeforeAutoRotate = 2 + + local lastUpdate = tick() + module.LastUserPanCamera = tick() + + function module:Update() + module:ProcessTweens() + local now = tick() + local timeDelta = (now - lastUpdate) + local userPanningTheCamera = (self.UserPanningTheCamera == true) + local camera = workspace.CurrentCamera + local player = PlayersService.LocalPlayer + local humanoid = self:GetHumanoid() + local cameraSubject = camera and camera.CameraSubject + local isInVehicle = cameraSubject and cameraSubject:IsA('VehicleSeat') + local isOnASkateboard = cameraSubject and cameraSubject:IsA('SkateboardPlatform') + + if lastUpdate == nil or now - lastUpdate > 1 then + module:ResetCameraLook() + self.LastCameraTransform = nil + end + + if lastUpdate then + local gamepadRotation = self:UpdateGamepad() + + if self:ShouldUseVRRotation() then + self.RotateInput = self.RotateInput + self:GetVRRotationInput() + else + -- Cap out the delta to 0.1 so we don't get some crazy things when we re-resume from + local delta = math_min(0.1, now - lastUpdate) + + if gamepadRotation ~= ZERO_VECTOR2 then + userPanningTheCamera = true + self.RotateInput = self.RotateInput + (gamepadRotation * delta) + end + + local angle = 0 + if not (isInVehicle or isOnASkateboard) then + angle = angle + (self.TurningLeft and -120 or 0) + angle = angle + (self.TurningRight and 120 or 0) + end + + if angle ~= 0 then + self.RotateInput = self.RotateInput + Vector2.new(math_rad(angle * delta), 0) + userPanningTheCamera = true + end + end + end + + -- Reset tween speed if user is panning + if userPanningTheCamera then + tweenSpeed = 0 + module.LastUserPanCamera = tick() + end + + local userRecentlyPannedCamera = now - module.LastUserPanCamera < timeBeforeAutoRotate + local subjectPosition = self:GetSubjectPosition() + + if subjectPosition and player and camera then + + + local zoom = self:ZoomCamera(curDistance * currentZoomSpeed) + + + if not userPanningTheCamera and self.LastCameraTransform then + local isInFirstPerson = self:IsInFirstPerson() + if (isInVehicle or isOnASkateboard) and lastUpdate and humanoid and humanoid.Torso then + if isInFirstPerson then + if self.LastSubjectCFrame and (isInVehicle or isOnASkateboard) and cameraSubject:IsA('BasePart') then + local y = -findAngleBetweenXZVectors(self.LastSubjectCFrame.lookVector, cameraSubject.CFrame.lookVector) + if IsFinite(y) then + self.RotateInput = self.RotateInput + Vector2.new(y, 0) + end + tweenSpeed = 0 + end + elseif not userRecentlyPannedCamera then + local forwardVector = humanoid.Torso.CFrame.lookVector + if isOnASkateboard then + forwardVector = cameraSubject.CFrame.lookVector + end + + tweenSpeed = clamp(0, tweenMaxSpeed, tweenSpeed + tweenAcceleration * timeDelta) + + local percent = clamp(0, 1, tweenSpeed * timeDelta) + if self:IsInFirstPerson() then + percent = 1 + end + + local y = findAngleBetweenXZVectors(forwardVector, self:GetCameraLook()) + if IsFinite(y) and math_abs(y) > 0.0001 then + self.RotateInput = self.RotateInput + Vector2.new(y * percent, 0) + end + end + end + end + + local VREnabled = VRService.VREnabled + camera.Focus = VREnabled and self:GetVRFocus(subjectPosition, timeDelta) or CFrame_new(subjectPosition) + + local cameraFocusP = camera.Focus.p + if VREnabled and not self:IsInFirstPerson() then + local cameraHeight = self:GetCameraHeight() + local vecToSubject = (subjectPosition - camera.CFrame.p) + local distToSubject = vecToSubject.magnitude + + -- Only move the camera if it exceeded a maximum distance to the subject in VR + if distToSubject > zoom or self.RotateInput.x ~= 0 then + local desiredDist = math_min(distToSubject, zoom) + vecToSubject = self:RotateCamera(vecToSubject.unit * XZ_VECTOR, Vector2.new(self.RotateInput.x, 0)) * desiredDist + local newPos = cameraFocusP - vecToSubject + local desiredLookDir = camera.CFrame.lookVector + if self.RotateInput.x ~= 0 then + desiredLookDir = vecToSubject + end + local lookAt = Vector3.new(newPos.x + desiredLookDir.x, newPos.y, newPos.z + desiredLookDir.z) + self.RotateInput = ZERO_VECTOR2 + + camera.CFrame = CFrame_new(newPos, lookAt) + Vector3_new(0, cameraHeight, 0) + end + else + -- self.RotateInput is a Vector2 of mouse movement deltas since last update + curAzimuthRad = curAzimuthRad - self.RotateInput.x + + if useAzimuthLimits then + curAzimuthRad = clamp(curAzimuthRad, minAzimuthAbsoluteRad, maxAzimuthAbsoluteRad) + else + curAzimuthRad = (curAzimuthRad ~= 0) and (math.sign(curAzimuthRad) * (math.abs(curAzimuthRad) % TAU)) or 0 + end + + curDistance = clamp(zoom, minDistance, maxDistance) + + curElevationRad = clamp(curElevationRad + self.RotateInput.y, minElevationRad,maxElevationRad) + + local cameraPosVector = curDistance * ( CFrame.fromEulerAnglesYXZ( -curElevationRad, curAzimuthRad, 0 ) * UNIT_Z ) + local camPos = subjectPosition + cameraPosVector + + camera.CFrame = CFrame.new(camPos, subjectPosition) + + self.RotateInput = ZERO_VECTOR2 + end + + self.LastCameraTransform = camera.CFrame + self.LastCameraFocus = camera.Focus + if (isInVehicle or isOnASkateboard) and cameraSubject:IsA('BasePart') then + self.LastSubjectCFrame = cameraSubject.CFrame + else + self.LastSubjectCFrame = nil + end + end + + lastUpdate = now + end + + function module:GetCameraZoom() + return curDistance + end + + function module:ZoomCamera(desiredZoom) + local player = PlayersService.LocalPlayer + if player then + curDistance = clamp(desiredZoom, minDistance, maxDistance) + end + + local isFirstPerson = self:GetCameraZoom() < 2 + + --ShiftLockController:SetIsInFirstPerson(isFirstPerson) + -- set mouse behavior + self:UpdateMouseBehavior() + return self:GetCameraZoom() + end + + function module:ZoomCameraBy(zoomScale) + local newDist = curDistance + -- Can break into more steps to get more accurate integration + newDist = self:rk4Integrator(curDistance, zoomScale, 1) + self:ZoomCamera(newDist) + return self:GetCameraZoom() + end + + function module:ZoomCameraFixedBy(zoomIncrement) + return self:ZoomCamera(self:GetCameraZoom() + zoomIncrement) + end + + function module:SetInitialOrientation(humanoid) + local newDesiredLook = (humanoid.Torso.CFrame.lookVector - Vector3.new(0,0.23,0)).unit + local horizontalShift = findAngleBetweenXZVectors(newDesiredLook, self:GetCameraLook()) + local vertShift = math.asin(self:GetCameraLook().y) - math.asin(newDesiredLook.y) + if not IsFinite(horizontalShift) then + horizontalShift = 0 + end + if not IsFinite(vertShift) then + vertShift = 0 + end + self.RotateInput = Vector2.new(horizontalShift, vertShift) + end + + function module.getGamepadPan(name, state, input) + if input.UserInputType == module.activeGamepad and input.KeyCode == Enum.KeyCode.Thumbstick2 then + if r3ButtonDown or l3ButtonDown then + -- R3 or L3 Thumbstick is depressed, right stick controls dolly in/out + if (input.Position.Y > THUMBSTICK_DEADZONE) then + currentZoomSpeed = 0.96 + elseif (input.Position.Y < -THUMBSTICK_DEADZONE) then + currentZoomSpeed = 1.04 + else + currentZoomSpeed = 1.00 + end + else + if state == Enum.UserInputState.Cancel then + module.GamepadPanningCamera = ZERO_VECTOR2 + return + end + + local inputVector = Vector2.new(input.Position.X, -input.Position.Y) + if inputVector.magnitude > THUMBSTICK_DEADZONE then + module.GamepadPanningCamera = Vector2.new(input.Position.X, -input.Position.Y) + else + module.GamepadPanningCamera = ZERO_VECTOR2 + end + end + end + end + + function module.doGamepadZoom(name, state, input) + if input.UserInputType == module.activeGamepad and (input.KeyCode == Enum.KeyCode.ButtonR3 or input.KeyCode == Enum.KeyCode.ButtonL3) then + if (state == Enum.UserInputState.Begin) then + r3ButtonDown = input.KeyCode == Enum.KeyCode.ButtonR3 + l3ButtonDown = input.KeyCode == Enum.KeyCode.ButtonL3 + elseif (state == Enum.UserInputState.End) then + if (input.KeyCode == Enum.KeyCode.ButtonR3) then + r3ButtonDown = false + elseif (input.KeyCode == Enum.KeyCode.ButtonL3) then + l3ButtonDown = false + end + if (not r3ButtonDown) and (not l3ButtonDown) then + currentZoomSpeed = 1.00 + end + end + end + end + + function module:BindGamepadInputActions() + local ContextActionService = game:GetService('ContextActionService') + ContextActionService:BindAction("OrbitalCamGamepadPan", module.getGamepadPan, false, Enum.KeyCode.Thumbstick2) + ContextActionService:BindAction("OrbitalCamGamepadZoom", module.doGamepadZoom, false, Enum.KeyCode.ButtonR3) + ContextActionService:BindAction("OrbitalCamGamepadZoomAlt", module.doGamepadZoom, false, Enum.KeyCode.ButtonL3) + end + + return module +end + +return CreateOrbitalCamera diff --git a/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/ScriptableCamera.lua b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/ScriptableCamera.lua new file mode 100644 index 0000000..9526781 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/ScriptableCamera.lua @@ -0,0 +1,12 @@ +local RootCameraCreator = require(script.Parent) + +local function CreateScriptableCamera() + local module = RootCameraCreator() + + function module:Update() + end + + return module +end + +return CreateScriptableCamera diff --git a/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/TrackCamera.lua b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/TrackCamera.lua new file mode 100644 index 0000000..44ba394 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/TrackCamera.lua @@ -0,0 +1,54 @@ +local PlayersService = game:GetService('Players') +local RootCameraCreator = require(script.Parent) + +local ZERO_VECTOR2 = Vector2.new(0, 0) + +local CFrame_new = CFrame.new +local math_min = math.min + +local function CreateTrackCamera() + local module = RootCameraCreator() + + local lastUpdate = tick() + function module:Update() + local now = tick() + + local userPanningTheCamera = (self.UserPanningTheCamera == true) + local camera = workspace.CurrentCamera + local player = PlayersService.LocalPlayer + + if lastUpdate == nil or now - lastUpdate > 1 then + module:ResetCameraLook() + self.LastCameraTransform = nil + end + + if lastUpdate then + -- Cap out the delta to 0.1 so we don't get some crazy things when we re-resume from + local delta = math_min(0.1, now - lastUpdate) + local gamepadRotation = self:UpdateGamepad() + if gamepadRotation ~= ZERO_VECTOR2 then + userPanningTheCamera = true + self.RotateInput = self.RotateInput + (gamepadRotation * delta) + end + end + + local subjectPosition = self:GetSubjectPosition() + if subjectPosition and player and camera then + local zoom = self:GetCameraZoom() + if zoom <= 0 then + zoom = 0.1 + end + local newLookVector = self:RotateCamera(self:GetCameraLook(), self.RotateInput) + self.RotateInput = ZERO_VECTOR2 + + camera.Focus = CFrame_new(subjectPosition) + camera.CFrame = CFrame_new(subjectPosition - (zoom * newLookVector), subjectPosition) + self.LastCameraTransform = camera.CoordinateFrame + end + lastUpdate = now + end + + return module +end + +return CreateTrackCamera diff --git a/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/VRCamera.lua b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/VRCamera.lua new file mode 100644 index 0000000..e69de29 diff --git a/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/WatchCamera.lua b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/WatchCamera.lua new file mode 100644 index 0000000..007a1aa --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/WatchCamera.lua @@ -0,0 +1,63 @@ +local PlayersService = game:GetService('Players') +local RootCameraCreator = require(script.Parent) + +local ZERO_VECTOR2 = Vector2.new(0, 0) + +local CFrame_new = CFrame.new + +local function CreateWatchCamera() + local module = RootCameraCreator() + module.PanEnabled = false + + local lastUpdate = tick() + function module:Update() + local now = tick() + + local camera = workspace.CurrentCamera + local player = PlayersService.LocalPlayer + + if lastUpdate == nil or now - lastUpdate > 1 then + module:ResetCameraLook() + self.LastZoom = nil + end + + + local subjectPosition = self:GetSubjectPosition() + if subjectPosition and player and camera then + local cameraLook = nil + + local humanoid = self:GetHumanoid() + if humanoid and humanoid.Torso then + -- TODO: let the paging buttons move the camera but not the mouse/touch + -- currently neither do + local diffVector = subjectPosition - camera.CFrame.p + cameraLook = diffVector.unit + + if self.LastZoom and self.LastZoom == self:GetCameraZoom() then + -- Don't clobber the zoom if they zoomed the camera + local zoom = diffVector.magnitude + self:ZoomCamera(zoom) + end + end + + local zoom = self:GetCameraZoom() + if zoom <= 0 then + zoom = 0.1 + end + + local newLookVector = self:RotateVector(cameraLook or self:GetCameraLook(), self.RotateInput) + self.RotateInput = ZERO_VECTOR2 + local newFocus = CFrame_new(subjectPosition) + local newCamCFrame = CFrame_new(newFocus.p - (zoom * newLookVector), subjectPosition) + + camera.Focus = newFocus + camera.CFrame = newCamCFrame + self.LastZoom = zoom + end + lastUpdate = now + end + + return module +end + +return CreateWatchCamera diff --git a/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/init.lua b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/init.lua new file mode 100644 index 0000000..d39ae46 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/RootCamera/init.lua @@ -0,0 +1,1558 @@ +--!nocheck +local PlayersService = game:GetService('Players') +local UserInputService = game:GetService('UserInputService') +local StarterGui = game:GetService('StarterGui') +local GuiService = game:GetService('GuiService') +local ContextActionService = game:GetService('ContextActionService') +local VRService = game:GetService("VRService") + +local GuiRoot = PlayersService.LocalPlayer.PlayerGui:WaitForChild("MainGui") + +local LocalPlayer = PlayersService.LocalPlayer +local PlayerGui = nil +if LocalPlayer then + PlayerGui = PlayersService.LocalPlayer:WaitForChild("PlayerGui") +end + +local PortraitMode = false + +local CameraScript = script.Parent +local ShiftLockController = require(CameraScript:WaitForChild('ShiftLockController')) + +local Settings = UserSettings() +local GameSettings = Settings.GameSettings + +local function clamp(low, high, num) + return (num > high and high or num < low and low or num) +end + +local math_atan2 = math.atan2 +local function findAngleBetweenXZVectors(vec2, vec1) + return math_atan2(vec1.X*vec2.Z-vec1.Z*vec2.X, vec1.X*vec2.X + vec1.Z*vec2.Z) +end + +local function IsFinite(num) + return num == num and num ~= 1/0 and num ~= -1/0 +end + +local THUMBSTICK_DEADZONE = 0.2 + +local LANDSCAPE_DEFAULT_ZOOM = 12.5 +local PORTRAIT_DEFAULT_ZOOM = 25 + +local humanoidCache = {} +local function findPlayerHumanoid(player) + local character = player and player.Character + if character then + local resultHumanoid = humanoidCache[player] + if resultHumanoid and resultHumanoid.Parent == character then + return resultHumanoid + else + humanoidCache[player] = nil -- Bust Old Cache + local humanoid = character:FindFirstChildOfClass("Humanoid") + if humanoid then + humanoidCache[player] = humanoid + end + return humanoid + end + end +end + +local MIN_Y = math.rad(-80) +local MAX_Y = math.rad(80) + +local DEFAULT_CAMERA_ANGLE = 25 +local VR_ANGLE = math.rad(15) + +local VR_LOW_INTENSITY_ROTATION = Vector2.new(math.rad(15), 0) +local VR_HIGH_INTENSITY_ROTATION = Vector2.new(math.rad(45), 0) +local VR_LOW_INTENSITY_REPEAT = 0.1 +local VR_HIGH_INTENSITY_REPEAT = 0.4 + +local ZERO_VECTOR2 = Vector2.new(0, 0) +local ZERO_VECTOR3 = Vector3.new(0, 0, 0) + +local TOUCH_SENSITIVTY = Vector2.new(math.pi*2.25, math.pi*2) +local MOUSE_SENSITIVITY = Vector2.new(math.pi*4, math.pi*1.9) + +local MAX_TIME_FOR_DOUBLE_TAP = 1.5 +local MAX_TAP_POS_DELTA = 15 +local MAX_TAP_TIME_DELTA = 0.75 + +local SEAT_OFFSET = Vector3.new(0,5,0) +local VR_SEAT_OFFSET = Vector3.new(0, 4, 0) +local HEAD_OFFSET = Vector3.new(0, 1.5, 0) +local R15_HEAD_OFFSET = Vector3.new(0, 2.0, 0) + +local PORTRAIT_MODE_CAMERA_OFFSET = 2 + +-- Reset the camera look vector when the camera is enabled for the first time +local SetCameraOnSpawn = true + +local hasGameLoaded = false + +local GestureArea = nil +local GestureAreaManagedByControlScript = false + +local SCROLL_DELTA = Vector3.new(0, 0, 0) + +local function layoutGestureArea(portraitMode) + if GestureArea and not GestureAreaManagedByControlScript then + if portraitMode then + GestureArea.Size = UDim2.new(1, 0, .6, 0) + GestureArea.Position = UDim2.new(0, 0, 0, 0) + else + GestureArea.Size = UDim2.new(1, 0, .5, -18) + GestureArea.Position = UDim2.new(0, 0, 0, 0) + end + end +end + +-- Setup gesture area that camera uses while DynamicThumbstick is enabled +local function OnCharacterAdded(character) + if UserInputService.TouchEnabled then + if PlayerGui then + local TouchGui = PlayerGui:FindFirstChild("TouchGui") + if TouchGui and TouchGui:WaitForChild("GestureArea", 0.5) then + GestureArea = TouchGui.GestureArea + GestureAreaManagedByControlScript = true + else + GestureAreaManagedByControlScript = false + local ScreenGui = Instance.new("ScreenGui") + ScreenGui.Name = "GestureArea" + ScreenGui.Parent = PlayerGui + + GestureArea = Instance.new("Frame") + GestureArea.BackgroundTransparency = 1.0 + GestureArea.Visible = true + GestureArea.BackgroundColor3 = Color3.fromRGB(0, 0, 0) + layoutGestureArea(PortraitMode) + GestureArea.Parent = ScreenGui + end + end + end +end + +if LocalPlayer then + if LocalPlayer.Character ~= nil then + OnCharacterAdded(LocalPlayer.Character) + end + LocalPlayer.CharacterAdded:connect(function(character) + OnCharacterAdded(character) + end) +end + + +local function positionIntersectsGuiObject(position, guiObject) + if position.X < guiObject.AbsolutePosition.X + guiObject.AbsoluteSize.X + and position.X > guiObject.AbsolutePosition.X + and position.Y < guiObject.AbsolutePosition.Y + guiObject.AbsoluteSize.Y + and position.Y > guiObject.AbsolutePosition.Y then + return true + end + return false +end + +local function GetRenderCFrame(part) + return part:GetRenderCFrame() +end + +local function CreateCamera() + local this = {} + local R15HeadHeight = R15_HEAD_OFFSET + local heightScaleChangedConn + function this:GetActivateValue() + return 0.7 + end + + function this:IsPortraitMode() + return PortraitMode + end + + function this:GetRotateAmountValue(vrRotationIntensity) + vrRotationIntensity = vrRotationIntensity or StarterGui:GetCore("VRRotationIntensity") + if vrRotationIntensity then + if vrRotationIntensity == "Low" then + return VR_LOW_INTENSITY_ROTATION + elseif vrRotationIntensity == "High" then + return VR_HIGH_INTENSITY_ROTATION + end + end + return ZERO_VECTOR2 + end + function this:GetRepeatDelayValue(vrRotationIntensity) + vrRotationIntensity = vrRotationIntensity or StarterGui:GetCore("VRRotationIntensity") + if vrRotationIntensity then + if vrRotationIntensity == "Low" then + return VR_LOW_INTENSITY_REPEAT + elseif vrRotationIntensity == "High" then + return VR_HIGH_INTENSITY_REPEAT + end + end + return 0 + end + + this.ShiftLock = false + this.Enabled = false + local isFirstPerson = false + local isRightMouseDown = false + local isMiddleMouseDown = false + this.RotateInput = ZERO_VECTOR2 + this.DefaultZoom = LANDSCAPE_DEFAULT_ZOOM + this.GamepadPanningCamera = nil + this.activeGamepad = nil + + local tweens = {} + + this.currentZoom = nil + this.lastSubject = nil + this.lastSubjectPosition = Vector3.new(0, 5, 0) + + local lastVRRotation = 0 + local vrRotateKeyCooldown = {} + + local isDynamicThumbstickEnabled = false + local dynamicThumbstickFrame = nil + + local function getDynamicThumbstickFrame() + if dynamicThumbstickFrame and dynamicThumbstickFrame:IsDescendantOf(game) then + return dynamicThumbstickFrame + else + local touchGui = PlayerGui:FindFirstChild("TouchGui") + if not touchGui then return nil end + + local touchControlFrame = touchGui:FindFirstChild("TouchControlFrame") + if not touchControlFrame then return nil end + + dynamicThumbstickFrame = touchControlFrame:FindFirstChild("DynamicThumbstickFrame") + return dynamicThumbstickFrame + end + end + + -- Check for changes in ViewportSize to decide if PortraitMode + local CameraChangedConn = nil + local workspaceCameraChangedConn = nil + local function onWorkspaceCameraChanged() + if UserInputService.TouchEnabled then + if CameraChangedConn then + CameraChangedConn:Disconnect() + CameraChangedConn = nil + end + local newCamera = workspace.CurrentCamera + if newCamera then + local size = newCamera.ViewportSize + PortraitMode = size.X < size.Y + layoutGestureArea(PortraitMode) + this.DefaultZoom = PortraitMode and PORTRAIT_DEFAULT_ZOOM or LANDSCAPE_DEFAULT_ZOOM + CameraChangedConn = newCamera:GetPropertyChangedSignal("ViewportSize"):Connect(function() + size = newCamera.ViewportSize + PortraitMode = size.X < size.Y + layoutGestureArea(PortraitMode) + this.DefaultZoom = PortraitMode and PORTRAIT_DEFAULT_ZOOM or LANDSCAPE_DEFAULT_ZOOM + end) + end + end + end + workspaceCameraChangedConn = workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(onWorkspaceCameraChanged) + if workspace.CurrentCamera then + onWorkspaceCameraChanged() + end + + + function this:GetShiftLock() + return ShiftLockController:IsShiftLocked() + end + + function this:GetHumanoid() + local player = PlayersService.LocalPlayer + return findPlayerHumanoid(player) + end + + function this:GetHumanoidRootPart() + local humanoid = this:GetHumanoid() + return humanoid and humanoid.Torso + end + + function this:GetRenderCFrame(part) + GetRenderCFrame(part) + end + + local STATE_DEAD = Enum.HumanoidStateType.Dead + + -- HumanoidRootPart when alive, Head part when dead + local function getHumanoidPartToFollow(humanoid, humanoidStateType) + if humanoidStateType == STATE_DEAD then + local character = humanoid.Parent + if character then + return character:FindFirstChild("Head") or humanoid.Torso + else + return humanoid.Torso + end + else + return humanoid.Torso + end + end + + local HUMANOID_STATE_DEAD = Enum.HumanoidStateType.Dead + + function this:GetSubjectPosition() + local result = nil + local camera = workspace.CurrentCamera + local cameraSubject = camera and camera.CameraSubject + if cameraSubject then + if cameraSubject:IsA('Humanoid') then + local humanoidStateType = cameraSubject:GetState() + if VRService.VREnabled and humanoidStateType == STATE_DEAD and cameraSubject == this.lastSubject then + result = this.lastSubjectPosition + else + local humanoidRootPart = getHumanoidPartToFollow(cameraSubject, humanoidStateType) + if humanoidRootPart and humanoidRootPart:IsA('BasePart') then + local subjectCFrame = GetRenderCFrame(humanoidRootPart) + local heightOffset = ZERO_VECTOR3 + if humanoidStateType ~= STATE_DEAD then + heightOffset = cameraSubject.RigType == Enum.HumanoidRigType.R15 and R15HeadHeight or HEAD_OFFSET + end + + if PortraitMode then + heightOffset = heightOffset + Vector3.new(0, PORTRAIT_MODE_CAMERA_OFFSET, 0) + end + + result = subjectCFrame.p + + subjectCFrame:vectorToWorldSpace(heightOffset) + end + end + elseif cameraSubject:IsA('VehicleSeat') then + local subjectCFrame = GetRenderCFrame(cameraSubject) + local offset = SEAT_OFFSET + if VRService.VREnabled then + offset = VR_SEAT_OFFSET + end + result = subjectCFrame.p + subjectCFrame:vectorToWorldSpace(offset) + elseif cameraSubject:IsA('SkateboardPlatform') then + local subjectCFrame = GetRenderCFrame(cameraSubject) + result = subjectCFrame.p + SEAT_OFFSET + elseif cameraSubject:IsA('BasePart') then + local subjectCFrame = GetRenderCFrame(cameraSubject) + result = subjectCFrame.p + elseif cameraSubject:IsA('Model') then + result = cameraSubject:GetModelCFrame().p + end + end + this.lastSubject = cameraSubject + this.lastSubjectPosition = result + return result + end + + function this:ResetCameraLook() + end + + function this:GetCameraLook() + return workspace.CurrentCamera and workspace.CurrentCamera.CoordinateFrame.lookVector or Vector3.new(0,0,1) + end + + function this:GetCameraZoom() + if this.currentZoom == nil then + local player = PlayersService.LocalPlayer + this.currentZoom = player and clamp(player.CameraMinZoomDistance, player.CameraMaxZoomDistance, this.DefaultZoom) or this.DefaultZoom + end + return this.currentZoom + end + + function this:GetCameraActualZoom() + local camera = workspace.CurrentCamera + if camera then + return (camera.CoordinateFrame.p - camera.Focus.p).magnitude + end + end + + function this:GetCameraHeight() + if VRService.VREnabled and not this:IsInFirstPerson() then + local zoom = this:GetCameraZoom() + return math.sin(VR_ANGLE) * zoom + end + return 0 + end + + function this:ViewSizeX() + local result = 1024 + local camera = workspace.CurrentCamera + if camera then + result = camera.ViewportSize.X + end + return result + end + + function this:ViewSizeY() + local result = 768 + local camera = workspace.CurrentCamera + if camera then + result = camera.ViewportSize.Y + end + return result + end + + + local math_asin = math.asin + local math_atan2 = math.atan2 + local math_floor = math.floor + local math_max = math.max + local math_pi = math.pi + local Vector2_new = Vector2.new + local Vector3_new = Vector3.new + local CFrame_Angles = CFrame.Angles + local CFrame_new = CFrame.new + + function this:ScreenTranslationToAngle(translationVector) + local screenX = this:ViewSizeX() + local screenY = this:ViewSizeY() + local xTheta = (translationVector.x / screenX) + local yTheta = (translationVector.y / screenY) + return Vector2_new(xTheta, yTheta) + end + + function this:MouseTranslationToAngle(translationVector) + local xTheta = (translationVector.x / 1920) + local yTheta = (translationVector.y / 1200) + return Vector2_new(xTheta, yTheta) + end + + function this:RotateVector(startVector, xyRotateVector) + local startCFrame = CFrame_new(ZERO_VECTOR3, startVector) + local resultLookVector = (CFrame_Angles(0, -xyRotateVector.x, 0) * startCFrame * CFrame_Angles(-xyRotateVector.y,0,0)).lookVector + return resultLookVector, Vector2_new(xyRotateVector.x, xyRotateVector.y) + end + + function this:RotateCamera(startLook, xyRotateVector) + if VRService.VREnabled then + local yawRotatedVector, xyRotateVector = self:RotateVector(startLook, Vector2.new(xyRotateVector.x, 0)) + return Vector3_new(yawRotatedVector.x, 0, yawRotatedVector.z).unit, xyRotateVector + else + local startVertical = math_asin(startLook.y) + local yTheta = clamp(-MAX_Y + startVertical, -MIN_Y + startVertical, xyRotateVector.y) + return self:RotateVector(startLook, Vector2_new(xyRotateVector.x, yTheta)) + end + end + + function this:IsInFirstPerson() + return isFirstPerson + end + + -- there are several cases to consider based on the state of input and camera rotation mode + function this:UpdateMouseBehavior() + -- first time transition to first person mode or shiftlock + local camera = workspace.CurrentCamera + if camera.CameraType == Enum.CameraType.Scriptable then + return + end + + if isFirstPerson or self:GetShiftLock() then + pcall(function() GameSettings.RotationType = Enum.RotationType.CameraRelative end) + if UserInputService.MouseBehavior ~= Enum.MouseBehavior.LockCenter then + UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter + end + else + pcall(function() GameSettings.RotationType = Enum.RotationType.MovementRelative end) + if isRightMouseDown or isMiddleMouseDown then + UserInputService.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition + else + UserInputService.MouseBehavior = Enum.MouseBehavior.Default + end + end + end + + function this:ZoomCamera(desiredZoom) + local player = PlayersService.LocalPlayer + if player then + if player.CameraMode == Enum.CameraMode.LockFirstPerson then + this.currentZoom = 0 + else + this.currentZoom = clamp(player.CameraMinZoomDistance, player.CameraMaxZoomDistance, desiredZoom) + GuiRoot.CameraControl.ZoomedIn.Visible = (this.currentZoom == player.CameraMinZoomDistance) + --GuiRoot.CameraControl.ZoomedOut.Visible = (this.currentZoom == player.CameraMaxZoomDistance) + end + end + + isFirstPerson = self:GetCameraZoom() < 0 --disable first person lock + + + + ShiftLockController:SetIsInFirstPerson(isFirstPerson) + -- set mouse behavior + self:UpdateMouseBehavior() + return self:GetCameraZoom() + end + + function this:rk4Integrator(position, velocity, t) + local direction = velocity < 0 and -1 or 1 + local function acceleration(p, v) + local accel = direction * math_max(1, (p / 3.3) + 0.5) + return accel + end + + local p1 = position + local v1 = velocity + local a1 = acceleration(p1, v1) + local p2 = p1 + v1 * (t / 2) + local v2 = v1 + a1 * (t / 2) + local a2 = acceleration(p2, v2) + local p3 = p1 + v2 * (t / 2) + local v3 = v1 + a2 * (t / 2) + local a3 = acceleration(p3, v3) + local p4 = p1 + v3 * t + local v4 = v1 + a3 * t + local a4 = acceleration(p4, v4) + + local positionResult = position + (v1 + 2 * v2 + 2 * v3 + v4) * (t / 6) + local velocityResult = velocity + (a1 + 2 * a2 + 2 * a3 + a4) * (t / 6) + return positionResult, velocityResult + end + + function this:ZoomCameraBy(zoomScale) + local zoom = this:GetCameraActualZoom() + + if zoom then + -- Can break into more steps to get more accurate integration + zoom = self:rk4Integrator(zoom, zoomScale, 1) + self:ZoomCamera(zoom) + end + return self:GetCameraZoom() + end + + function this:ZoomCameraFixedBy(zoomIncrement) + return self:ZoomCamera(self:GetCameraZoom() + zoomIncrement) + end + + function this:Update() + end + + ----- VR STUFF ------ + + function this:ApplyVRTransform() + if not VRService.VREnabled then + return + end + --we only want this to happen in first person VR + local player = PlayersService.LocalPlayer + if not (player and player.Character + and player.Character:FindFirstChild("HumanoidRootPart") + and player.Character.HumanoidRootPart:FindFirstChild("RootJoint")) then + return + end + + local camera = workspace.CurrentCamera + local cameraSubject = camera.CameraSubject + local isInVehicle = cameraSubject and cameraSubject:IsA('VehicleSeat') + + if this:IsInFirstPerson() and not isInVehicle then + local vrFrame = VRService:GetUserCFrame(Enum.UserCFrame.Head) + local vrRotation = vrFrame - vrFrame.p + local rootJoint = player.Character.HumanoidRootPart.RootJoint + rootJoint.C0 = CFrame.new(vrRotation:vectorToObjectSpace(vrFrame.p)) * CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0) + else + local rootJoint = player.Character.HumanoidRootPart.RootJoint + rootJoint.C0 = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0) + end + end + + local vrRotationIntensityExists = true + local lastVrRotationCheck = 0 + function this:ShouldUseVRRotation() + if not VRService.VREnabled then + return false + end + if not vrRotationIntensityExists and tick() - lastVrRotationCheck < 1 then return false end + + local success, vrRotationIntensity = pcall(function() return StarterGui:GetCore("VRRotationIntensity") end) + vrRotationIntensityExists = success and vrRotationIntensity ~= nil + lastVrRotationCheck = tick() + + return success and vrRotationIntensity ~= nil and vrRotationIntensity ~= "Smooth" + end + + function this:GetVRRotationInput() + local vrRotateSum = ZERO_VECTOR2 + + local vrRotationIntensity = StarterGui:GetCore("VRRotationIntensity") + + local vrGamepadRotation = self.GamepadPanningCamera or ZERO_VECTOR2 + local delayExpired = (tick() - lastVRRotation) >= self:GetRepeatDelayValue(vrRotationIntensity) + + if math.abs(vrGamepadRotation.x) >= self:GetActivateValue() then + if (delayExpired or not vrRotateKeyCooldown[Enum.KeyCode.Thumbstick2]) then + local sign = 1 + if vrGamepadRotation.x < 0 then + sign = -1 + end + vrRotateSum = vrRotateSum + self:GetRotateAmountValue(vrRotationIntensity) * sign + vrRotateKeyCooldown[Enum.KeyCode.Thumbstick2] = true + end + elseif math.abs(vrGamepadRotation.x) < self:GetActivateValue() - 0.1 then + vrRotateKeyCooldown[Enum.KeyCode.Thumbstick2] = nil + end + if self.TurningLeft then + if delayExpired or not vrRotateKeyCooldown[Enum.KeyCode.Left] then + vrRotateSum = vrRotateSum - self:GetRotateAmountValue(vrRotationIntensity) + vrRotateKeyCooldown[Enum.KeyCode.Left] = true + end + else + vrRotateKeyCooldown[Enum.KeyCode.Left] = nil + end + if self.TurningRight then + if (delayExpired or not vrRotateKeyCooldown[Enum.KeyCode.Right]) then + vrRotateSum = vrRotateSum + self:GetRotateAmountValue(vrRotationIntensity) + vrRotateKeyCooldown[Enum.KeyCode.Right] = true + end + else + vrRotateKeyCooldown[Enum.KeyCode.Right] = nil + end + + if vrRotateSum ~= ZERO_VECTOR2 then + lastVRRotation = tick() + end + + return vrRotateSum + end + + local cameraTranslationConstraints = Vector3.new(1, 1, 1) + local humanoidJumpOrigin = nil + local trackingHumanoid = nil + local cameraFrozen = false + local subjectStateChangedConn = nil + local cameraSubjectChangedConn = nil + local workspaceChangedConn = nil + local humanoidChildAddedConn = nil + local humanoidChildRemovedConn = nil + + local function cancelCameraFreeze(keepConstraints) + if not keepConstraints then + cameraTranslationConstraints = Vector3.new(cameraTranslationConstraints.x, 1, cameraTranslationConstraints.z) + end + if cameraFrozen then + trackingHumanoid = nil + cameraFrozen = false + end + end + + local function startCameraFreeze(subjectPosition, humanoidToTrack) + if not cameraFrozen then + humanoidJumpOrigin = subjectPosition + trackingHumanoid = humanoidToTrack + cameraTranslationConstraints = Vector3.new(cameraTranslationConstraints.x, 0, cameraTranslationConstraints.z) + cameraFrozen = true + end + end + + local function rescaleCameraOffset(newScaleFactor) + R15HeadHeight = R15_HEAD_OFFSET*newScaleFactor + end + + local function onHumanoidSubjectChildAdded(child) + if child.Name == "BodyHeightScale" and child:IsA("NumberValue") then + if heightScaleChangedConn then + heightScaleChangedConn:disconnect() + end + heightScaleChangedConn = child.Changed:connect(rescaleCameraOffset) + rescaleCameraOffset(child.Value) + end + end + + local function onHumanoidSubjectChildRemoved(child) + if child.Name == "BodyHeightScale" then + rescaleCameraOffset(1) + if heightScaleChangedConn then + heightScaleChangedConn:disconnect() + heightScaleChangedConn = nil + end + end + end + + local function onNewCameraSubject() + if subjectStateChangedConn then + subjectStateChangedConn:disconnect() + subjectStateChangedConn = nil + end + if humanoidChildAddedConn then + humanoidChildAddedConn:disconnect() + humanoidChildAddedConn = nil + end + if humanoidChildRemovedConn then + humanoidChildRemovedConn:disconnect() + humanoidChildRemovedConn = nil + end + if heightScaleChangedConn then + heightScaleChangedConn:disconnect() + heightScaleChangedConn = nil + end + + local humanoid = workspace.CurrentCamera and workspace.CurrentCamera.CameraSubject + if trackingHumanoid ~= humanoid then + cancelCameraFreeze() + end + if humanoid and humanoid:IsA('Humanoid') then + humanoidChildAddedConn = humanoid.ChildAdded:connect(onHumanoidSubjectChildAdded) + humanoidChildRemovedConn = humanoid.ChildRemoved:connect(onHumanoidSubjectChildRemoved) + for _, child in pairs(humanoid:GetChildren()) do + onHumanoidSubjectChildAdded(child) + end + + subjectStateChangedConn = humanoid.StateChanged:connect(function(oldState, newState) + if VRService.VREnabled and newState == Enum.HumanoidStateType.Jumping and not this:IsInFirstPerson() then + startCameraFreeze(this:GetSubjectPosition(), humanoid) + elseif newState ~= Enum.HumanoidStateType.Jumping and newState ~= Enum.HumanoidStateType.Freefall then + cancelCameraFreeze(true) + end + end) + end + end + + local function onCurrentCameraChanged() + if cameraSubjectChangedConn then + cameraSubjectChangedConn:disconnect() + cameraSubjectChangedConn = nil + end + local camera = workspace.CurrentCamera + if camera then + cameraSubjectChangedConn = camera:GetPropertyChangedSignal("CameraSubject"):connect(onNewCameraSubject) + onNewCameraSubject() + end + end + + function this:GetVRFocus(subjectPosition, timeDelta) + local newFocus = nil + + local camera = workspace.CurrentCamera + local lastFocus = self.LastCameraFocus or subjectPosition + if not cameraFrozen then + cameraTranslationConstraints = Vector3.new(cameraTranslationConstraints.x, math.min(1, cameraTranslationConstraints.y + 0.42 * timeDelta), cameraTranslationConstraints.z) + end + if cameraFrozen and humanoidJumpOrigin and humanoidJumpOrigin.y > lastFocus.y then + newFocus = CFrame.new(Vector3.new(subjectPosition.x, math.min(humanoidJumpOrigin.y, lastFocus.y + 5 * timeDelta), subjectPosition.z)) + else + newFocus = CFrame.new(Vector3.new(subjectPosition.x, lastFocus.y, subjectPosition.z):Lerp(subjectPosition, cameraTranslationConstraints.y)) + end + + if cameraFrozen then + -- No longer in 3rd person + if self:IsInFirstPerson() then -- not VRService.VREnabled + cancelCameraFreeze() + end + -- This case you jumped off a cliff and want to keep your character in view + -- 0.5 is to fix floating point error when not jumping off cliffs + if humanoidJumpOrigin and subjectPosition.y < (humanoidJumpOrigin.y - 0.5) then + cancelCameraFreeze() + end + end + + return newFocus + end + + ------------------------ + + ---- Input Events ---- + local startPos = nil + local lastPos = nil + local panBeginLook = nil + local lastTapTime = nil + + local fingerTouches = {} + local NumUnsunkTouches = 0 + + local inputStartPositions = {} + local inputStartTimes = {} + + local StartingDiff = nil + local pinchBeginZoom = nil + + this.ZoomEnabled = true + this.PanEnabled = true + this.KeyPanEnabled = true + + local function OnTouchBegan(input, processed) + --If isDynamicThumbstickEnabled, then only process TouchBegan event if it starts in GestureArea + + local dtFrame = getDynamicThumbstickFrame() + + local isDynamicThumbstickUsingThisInput = false + if isDynamicThumbstickEnabled then + local ControlScript = CameraScript.Parent:FindFirstChild("ControlScript") + if ControlScript then + local MasterControl = ControlScript:FindFirstChild("MasterControl") + if MasterControl then + local DynamicThumbstickModule = MasterControl:FindFirstChild("DynamicThumbstick") + if DynamicThumbstickModule then + DynamicThumbstickModule = require(DynamicThumbstickModule) + local dynamicInputObject = DynamicThumbstickModule:GetInputObject() + isDynamicThumbstickUsingThisInput = (dynamicInputObject == input) + end + end + end + end + + if not isDynamicThumbstickUsingThisInput then + fingerTouches[input] = processed + if not processed then + inputStartPositions[input] = input.Position + inputStartTimes[input] = tick() + NumUnsunkTouches = NumUnsunkTouches + 1 + end + end + end + + local function OnTouchChanged(input, processed) + + if fingerTouches[input] == nil then + if isDynamicThumbstickEnabled then + return + end + fingerTouches[input] = processed + if not processed then + NumUnsunkTouches = NumUnsunkTouches + 1 + end + end + + if NumUnsunkTouches == 1 then + if fingerTouches[input] == false then + panBeginLook = panBeginLook or this:GetCameraLook() + startPos = startPos or input.Position + lastPos = lastPos or startPos + this.UserPanningTheCamera = true + + local delta = input.Position - lastPos + + delta = Vector2.new(delta.X, delta.Y * GameSettings:GetCameraYInvertValue()) + + if this.PanEnabled then + local desiredXYVector = this:ScreenTranslationToAngle(delta) * TOUCH_SENSITIVTY + this.RotateInput = this.RotateInput + desiredXYVector + end + + lastPos = input.Position + end + else + panBeginLook = nil + startPos = nil + lastPos = nil + this.UserPanningTheCamera = false + end + if NumUnsunkTouches == 2 then + local unsunkTouches = {} + for touch, wasSunk in pairs(fingerTouches) do + if not wasSunk then + table.insert(unsunkTouches, touch) + end + end + if #unsunkTouches == 2 then + local difference = (unsunkTouches[1].Position - unsunkTouches[2].Position).magnitude + if StartingDiff and pinchBeginZoom then + local scale = difference / math_max(0.01, StartingDiff) + local clampedScale = clamp(0.1, 10, scale) + if this.ZoomEnabled then + this:ZoomCamera(pinchBeginZoom / clampedScale) + end + else + StartingDiff = difference + pinchBeginZoom = this:GetCameraActualZoom() + end + end + else + StartingDiff = nil + pinchBeginZoom = nil + end + end + + local function calcLookBehindRotateInput(torso) + if torso then + local newDesiredLook = (torso.CFrame.lookVector - Vector3.new(0, math.sin(math.rad(DEFAULT_CAMERA_ANGLE)), 0)).unit + local horizontalShift = findAngleBetweenXZVectors(newDesiredLook, this:GetCameraLook()) + local vertShift = math.asin(this:GetCameraLook().y) - math.asin(newDesiredLook.y) + if not IsFinite(horizontalShift) then + horizontalShift = 0 + end + if not IsFinite(vertShift) then + vertShift = 0 + end + + return Vector2.new(horizontalShift, vertShift) + end + return nil + end + + local function IsTouchTap(input) + -- We can't make the assumption that the input exists in the inputStartPositions because we may have switched from a different camera type. + if inputStartPositions[input] then + local posDelta = (inputStartPositions[input] - input.Position).magnitude + if posDelta < MAX_TAP_POS_DELTA then + local timeDelta = inputStartTimes[input] - tick() + if timeDelta < MAX_TAP_TIME_DELTA then + return true + end + end + end + return false + end + + + local function OnTouchEnded(input, processed) + if fingerTouches[input] == false then + if NumUnsunkTouches == 1 then + panBeginLook = nil + startPos = nil + lastPos = nil + this.UserPanningTheCamera = false + elseif NumUnsunkTouches == 2 then + StartingDiff = nil + pinchBeginZoom = nil + end + end + + if fingerTouches[input] ~= nil and fingerTouches[input] == false then + NumUnsunkTouches = NumUnsunkTouches - 1 + end + fingerTouches[input] = nil + inputStartPositions[input] = nil + inputStartTimes[input] = nil + end + + local function OnMousePanButtonPressed(input, processed) + if processed then return end + this:UpdateMouseBehavior() + panBeginLook = panBeginLook or this:GetCameraLook() + startPos = startPos or input.Position + lastPos = lastPos or startPos + this.UserPanningTheCamera = true + end + + local function OnMousePanButtonReleased(input, processed) + this:UpdateMouseBehavior() + if not (isRightMouseDown or isMiddleMouseDown) then + panBeginLook = nil + startPos = nil + lastPos = nil + this.UserPanningTheCamera = false + end + end + + local function OnMouse2Down(input, processed) + if processed then return end + + isRightMouseDown = true + OnMousePanButtonPressed(input, processed) + end + + local function OnMouse2Up(input, processed) + isRightMouseDown = false + OnMousePanButtonReleased(input, processed) + end + + local function OnMouse3Down(input, processed) + if processed then return end + + isMiddleMouseDown = true + OnMousePanButtonPressed(input, processed) + end + + local function OnMouse3Up(input, processed) + isMiddleMouseDown = false + OnMousePanButtonReleased(input, processed) + end + + local function OnMouseMoved(input, processed) + if not hasGameLoaded and VRService.VREnabled then + return + end + + local inputDelta = input.Delta + inputDelta = Vector2.new(inputDelta.X, inputDelta.Y * GameSettings:GetCameraYInvertValue()) + + if startPos and lastPos and panBeginLook then + local currPos = lastPos + input.Delta + local totalTrans = currPos - startPos + if this.PanEnabled then + local desiredXYVector = this:MouseTranslationToAngle(inputDelta) * MOUSE_SENSITIVITY + this.RotateInput = this.RotateInput + desiredXYVector + end + lastPos = currPos + elseif this:IsInFirstPerson() or this:GetShiftLock() then + if this.PanEnabled then + local desiredXYVector = this:MouseTranslationToAngle(inputDelta) * MOUSE_SENSITIVITY + this.RotateInput = this.RotateInput + desiredXYVector + end + end + end + + local function OnMouseWheel(input, processed) + if not hasGameLoaded and VRService.VREnabled then + return + end + if not processed then + if this.ZoomEnabled then + this:ZoomCameraBy(clamp(-1, 1, -input.Position.Z) * 1.4) + end + end + end + + local function round(num) + return math_floor(num + 0.5) + end + + local eight2Pi = math_pi / 4 + + local function rotateVectorByAngleAndRound(camLook, rotateAngle, roundAmount) + if camLook ~= ZERO_VECTOR3 then + camLook = camLook.unit + local currAngle = math_atan2(camLook.z, camLook.x) + local newAngle = round((math_atan2(camLook.z, camLook.x) + rotateAngle) / roundAmount) * roundAmount + return newAngle - currAngle + end + return 0 + end + + local function OnKeyDown(input, processed) + if not hasGameLoaded and VRService.VREnabled then + return + end + if processed then return end + if this.ZoomEnabled then + if input.KeyCode == Enum.KeyCode.I then + this:ZoomCameraBy(-5) + elseif input.KeyCode == Enum.KeyCode.O then + this:ZoomCameraBy(5) + end + end + if panBeginLook == nil and this.KeyPanEnabled then + if input.KeyCode == Enum.KeyCode.Left then + this.TurningLeft = true + elseif input.KeyCode == Enum.KeyCode.Right then + this.TurningRight = true + elseif input.KeyCode == Enum.KeyCode.Comma then + local angle = rotateVectorByAngleAndRound(this:GetCameraLook() * Vector3.new(1,0,1), -eight2Pi * (3/4), eight2Pi) + if angle ~= 0 then + this.RotateInput = this.RotateInput + Vector2.new(angle, 0) + this.LastUserPanCamera = tick() + this.LastCameraTransform = nil + end + elseif input.KeyCode == Enum.KeyCode.Period then + local angle = rotateVectorByAngleAndRound(this:GetCameraLook() * Vector3.new(1,0,1), eight2Pi * (3/4), eight2Pi) + if angle ~= 0 then + this.RotateInput = this.RotateInput + Vector2.new(angle, 0) + this.LastUserPanCamera = tick() + this.LastCameraTransform = nil + end + elseif input.KeyCode == Enum.KeyCode.PageUp then + --elseif input.KeyCode == Enum.KeyCode.Home then + this.RotateInput = this.RotateInput + Vector2.new(0,math.rad(15)) + --this.LastCameraTransform = nil + elseif input.KeyCode == Enum.KeyCode.PageDown then + --elseif input.KeyCode == Enum.KeyCode.End then + this.RotateInput = this.RotateInput + Vector2.new(0,math.rad(-15)) + --this.LastCameraTransform = nil + end + end + end + + local function CameraTiltUp() + this.RotateInput = this.RotateInput + Vector2.new(0,math.rad(15)) + --this.LastCameraTransform = nil + end + + local function CameraTiltDown() + this.RotateInput = this.RotateInput + Vector2.new(0,math.rad(-15)) + --this.LastCameraTransform = nil + end + + local function CameraZoomIn() + if this.ZoomEnabled then + this:ZoomCameraBy(clamp(-1, 1, -1) * 1.4) + end + end + + local function CameraZoomOut() + if this.ZoomEnabled then + this:ZoomCameraBy(clamp(-1, 1, 1) * 1.4) + end + end + + --ME HOOKING UP FUNCTIONS IN THE FUNCTIONS INIT EPIC!!!!!!!!! + GuiRoot.CameraControl.CameraButtons.CameraTiltUp.MouseButton1Click:Connect(CameraTiltUp) + GuiRoot.CameraControl.CameraButtons.CameraTiltDown.MouseButton1Click:Connect(CameraTiltDown) + GuiRoot.CameraControl.CameraButtons.CameraZoomIn.MouseButton1Click:Connect(CameraZoomIn) + GuiRoot.CameraControl.CameraButtons.CameraZoomOut.MouseButton1Click:Connect(CameraZoomOut) + + local function OnKeyUp(input, processed) + if input.KeyCode == Enum.KeyCode.Left then + this.TurningLeft = false + elseif input.KeyCode == Enum.KeyCode.Right then + this.TurningRight = false + end + end + + local function onWindowFocusReleased() + this:ResetInputStates() + end + + local lastThumbstickRotate = nil + local numOfSeconds = 0.7 + local currentSpeed = 0 + local maxSpeed = 6 + local vrMaxSpeed = 4 + local lastThumbstickPos = Vector2.new(0,0) + local ySensitivity = 0.65 + local lastVelocity = nil + + -- K is a tunable parameter that changes the shape of the S-curve + -- the larger K is the more straight/linear the curve gets + local k = 0.35 + local lowerK = 0.8 + local function SCurveTranform(t) + t = clamp(-1,1,t) + if t >= 0 then + return (k*t) / (k - t + 1) + end + return -((lowerK*-t) / (lowerK + t + 1)) + end + + -- DEADZONE + local DEADZONE = 0.1 + local function toSCurveSpace(t) + return (1 + DEADZONE) * (2*math.abs(t) - 1) - DEADZONE + end + + local function fromSCurveSpace(t) + return t/2 + 0.5 + end + + local function gamepadLinearToCurve(thumbstickPosition) + local function onAxis(axisValue) + local sign = 1 + if axisValue < 0 then + sign = -1 + end + local point = fromSCurveSpace(SCurveTranform(toSCurveSpace(math.abs(axisValue)))) + point = point * sign + return clamp(-1, 1, point) + end + return Vector2_new(onAxis(thumbstickPosition.x), onAxis(thumbstickPosition.y)) + end + + function this:UpdateGamepad() + local gamepadPan = this.GamepadPanningCamera + if gamepadPan and (hasGameLoaded or not VRService.VREnabled) then + gamepadPan = gamepadLinearToCurve(gamepadPan) + local currentTime = tick() + if gamepadPan.X ~= 0 or gamepadPan.Y ~= 0 then + this.userPanningTheCamera = true + elseif gamepadPan == ZERO_VECTOR2 then + lastThumbstickRotate = nil + if lastThumbstickPos == ZERO_VECTOR2 then + currentSpeed = 0 + end + end + + local finalConstant = 0 + + if lastThumbstickRotate then + if VRService.VREnabled then + currentSpeed = vrMaxSpeed + else + local elapsedTime = (currentTime - lastThumbstickRotate) * 10 + currentSpeed = currentSpeed + (maxSpeed * ((elapsedTime*elapsedTime)/numOfSeconds)) + + if currentSpeed > maxSpeed then currentSpeed = maxSpeed end + + if lastVelocity then + local velocity = (gamepadPan - lastThumbstickPos)/(currentTime - lastThumbstickRotate) + local velocityDeltaMag = (velocity - lastVelocity).magnitude + + if velocityDeltaMag > 12 then + currentSpeed = currentSpeed * (20/velocityDeltaMag) + if currentSpeed > maxSpeed then currentSpeed = maxSpeed end + end + end + end + + local success, gamepadCameraSensitivity = pcall(function() return GameSettings.GamepadCameraSensitivity end) + finalConstant = success and (gamepadCameraSensitivity * currentSpeed) or currentSpeed + lastVelocity = (gamepadPan - lastThumbstickPos)/(currentTime - lastThumbstickRotate) + end + + lastThumbstickPos = gamepadPan + lastThumbstickRotate = currentTime + + return Vector2_new( gamepadPan.X * finalConstant, gamepadPan.Y * finalConstant * ySensitivity * GameSettings:GetCameraYInvertValue()) + end + + return ZERO_VECTOR2 + end + + local InputBeganConn, InputChangedConn, InputEndedConn, WindowUnfocusConn, MenuOpenedConn, ShiftLockToggleConn, GamepadConnectedConn, GamepadDisconnectedConn, TouchActivateConn = nil, nil, nil, nil, nil, nil, nil, nil, nil + + function this:DisconnectInputEvents() + if InputBeganConn then + InputBeganConn:disconnect() + InputBeganConn = nil + end + if InputChangedConn then + InputChangedConn:disconnect() + InputChangedConn = nil + end + if InputEndedConn then + InputEndedConn:disconnect() + InputEndedConn = nil + end + if WindowUnfocusConn then + WindowUnfocusConn:disconnect() + WindowUnfocusConn = nil + end + if MenuOpenedConn then + MenuOpenedConn:disconnect() + MenuOpenedConn = nil + end + if ShiftLockToggleConn then + ShiftLockToggleConn:disconnect() + ShiftLockToggleConn = nil + end + if GamepadConnectedConn then + GamepadConnectedConn:disconnect() + GamepadConnectedConn = nil + end + if GamepadDisconnectedConn then + GamepadDisconnectedConn:disconnect() + GamepadDisconnectedConn = nil + end + if subjectStateChangedConn then + subjectStateChangedConn:disconnect() + subjectStateChangedConn = nil + end + if workspaceChangedConn then + workspaceChangedConn:disconnect() + workspaceChangedConn = nil + end + if TouchActivateConn then + TouchActivateConn:disconnect() + TouchActivateConn = nil + end + + this.TurningLeft = false + this.TurningRight = false + this.LastCameraTransform = nil + self.LastSubjectCFrame = nil + this.UserPanningTheCamera = false + this.RotateInput = Vector2.new() + this.GamepadPanningCamera = Vector2.new(0,0) + + -- Reset input states + startPos = nil + lastPos = nil + panBeginLook = nil + isRightMouseDown = false + isMiddleMouseDown = false + + fingerTouches = {} + NumUnsunkTouches = 0 + + StartingDiff = nil + pinchBeginZoom = nil + + -- Unlock mouse for example if right mouse button was being held down + if UserInputService.MouseBehavior ~= Enum.MouseBehavior.LockCenter then + UserInputService.MouseBehavior = Enum.MouseBehavior.Default + end + end + + function this:ResetInputStates() + isRightMouseDown = false + isMiddleMouseDown = false + this.TurningRight = false + this.TurningLeft = false + OnMousePanButtonReleased() -- this function doesn't seem to actually need parameters + + if UserInputService.TouchEnabled then + --[[menu opening was causing serious touch issues + this should disable all active touch events if + they're active when menu opens.]] + for inputObject, value in pairs(fingerTouches) do + fingerTouches[inputObject] = nil + end + panBeginLook = nil + startPos = nil + lastPos = nil + this.UserPanningTheCamera = false + StartingDiff = nil + pinchBeginZoom = nil + NumUnsunkTouches = 0 + end + end + + function this.getGamepadPan(name, state, input) + if state == Enum.UserInputState.Cancel then + this.GamepadPanningCamera = ZERO_VECTOR2 + return + end + + if input.UserInputType == this.activeGamepad and input.KeyCode == Enum.KeyCode.Thumbstick2 then + local inputVector = Vector2.new(input.Position.X, -input.Position.Y) + if inputVector.magnitude > THUMBSTICK_DEADZONE then + this.GamepadPanningCamera = Vector2_new(input.Position.X, -input.Position.Y) + else + this.GamepadPanningCamera = ZERO_VECTOR2 + end + end + end + + function this.doGamepadZoom(name, state, input) + if input.UserInputType == this.activeGamepad and input.KeyCode == Enum.KeyCode.ButtonR3 and state == Enum.UserInputState.Begin then + if this.ZoomEnabled then + if this:GetCameraZoom() > 0.5 then + this:ZoomCamera(0) + else + this:ZoomCamera(10) + end + end + end + end + + function this:BindGamepadInputActions() + ContextActionService:BindAction("RootCamGamepadPan", this.getGamepadPan, false, Enum.KeyCode.Thumbstick2) + ContextActionService:BindAction("RootCamGamepadZoom", this.doGamepadZoom, false, Enum.KeyCode.ButtonR3) + end + + function this:ConnectInputEvents() + InputBeganConn = UserInputService.InputBegan:connect(function(input, processed) + if input.UserInputType == Enum.UserInputType.Touch then + OnTouchBegan(input, processed) + elseif input.UserInputType == Enum.UserInputType.MouseButton2 then + OnMouse2Down(input, processed) + --elseif input.UserInputType == Enum.UserInputType.MouseButton3 then + --OnMouse3Down(input, processed) + end + -- Keyboard + if input.UserInputType == Enum.UserInputType.Keyboard then + OnKeyDown(input, processed) + end + end) + + InputChangedConn = UserInputService.InputChanged:connect(function(input, processed) + if input.UserInputType == Enum.UserInputType.Touch then + OnTouchChanged(input, processed) + elseif input.UserInputType == Enum.UserInputType.MouseMovement then + OnMouseMoved(input, processed) + elseif input.UserInputType == Enum.UserInputType.MouseWheel then + OnMouseWheel(input, processed) + end + end) + + InputEndedConn = UserInputService.InputEnded:connect(function(input, processed) + if input.UserInputType == Enum.UserInputType.Touch then + OnTouchEnded(input, processed) + elseif input.UserInputType == Enum.UserInputType.MouseButton2 then + OnMouse2Up(input, processed) + elseif input.UserInputType == Enum.UserInputType.MouseButton3 then + OnMouse3Up(input, processed) + end + -- Keyboard + if input.UserInputType == Enum.UserInputType.Keyboard then + OnKeyUp(input, processed) + end + end) + + WindowUnfocusConn = UserInputService.WindowFocusReleased:connect(onWindowFocusReleased) + + MenuOpenedConn = GuiService.MenuOpened:connect(function() + this:ResetInputStates() + end) + + workspaceChangedConn = workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(onCurrentCameraChanged) + if workspace.CurrentCamera then + onCurrentCameraChanged() + end + + ShiftLockToggleConn = ShiftLockController.OnShiftLockToggled.Event:connect(function() + this:UpdateMouseBehavior() + end) + + this.RotateInput = Vector2.new() + + this.activeGamepad = nil + local function assignActivateGamepad() + local connectedGamepads = UserInputService:GetConnectedGamepads() + if #connectedGamepads > 0 then + for i = 1, #connectedGamepads do + if this.activeGamepad == nil then + this.activeGamepad = connectedGamepads[i] + elseif connectedGamepads[i].Value < this.activeGamepad.Value then + this.activeGamepad = connectedGamepads[i] + end + end + end + + if this.activeGamepad == nil then -- nothing is connected, at least set up for gamepad1 + this.activeGamepad = Enum.UserInputType.Gamepad1 + end + end + + GamepadConnectedConn = UserInputService.GamepadDisconnected:connect(function(gamepadEnum) + if this.activeGamepad ~= gamepadEnum then return end + this.activeGamepad = nil + assignActivateGamepad() + end) + + GamepadDisconnectedConn = UserInputService.GamepadConnected:connect(function(gamepadEnum) + if this.activeGamepad == nil then + assignActivateGamepad() + end + end) + + self:BindGamepadInputActions() + + assignActivateGamepad() + + -- set mouse behavior + self:UpdateMouseBehavior() + end + + --Process tweens related to tap-to-recenter and double-tap-to-zoom + --Needs to be called from specific cameras on each update + function this:ProcessTweens() + for name, tween in pairs(tweens) do + local alpha = math.min(1.0, (tick() - tween.start)/tween.duration) + tween.to = tween.func(tween.from, tween.to, alpha) + if math.abs(1 - alpha) < 0.0001 then + tweens[name] = nil + end + end + end + + function this:SetEnabled(newState) + if newState ~= self.Enabled then + self.Enabled = newState + if self.Enabled then + self:ConnectInputEvents() + self.cframe = workspace.CurrentCamera.CFrame + else + self:DisconnectInputEvents() + end + end + end + + local function OnPlayerAdded(player) + player.Changed:connect(function(prop) + if this.Enabled then + if prop == "CameraMode" or prop == "CameraMaxZoomDistance" or prop == "CameraMinZoomDistance" then + this:ZoomCameraFixedBy(0) + end + end + end) + + local function OnCharacterAdded(newCharacter) + + local humanoid = findPlayerHumanoid(player) + local start = tick() + while tick() - start < 0.3 and (humanoid == nil or humanoid.Torso == nil) do + wait() + humanoid = findPlayerHumanoid(player) + end + + if humanoid and humanoid.Torso and player.Character == newCharacter then + local newDesiredLook = (humanoid.Torso.CFrame.lookVector - Vector3.new(0, math.sin(math.rad(DEFAULT_CAMERA_ANGLE)), 0)).unit + local horizontalShift = findAngleBetweenXZVectors(newDesiredLook, this:GetCameraLook()) + local vertShift = math.asin(this:GetCameraLook().y) - math.asin(newDesiredLook.y) + if not IsFinite(horizontalShift) then + horizontalShift = 0 + end + if not IsFinite(vertShift) then + vertShift = 0 + end + this.RotateInput = Vector2.new(horizontalShift, vertShift) + + -- reset old camera info so follow cam doesn't rotate us + this.LastCameraTransform = nil + end + + -- Need to wait for camera cframe to update before we zoom in + -- Not waiting will force camera to original cframe + wait() + this:ZoomCamera(this.DefaultZoom) + end + + player.CharacterAdded:connect(function(character) + if this.Enabled or SetCameraOnSpawn then + OnCharacterAdded(character) + SetCameraOnSpawn = false + end + end) + if player.Character then + spawn(function() OnCharacterAdded(player.Character) end) + end + end + if PlayersService.LocalPlayer then + OnPlayerAdded(PlayersService.LocalPlayer) + end + PlayersService.ChildAdded:connect(function(child) + if child and PlayersService.LocalPlayer == child then + OnPlayerAdded(PlayersService.LocalPlayer) + end + end) + + local function OnGameLoaded() + hasGameLoaded = true + end + + spawn(function() + if game:IsLoaded() then + OnGameLoaded() + else + game.Loaded:wait() + OnGameLoaded() + end + end) + + local function OnDynamicThumbstickEnabled() + if UserInputService.TouchEnabled then + isDynamicThumbstickEnabled = true + end + end + + local function OnDynamicThumbstickDisabled() + isDynamicThumbstickEnabled = false + end + + local function OnGameSettingsTouchMovementModeChanged() + if LocalPlayer.DevTouchMovementMode == Enum.DevTouchMovementMode.UserChoice then + if GameSettings.TouchMovementMode.Name == "DynamicThumbstick" then + OnDynamicThumbstickEnabled() + else + OnDynamicThumbstickDisabled() + end + end + end + + local function OnDevTouchMovementModeChanged() + if LocalPlayer.DevTouchMovementMode.Name == "DynamicThumbstick" then + OnDynamicThumbstickEnabled() + else + OnGameSettingsTouchMovementModeChanged() + end + end + + if PlayersService.LocalPlayer then + PlayersService.LocalPlayer.Changed:Connect(function(prop) + if prop == "DevTouchMovementMode" then + OnDevTouchMovementModeChanged() + end + end) + OnDevTouchMovementModeChanged() + end + + GameSettings.Changed:Connect(function(prop) + if prop == "TouchMovementMode" then + OnGameSettingsTouchMovementModeChanged() + end + end) + OnGameSettingsTouchMovementModeChanged() + GameSettings:SetCameraYInvertVisible() + pcall(function() GameSettings:SetGamepadCameraSensitivityVisible() end) + + return this +end + +return CreateCamera diff --git a/rojo/MainModule/src/StarterPlayerScripts/CameraScript/ShiftLockController.lua b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/ShiftLockController.lua new file mode 100644 index 0000000..796d6ab --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/ShiftLockController.lua @@ -0,0 +1,206 @@ +--[[ + // FileName: ShiftLockController + // Written by: jmargh + // Version 1.2 + // Description: Manages the state of shift lock mode + + // Required by: + RootCamera + + // Note: ContextActionService sinks keys, so until we allow binding to ContextActionService without sinking + // keys, this module will use UserInputService. +--]] + +local Players = game:GetService('Players') +local UserInputService = game:GetService('UserInputService') +-- Settings and GameSettings are read only +local Settings = UserSettings() -- ignore warning +local GameSettings = Settings.GameSettings + +local ShiftLockController = {} + +--[[ Script Variables ]]-- +while not Players.LocalPlayer do + Players.PlayerAdded:wait() +end + +local LocalPlayer = Players.LocalPlayer +local Mouse = LocalPlayer:GetMouse() +local PlayerGui = LocalPlayer:WaitForChild('PlayerGui') +local ScreenGui = nil +local ShiftLockIcon = nil +local InputCn = nil +local IsShiftLockMode = false +local IsShiftLocked = false +local IsActionBound = false +local IsInFirstPerson = false + +-- Toggle Event +ShiftLockController.OnShiftLockToggled = Instance.new('BindableEvent') + +-- wrapping long conditional in function +local function isShiftLockMode() + return LocalPlayer.DevEnableMouseLock and GameSettings.ControlMode == Enum.ControlMode.MouseLockSwitch and + LocalPlayer.DevComputerMovementMode ~= Enum.DevComputerMovementMode.ClickToMove and + GameSettings.ComputerMovementMode ~= Enum.ComputerMovementMode.ClickToMove and + LocalPlayer.DevComputerMovementMode ~= Enum.DevComputerMovementMode.Scriptable +end + +if not UserInputService.TouchEnabled then -- TODO: Remove when safe on mobile + IsShiftLockMode = isShiftLockMode() +end + +--[[ Constants ]]-- +local SHIFT_LOCK_OFF = 'rbxasset://textures/ui/mouseLock_off.png' +local SHIFT_LOCK_ON = 'rbxasset://textures/ui/mouseLock_on.png' +local SHIFT_LOCK_CURSOR = 'rbxasset://textures/MouseLockedCursor.png' + +--[[ Local Functions ]]-- +local function onShiftLockToggled() + IsShiftLocked = not IsShiftLocked + if IsShiftLocked then + ShiftLockIcon.Image = SHIFT_LOCK_ON + Mouse.Icon = SHIFT_LOCK_CURSOR + else + ShiftLockIcon.Image = SHIFT_LOCK_OFF + Mouse.Icon = "" + end + ShiftLockController.OnShiftLockToggled:Fire() +end + +local function initialize() + if ScreenGui then + ScreenGui:Destroy() + ScreenGui = nil + end + ScreenGui = Instance.new('ScreenGui') + ScreenGui.Name = "ControlGui" + + local frame = Instance.new('Frame') + frame.Name = "BottomLeftControl" + frame.Size = UDim2.new(0, 130, 0, 46) + frame.Position = UDim2.new(0, 0, 1, -46) + frame.BackgroundTransparency = 1 + frame.Parent = ScreenGui + + ShiftLockIcon = Instance.new('ImageButton') + ShiftLockIcon.Name = "MouseLockLabel" + ShiftLockIcon.Size = UDim2.new(0, 31, 0, 31) + ShiftLockIcon.Position = UDim2.new(0, 12, 0, 2) + ShiftLockIcon.BackgroundTransparency = 1 + ShiftLockIcon.Image = IsShiftLocked and SHIFT_LOCK_ON or SHIFT_LOCK_OFF + ShiftLockIcon.Visible = true + ShiftLockIcon.Parent = frame + + ShiftLockIcon.MouseButton1Click:connect(onShiftLockToggled) + + ScreenGui.Parent = IsShiftLockMode and PlayerGui or nil +end + +--[[ Public API ]]-- +function ShiftLockController:IsShiftLocked() + return IsShiftLockMode and IsShiftLocked +end + +function ShiftLockController:SetIsInFirstPerson(isInFirstPerson) + --IsInFirstPerson = isInFirstPerson --line 106 +end + +--[[ Input/Settings Changed Events ]]-- +local mouseLockSwitchFunc = function(actionName, inputState, inputObject) + if IsShiftLockMode then + onShiftLockToggled() + end +end + +local function disableShiftLock() + if ScreenGui then ScreenGui.Parent = nil end + IsShiftLockMode = false + Mouse.Icon = "" + if InputCn then + InputCn:disconnect() + InputCn = nil + end + IsActionBound = false + ShiftLockController.OnShiftLockToggled:Fire() +end + +-- TODO: Remove when we figure out ContextActionService without sinking keys +local function onShiftInputBegan(inputObject, isProcessed) + if isProcessed then return end + if inputObject.UserInputType == Enum.UserInputType.Keyboard and + (inputObject.KeyCode == Enum.KeyCode.LeftShift or inputObject.KeyCode == Enum.KeyCode.RightShift) then + -- + mouseLockSwitchFunc() + end +end + +local function enableShiftLock() + IsShiftLockMode = isShiftLockMode() + if IsShiftLockMode then + if ScreenGui then + ScreenGui.Parent = PlayerGui + end + if IsShiftLocked then + Mouse.Icon = SHIFT_LOCK_CURSOR + ShiftLockController.OnShiftLockToggled:Fire() + end + if not IsActionBound then + InputCn = UserInputService.InputBegan:connect(onShiftInputBegan) + IsActionBound = true + end + end +end + +GameSettings.Changed:connect(function(property) + if property == 'ControlMode' then + if GameSettings.ControlMode == Enum.ControlMode.MouseLockSwitch then + enableShiftLock() + else + disableShiftLock() + end + elseif property == 'ComputerMovementMode' then + if GameSettings.ComputerMovementMode == Enum.ComputerMovementMode.ClickToMove then + disableShiftLock() + else + enableShiftLock() + end + end +end) + +LocalPlayer.Changed:connect(function(property) + if property == 'DevEnableMouseLock' then + if LocalPlayer.DevEnableMouseLock then + enableShiftLock() + else + disableShiftLock() + end + elseif property == 'DevComputerMovementMode' then + if LocalPlayer.DevComputerMovementMode == Enum.DevComputerMovementMode.ClickToMove or + LocalPlayer.DevComputerMovementMode == Enum.DevComputerMovementMode.Scriptable then + -- + disableShiftLock() + else + enableShiftLock() + end + end +end) + +LocalPlayer.CharacterAdded:connect(function(character) + -- we need to recreate guis on character load + if not UserInputService.TouchEnabled then + initialize() + end +end) + +--[[ Initialization ]]-- + -- TODO: Remove when safe! ContextActionService crashes touch clients with tupele is 2 or more +if not UserInputService.TouchEnabled then + initialize() + if isShiftLockMode() then + InputCn = UserInputService.InputBegan:connect(onShiftInputBegan) + IsActionBound = true + end +end + +return ShiftLockController diff --git a/rojo/MainModule/src/StarterPlayerScripts/CameraScript/init.client.lua b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/init.client.lua new file mode 100644 index 0000000..d094a66 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/CameraScript/init.client.lua @@ -0,0 +1,324 @@ +local RunService = game:GetService('RunService') +local UserInputService = game:GetService('UserInputService') +local PlayersService = game:GetService('Players') +local VRService = game:GetService("VRService") +local StarterPlayer = game:GetService('StarterPlayer') + +local RootCamera = script:WaitForChild('RootCamera') + +local AttachCamera = require(RootCamera:WaitForChild('AttachCamera'))() +local FixedCamera = require(RootCamera:WaitForChild('FixedCamera'))() +local ScriptableCamera = require(RootCamera:WaitForChild('ScriptableCamera'))() +local TrackCamera = require(RootCamera:WaitForChild('TrackCamera'))() +local WatchCamera = require(RootCamera:WaitForChild('WatchCamera'))() + +local OrbitalCamera = require(RootCamera:WaitForChild('OrbitalCamera'))() +local ClassicCamera = require(RootCamera:WaitForChild('ClassicCamera'))() +local FollowCamera = require(RootCamera:WaitForChild('FollowCamera'))() +local PopperCam = require(script:WaitForChild('PopperCam')) +local Invisicam = require(script:WaitForChild('Invisicam')) +--local TransparencyController = require(script:WaitForChild('TransparencyController'))() + +--local VRCamera = require(RootCamera:WaitForChild("VRCamera"))() + +local GameSettings = UserSettings().GameSettings + +local AllCamerasInLua = false +local success, msg = pcall(function() + --AllCamerasInLua = UserSettings():IsUserFeatureEnabled("UserAllCamerasInLua") + AllCamerasInLua = true +end) +if not success then + print("Couldn't get feature UserAllCamerasInLua because:" , msg) +end + +local FFlagUserNoCameraClickToMoveSuccess, FFlagUserNoCameraClickToMoveResult = pcall(function() return UserSettings():IsUserFeatureEnabled("UserNoCameraClickToMove") end) +local FFlagUserNoCameraClickToMove = FFlagUserNoCameraClickToMoveSuccess and FFlagUserNoCameraClickToMoveResult + +local isOrbitalCameraEnabled = pcall(function() local test = Enum.CameraType.Orbital end) + +-- register what camera scripts we are using +do + local PlayerScripts = PlayersService.LocalPlayer:WaitForChild("PlayerScripts") + local canRegisterCameras = pcall(function() PlayerScripts:RegisterTouchCameraMovementMode(Enum.TouchCameraMovementMode.Default) end) + + if canRegisterCameras then + PlayerScripts:RegisterTouchCameraMovementMode(Enum.TouchCameraMovementMode.Follow) + PlayerScripts:RegisterTouchCameraMovementMode(Enum.TouchCameraMovementMode.Classic) + + PlayerScripts:RegisterComputerCameraMovementMode(Enum.ComputerCameraMovementMode.Default) + PlayerScripts:RegisterComputerCameraMovementMode(Enum.ComputerCameraMovementMode.Follow) + PlayerScripts:RegisterComputerCameraMovementMode(Enum.ComputerCameraMovementMode.Classic) + end +end + +local CameraTypeEnumMap = + { + [Enum.CameraType.Attach] = AttachCamera; + [Enum.CameraType.Fixed] = FixedCamera; + [Enum.CameraType.Scriptable] = ScriptableCamera; + [Enum.CameraType.Track] = TrackCamera; + [Enum.CameraType.Watch] = WatchCamera; + [Enum.CameraType.Follow] = FollowCamera; + } + +if isOrbitalCameraEnabled then + CameraTypeEnumMap[Enum.CameraType.Orbital] = OrbitalCamera; +end + +local EnabledCamera = nil +local EnabledOcclusion = nil + +local cameraSubjectChangedConn = nil +local cameraTypeChangedConn = nil +local renderSteppedConn = nil + +local lastInputType = nil +local hasLastInput = false + +local function IsTouch() + return UserInputService.TouchEnabled +end + +local function shouldUsePlayerScriptsCamera() + local player = PlayersService.LocalPlayer + local currentCamera = workspace.CurrentCamera + if AllCamerasInLua then + return true + else + if player then + if currentCamera == nil or (currentCamera.CameraType == Enum.CameraType.Custom) + or (isOrbitalCameraEnabled and currentCamera.CameraType == Enum.CameraType.Orbital) then + return true + end + end + end + return false +end + +local function isClickToMoveOn() + local usePlayerScripts = shouldUsePlayerScriptsCamera() + local player = PlayersService.LocalPlayer + if usePlayerScripts and player then + if (hasLastInput and lastInputType == Enum.UserInputType.Touch) or IsTouch() then -- Touch + if player.DevTouchMovementMode == Enum.DevTouchMovementMode.ClickToMove or + (player.DevTouchMovementMode == Enum.DevTouchMovementMode.UserChoice and GameSettings.TouchMovementMode == Enum.TouchMovementMode.ClickToMove) then + return true + end + else -- Computer + if player.DevComputerMovementMode == Enum.DevComputerMovementMode.ClickToMove or + (player.DevComputerMovementMode == Enum.DevComputerMovementMode.UserChoice and GameSettings.ComputerMovementMode == Enum.ComputerMovementMode.ClickToMove) then + return true + end + end + end + return false +end + +local function getCurrentCameraMode() + local usePlayerScripts = shouldUsePlayerScriptsCamera() + local player = PlayersService.LocalPlayer + if usePlayerScripts and player then + if (hasLastInput and lastInputType == Enum.UserInputType.Touch) or IsTouch() then -- Touch (iPad, etc...) + if not FFlagUserNoCameraClickToMove and isClickToMoveOn() then + return Enum.DevTouchMovementMode.ClickToMove.Name + elseif player.DevTouchCameraMode == Enum.DevTouchCameraMovementMode.UserChoice then + local touchMovementMode = GameSettings.TouchCameraMovementMode + if touchMovementMode == Enum.TouchCameraMovementMode.Default then + return Enum.TouchCameraMovementMode.Follow.Name + end + return touchMovementMode.Name + else + return player.DevTouchCameraMode.Name + end + else -- Computer + if not FFlagUserNoCameraClickToMove and isClickToMoveOn() then + return Enum.DevComputerMovementMode.ClickToMove.Name + elseif player.DevComputerCameraMode == Enum.DevComputerCameraMovementMode.UserChoice then + local computerMovementMode = GameSettings.ComputerCameraMovementMode + if computerMovementMode == Enum.ComputerCameraMovementMode.Default then + return Enum.ComputerCameraMovementMode.Classic.Name + end + return computerMovementMode.Name + else + return player.DevComputerCameraMode.Name + end + end + end +end + +local function getCameraOcclusionMode() + local usePlayerScripts = shouldUsePlayerScriptsCamera() + local player = PlayersService.LocalPlayer + if usePlayerScripts and player then + return player.DevCameraOcclusionMode + end +end + +-- New for AllCameraInLua support +local function shouldUseOcclusionModule() + local player = PlayersService.LocalPlayer + if player and workspace.CurrentCamera and workspace.CurrentCamera.CameraType == Enum.CameraType.Custom then + return true + end + return false +end + +local function Update() + if EnabledCamera then + EnabledCamera:Update() + end + if EnabledOcclusion and not VRService.VREnabled then + EnabledOcclusion:Update(EnabledCamera) + end + if shouldUsePlayerScriptsCamera() then + --TransparencyController:Update() + end +end + +local function SetEnabledCamera(newCamera) + if EnabledCamera ~= newCamera then + if EnabledCamera then + EnabledCamera:SetEnabled(false) + end + EnabledCamera = newCamera + if EnabledCamera then + EnabledCamera:SetEnabled(true) + end + end +end + +local function OnCameraMovementModeChange(newCameraMode) + if newCameraMode == Enum.DevComputerMovementMode.ClickToMove.Name then + if FFlagUserNoCameraClickToMove then + --No longer responding to ClickToMove here! + return + end + SetEnabledCamera(nil) + --TransparencyController:SetEnabled(true) + else + local currentCameraType = workspace.CurrentCamera and workspace.CurrentCamera.CameraType + if VRService.VREnabled and currentCameraType ~= Enum.CameraType.Scriptable then + --SetEnabledCamera(VRCamera) + --TransparencyController:SetEnabled(false) + elseif (currentCameraType == Enum.CameraType.Custom or not AllCamerasInLua) and newCameraMode == Enum.ComputerCameraMovementMode.Classic.Name then + SetEnabledCamera(ClassicCamera) + --TransparencyController:SetEnabled(true) + elseif (currentCameraType == Enum.CameraType.Custom or not AllCamerasInLua) and newCameraMode == Enum.ComputerCameraMovementMode.Follow.Name then + SetEnabledCamera(FollowCamera) + --TransparencyController:SetEnabled(true) + elseif (currentCameraType == Enum.CameraType.Custom or not AllCamerasInLua) and (isOrbitalCameraEnabled and (newCameraMode == Enum.ComputerCameraMovementMode.Orbital.Name)) then + SetEnabledCamera(OrbitalCamera) + --TransparencyController:SetEnabled(true) + elseif AllCamerasInLua and CameraTypeEnumMap[currentCameraType] then + SetEnabledCamera(CameraTypeEnumMap[currentCameraType]) + --TransparencyController:SetEnabled(false) + else -- Our camera movement code was disabled by the developer + SetEnabledCamera(nil) + --TransparencyController:SetEnabled(false) + end + end + + local useOcclusion = shouldUseOcclusionModule() + local newOcclusionMode = getCameraOcclusionMode() + if EnabledOcclusion == Invisicam and (newOcclusionMode ~= Enum.DevCameraOcclusionMode.Invisicam or (not useOcclusion)) then + Invisicam:Cleanup() + end + + -- PopperCam does not work with OrbitalCamera, as OrbitalCamera's distance can be fixed. + if useOcclusion then + if newOcclusionMode == Enum.DevCameraOcclusionMode.Zoom and ( isOrbitalCameraEnabled and newCameraMode ~= Enum.ComputerCameraMovementMode.Orbital.Name ) then + EnabledOcclusion = PopperCam + elseif newOcclusionMode == Enum.DevCameraOcclusionMode.Invisicam then + EnabledOcclusion = Invisicam + else + EnabledOcclusion = PopperCam + end + else + EnabledOcclusion = PopperCam + end +end + +local function OnCameraTypeChanged(newCameraType) + if newCameraType == Enum.CameraType.Scriptable then + UserInputService.MouseBehavior = Enum.MouseBehavior.Default + end +end + + +local function OnCameraSubjectChanged(newSubject) + --TransparencyController:SetSubject(newSubject) +end + +local function OnNewCamera() + OnCameraMovementModeChange(getCurrentCameraMode()) + + local currentCamera = workspace.CurrentCamera + if currentCamera then + if cameraSubjectChangedConn then + cameraSubjectChangedConn:disconnect() + end + + if cameraTypeChangedConn then + cameraTypeChangedConn:disconnect() + end + + cameraSubjectChangedConn = currentCamera:GetPropertyChangedSignal("CameraSubject"):connect(function() + OnCameraSubjectChanged(currentCamera.CameraSubject) + end) + + cameraTypeChangedConn = currentCamera:GetPropertyChangedSignal("CameraType"):connect(function() + OnCameraMovementModeChange(getCurrentCameraMode()) + OnCameraTypeChanged(currentCamera.CameraType) + end) + + OnCameraSubjectChanged(currentCamera.CameraSubject) + OnCameraTypeChanged(currentCamera.CameraType) + end +end + + +local function OnPlayerAdded(player) + workspace.Changed:connect(function(prop) + if prop == 'CurrentCamera' then + OnNewCamera() + end + end) + + player.Changed:connect(function(prop) + OnCameraMovementModeChange(getCurrentCameraMode()) + end) + + GameSettings.Changed:connect(function(prop) + OnCameraMovementModeChange(getCurrentCameraMode()) + end) + + RunService:BindToRenderStep("cameraRenderUpdate", Enum.RenderPriority.Camera.Value, Update) + + OnNewCamera() + OnCameraMovementModeChange(getCurrentCameraMode()) +end + +do + while PlayersService.LocalPlayer == nil do PlayersService.PlayerAdded:wait() end + hasLastInput = pcall(function() + lastInputType = UserInputService:GetLastInputType() + UserInputService.LastInputTypeChanged:connect(function(newLastInputType) + lastInputType = newLastInputType + end) + end) + OnPlayerAdded(PlayersService.LocalPlayer) +end + +local function OnVREnabled() + OnCameraMovementModeChange(getCurrentCameraMode()) +end + +VRService:GetPropertyChangedSignal("VREnabled"):connect(OnVREnabled) + +--set camera type to follow (stanky method but dont care BTW): +workspace.Camera.CameraType = Enum.CameraType.Follow + +workspace.Camera:GetPropertyChangedSignal("CameraType"):Connect(function() + workspace.Camera.CameraType = Enum.CameraType.Follow +end) \ No newline at end of file diff --git a/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/DPad.lua b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/DPad.lua new file mode 100644 index 0000000..ff70e19 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/DPad.lua @@ -0,0 +1,170 @@ +--[[ + // FileName: DPad + // Version 1.0 + // Written by: jmargh + // Description: Implements DPad controls for touch devices +--]] + +local Players = game:GetService('Players') +local GuiService = game:GetService('GuiService') + +local DPad = {} + +local MasterControl = require(script.Parent) + +--[[ Script Variables ]]-- +while not Players.LocalPlayer do + wait() +end +local LocalPlayer = Players.LocalPlayer +local DPadFrame = nil +local TouchObject = nil +local OnInputEnded = nil -- defined in Create() + +--[[ Constants ]]-- +local DPAD_SHEET = "rbxasset://textures/ui/DPadSheet.png" +local COMPASS_DIR = { + Vector3.new(1, 0, 0), -- E + Vector3.new(1, 0, 1).Unit, -- SE + Vector3.new(0, 0, 1), -- S + Vector3.new(-1, 0, 1).Unit, -- SW + Vector3.new(-1, 0, 0), -- W + Vector3.new(-1, 0, -1).Unit, -- NW + Vector3.new(0, 0, -1), -- N + Vector3.new(1, 0, -1).Unit, -- NE +} + +--[[ lua Function Cache ]]-- +local ATAN2 = math.atan2 +local FLOOR = math.floor +local PI = math.pi + +--[[ Local Functions ]]-- +local function createArrowLabel(name, position, size, rectOffset, rectSize) + local image = Instance.new('ImageLabel') + image.Name = name + image.Image = DPAD_SHEET + image.ImageRectOffset = rectOffset + image.ImageRectSize = rectSize + image.BackgroundTransparency = 1 + image.Size = size + image.Position = position + image.Parent = DPadFrame + + return image +end + +local function getCenterPosition() + return Vector2.new(DPadFrame.AbsolutePosition.x + DPadFrame.AbsoluteSize.x/2, DPadFrame.AbsolutePosition.y + DPadFrame.AbsoluteSize.y/2) +end + +--[[ Public API ]]-- +function DPad:Enable() + DPadFrame.Visible = true +end + +function DPad:Disable() + DPadFrame.Visible = false + OnInputEnded() +end + +function DPad:Create(parentFrame) + if DPadFrame then + DPadFrame:Destroy() + DPadFrame = nil + end + + local position = UDim2.new(0, 10, 1, -230) + DPadFrame = Instance.new('Frame') + DPadFrame.Name = "DPadFrame" + DPadFrame.Active = true + DPadFrame.Visible = false + DPadFrame.Size = UDim2.new(0, 192, 0, 192) + DPadFrame.Position = position + DPadFrame.BackgroundTransparency = 1 + + local smArrowSize = UDim2.new(0, 23, 0, 23) + local lgArrowSize = UDim2.new(0, 64, 0, 64) + local smImgOffset = Vector2.new(46, 46) + local lgImgOffset = Vector2.new(128, 128) + + local bBtn = createArrowLabel("BackButton", UDim2.new(0.5, -32, 1, -64), lgArrowSize, Vector2.new(0, 0), lgImgOffset) + local fBtn = createArrowLabel("ForwardButton", UDim2.new(0.5, -32, 0, 0), lgArrowSize, Vector2.new(0, 258), lgImgOffset) + local lBtn = createArrowLabel("LeftButton", UDim2.new(0, 0, 0.5, -32), lgArrowSize, Vector2.new(129, 129), lgImgOffset) + local rBtn = createArrowLabel("RightButton", UDim2.new(1, -64, 0.5, -32), lgArrowSize, Vector2.new(0, 129), lgImgOffset) + local jumpBtn = createArrowLabel("JumpButton", UDim2.new(0.5, -32, 0.5, -32), lgArrowSize, Vector2.new(129, 0), lgImgOffset) + local flBtn = createArrowLabel("ForwardLeftButton", UDim2.new(0, 35, 0, 35), smArrowSize, Vector2.new(129, 258), smImgOffset) + local frBtn = createArrowLabel("ForwardRightButton", UDim2.new(1, -55, 0, 35), smArrowSize, Vector2.new(176, 258), smImgOffset) + flBtn.Visible = false + frBtn.Visible = false + + -- input connections + jumpBtn.InputBegan:connect(function(inputObject) + MasterControl:DoJump() + end) + + local movementVector = Vector3.new(0,0,0) + local function normalizeDirection(inputPosition) + local jumpRadius = jumpBtn.AbsoluteSize.x/2 + local centerPosition = getCenterPosition() + local direction = Vector2.new(inputPosition.x - centerPosition.x, inputPosition.y - centerPosition.y) + + if direction.magnitude > jumpRadius then + local angle = ATAN2(direction.y, direction.x) + local octant = (FLOOR(8 * angle / (2 * PI) + 8.5)%8) + 1 + movementVector = COMPASS_DIR[octant] + end + + if not flBtn.Visible and movementVector == COMPASS_DIR[7] then + flBtn.Visible = true + frBtn.Visible = true + end + end + + DPadFrame.InputBegan:connect(function(inputObject) + if TouchObject or inputObject.UserInputType ~= Enum.UserInputType.Touch then + return + end + + MasterControl:AddToPlayerMovement(-movementVector) + + TouchObject = inputObject + normalizeDirection(TouchObject.Position) + + MasterControl:AddToPlayerMovement(movementVector) + end) + + DPadFrame.InputChanged:connect(function(inputObject) + if inputObject == TouchObject then + MasterControl:AddToPlayerMovement(-movementVector) + normalizeDirection(TouchObject.Position) + MasterControl:AddToPlayerMovement(movementVector) + MasterControl:SetIsJumping(false) + end + end) + + OnInputEnded = function() + TouchObject = nil + flBtn.Visible = false + frBtn.Visible = false + + MasterControl:AddToPlayerMovement(-movementVector) + movementVector = Vector3.new(0, 0, 0) + end + + DPadFrame.InputEnded:connect(function(inputObject) + if inputObject == TouchObject then + OnInputEnded() + end + end) + + GuiService.MenuOpened:connect(function() + if TouchObject then + OnInputEnded() + end + end) + + DPadFrame.Parent = parentFrame +end + +return DPad diff --git a/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/DynamicThumbstick.lua b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/DynamicThumbstick.lua new file mode 100644 index 0000000..fa468f5 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/DynamicThumbstick.lua @@ -0,0 +1,559 @@ +--[[ + // FileName: DynamicThumbstick + // Version 0.9 + // Written by: jhelms + // Description: Implements dynamic thumbstick controls for touch devices +--]] +local Players = game:GetService("Players") +local UserInputService = game:GetService("UserInputService") +local GuiService = game:GetService("GuiService") +local RunService = game:GetService("RunService") +local TweenService = game:GetService("TweenService") +local Settings = UserSettings() +local GameSettings = Settings.GameSettings + +local MasterControl = require(script.Parent) + +local Thumbstick = {} +local Enabled = false + +--[[ Script Variables ]]-- +while not Players.LocalPlayer do + Players.PlayerAdded:wait() +end +local LocalPlayer = Players.LocalPlayer + +local Tools = {} +local ToolEquipped = nil + +local RevertAutoJumpEnabledToFalse = false + +local ThumbstickFrame = nil +local GestureArea = nil +local StartImage = nil +local EndImage = nil +local MiddleImages = {} + +local MoveTouchObject = nil +local IsFollowStick = false +local ThumbstickFrame = nil +local OnMoveTouchEnded = nil -- defined in Create() +local OnTouchMovedCn = nil +local OnTouchEndedCn = nil +local TouchActivateCn = nil +local OnRenderSteppedCn = nil +local currentMoveVector = Vector3.new(0,0,0) +local IsFirstTouch = true + +--[[ Constants ]]-- + +local TOUCH_CONTROLS_SHEET = "rbxasset://textures/ui/Input/TouchControlsSheetV2.png" + +local MIDDLE_TRANSPARENCIES = { + 1 - 0.89, + 1 - 0.70, + 1 - 0.60, + 1 - 0.50, + 1 - 0.40, + 1 - 0.30, + 1 - 0.25 +} +local NUM_MIDDLE_IMAGES = #MIDDLE_TRANSPARENCIES + +local TOUCH_IS_TAP_TIME_THRESHOLD = 0.5 +local TOUCH_IS_TAP_DISTANCE_THRESHOLD = 25 + +local HasFadedBackgroundInPortrait = false +local HasFadedBackgroundInLandscape = false +local FadeInAndOutBackground = true +local FadeInAndOutMaxAlpha = 0.35 +local TweenInAlphaStart = nil +local TweenOutAlphaStart = nil + +local FADE_IN_OUT_HALF_DURATION_DEFAULT = 0.3 +local FADE_IN_OUT_HALF_DURATION_ORIENTATION_CHANGE = 2 +local FADE_IN_OUT_BALANCE_DEFAULT = 0.5 +local FadeInAndOutHalfDuration = FADE_IN_OUT_HALF_DURATION_DEFAULT +local FadeInAndOutBalance = FADE_IN_OUT_BALANCE_DEFAULT + +local ThumbstickFadeTweenInfo = TweenInfo.new(0.15, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut) + +--[[ Local functionality ]]-- + +local function isDynamicThumbstickEnabled() + return ThumbstickFrame and ThumbstickFrame.Visible +end + +local function enableAutoJump(humanoid) + if humanoid and isDynamicThumbstickEnabled() then + local shouldRevert = humanoid.AutoJumpEnabled == false + shouldRevert = shouldRevert and LocalPlayer.DevTouchMovementMode == Enum.DevTouchMovementMode.UserChoice + RevertAutoJumpEnabledToFalse = shouldRevert + humanoid.AutoJumpEnabled = true + end +end + +do + local function onCharacterAdded(character) + for _, child in ipairs(LocalPlayer.Character:GetChildren()) do + if child:IsA("Tool") then + ToolEquipped = child + end + end + character.ChildAdded:Connect(function(child) + if child:IsA("Tool") then + ToolEquipped = child + elseif child:IsA("Humanoid") then + enableAutoJump(child) + end + end) + character.ChildRemoved:Connect(function(child) + if child:IsA("Tool") then + if child == ToolEquipped then + ToolEquipped = nil + end + end + end) + + local humanoid = character:FindFirstChildOfClass("Humanoid") + if humanoid then + enableAutoJump(humanoid) + end + end + LocalPlayer.CharacterAdded:Connect(onCharacterAdded) + if LocalPlayer.Character then + onCharacterAdded(LocalPlayer.Character) + end +end + + + +--[[ Public API ]]-- +function Thumbstick:Enable() + Enabled = true + ThumbstickFrame.Visible = true + local humanoid = MasterControl:GetHumanoid() + enableAutoJump(humanoid) +end + +function Thumbstick:Disable() + Enabled = false + if RevertAutoJumpEnabledToFalse then + local humanoid = MasterControl:GetHumanoid() + if humanoid then + humanoid.AutoJumpEnabled = false + end + end + ThumbstickFrame.Visible = false + OnMoveTouchEnded() +end + +function Thumbstick:GetInputObject() + return MoveTouchObject +end + +function Thumbstick:Create(parentFrame) + if ThumbstickFrame then + ThumbstickFrame:Destroy() + ThumbstickFrame = nil + if OnTouchMovedCn then + OnTouchMovedCn:disconnect() + OnTouchMovedCn = nil + end + if OnTouchEndedCn then + OnTouchEndedCn:disconnect() + OnTouchEndedCn = nil + end + if OnRenderSteppedCn then + OnRenderSteppedCn:disconnect() + OnRenderSteppedCn = nil + end + if TouchActivateCn then + TouchActivateCn:disconnect() + TouchActivateCn = nil + end + end + + local ThumbstickSize = 45 + local ThumbstickRingSize = 20 + local MiddleSize = 10 + local MiddleSpacing = MiddleSize + 4 + local RadiusOfDeadZone = 2 + local RadiusOfMaxSpeed = 50 + + local screenSize = parentFrame.AbsoluteSize + local isBigScreen = math.min(screenSize.x, screenSize.y) > 500 + if isBigScreen then + ThumbstickSize = ThumbstickSize * 2 + ThumbstickRingSize = ThumbstickRingSize * 2 + MiddleSize = MiddleSize * 2 + MiddleSpacing = MiddleSpacing * 2 + RadiusOfDeadZone = RadiusOfDeadZone * 2 + RadiusOfMaxSpeed = RadiusOfMaxSpeed * 2 + end + + local color = Color3.fromRGB(255, 255, 255) + + local function layoutThumbstickFrame(portraitMode) + if portraitMode then + ThumbstickFrame.Size = UDim2.new(1, 0, 0.4, 0) + ThumbstickFrame.Position = UDim2.new(0, 0, 0.6, 0) + GestureArea.Size = UDim2.new(1, 0, 0.6, 0) + GestureArea.Position = UDim2.new(0, 0, 0, 0) + else + ThumbstickFrame.Size = UDim2.new(0.4, 0, 2/3, 0) + ThumbstickFrame.Position = UDim2.new(0, 0, 1/3, 0) + GestureArea.Size = UDim2.new(1, 0, 1, 0) + GestureArea.Position = UDim2.new(0, 0, 0, 0) + end + end + + GestureArea = Instance.new("Frame") + GestureArea.Name = "GestureArea" + GestureArea.Active = false + GestureArea.Visible = true + GestureArea.BackgroundTransparency = 1 + GestureArea.BackgroundColor3 = Color3.fromRGB(0, 0, 0) + + ThumbstickFrame = Instance.new('Frame') + ThumbstickFrame.Name = "DynamicThumbstickFrame" + ThumbstickFrame.Active = false + ThumbstickFrame.Visible = false + ThumbstickFrame.BackgroundTransparency = 1.0 + ThumbstickFrame.BackgroundColor3 = Color3.fromRGB(0, 0, 0) + layoutThumbstickFrame() + + StartImage = Instance.new("ImageLabel") + StartImage.Name = "ThumbstickStart" + StartImage.Visible = true + StartImage.BackgroundTransparency = 1 + + StartImage.Image = TOUCH_CONTROLS_SHEET + StartImage.ImageRectOffset = Vector2.new(1,1) + StartImage.ImageRectSize = Vector2.new(144, 144) + StartImage.ImageColor3 = Color3.new(0, 0, 0) + StartImage.AnchorPoint = Vector2.new(0.5, 0.5) + StartImage.Position = UDim2.new(0, ThumbstickRingSize * 3.3, 1, -ThumbstickRingSize * 2.8) + StartImage.Size = UDim2.new(0, ThumbstickRingSize * 3.7, 0, ThumbstickRingSize * 3.7) + StartImage.ZIndex = 10 + StartImage.Parent = ThumbstickFrame + + EndImage = Instance.new("ImageLabel") + EndImage.Name = "ThumbstickEnd" + EndImage.Visible = true + EndImage.BackgroundTransparency = 1 + EndImage.Image = TOUCH_CONTROLS_SHEET + EndImage.ImageRectOffset = Vector2.new(1,1) + EndImage.ImageRectSize = Vector2.new(144, 144) + EndImage.AnchorPoint = Vector2.new(0.5, 0.5) + EndImage.Position = StartImage.Position + EndImage.Size = UDim2.new(0, ThumbstickSize * 0.8, 0, ThumbstickSize * 0.8) + EndImage.ZIndex = 10 + EndImage.Parent = ThumbstickFrame + + for i = 1, NUM_MIDDLE_IMAGES do + MiddleImages[i] = Instance.new("ImageLabel") + MiddleImages[i].Name = "ThumbstickMiddle" + MiddleImages[i].Visible = false + MiddleImages[i].BackgroundTransparency = 1 + MiddleImages[i].Image = TOUCH_CONTROLS_SHEET + MiddleImages[i].ImageRectOffset = Vector2.new(1,1) + MiddleImages[i].ImageRectSize = Vector2.new(144, 144) + MiddleImages[i].ImageTransparency = MIDDLE_TRANSPARENCIES[i] + MiddleImages[i].AnchorPoint = Vector2.new(0.5, 0.5) + MiddleImages[i].ZIndex = 9 + MiddleImages[i].Parent = ThumbstickFrame + end + + local CameraChangedConn = nil + local function onCurrentCameraChanged() + if CameraChangedConn then + CameraChangedConn:Disconnect() + CameraChangedConn = nil + end + local newCamera = workspace.CurrentCamera + if newCamera then + local function onViewportSizeChanged() + local size = newCamera.ViewportSize + local portraitMode = size.X < size.Y + layoutThumbstickFrame(portraitMode) + end + CameraChangedConn = newCamera:GetPropertyChangedSignal("ViewportSize"):Connect(onViewportSizeChanged) + onViewportSizeChanged() + end + end + workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(onCurrentCameraChanged) + if workspace.CurrentCamera then + onCurrentCameraChanged() + end + + MoveTouchObject = nil + local MoveTouchStartTime = nil + local MoveTouchStartPosition = nil + + local startImageFadeTween, endImageFadeTween, middleImageFadeTweens = nil, nil, {} + local function fadeThumbstick(visible) + if not visible and MoveTouchObject then + return + end + if IsFirstTouch then return end + + if startImageFadeTween then + startImageFadeTween:Cancel() + end + if endImageFadeTween then + endImageFadeTween:Cancel() + end + for i = 1, #MiddleImages do + if middleImageFadeTweens[i] then + middleImageFadeTweens[i]:Cancel() + end + end + + if visible then + startImageFadeTween = TweenService:Create(StartImage, ThumbstickFadeTweenInfo, { ImageTransparency = 0 }) + startImageFadeTween:Play() + + endImageFadeTween = TweenService:Create(EndImage, ThumbstickFadeTweenInfo, { ImageTransparency = 0.2 }) + endImageFadeTween:Play() + + for i = 1, #MiddleImages do + middleImageFadeTweens[i] = TweenService:Create(MiddleImages[i], ThumbstickFadeTweenInfo, { ImageTransparency = MIDDLE_TRANSPARENCIES[i] }) + middleImageFadeTweens[i]:Play() + end + else + startImageFadeTween = TweenService:Create(StartImage, ThumbstickFadeTweenInfo, { ImageTransparency = 1 }) + startImageFadeTween:Play() + + endImageFadeTween = TweenService:Create(EndImage, ThumbstickFadeTweenInfo, { ImageTransparency = 1 }) + endImageFadeTween:Play() + + for i = 1, #MiddleImages do + middleImageFadeTweens[i] = TweenService:Create(MiddleImages[i], ThumbstickFadeTweenInfo, { ImageTransparency = 1 }) + middleImageFadeTweens[i]:Play() + end + end + end + local function fadeThumbstickFrame(fadeDuration, fadeRatio) + FadeInAndOutHalfDuration = fadeDuration * 0.5 + FadeInAndOutBalance = fadeRatio + TweenInAlphaStart = tick() + end + + local function doMove(direction) + MasterControl:AddToPlayerMovement(-currentMoveVector) + + currentMoveVector = direction + + -- Scaled Radial Dead Zone + local inputAxisMagnitude = currentMoveVector.magnitude + if inputAxisMagnitude < RadiusOfDeadZone then + currentMoveVector = Vector3.new() + else + currentMoveVector = currentMoveVector.unit*(1 - math.max(0, (RadiusOfMaxSpeed - currentMoveVector.magnitude)/RadiusOfMaxSpeed)) + currentMoveVector = Vector3.new(currentMoveVector.x, 0, currentMoveVector.y) + end + + MasterControl:AddToPlayerMovement(currentMoveVector) + end + + local function layoutMiddleImages(startPos, endPos) + local startDist = (ThumbstickSize / 2) + MiddleSize + local vector = endPos - startPos + local distAvailable = vector.magnitude - (ThumbstickRingSize / 2) - MiddleSize + local direction = vector.unit + + local distNeeded = MiddleSpacing * NUM_MIDDLE_IMAGES + local spacing = MiddleSpacing + + if distNeeded < distAvailable then + spacing = distAvailable / NUM_MIDDLE_IMAGES + end + + for i = 1, NUM_MIDDLE_IMAGES do + local image = MiddleImages[i] + local distWithout = startDist + (spacing * (i - 2)) + local currentDist = startDist + (spacing * (i - 1)) + + if distWithout < distAvailable then + local pos = endPos - direction * currentDist + local exposedFraction = math.clamp(1 - ((currentDist - distAvailable) / spacing), 0, 1) + + image.Visible = true + image.Position = UDim2.new(0, pos.X, 0, pos.Y) + image.Size = UDim2.new(0, MiddleSize * exposedFraction, 0, MiddleSize * exposedFraction) + else + image.Visible = false + end + end + end + + local function moveStick(pos) + local startPos = Vector2.new(MoveTouchStartPosition.X, MoveTouchStartPosition.Y) - ThumbstickFrame.AbsolutePosition + local endPos = Vector2.new(pos.X, pos.Y) - ThumbstickFrame.AbsolutePosition + local relativePosition = endPos - startPos + local length = relativePosition.magnitude + local maxLength = ThumbstickFrame.AbsoluteSize.X + + length = math.min(length, maxLength) + relativePosition = relativePosition*length + + EndImage.Position = UDim2.new(0, endPos.X, 0, endPos.Y) + + layoutMiddleImages(startPos, endPos) + end + + -- input connections + ThumbstickFrame.InputBegan:connect(function(inputObject) + if inputObject.UserInputType ~= Enum.UserInputType.Touch or inputObject.UserInputState ~= Enum.UserInputState.Begin then + return + end + if MoveTouchObject then + return + end + + if IsFirstTouch then + IsFirstTouch = false + local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Quad, Enum.EasingDirection.Out,0,false,0) + TweenService:Create(StartImage, tweenInfo, {Size = UDim2.new(0, 0, 0, 0)}):Play() + TweenService:Create(EndImage, tweenInfo, {Size = UDim2.new(0, ThumbstickSize, 0, ThumbstickSize), ImageColor3 = Color3.new(0,0,0)}):Play() + end + + MoveTouchObject = inputObject + MoveTouchStartTime = tick() + MoveTouchStartPosition = inputObject.Position + local startPosVec2 = Vector2.new(inputObject.Position.X - ThumbstickFrame.AbsolutePosition.X, inputObject.Position.Y - ThumbstickFrame.AbsolutePosition.Y) + + StartImage.Visible = true + StartImage.Position = UDim2.new(0, startPosVec2.X, 0, startPosVec2.Y) + EndImage.Visible = true + EndImage.Position = StartImage.Position + + fadeThumbstick(true) + moveStick(inputObject.Position) + + if FadeInAndOutBackground then + local playerGui = LocalPlayer:FindFirstChildOfClass("PlayerGui") + local hasFadedBackgroundInOrientation = false + + -- only fade in/out the background once per orientation + if playerGui then + if playerGui.CurrentScreenOrientation == Enum.ScreenOrientation.LandscapeLeft or + playerGui.CurrentScreenOrientation == Enum.ScreenOrientation.LandscapeRight then + hasFadedBackgroundInOrientation = HasFadedBackgroundInLandscape + HasFadedBackgroundInLandscape = true + elseif playerGui.CurrentScreenOrientation == Enum.ScreenOrientation.Portrait then + hasFadedBackgroundInOrientation = HasFadedBackgroundInPortrait + HasFadedBackgroundInPortrait = true + end + end + + if not hasFadedBackgroundInOrientation then + FadeInAndOutHalfDuration = FADE_IN_OUT_HALF_DURATION_DEFAULT + FadeInAndOutBalance = FADE_IN_OUT_BALANCE_DEFAULT + TweenInAlphaStart = tick() + end + end + end) + + OnTouchMovedCn = UserInputService.TouchMoved:connect(function(inputObject, isProcessed) + if inputObject == MoveTouchObject then + + local direction = Vector2.new(inputObject.Position.x - MoveTouchStartPosition.x, inputObject.Position.y - MoveTouchStartPosition.y) + if math.abs(direction.x) > 0 or math.abs(direction.y) > 0 then + doMove(direction) + moveStick(inputObject.Position) + end + end + end) + + OnMoveTouchEnded = function(inputObject) + if inputObject then + local direction = Vector2.new(inputObject.Position.x - MoveTouchStartPosition.x, inputObject.Position.y - MoveTouchStartPosition.y) + end + + MoveTouchObject = nil + fadeThumbstick(false) + + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(0,0,0) + end + + OnRenderSteppedCn = RunService.RenderStepped:Connect(function(step) + if TweenInAlphaStart ~= nil then + local delta = tick() - TweenInAlphaStart + local fadeInTime = (FadeInAndOutHalfDuration * 2 * FadeInAndOutBalance) + ThumbstickFrame.BackgroundTransparency = 1 - FadeInAndOutMaxAlpha*math.min(delta/fadeInTime, 1) + if delta > fadeInTime then + TweenOutAlphaStart = tick() + TweenInAlphaStart = nil + end + elseif TweenOutAlphaStart ~= nil then + local delta = tick() - TweenOutAlphaStart + local fadeOutTime = (FadeInAndOutHalfDuration * 2) - (FadeInAndOutHalfDuration * 2 * FadeInAndOutBalance) + ThumbstickFrame.BackgroundTransparency = 1 - FadeInAndOutMaxAlpha + FadeInAndOutMaxAlpha*math.min(delta/fadeOutTime, 1) + if delta > fadeOutTime then + TweenOutAlphaStart = nil + end + end + end) + + OnTouchEndedCn = UserInputService.TouchEnded:connect(function(inputObject, isProcessed) + if inputObject == MoveTouchObject then + OnMoveTouchEnded(inputObject) + end + end) + + + GuiService.MenuOpened:connect(function() + if MoveTouchObject then + OnMoveTouchEnded(nil) + end + end) + + local playerGui = LocalPlayer:FindFirstChildOfClass("PlayerGui") + while not playerGui do + LocalPlayer.ChildAdded:wait() + playerGui = LocalPlayer:FindFirstChildOfClass("PlayerGui") + end + + local playerGuiChangedConn = nil + local originalScreenOrientationWasLandscape = playerGui.CurrentScreenOrientation == Enum.ScreenOrientation.LandscapeLeft or + playerGui.CurrentScreenOrientation == Enum.ScreenOrientation.LandscapeRight + + local function longShowBackground() + FadeInAndOutHalfDuration = 2.5 + FadeInAndOutBalance = 0.05 + TweenInAlphaStart = tick() + end + + playerGuiChangedConn = playerGui.Changed:connect(function(prop) + if prop == "CurrentScreenOrientation" then + if (originalScreenOrientationWasLandscape and playerGui.CurrentScreenOrientation == Enum.ScreenOrientation.Portrait) or + (not originalScreenOrientationWasLandscape and playerGui.CurrentScreenOrientation ~= Enum.ScreenOrientation.Portrait) then + playerGuiChangedConn:disconnect() + longShowBackground() + + if originalScreenOrientationWasLandscape then + HasFadedBackgroundInPortrait = true + else + HasFadedBackgroundInLandscape = true + end + end + end + end) + + GestureArea.Parent = parentFrame.Parent + ThumbstickFrame.Parent = parentFrame + + spawn(function() + if game:IsLoaded() then + longShowBackground() + else + game.Loaded:wait() + longShowBackground() + end + end) +end + +return Thumbstick diff --git a/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/Gamepad.lua b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/Gamepad.lua new file mode 100644 index 0000000..49527fb --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/Gamepad.lua @@ -0,0 +1,198 @@ +--[[ + // FileName: Gamepad + // Written by: jeditkacheff + // Description: Implements movement controls for gamepad devices (XBox, PS4, MFi, etc.) +--]] +local Gamepad = {} + +local MasterControl = require(script.Parent) + +local Players = game:GetService('Players') +local RunService = game:GetService('RunService') +local UserInputService = game:GetService('UserInputService') +local ContextActionService = game:GetService('ContextActionService') +local StarterPlayer = game:GetService('StarterPlayer') +local Settings = UserSettings() +local GameSettings = Settings.GameSettings +local currentMoveVector = Vector3.new(0,0,0) +local activateGamepad = nil + +local gamepadConnectedCon = nil +local gamepadDisconnectedCon = nil + +while not Players.LocalPlayer do + wait() +end +local LocalPlayer = Players.LocalPlayer + +--[[ Constants ]]-- +local thumbstickDeadzone = 0.22 --raised from 14% on 3/1/16 to accommodate looser XB360 controllers + +function assignActivateGamepad() + local connectedGamepads = UserInputService:GetConnectedGamepads() + if #connectedGamepads > 0 then + for i = 1, #connectedGamepads do + if activateGamepad == nil then + activateGamepad = connectedGamepads[i] + elseif connectedGamepads[i].Value < activateGamepad.Value then + activateGamepad = connectedGamepads[i] + end + end + end + + if activateGamepad == nil then -- nothing is connected, at least set up for gamepad1 + activateGamepad = Enum.UserInputType.Gamepad1 + end +end + +--[[ Public API ]]-- +function Gamepad:Enable() + local forwardValue = 0 + local backwardValue = 0 + local leftValue = 0 + local rightValue = 0 + + local moveFunc = LocalPlayer.Move + local gamepadSupports = UserInputService.GamepadSupports + + local controlCharacterGamepad = function(actionName, inputState, inputObject) + if inputState == Enum.UserInputState.Cancel then + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(0,0,0) + return + end + + if activateGamepad ~= inputObject.UserInputType then return end + if inputObject.KeyCode ~= Enum.KeyCode.Thumbstick1 then return end + + if inputObject.Position.magnitude > thumbstickDeadzone then + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(inputObject.Position.X, 0, -inputObject.Position.Y) + MasterControl:AddToPlayerMovement(currentMoveVector) + else + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(0,0,0) + end + end + + local jumpCharacterGamepad = function(actionName, inputState, inputObject) + if inputState == Enum.UserInputState.Cancel then + MasterControl:SetIsJumping(false) + return + end + + if activateGamepad ~= inputObject.UserInputType then return end + if inputObject.KeyCode ~= Enum.KeyCode.ButtonA then return end + + MasterControl:SetIsJumping(inputObject.UserInputState == Enum.UserInputState.Begin) + end + + local doDpadMoveUpdate = function(userInputType) + if LocalPlayer and LocalPlayer.Character then + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(leftValue + rightValue,0,forwardValue + backwardValue) + MasterControl:AddToPlayerMovement(currentMoveVector) + end + end + + local moveForwardFunc = function(actionName, inputState, inputObject) + if inputState == Enum.UserInputState.End then + forwardValue = -1 + elseif inputState == Enum.UserInputState.Begin or inputState == Enum.UserInputState.Cancel then + forwardValue = 0 + end + + doDpadMoveUpdate(inputObject.UserInputType) + end + + local moveBackwardFunc = function(actionName, inputState, inputObject) + if inputState == Enum.UserInputState.End then + backwardValue = 1 + elseif inputState == Enum.UserInputState.Begin or inputState == Enum.UserInputState.Cancel then + backwardValue = 0 + end + + doDpadMoveUpdate(inputObject.UserInputType) + end + + local moveLeftFunc = function(actionName, inputState, inputObject) + if inputState == Enum.UserInputState.End then + leftValue = -1 + elseif inputState == Enum.UserInputState.Begin or inputState == Enum.UserInputState.Cancel then + leftValue = 0 + end + + doDpadMoveUpdate(inputObject.UserInputType) + end + + local moveRightFunc = function(actionName, inputState, inputObject) + if inputState == Enum.UserInputState.End then + rightValue = 1 + elseif inputState == Enum.UserInputState.Begin or inputState == Enum.UserInputState.Cancel then + rightValue = 0 + end + + doDpadMoveUpdate(inputObject.UserInputType) + end + + local function setActivateGamepad() + if activateGamepad then + ContextActionService:UnbindActivate(activateGamepad, Enum.KeyCode.ButtonR2) + end + assignActivateGamepad() + if activateGamepad then + ContextActionService:BindActivate(activateGamepad, Enum.KeyCode.ButtonR2) + end + end + + ContextActionService:BindAction("JumpButton",jumpCharacterGamepad, false, Enum.KeyCode.ButtonA) + ContextActionService:BindAction("MoveThumbstick",controlCharacterGamepad, false, Enum.KeyCode.Thumbstick1) + + setActivateGamepad() + + if not gamepadSupports(UserInputService, activateGamepad, Enum.KeyCode.Thumbstick1) then + -- if the gamepad supports thumbsticks, theres no point in having the dpad buttons getting eaten up by these actions + ContextActionService:BindAction("forwardDpad", moveForwardFunc, false, Enum.KeyCode.DPadUp) + ContextActionService:BindAction("backwardDpad", moveBackwardFunc, false, Enum.KeyCode.DPadDown) + ContextActionService:BindAction("leftDpad", moveLeftFunc, false, Enum.KeyCode.DPadLeft) + ContextActionService:BindAction("rightDpad", moveRightFunc, false, Enum.KeyCode.DPadRight) + end + + gamepadConnectedCon = UserInputService.GamepadDisconnected:connect(function(gamepadEnum) + if activateGamepad ~= gamepadEnum then return end + + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(0,0,0) + + activateGamepad = nil + setActivateGamepad() + end) + + gamepadDisconnectedCon = UserInputService.GamepadConnected:connect(function(gamepadEnum) + if activateGamepad == nil then + setActivateGamepad() + end + end) +end + +function Gamepad:Disable() + + ContextActionService:UnbindAction("forwardDpad") + ContextActionService:UnbindAction("backwardDpad") + ContextActionService:UnbindAction("leftDpad") + ContextActionService:UnbindAction("rightDpad") + + ContextActionService:UnbindAction("MoveThumbstick") + ContextActionService:UnbindAction("JumpButton") + ContextActionService:UnbindActivate(activateGamepad, Enum.KeyCode.ButtonR2) + + if gamepadConnectedCon then gamepadConnectedCon:disconnect() end + if gamepadDisconnectedCon then gamepadDisconnectedCon:disconnect() end + + activateGamepad = nil + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(0,0,0) + MasterControl:SetIsJumping(false) +end + +return Gamepad diff --git a/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/KeyboardMovement.lua b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/KeyboardMovement.lua new file mode 100644 index 0000000..ce30bcc --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/KeyboardMovement.lua @@ -0,0 +1,176 @@ +--[[ + // FileName: ComputerMovementKeyboardMovement + // Version 1.2 + // Written by: jeditkacheff/jmargh + // Description: Implements movement controls for keyboard devices +--]] +local Players = game:GetService('Players') +local UserInputService = game:GetService('UserInputService') +local ContextActionService = game:GetService('ContextActionService') +local StarterPlayer = game:GetService('StarterPlayer') +local Settings = UserSettings() +local GameSettings = Settings.GameSettings + +local KeyboardMovement = {} + +while not Players.LocalPlayer do + wait() +end +local LocalPlayer = Players.LocalPlayer +local CachedHumanoid = nil +local SeatJumpCn = nil +local TextFocusReleasedCn = nil +local TextFocusGainedCn = nil +local WindowFocusReleasedCn = nil + +local MasterControl = require(script.Parent) +local currentMoveVector = Vector3.new(0,0,0) + +--[[ Local Functions ]]-- +local function getHumanoid() + local character = LocalPlayer and LocalPlayer.Character + if character then + if CachedHumanoid and CachedHumanoid.Parent == character then + return CachedHumanoid + else + CachedHumanoid = nil + for _,child in pairs(character:GetChildren()) do + if child:IsA('Humanoid') then + CachedHumanoid = child + return CachedHumanoid + end + end + end + end +end + +--[[ Public API ]]-- +function KeyboardMovement:Enable() + if not UserInputService.KeyboardEnabled then + return + end + + local forwardValue = 0 + local backwardValue = 0 + local leftValue = 0 + local rightValue = 0 + + local updateMovement = function(inputState) + if inputState == Enum.UserInputState.Cancel then + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(0, 0, 0) + else + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(leftValue + rightValue,0,forwardValue + backwardValue) + MasterControl:AddToPlayerMovement(currentMoveVector) + end + end + + local moveForwardFunc = function(actionName, inputState, inputObject) + if inputState == Enum.UserInputState.Begin then + forwardValue = -1 + elseif inputState == Enum.UserInputState.End or inputState == Enum.UserInputState.Cancel then + forwardValue = 0 + end + updateMovement(inputState) + end + + local moveBackwardFunc = function(actionName, inputState, inputObject) + if inputState == Enum.UserInputState.Begin then + backwardValue = 1 + elseif inputState == Enum.UserInputState.End or inputState == Enum.UserInputState.Cancel then + backwardValue = 0 + end + updateMovement(inputState) + end + + local moveLeftFunc = function(actionName, inputState, inputObject) + if inputState == Enum.UserInputState.Begin then + leftValue = -1 + elseif inputState == Enum.UserInputState.End or inputState == Enum.UserInputState.Cancel then + leftValue = 0 + end + updateMovement(inputState) + end + + local moveRightFunc = function(actionName, inputState, inputObject) + if inputState == Enum.UserInputState.Begin then + rightValue = 1 + elseif inputState == Enum.UserInputState.End or inputState == Enum.UserInputState.Cancel then + rightValue = 0 + end + updateMovement(inputState) + end + + local jumpFunc = function(actionName, inputState, inputObject) + MasterControl:SetIsJumping(inputState == Enum.UserInputState.Begin) + end + + -- TODO: remove up and down arrows, these seem unnecessary + ContextActionService:BindActionToInputTypes("forwardMovement", moveForwardFunc, false, Enum.PlayerActions.CharacterForward) + ContextActionService:BindActionToInputTypes("backwardMovement", moveBackwardFunc, false, Enum.PlayerActions.CharacterBackward) + ContextActionService:BindActionToInputTypes("leftMovement", moveLeftFunc, false, Enum.PlayerActions.CharacterLeft, Enum.KeyCode.Left) + ContextActionService:BindActionToInputTypes("rightMovement", moveRightFunc, false, Enum.PlayerActions.CharacterRight, Enum.KeyCode.Right) + ContextActionService:BindActionToInputTypes("jumpAction", jumpFunc, false, Enum.PlayerActions.CharacterJump) + + -- TODO: make sure we check key state before binding to check if key is already down + + local function onFocusReleased() + local humanoid = getHumanoid() + if humanoid then + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(0, 0, 0) + forwardValue, backwardValue, leftValue, rightValue = 0, 0, 0, 0 + MasterControl:SetIsJumping(false) + end + end + + local function onTextFocusGained(textboxFocused) + MasterControl:SetIsJumping(false) + end + + SeatJumpCn = UserInputService.InputBegan:connect(function(inputObject, isProcessed) + if inputObject.KeyCode == Enum.KeyCode.Backspace and not isProcessed then + local humanoid = getHumanoid() + if humanoid and (humanoid.Sit or humanoid.PlatformStand) then + MasterControl:DoJump() + end + end + end) + + TextFocusReleasedCn = UserInputService.TextBoxFocusReleased:connect(onFocusReleased) + TextFocusGainedCn = UserInputService.TextBoxFocused:connect(onTextFocusGained) + -- TODO: remove pcall when API is live + WindowFocusReleasedCn = UserInputService.WindowFocusReleased:connect(onFocusReleased) +end + +function KeyboardMovement:Disable() + ContextActionService:UnbindAction("forwardMovement") + ContextActionService:UnbindAction("backwardMovement") + ContextActionService:UnbindAction("leftMovement") + ContextActionService:UnbindAction("rightMovement") + ContextActionService:UnbindAction("jumpAction") + + if SeatJumpCn then + SeatJumpCn:disconnect() + SeatJumpCn = nil + end + if TextFocusReleasedCn then + TextFocusReleasedCn:disconnect() + TextFocusReleasedCn = nil + end + if TextFocusGainedCn then + TextFocusGainedCn:disconnect() + TextFocusGainedCn = nil + end + if WindowFocusReleasedCn then + WindowFocusReleasedCn:disconnect() + WindowFocusReleasedCn = nil + end + + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(0,0,0) + MasterControl:SetIsJumping(false) +end + +return KeyboardMovement diff --git a/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/Thumbpad.lua b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/Thumbpad.lua new file mode 100644 index 0000000..5812b3c --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/Thumbpad.lua @@ -0,0 +1,228 @@ +--[[ + // FileName: Thumbpad + // Version 1.0 + // Written by: jmargh + // Description: Implements thumbpad controls for touch devices +--]] + +local Players = game:GetService('Players') +local UserInputService = game:GetService('UserInputService') +local GuiService = game:GetService('GuiService') + +local Thumbpad = {} + +local MasterControl = require(script.Parent) + +--[[ Script Variables ]]-- +while not Players.LocalPlayer do + wait() +end +local LocalPlayer = Players.LocalPlayer +local ThumbpadFrame = nil +local TouchObject = nil +local OnInputEnded = nil -- is defined in Create() +local OnTouchChangedCn = nil +local OnTouchEndedCn = nil +local currentMoveVector = Vector3.new(0,0,0) + +--[[ Constants ]]-- +local DPAD_SHEET = "rbxasset://textures/ui/DPadSheet.png" +local TOUCH_CONTROL_SHEET = "rbxasset://textures/ui/TouchControlsSheet.png" + +--[[ Local Functions ]]-- +local function createArrowLabel(name, parent, position, size, rectOffset, rectSize) + local image = Instance.new('ImageLabel') + image.Name = name + image.Image = DPAD_SHEET + image.ImageRectOffset = rectOffset + image.ImageRectSize = rectSize + image.BackgroundTransparency = 1 + image.ImageColor3 = Color3.new(190/255, 190/255, 190/255) + image.Size = size + image.Position = position + image.Parent = parent + + return image +end + +--[[ Public API ]]-- +function Thumbpad:Enable() + ThumbpadFrame.Visible = true +end + +function Thumbpad:Disable() + ThumbpadFrame.Visible = false + OnInputEnded() +end + +function Thumbpad:Create(parentFrame) + if ThumbpadFrame then + ThumbpadFrame:Destroy() + ThumbpadFrame = nil + if OnTouchChangedCn then + OnTouchChangedCn:disconnect() + OnTouchChangedCn = nil + end + if OnTouchEndedCn then + OnTouchEndedCn:disconnect() + OnTouchEndedCn = nil + end + end + + local minAxis = math.min(parentFrame.AbsoluteSize.x, parentFrame.AbsoluteSize.y) + local isSmallScreen = minAxis <= 500 + local thumbpadSize = isSmallScreen and 70 or 120 + local position = isSmallScreen and UDim2.new(0, thumbpadSize * 1.25, 1, -thumbpadSize - 20) or + UDim2.new(0, thumbpadSize/2 - 10, 1, -thumbpadSize * 1.75 - 10) + + ThumbpadFrame = Instance.new('Frame') + ThumbpadFrame.Name = "ThumbpadFrame" + ThumbpadFrame.Visible = false + ThumbpadFrame.Active = true + ThumbpadFrame.Size = UDim2.new(0, thumbpadSize + 20, 0, thumbpadSize + 20) + ThumbpadFrame.Position = position + ThumbpadFrame.BackgroundTransparency = 1 + + local outerImage = Instance.new('ImageLabel') + outerImage.Name = "OuterImage" + outerImage.Image = TOUCH_CONTROL_SHEET + outerImage.ImageRectOffset = Vector2.new(0, 0) + outerImage.ImageRectSize = Vector2.new(220, 220) + outerImage.BackgroundTransparency = 1 + outerImage.Size = UDim2.new(0, thumbpadSize, 0, thumbpadSize) + outerImage.Position = UDim2.new(0, 10, 0, 10) + outerImage.Parent = ThumbpadFrame + + local smArrowSize = isSmallScreen and UDim2.new(0, 32, 0, 32) or UDim2.new(0, 64, 0, 64) + local lgArrowSize = UDim2.new(0, smArrowSize.X.Offset * 2, 0, smArrowSize.Y.Offset * 2) + local imgRectSize = Vector2.new(110, 110) + local smImgOffset = isSmallScreen and -4 or -9 + local lgImgOffset = isSmallScreen and -28 or -55 + + local dArrow = createArrowLabel("DownArrow", outerImage, UDim2.new(0.5, -smArrowSize.X.Offset/2, 1, lgImgOffset), smArrowSize, Vector2.new(8, 8), imgRectSize) + local uArrow = createArrowLabel("UpArrow", outerImage, UDim2.new(0.5, -smArrowSize.X.Offset/2, 0, smImgOffset), smArrowSize, Vector2.new(8, 266), imgRectSize) + local lArrow = createArrowLabel("LeftArrow", outerImage, UDim2.new(0, smImgOffset, 0.5, -smArrowSize.Y.Offset/2), smArrowSize, Vector2.new(137, 137), imgRectSize) + local rArrow = createArrowLabel("RightArrow", outerImage, UDim2.new(1, lgImgOffset, 0.5, -smArrowSize.Y.Offset/2), smArrowSize, Vector2.new(8, 137), imgRectSize) + + local function doTween(guiObject, endSize, endPosition) + guiObject:TweenSizeAndPosition(endSize, endPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Linear, 0.15, true) + end + + local padOrigin = nil + local deadZone = 0.1 + local isRight, isLeft, isUp, isDown = false, false, false, false + local vForward = Vector3.new(0, 0, -1) + local vRight = Vector3.new(1, 0, 0) + local function doMove(pos) + MasterControl:AddToPlayerMovement(-currentMoveVector) + + local delta = Vector2.new(pos.x, pos.y) - padOrigin + currentMoveVector = delta / (thumbpadSize/2) + + -- Scaled Radial Dead Zone + local inputAxisMagnitude = currentMoveVector.magnitude + if inputAxisMagnitude < deadZone then + currentMoveVector = Vector3.new(0, 0, 0) + else + currentMoveVector = currentMoveVector.unit * ((inputAxisMagnitude - deadZone) / (1 - deadZone)) + -- catch possible NAN Vector + if currentMoveVector.magnitude == 0 then + currentMoveVector = Vector3.new(0, 0, 0) + else + currentMoveVector = Vector3.new(currentMoveVector.x, 0, currentMoveVector.y).Unit + end + end + + MasterControl:AddToPlayerMovement(currentMoveVector) + + local forwardDot = currentMoveVector:Dot(vForward) + local rightDot = currentMoveVector:Dot(vRight) + if forwardDot > 0.5 then -- UP + if not isUp then + isUp, isDown = true, false + doTween(uArrow, lgArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset, 0, smImgOffset - smArrowSize.Y.Offset * 1.5)) + doTween(dArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 1, lgImgOffset)) + end + elseif forwardDot < -0.5 then -- DOWN + if not isDown then + isDown, isUp = true, false + doTween(dArrow, lgArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset, 1, lgImgOffset + smArrowSize.Y.Offset/2)) + doTween(uArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 0, smImgOffset)) + end + else + isUp, isDown = false, false + doTween(dArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 1, lgImgOffset)) + doTween(uArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 0, smImgOffset)) + end + + if rightDot > 0.5 then + if not isRight then + isRight, isLeft = true, false + doTween(rArrow, lgArrowSize, UDim2.new(1, lgImgOffset + smArrowSize.X.Offset/2, 0.5, -smArrowSize.Y.Offset)) + doTween(lArrow, smArrowSize, UDim2.new(0, smImgOffset, 0.5, -smArrowSize.Y.Offset/2)) + end + elseif rightDot < -0.5 then + if not isLeft then + isLeft, isRight = true, false + doTween(lArrow, lgArrowSize, UDim2.new(0, smImgOffset - smArrowSize.X.Offset * 1.5, 0.5, -smArrowSize.Y.Offset)) + doTween(rArrow, smArrowSize, UDim2.new(1, lgImgOffset, 0.5, -smArrowSize.Y.Offset/2)) + end + else + isRight, isLeft = false, false + doTween(lArrow, smArrowSize, UDim2.new(0, smImgOffset, 0.5, -smArrowSize.Y.Offset/2)) + doTween(rArrow, smArrowSize, UDim2.new(1, lgImgOffset, 0.5, -smArrowSize.Y.Offset/2)) + end + end + + --input connections + ThumbpadFrame.InputBegan:connect(function(inputObject) + --A touch that starts elsewhere on the screen will be sent to a frame's InputBegan event + --if it moves over the frame. So we check that this is actually a new touch (inputObject.UserInputState ~= Enum.UserInputState.Begin) + if TouchObject or inputObject.UserInputType ~= Enum.UserInputType.Touch + or inputObject.UserInputState ~= Enum.UserInputState.Begin then + return + end + + ThumbpadFrame.Position = UDim2.new(0, inputObject.Position.x - ThumbpadFrame.AbsoluteSize.x/2, 0, inputObject.Position.y - ThumbpadFrame.Size.Y.Offset/2) + padOrigin = Vector2.new(ThumbpadFrame.AbsolutePosition.x + ThumbpadFrame.AbsoluteSize.x/2, + ThumbpadFrame.AbsolutePosition.y + ThumbpadFrame.AbsoluteSize.y/2) + doMove(inputObject.Position) + TouchObject = inputObject + end) + + OnTouchChangedCn = UserInputService.TouchMoved:connect(function(inputObject, isProcessed) + if inputObject == TouchObject then + doMove(TouchObject.Position) + end + end) + + OnInputEnded = function() + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(0,0,0) + MasterControl:SetIsJumping(false) + + ThumbpadFrame.Position = position + TouchObject = nil + isUp, isDown, isLeft, isRight = false, false, false, false + doTween(dArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 1, lgImgOffset)) + doTween(uArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 0, smImgOffset)) + doTween(lArrow, smArrowSize, UDim2.new(0, smImgOffset, 0.5, -smArrowSize.Y.Offset/2)) + doTween(rArrow, smArrowSize, UDim2.new(1, lgImgOffset, 0.5, -smArrowSize.Y.Offset/2)) + end + + OnTouchEndedCn = UserInputService.TouchEnded:connect(function(inputObject) + if inputObject == TouchObject then + OnInputEnded() + end + end) + + GuiService.MenuOpened:connect(function() + if TouchObject then + OnInputEnded() + end + end) + + ThumbpadFrame.Parent = parentFrame +end + +return Thumbpad diff --git a/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/Thumbstick.lua b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/Thumbstick.lua new file mode 100644 index 0000000..73df88f --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/Thumbstick.lua @@ -0,0 +1,178 @@ +--[[ + // FileName: Thumbstick + // Version 1.0 + // Written by: jmargh + // Description: Implements thumbstick controls for touch devices +--]] +local Players = game:GetService('Players') +local UserInputService = game:GetService('UserInputService') +local GuiService = game:GetService('GuiService') + +local MasterControl = require(script.Parent) + +local Thumbstick = {} + +--[[ Script Variables ]]-- +while not Players.LocalPlayer do + wait() +end +local LocalPlayer = Players.LocalPlayer +local IsFollowStick = false +local ThumbstickFrame = nil +local MoveTouchObject = nil +local OnTouchEnded = nil -- defined in Create() +local OnTouchMovedCn = nil +local OnTouchEndedCn = nil +local currentMoveVector = Vector3.new(0,0,0) + +--[[ Constants ]]-- +local TOUCH_CONTROL_SHEET = "rbxasset://textures/ui/TouchControlsSheet.png" + +--[[ Public API ]]-- +function Thumbstick:Enable() + ThumbstickFrame.Visible = true +end + +function Thumbstick:Disable() + ThumbstickFrame.Visible = false + OnTouchEnded() +end + +function Thumbstick:Create(parentFrame) + if ThumbstickFrame then + ThumbstickFrame:Destroy() + ThumbstickFrame = nil + if OnTouchMovedCn then + OnTouchMovedCn:disconnect() + OnTouchMovedCn = nil + end + if OnTouchEndedCn then + OnTouchEndedCn:disconnect() + OnTouchEndedCn = nil + end + end + + local minAxis = math.min(parentFrame.AbsoluteSize.x, parentFrame.AbsoluteSize.y) + local isSmallScreen = minAxis <= 500 + local thumbstickSize = isSmallScreen and 70 or 120 + local position = isSmallScreen and UDim2.new(0, (thumbstickSize/2) - 10, 1, -thumbstickSize - 20) or + UDim2.new(0, thumbstickSize/2, 1, -thumbstickSize * 1.75) + + ThumbstickFrame = Instance.new('Frame') + ThumbstickFrame.Name = "ThumbstickFrame" + ThumbstickFrame.Active = true + ThumbstickFrame.Visible = false + ThumbstickFrame.Size = UDim2.new(0, thumbstickSize, 0, thumbstickSize) + ThumbstickFrame.Position = position + ThumbstickFrame.BackgroundTransparency = 1 + + local outerImage = Instance.new('ImageLabel') + outerImage.Name = "OuterImage" + outerImage.Image = TOUCH_CONTROL_SHEET + outerImage.ImageRectOffset = Vector2.new() + outerImage.ImageRectSize = Vector2.new(220, 220) + outerImage.BackgroundTransparency = 1 + outerImage.Size = UDim2.new(0, thumbstickSize, 0, thumbstickSize) + outerImage.Position = UDim2.new(0, 0, 0, 0) + outerImage.Parent = ThumbstickFrame + + local StickImage = Instance.new('ImageLabel') + StickImage.Name = "StickImage" + StickImage.Image = TOUCH_CONTROL_SHEET + StickImage.ImageRectOffset = Vector2.new(220, 0) + StickImage.ImageRectSize = Vector2.new(111, 111) + StickImage.BackgroundTransparency = 1 + StickImage.Size = UDim2.new(0, thumbstickSize/2, 0, thumbstickSize/2) + StickImage.Position = UDim2.new(0, thumbstickSize/2 - thumbstickSize/4, 0, thumbstickSize/2 - thumbstickSize/4) + StickImage.ZIndex = 2 + StickImage.Parent = ThumbstickFrame + + local centerPosition = nil + local deadZone = 0.05 + local function doMove(direction) + MasterControl:AddToPlayerMovement(-currentMoveVector) + + currentMoveVector = direction / (thumbstickSize/2) + + -- Scaled Radial Dead Zone + local inputAxisMagnitude = currentMoveVector.magnitude + if inputAxisMagnitude < deadZone then + currentMoveVector = Vector3.new() + else + currentMoveVector = currentMoveVector.unit * ((inputAxisMagnitude - deadZone) / (1 - deadZone)) + -- NOTE: Making currentMoveVector a unit vector will cause the player to instantly go max speed + -- must check for zero length vector is using unit + currentMoveVector = Vector3.new(currentMoveVector.x, 0, currentMoveVector.y) + end + + MasterControl:AddToPlayerMovement(currentMoveVector) + end + + local function moveStick(pos) + local relativePosition = Vector2.new(pos.x - centerPosition.x, pos.y - centerPosition.y) + local length = relativePosition.magnitude + local maxLength = ThumbstickFrame.AbsoluteSize.x/2 + if IsFollowStick and length > maxLength then + local offset = relativePosition.unit * maxLength + ThumbstickFrame.Position = UDim2.new( + 0, pos.x - ThumbstickFrame.AbsoluteSize.x/2 - offset.x, + 0, pos.y - ThumbstickFrame.AbsoluteSize.y/2 - offset.y) + else + length = math.min(length, maxLength) + relativePosition = relativePosition.unit * length + end + StickImage.Position = UDim2.new(0, relativePosition.x + StickImage.AbsoluteSize.x/2, 0, relativePosition.y + StickImage.AbsoluteSize.y/2) + end + + -- input connections + ThumbstickFrame.InputBegan:connect(function(inputObject) + --A touch that starts elsewhere on the screen will be sent to a frame's InputBegan event + --if it moves over the frame. So we check that this is actually a new touch (inputObject.UserInputState ~= Enum.UserInputState.Begin) + if MoveTouchObject or inputObject.UserInputType ~= Enum.UserInputType.Touch + or inputObject.UserInputState ~= Enum.UserInputState.Begin then + return + end + + MoveTouchObject = inputObject + ThumbstickFrame.Position = UDim2.new(0, inputObject.Position.x - ThumbstickFrame.Size.X.Offset/2, 0, inputObject.Position.y - ThumbstickFrame.Size.Y.Offset/2) + centerPosition = Vector2.new(ThumbstickFrame.AbsolutePosition.x + ThumbstickFrame.AbsoluteSize.x/2, + ThumbstickFrame.AbsolutePosition.y + ThumbstickFrame.AbsoluteSize.y/2) + local direction = Vector2.new(inputObject.Position.x - centerPosition.x, inputObject.Position.y - centerPosition.y) + end) + + OnTouchMovedCn = UserInputService.TouchMoved:connect(function(inputObject, isProcessed) + if inputObject == MoveTouchObject then + centerPosition = Vector2.new(ThumbstickFrame.AbsolutePosition.x + ThumbstickFrame.AbsoluteSize.x/2, + ThumbstickFrame.AbsolutePosition.y + ThumbstickFrame.AbsoluteSize.y/2) + local direction = Vector2.new(inputObject.Position.x - centerPosition.x, inputObject.Position.y - centerPosition.y) + doMove(direction) + moveStick(inputObject.Position) + end + end) + + OnTouchEnded = function() + ThumbstickFrame.Position = position + StickImage.Position = UDim2.new(0, ThumbstickFrame.Size.X.Offset/2 - thumbstickSize/4, 0, ThumbstickFrame.Size.Y.Offset/2 - thumbstickSize/4) + MoveTouchObject = nil + + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(0,0,0) + MasterControl:SetIsJumping(false) + end + + OnTouchEndedCn = UserInputService.TouchEnded:connect(function(inputObject, isProcessed) + if inputObject == MoveTouchObject then + OnTouchEnded() + end + end) + + GuiService.MenuOpened:connect(function() + if MoveTouchObject then + OnTouchEnded() + end + end) + + ThumbstickFrame.Parent = parentFrame +end + +return Thumbstick diff --git a/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/TouchJump.lua b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/TouchJump.lua new file mode 100644 index 0000000..58668a3 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/TouchJump.lua @@ -0,0 +1,172 @@ +--[[ + // FileName: TouchJump + // Version 1.0 + // Written by: jmargh + // Description: Implements jump controls for touch devices. Use with Thumbstick and Thumbpad +--]] + +local Players = game:GetService('Players') +local GuiService = game:GetService('GuiService') + +local TouchJump = {} + +local MasterControl = require(script.Parent) + +--[[ Script Variables ]]-- +while not Players.LocalPlayer do + wait() +end +local LocalPlayer = Players.LocalPlayer +local Humanoid = MasterControl:GetHumanoid() +local JumpButton = nil +local OnInputEnded = nil -- defined in Create() +local CharacterAddedConnection = nil +local HumStateConnection = nil +local HumChangeConnection = nil +local ExternallyEnabled = false +local JumpPower = 0 +local JumpStateEnabled = true + +--[[ Constants ]]-- +local TOUCH_CONTROL_SHEET = "rbxasset://textures/ui/Input/TouchControlsSheetV2.png" + +--[[ Private Functions ]]-- + +local function disableButton() + JumpButton.Visible = false + OnInputEnded() +end + +local function enableButton() + if Humanoid and ExternallyEnabled then + if ExternallyEnabled then + if Humanoid.JumpPower > 0 then + JumpButton.Visible = true + end + end + end +end + +local function updateEnabled() + if JumpPower > 0 and JumpStateEnabled then + enableButton() + else + disableButton() + end +end + +local function humanoidChanged(prop) + if prop == "JumpPower" then + JumpPower = Humanoid.JumpPower + updateEnabled() + elseif prop == "Parent" then + if not Humanoid.Parent then + HumChangeConnection:disconnect() + end + end +end + +local function humandoidStateEnabledChanged(state, isEnabled) + if state == Enum.HumanoidStateType.Jumping then + JumpStateEnabled = isEnabled + updateEnabled() + end +end + +local function characterAdded(newCharacter) + if HumChangeConnection then + HumChangeConnection:disconnect() + end + -- rebind event to new Humanoid + Humanoid = nil + repeat + Humanoid = MasterControl:GetHumanoid() + wait() + until Humanoid and Humanoid.Parent == newCharacter + HumChangeConnection = Humanoid.Changed:connect(humanoidChanged) + HumStateConnection = Humanoid.StateEnabledChanged:connect(humandoidStateEnabledChanged) + JumpPower = Humanoid.JumpPower + JumpStateEnabled = Humanoid:GetStateEnabled(Enum.HumanoidStateType.Jumping) + updateEnabled() +end + +local function setupCharacterAddedFunction() + CharacterAddedConnection = LocalPlayer.CharacterAdded:connect(characterAdded) + if LocalPlayer.Character then + characterAdded(LocalPlayer.Character) + end +end + +--[[ Public API ]]-- +function TouchJump:Enable() + ExternallyEnabled = true + enableButton() +end + +function TouchJump:Disable() + ExternallyEnabled = false + disableButton() +end + +function TouchJump:Create(parentFrame) + if JumpButton then + JumpButton:Destroy() + JumpButton = nil + end + + local minAxis = math.min(parentFrame.AbsoluteSize.x, parentFrame.AbsoluteSize.y) + local isSmallScreen = minAxis <= 500 + local jumpButtonSize = isSmallScreen and 70 or 120 + + JumpButton = Instance.new('ImageButton') + JumpButton.Name = "JumpButton" + JumpButton.Visible = false + JumpButton.BackgroundTransparency = 1 + JumpButton.Image = TOUCH_CONTROL_SHEET + JumpButton.ImageRectOffset = Vector2.new(1, 146) + JumpButton.ImageRectSize = Vector2.new(144, 144) + JumpButton.Size = UDim2.new(0, jumpButtonSize, 0, jumpButtonSize) + + JumpButton.Position = isSmallScreen and UDim2.new(1, -(jumpButtonSize*1.5-10), 1, -jumpButtonSize - 20) or + UDim2.new(1, -(jumpButtonSize*1.5-10), 1, -jumpButtonSize * 1.75) + + local touchObject = nil + JumpButton.InputBegan:connect(function(inputObject) + --A touch that starts elsewhere on the screen will be sent to a frame's InputBegan event + --if it moves over the frame. So we check that this is actually a new touch (inputObject.UserInputState ~= Enum.UserInputState.Begin) + if touchObject or inputObject.UserInputType ~= Enum.UserInputType.Touch + or inputObject.UserInputState ~= Enum.UserInputState.Begin then + return + end + + touchObject = inputObject + JumpButton.ImageRectOffset = Vector2.new(146, 146) + MasterControl:SetIsJumping(true) + end) + + OnInputEnded = function() + touchObject = nil + MasterControl:SetIsJumping(false) + JumpButton.ImageRectOffset = Vector2.new(1, 146) + end + + JumpButton.InputEnded:connect(function(inputObject) + if inputObject == touchObject then + OnInputEnded() + end + end) + + GuiService.MenuOpened:connect(function() + if touchObject then + OnInputEnded() + end + end) + + if not CharacterAddedConnection then + setupCharacterAddedFunction() + end + + JumpButton.Parent = parentFrame +end + +return TouchJump diff --git a/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/VRNavigation.lua b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/VRNavigation.lua new file mode 100644 index 0000000..b308c43 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/VRNavigation.lua @@ -0,0 +1,433 @@ +local VRService = game:GetService("VRService") +local UserInputService = game:GetService("UserInputService") +local RunService = game:GetService("RunService") +local Players = game:GetService("Players") +local PathfindingService = game:GetService("PathfindingService") +local ContextActionService = game:GetService("ContextActionService") +local StarterGui = game:GetService("StarterGui") + +local MasterControl = require(script.Parent) +local PathDisplay = nil +local LocalPlayer = Players.LocalPlayer + +local VRNavigation = {} + +local RECALCULATE_PATH_THRESHOLD = 4 +local NO_PATH_THRESHOLD = 12 +local MAX_PATHING_DISTANCE = 200 +local POINT_REACHED_THRESHOLD = 1 +local STOPPING_DISTANCE = 4 +local OFFTRACK_TIME_THRESHOLD = 2 + +local ZERO_VECTOR3 = Vector3.new(0, 0, 0) +local XZ_VECTOR3 = Vector3.new(1, 0, 1) + +local THUMBSTICK_DEADZONE = 0.22 + +local navigationRequestedConn = nil +local heartbeatConn = nil + +local currentDestination = nil +local currentPath = nil +local currentPoints = nil +local currentPointIdx = 0 +local currentMoveVector = Vector3.new(0, 0, 0) + +local expectedTimeToNextPoint = 0 +local timeReachedLastPoint = tick() + +local movementUpdateEvent = Instance.new("BindableEvent") +movementUpdateEvent.Name = "MovementUpdate" +movementUpdateEvent.Parent = script + +coroutine.wrap(function() + local PathDisplayModule = script.Parent.Parent:WaitForChild("PathDisplay") + if PathDisplayModule then + PathDisplay = require(PathDisplayModule) + end +end)() + +local function setLaserPointerMode(mode) + pcall(function() + StarterGui:SetCore("VRLaserPointerMode", mode) + end) +end + +local function getLocalHumanoid() + local character = LocalPlayer.Character + if not character then + return + end + + for _, child in pairs(character:GetChildren()) do + if child:IsA("Humanoid") then + return child + end + end + return nil +end + +local function hasBothHandControllers() + return VRService:GetUserCFrameEnabled(Enum.UserCFrame.RightHand) and VRService:GetUserCFrameEnabled(Enum.UserCFrame.LeftHand) +end + +local function hasAnyHandControllers() + return VRService:GetUserCFrameEnabled(Enum.UserCFrame.RightHand) or VRService:GetUserCFrameEnabled(Enum.UserCFrame.LeftHand) +end + +local function isMobileVR() + return UserInputService.TouchEnabled +end + +local function hasGamepad() + return UserInputService.GamepadEnabled +end + +local function shouldUseNavigationLaser() + --Places where we use the navigation laser: + -- mobile VR with any number of hands tracked + -- desktop VR with only one hand tracked + -- desktop VR with no hands and no gamepad (i.e. with Oculus remote?) + --using an Xbox controller with a desktop VR headset means no laser since the user has a thumbstick. + --in the future, we should query thumbstick presence with a features API + if isMobileVR() then + return true + else + if hasBothHandControllers() then + return false + end + if not hasAnyHandControllers() then + return not hasGamepad() + end + return true + end +end + +local function IsFinite(num) + return num == num and num ~= 1/0 and num ~= -1/0 +end + +local function IsFiniteVector3(vec3) + return IsFinite(vec3.x) and IsFinite(vec3.y) and IsFinite(vec3.z) +end + +local moving = false + +local function startFollowingPath(newPath) + currentPath = newPath + currentPoints = currentPath:GetPointCoordinates() + currentPointIdx = 1 + moving = true + + timeReachedLastPoint = tick() + + local humanoid = getLocalHumanoid() + if humanoid and humanoid.Torso and #currentPoints >= 1 then + local dist = (currentPoints[1] - humanoid.Torso.Position).magnitude + expectedTimeToNextPoint = dist / humanoid.WalkSpeed + end + + movementUpdateEvent:Fire("targetPoint", currentDestination) +end + +local function goToPoint(point) + currentPath = true + currentPoints = { point } + currentPointIdx = 1 + moving = true + + local humanoid = getLocalHumanoid() + local distance = (humanoid.Torso.Position - point).magnitude + local estimatedTimeRemaining = distance / humanoid.WalkSpeed + + timeReachedLastPoint = tick() + expectedTimeToNextPoint = estimatedTimeRemaining + + movementUpdateEvent:Fire("targetPoint", point) +end + +local function stopFollowingPath() + currentPath = nil + currentPoints = nil + currentPointIdx = 0 + moving = false + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = ZERO_VECTOR3 +end + +local function tryComputePath(startPos, destination) + local numAttempts = 0 + local newPath = nil + + while not newPath and numAttempts < 5 do + newPath = PathfindingService:ComputeSmoothPathAsync(startPos, destination, MAX_PATHING_DISTANCE) + numAttempts = numAttempts + 1 + + if newPath.Status == Enum.PathStatus.ClosestNoPath or newPath.Status == Enum.PathStatus.ClosestOutOfRange then + newPath = nil + break + end + + if newPath and newPath.Status == Enum.PathStatus.FailStartNotEmpty then + startPos = startPos + (destination - startPos).unit + newPath = nil + end + + if newPath and newPath.Status == Enum.PathStatus.FailFinishNotEmpty then + destination = destination + Vector3.new(0, 1, 0) + newPath = nil + end + end + + return newPath +end + +local function onNavigationRequest(destinationCFrame, requestedWith) + local destinationPosition = destinationCFrame.p + local lastDestination = currentDestination + + if not IsFiniteVector3(destinationPosition) then + return + end + + currentDestination = destinationPosition + + local humanoid = getLocalHumanoid() + if not humanoid or not humanoid.Torso then + return + end + + local currentPosition = humanoid.Torso.Position + local distanceToDestination = (currentDestination - currentPosition).magnitude + + if distanceToDestination < NO_PATH_THRESHOLD then + goToPoint(currentDestination) + return + end + + if not lastDestination or (currentDestination - lastDestination).magnitude > RECALCULATE_PATH_THRESHOLD then + local newPath = tryComputePath(currentPosition, currentDestination) + if newPath then + startFollowingPath(newPath) + if PathDisplay then + PathDisplay.setCurrentPoints(currentPoints) + PathDisplay.renderPath() + end + else + stopFollowingPath() + if PathDisplay then + PathDisplay.clearRenderedPath() + end + end + else + if moving then + currentPoints[#currentPoints] = currentDestination + else + goToPoint(currentDestination) + end + end +end + +local isJumpBound = false +local function onJumpAction(actionName, inputState, inputObj) + if inputState == Enum.UserInputState.Begin then + MasterControl:DoJump() + end +end + +local function bindJumpAction(active) + if active then + if not isJumpBound then + isJumpBound = true + ContextActionService:BindAction("VRJumpAction", onJumpAction, false, Enum.KeyCode.ButtonA) + end + else + if isJumpBound then + isJumpBound = false + ContextActionService:UnbindAction("VRJumpAction") + end + end +end + +local moveLatch = false +local controlCharacterGamepad = function(actionName, inputState, inputObject) + if inputObject.KeyCode ~= Enum.KeyCode.Thumbstick1 then return end + + if inputState == Enum.UserInputState.Cancel then + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(0,0,0) + return + end + + if inputState ~= Enum.UserInputState.End then + stopFollowingPath() + if PathDisplay then + PathDisplay.clearRenderedPath() + end + + if shouldUseNavigationLaser() then + bindJumpAction(true) + setLaserPointerMode("Hidden") + end + + if inputObject.Position.magnitude > THUMBSTICK_DEADZONE then + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(inputObject.Position.X, 0, -inputObject.Position.Y) + if currentMoveVector.magnitude > 0 then + currentMoveVector = currentMoveVector.unit * math.min(1, inputObject.Position.magnitude) + end + MasterControl:AddToPlayerMovement(currentMoveVector) + + moveLatch = true + end + else + MasterControl:AddToPlayerMovement(-currentMoveVector) + currentMoveVector = Vector3.new(0,0,0) + + if shouldUseNavigationLaser() then + bindJumpAction(false) + setLaserPointerMode("Navigation") + end + + if moveLatch then + moveLatch = false + movementUpdateEvent:Fire("offtrack") + end + end +end + +local function onHeartbeat(dt) + local newMoveVector = currentMoveVector + local humanoid = getLocalHumanoid() + if not humanoid or not humanoid.Torso then + return + end + + if moving and currentPoints then + local currentPosition = humanoid.Torso.Position + local goalPosition = currentPoints[1] + local vectorToGoal = (goalPosition - currentPosition) * XZ_VECTOR3 + local moveDist = vectorToGoal.magnitude + local moveDir = vectorToGoal / moveDist + + if moveDist < POINT_REACHED_THRESHOLD then + local estimatedTimeRemaining = 0 + local prevPoint = currentPoints[1] + for i, point in pairs(currentPoints) do + if i ~= 1 then + local dist = (point - prevPoint).magnitude + prevPoint = point + estimatedTimeRemaining = estimatedTimeRemaining + (dist / humanoid.WalkSpeed) + end + end + + table.remove(currentPoints, 1) + currentPointIdx = currentPointIdx + 1 + + if #currentPoints == 0 then + stopFollowingPath() + if PathDisplay then + PathDisplay.clearRenderedPath() + end + return + else + if PathDisplay then + PathDisplay.setCurrentPoints(currentPoints) + PathDisplay.renderPath() + end + + local newGoal = currentPoints[1] + local distanceToGoal = (newGoal - currentPosition).magnitude + expectedTimeToNextPoint = distanceToGoal / humanoid.WalkSpeed + timeReachedLastPoint = tick() + end + else + local ignoreTable = { + Players.LocalPlayer.Character, + workspace.CurrentCamera + } + local obstructRay = Ray.new(currentPosition - Vector3.new(0, 1, 0), moveDir * 3) + local obstructPart, obstructPoint, obstructNormal = workspace:FindPartOnRayWithIgnoreList(obstructRay, ignoreTable) + + if obstructPart then + local heightOffset = Vector3.new(0, 100, 0) + local jumpCheckRay = Ray.new(obstructPoint + moveDir * 0.5 + heightOffset, -heightOffset) + local jumpCheckPart, jumpCheckPoint, jumpCheckNormal = workspace:FindPartOnRayWithIgnoreList(jumpCheckRay, ignoreTable) + + local heightDifference = jumpCheckPoint.Y - currentPosition.Y + if heightDifference < 6 and heightDifference > -2 then + humanoid.Jump = true + end + end + + local timeSinceLastPoint = tick() - timeReachedLastPoint + if timeSinceLastPoint > expectedTimeToNextPoint + OFFTRACK_TIME_THRESHOLD then + stopFollowingPath() + if PathDisplay then + PathDisplay.clearRenderedPath() + end + + movementUpdateEvent:Fire("offtrack") + end + + newMoveVector = currentMoveVector:Lerp(moveDir, dt * 10) + end + end + + if IsFiniteVector3(newMoveVector) then + MasterControl:AddToPlayerMovement(newMoveVector - currentMoveVector) + currentMoveVector = newMoveVector + end +end + +local userCFrameEnabledConn = nil +local function onUserCFrameEnabled() + if shouldUseNavigationLaser() then + bindJumpAction(false) + setLaserPointerMode("Navigation") + else + bindJumpAction(true) + setLaserPointerMode("Hidden") + end +end + +function VRNavigation:Enable() + navigationRequestedConn = VRService.NavigationRequested:connect(onNavigationRequest) + heartbeatConn = RunService.Heartbeat:connect(onHeartbeat) + + ContextActionService:BindAction("MoveThumbstick", controlCharacterGamepad, false, Enum.KeyCode.Thumbstick1) + ContextActionService:BindActivate(Enum.UserInputType.Gamepad1, Enum.KeyCode.ButtonR2) + + userCFrameEnabledConn = VRService.UserCFrameEnabled:connect(onUserCFrameEnabled) + onUserCFrameEnabled() + + pcall(function() + VRService:SetTouchpadMode(Enum.VRTouchpad.Left, Enum.VRTouchpadMode.VirtualThumbstick) + VRService:SetTouchpadMode(Enum.VRTouchpad.Right, Enum.VRTouchpadMode.ABXY) + end) +end + +function VRNavigation:Disable() + stopFollowingPath() + + ContextActionService:UnbindAction("MoveThumbstick") + ContextActionService:UnbindActivate(Enum.UserInputType.Gamepad1, Enum.KeyCode.ButtonR2) + + bindJumpAction(false) + setLaserPointerMode("Disabled") + + if navigationRequestedConn then + navigationRequestedConn:disconnect() + navigationRequestedConn = nil + end + if heartbeatConn then + heartbeatConn:disconnect() + heartbeatConn = nil + end + if userCFrameEnabledConn then + userCFrameEnabledConn:disconnect() + userCFrameEnabledConn = nil + end +end + +return VRNavigation diff --git a/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/VRNavigation.meta.json b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/VRNavigation.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/VRNavigation.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/VehicleController.lua b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/VehicleController.lua new file mode 100644 index 0000000..e2a3db1 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/VehicleController.lua @@ -0,0 +1,180 @@ +--[[ + // FileName: VehicleControl + // Version 1.0 + // Written by: jmargh + // Description: Implements in-game vehicle controls for all input devices + + // NOTE: This works for basic vehicles (single vehicle seat). If you use custom VehicleSeat code, + // multiple VehicleSeats or your own implementation of a VehicleSeat this will not work. +--]] + +local VehicleController = {} + +local ContextActionService = game:GetService('ContextActionService') +local Players = game:GetService('Players') +local RunService = game:GetService('RunService') + +local MasterControl = require(script.Parent) + +while not Players.LocalPlayer do + wait() +end +local LocalPlayer = Players.LocalPlayer +local CurrentVehicleSeat = nil +local CurrentThrottle = 0 +local CurrentSteer = 0 +local HumanoidSeatedCn = nil +local RenderSteppedCn = nil +local Accelerating = false +local Deccelerating = false +local TurningRight = false +local TurningLeft = false +-- Set this to true if you want to instead use the triggers for the throttle +local useTriggersForThrottle = true +-- Also set this to true if you want the thumbstick to not affect throttle, only triggers when a gamepad is conected +local onlyTriggersForThrottle = false + +local function onThrottleAccel(actionName, inputState, inputObject) + MasterControl:AddToPlayerMovement(Vector3.new(0, 0, -CurrentThrottle)) + CurrentThrottle = (inputState == Enum.UserInputState.End or Deccelerating) and 0 or -1 + MasterControl:AddToPlayerMovement(Vector3.new(0, 0, CurrentThrottle)) + Accelerating = not (inputState == Enum.UserInputState.End) + if (inputState == Enum.UserInputState.End) and Deccelerating then + CurrentThrottle = 1 + MasterControl:AddToPlayerMovement(Vector3.new(0, 0, CurrentThrottle)) + end +end + +local function onThrottleDeccel(actionName, inputState, inputObject) + MasterControl:AddToPlayerMovement(Vector3.new(0, 0, -CurrentThrottle)) + CurrentThrottle = (inputState == Enum.UserInputState.End or Accelerating) and 0 or 1 + MasterControl:AddToPlayerMovement(Vector3.new(0, 0, CurrentThrottle)) + Deccelerating = not (inputState == Enum.UserInputState.End) + if (inputState == Enum.UserInputState.End) and Accelerating then + CurrentThrottle = -1 + MasterControl:AddToPlayerMovement(Vector3.new(0, 0, CurrentThrottle)) + end +end + +local function onSteerRight(actionName, inputState, inputObject) + MasterControl:AddToPlayerMovement(Vector3.new(-CurrentSteer, 0, 0)) + CurrentSteer = (inputState == Enum.UserInputState.End or TurningLeft) and 0 or 1 + MasterControl:AddToPlayerMovement(Vector3.new(CurrentSteer, 0, 0)) + TurningRight = not (inputState == Enum.UserInputState.End) + if (inputState == Enum.UserInputState.End) and TurningLeft then + CurrentSteer = -1 + MasterControl:AddToPlayerMovement(Vector3.new(CurrentSteer, 0, 0)) + end +end + +local function onSteerLeft(actionName, inputState, inputObject) + MasterControl:AddToPlayerMovement(Vector3.new(-CurrentSteer, 0, 0)) + CurrentSteer = (inputState == Enum.UserInputState.End or TurningRight) and 0 or -1 + MasterControl:AddToPlayerMovement(Vector3.new(CurrentSteer, 0, 0)) + TurningLeft = not (inputState == Enum.UserInputState.End) + if (inputState == Enum.UserInputState.End) and TurningRight then + CurrentSteer = 1 + MasterControl:AddToPlayerMovement(Vector3.new(CurrentSteer, 0, 0)) + end +end + +local function getHumanoid() + local character = LocalPlayer and LocalPlayer.Character + if character then + for _,child in pairs(character:GetChildren()) do + if child:IsA('Humanoid') then + return child + end + end + end +end + +local function getClosestFittingValue(value) + if value > 0.5 then + return 1 + elseif value < -0.5 then + return -1 + end + return 0 +end + +local function onRenderStepped() + if CurrentVehicleSeat then + local moveValue = MasterControl:GetMoveVector() + local didSetThrottleSteerFloat = false + didSetThrottleSteerFloat = pcall(function() + if game:GetService("UserInputService"):GetGamepadConnected(Enum.UserInputType.Gamepad1) and onlyTriggersForThrottle and useTriggersForThrottle then + CurrentVehicleSeat.ThrottleFloat = -CurrentThrottle + else + CurrentVehicleSeat.ThrottleFloat = -moveValue.z + end + CurrentVehicleSeat.SteerFloat = moveValue.x + end) + + if didSetThrottleSteerFloat == false then + if game:GetService("UserInputService"):GetGamepadConnected(Enum.UserInputType.Gamepad1) and onlyTriggersForThrottle and useTriggersForThrottle then + CurrentVehicleSeat.Throttle = -CurrentThrottle + else + CurrentVehicleSeat.Throttle = getClosestFittingValue(-moveValue.z) + end + CurrentVehicleSeat.Steer = getClosestFittingValue(moveValue.x) + end + end +end + +local function onSeated(active, currentSeatPart) + if active then + if currentSeatPart and currentSeatPart:IsA('VehicleSeat') then + CurrentVehicleSeat = currentSeatPart + if useTriggersForThrottle then + ContextActionService:BindAction("throttleAccel", onThrottleAccel, false, Enum.KeyCode.ButtonR2) + ContextActionService:BindAction("throttleDeccel", onThrottleDeccel, false, Enum.KeyCode.ButtonL2) + end + ContextActionService:BindAction("arrowSteerRight", onSteerRight, false, Enum.KeyCode.Right) + ContextActionService:BindAction("arrowSteerLeft", onSteerLeft, false, Enum.KeyCode.Left) + local success = pcall(function() RunService:BindToRenderStep("VehicleControlStep", Enum.RenderPriority.Input.Value, onRenderStepped) end) + + if not success then + if RenderSteppedCn then return end + RenderSteppedCn = RunService.RenderStepped:connect(onRenderStepped) + end + end + else + CurrentVehicleSeat = nil + if useTriggersForThrottle then + ContextActionService:UnbindAction("throttleAccel") + ContextActionService:UnbindAction("throttleDeccel") + end + ContextActionService:UnbindAction("arrowSteerRight") + ContextActionService:UnbindAction("arrowSteerLeft") + MasterControl:AddToPlayerMovement(Vector3.new(-CurrentSteer, 0, -CurrentThrottle)) + CurrentThrottle = 0 + CurrentSteer = 0 + local success = pcall(function() RunService:UnbindFromRenderStep("VehicleControlStep") end) + if not success and RenderSteppedCn then + RenderSteppedCn:disconnect() + RenderSteppedCn = nil + end + end +end + +local function CharacterAdded(character) + local humanoid = getHumanoid() + while not humanoid do + wait() + humanoid = getHumanoid() + end + -- + if HumanoidSeatedCn then + HumanoidSeatedCn:disconnect() + HumanoidSeatedCn = nil + end + HumanoidSeatedCn = humanoid.Seated:connect(onSeated) +end + +if LocalPlayer.Character then + CharacterAdded(LocalPlayer.Character) +end +LocalPlayer.CharacterAdded:connect(CharacterAdded) + +return VehicleController diff --git a/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/init.lua b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/init.lua new file mode 100644 index 0000000..3cf9f3d --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/MasterControl/init.lua @@ -0,0 +1,181 @@ +--[[ + // FileName: MasterControl + // Version 1.0 + // Written by: jeditkacheff + // Description: All character control scripts go thru this script, this script makes sure all actions are performed +--]] + +-- [[ Constants ]]-- +local ZERO_VECTOR3 = Vector3.new(0, 0, 0) +local STATE_JUMPING = Enum.HumanoidStateType.Jumping +local STATE_FREEFALL = Enum.HumanoidStateType.Freefall +local STATE_LANDED = Enum.HumanoidStateType.Landed + +--[[ Local Variables ]]-- +local MasterControl = {} +MasterControl.ControlState = nil +MasterControl.TouchJumpModule = nil + +local Players = game:GetService('Players') +local RunService = game:GetService('RunService') + +while not Players.LocalPlayer do + Players.PlayerAdded:wait() +end +local LocalPlayer = Players.LocalPlayer +local LocalCharacter = LocalPlayer.Character +local CachedHumanoid = nil + +local isJumping = false +local moveValue = Vector3.new(0, 0, 0) + +local isJumpEnabled = true +local areControlsEnabled = true + +local clickToMoveFailStateChanged = Instance.new("BindableEvent") +clickToMoveFailStateChanged.Name = "ClickToMoveFailStateChanged" + +--[[ Local Functions ]]-- +function MasterControl:GetHumanoid() + if LocalCharacter then + if CachedHumanoid then + return CachedHumanoid + else + CachedHumanoid = LocalCharacter:FindFirstChildOfClass("Humanoid") + return CachedHumanoid + end + end +end + +local characterAncestryChangedConn = nil +local characterChildRemovedConn = nil +local function characterAdded(character) + if characterAncestryChangedConn then + characterAncestryChangedConn:disconnect() + end + + if characterChildRemovedConn then + characterChildRemovedConn:disconnect() + end + + LocalCharacter = character + CachedHumanoid = LocalCharacter:FindFirstChildOfClass("Humanoid") + characterAncestryChangedConn = character.AncestryChanged:connect(function() + if character.Parent == nil then + LocalCharacter = nil + else + LocalCharacter = character + end + end) + + characterChildRemovedConn = character.ChildRemoved:connect(function(child) + if child == CachedHumanoid then + CachedHumanoid = nil + end + end) +end + +if LocalCharacter then + characterAdded(LocalCharacter) +end +LocalPlayer.CharacterAdded:connect(characterAdded) + + +local getHumanoid = MasterControl.GetHumanoid +local moveFunc = LocalPlayer.Move +local updateMovement = function() + + if not areControlsEnabled then return end + + local humanoid = getHumanoid() + if not humanoid then return end + + if isJumpEnabled and isJumping and not humanoid.PlatformStand then + local state = humanoid:GetState() + if state ~= STATE_JUMPING and state ~= STATE_FREEFALL and state ~= STATE_LANDED then + humanoid.Jump = isJumping + end + end + + moveFunc(LocalPlayer, moveValue, true) +end + +local function clickToMoveFired(toPosition) + moveValue = moveValue + toPosition +end + +--[[ Public API ]]-- +function MasterControl:Init() + RunService:BindToRenderStep("MasterControlStep", Enum.RenderPriority.Input.Value, updateMovement) + --script.Parent.ClickToMove.Event:Connect(clickToMoveFired) +end + +function MasterControl:Enable() + areControlsEnabled = true + isJumpEnabled = true + + if self.ControlState.Current then + self.ControlState.Current:Enable() + end +end + +function MasterControl:Disable() + + if self.ControlState.Current then + self.ControlState.Current:Disable() + end + + --After current control state is disabled, moveValue has been set to zero, + --Call updateMovement one last time to make sure this propagates to the engine - + --Otherwise if disabled while humanoid is moving, humanoid won't stop moving. + updateMovement() + + isJumping = false + areControlsEnabled = false +end + +function MasterControl:EnableJump() + isJumpEnabled = true + if areControlsEnabled and self.ControlState:IsTouchJumpModuleUsed() then + self.TouchJumpModule:Enable() + end +end + +function MasterControl:DisableJump() + isJumpEnabled = false + if self.ControlState:IsTouchJumpModuleUsed() then + self.TouchJumpModule:Disable() + end +end + +function MasterControl:AddToPlayerMovement(playerMoveVector) + moveValue = Vector3.new(moveValue.X + playerMoveVector.X, moveValue.Y + playerMoveVector.Y, moveValue.Z + playerMoveVector.Z) +end + +function MasterControl:GetMoveVector() + return moveValue +end + +function MasterControl:SetIsJumping(jumping) + if not isJumpEnabled then return end + isJumping = jumping + local humanoid = self:GetHumanoid() + if humanoid and not humanoid.PlatformStand then + humanoid.Jump = isJumping + end +end + +function MasterControl:DoJump() + if not isJumpEnabled then return end + local humanoid = self:GetHumanoid() + if humanoid then + humanoid.Jump = true + end +end + +function MasterControl:GetClickToMoveFailStateChanged() + return clickToMoveFailStateChanged +end + +return MasterControl + diff --git a/rojo/MainModule/src/StarterPlayerScripts/ControlScript/PathDisplay.lua b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/PathDisplay.lua new file mode 100644 index 0000000..df2dd51 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/PathDisplay.lua @@ -0,0 +1,131 @@ +local Players = game:GetService("Players") + +local PathDisplay = {} +PathDisplay.spacing = 8 +PathDisplay.image = "rbxasset://textures/Cursors/Gamepad/Pointer.png" +PathDisplay.imageSize = Vector2.new(2, 2) + +local currentPoints = {} +local renderedPoints = {} + +local pointModel = Instance.new("Model") +pointModel.Name = "PathDisplayPoints" + +local adorneePart = Instance.new("Part") +adorneePart.Anchored = true +adorneePart.CanCollide = false +adorneePart.Transparency = 1 +adorneePart.Name = "PathDisplayAdornee" +adorneePart.CFrame = CFrame.new(0, 0, 0) +adorneePart.Parent = pointModel + +local pointPool = {} +local poolTop = 30 +for i = 1, poolTop do + local point = Instance.new("ImageHandleAdornment") + point.Archivable = false + point.Adornee = adorneePart + point.Image = PathDisplay.image + point.Size = PathDisplay.imageSize + pointPool[i] = point +end + +local function retrieveFromPool() + local point = pointPool[1] + if not point then + return + end + + pointPool[1], pointPool[poolTop] = pointPool[poolTop], nil + poolTop = poolTop - 1 + return point +end + +local function returnToPool(point) + poolTop = poolTop + 1 + pointPool[poolTop] = point +end + +local function renderPoint(point, isLast) + if poolTop == 0 then + return + end + + local rayDown = Ray.new(point + Vector3.new(0, 2, 0), Vector3.new(0, -8, 0)) + local hitPart, hitPoint, hitNormal = workspace:FindPartOnRayWithIgnoreList(rayDown, { Players.LocalPlayer.Character, workspace.CurrentCamera }) + if not hitPart then + return + end + + local pointCFrame = CFrame.new(hitPoint, hitPoint + hitNormal) + + local point = retrieveFromPool() + point.CFrame = pointCFrame + point.Parent = pointModel + return point +end + +function PathDisplay.setCurrentPoints(points) + if typeof(points) == 'table' then + currentPoints = points + else + currentPoints = {} + end +end + +function PathDisplay.clearRenderedPath() + for _, oldPoint in ipairs(renderedPoints) do + oldPoint.Parent = nil + returnToPool(oldPoint) + end + renderedPoints = {} + pointModel.Parent = nil +end + +function PathDisplay.renderPath() + PathDisplay.clearRenderedPath() + if not currentPoints or #currentPoints == 0 then + return + end + + local currentIdx = #currentPoints + local lastPos = currentPoints[currentIdx] + local distanceBudget = 0 + + renderedPoints[1] = renderPoint(lastPos, true) + if not renderedPoints[1] then + return + end + + while true do + local currentPoint = currentPoints[currentIdx] + local nextPoint = currentPoints[currentIdx - 1] + + if currentIdx < 2 then + break + else + + local toNextPoint = nextPoint - currentPoint + local distToNextPoint = toNextPoint.magnitude + + if distanceBudget > distToNextPoint then + distanceBudget = distanceBudget - distToNextPoint + currentIdx = currentIdx - 1 + else + local dirToNextPoint = toNextPoint.unit + local pointPos = currentPoint + (dirToNextPoint * distanceBudget) + local point = renderPoint(pointPos, false) + + if point then + renderedPoints[#renderedPoints + 1] = point + end + + distanceBudget = distanceBudget + PathDisplay.spacing + end + end + end + + pointModel.Parent = workspace.CurrentCamera +end + +return PathDisplay diff --git a/rojo/MainModule/src/StarterPlayerScripts/ControlScript/init.client.lua b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/init.client.lua new file mode 100644 index 0000000..2dc2882 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/ControlScript/init.client.lua @@ -0,0 +1,450 @@ +--[[ + // FileName: ControlScript.lua + // Version 1.1 + // Written by: jmargh and jeditkacheff + // Description: Manages in game controls for both touch and keyboard/mouse devices. + + // This script will be inserted into PlayerScripts under each player by default. If you want to + // create your own custom controls or modify these controls, you must place a script with this + // name, ControlScript, under StarterPlayer -> PlayerScripts. + + // Required Modules: + ClickToMove + DPad + KeyboardMovement + Thumbpad + Thumbstick + TouchJump + MasterControl + VehicleController +--]] + +--[[ Services ]]-- +local ContextActionService = game:GetService('ContextActionService') +local Players = game:GetService('Players') +local UserInputService = game:GetService('UserInputService') +local VRService = game:GetService('VRService') +-- Settings and GameSettings are read only +local Settings = UserSettings() +local GameSettings = Settings.GameSettings + +-- Issue with play solo? (F6) +while not UserInputService.KeyboardEnabled and not UserInputService.TouchEnabled and not UserInputService.GamepadEnabled do + wait() +end + +--[[ Script Variables ]]-- +while not Players.LocalPlayer do + wait() +end + +local lastInputType = nil +local LocalPlayer = Players.LocalPlayer +local PlayerGui = LocalPlayer:WaitForChild('PlayerGui') +local IsTouchDevice = UserInputService.TouchEnabled +local UserMovementMode = IsTouchDevice and GameSettings.TouchMovementMode or GameSettings.ComputerMovementMode +local DevMovementMode = IsTouchDevice and LocalPlayer.DevTouchMovementMode or LocalPlayer.DevComputerMovementMode +local IsUserChoice = (IsTouchDevice and DevMovementMode == Enum.DevTouchMovementMode.UserChoice) or (DevMovementMode == Enum.DevComputerMovementMode.UserChoice) +local TouchGui = nil +local TouchControlFrame = nil +local IsModalEnabled = UserInputService.ModalEnabled +local BindableEvent_OnFailStateChanged = nil +local isJumpEnabled = false + +-- register what control scripts we are using +do + local PlayerScripts = LocalPlayer:WaitForChild("PlayerScripts") + local canRegisterControls = pcall(function() PlayerScripts:RegisterTouchMovementMode(Enum.TouchMovementMode.Default) end) + + if canRegisterControls then + PlayerScripts:RegisterTouchMovementMode(Enum.TouchMovementMode.Thumbstick) + PlayerScripts:RegisterTouchMovementMode(Enum.TouchMovementMode.DPad) + PlayerScripts:RegisterTouchMovementMode(Enum.TouchMovementMode.Thumbpad) + PlayerScripts:RegisterTouchMovementMode(Enum.TouchMovementMode.ClickToMove) + PlayerScripts:RegisterTouchMovementMode(Enum.TouchMovementMode.DynamicThumbstick) + + + PlayerScripts:RegisterComputerMovementMode(Enum.ComputerMovementMode.Default) + PlayerScripts:RegisterComputerMovementMode(Enum.ComputerMovementMode.KeyboardMouse) + PlayerScripts:RegisterComputerMovementMode(Enum.ComputerMovementMode.ClickToMove) + end +end + +local DynamicThumbstickAvailable = pcall(function() + return Enum.DevTouchMovementMode.DynamicThumbstick and Enum.TouchMovementMode.DynamicThumbstick +end) + +--[[ Modules ]]-- +local ClickToMoveTouchControls = nil +local ControlModules = {} + +local ControlState = {} +ControlState.Current = nil +function ControlState:SwitchTo(newControl) + if ControlState.Current == newControl then return end + + if ControlState.Current then + ControlState.Current:Disable() + end + + ControlState.Current = newControl + + if ControlState.Current then + ControlState.Current:Enable() + end +end + +function ControlState:IsTouchJumpModuleUsed() + return isJumpEnabled +end + +local MasterControl = require(script:WaitForChild('MasterControl')) +--MasterControl needs access to ControlState in order to be able to fully enable and disable control +MasterControl.ControlState = ControlState + +local DynamicThumbstickModule = require(script.MasterControl:WaitForChild('DynamicThumbstick')) +local ThumbstickModule = require(script.MasterControl:WaitForChild('Thumbstick')) +local ThumbpadModule = require(script.MasterControl:WaitForChild('Thumbpad')) +local DPadModule = require(script.MasterControl:WaitForChild('DPad')) +local TouchJumpModule = require(script.MasterControl:WaitForChild('TouchJump')) + +MasterControl.TouchJumpModule = TouchJumpModule +local VRNavigationModule = require(script.MasterControl:WaitForChild('VRNavigation')) +local keyboardModule = require(script.MasterControl:WaitForChild('KeyboardMovement')) +ControlModules.Gamepad = require(script.MasterControl:WaitForChild('Gamepad')) + +local function getTouchModule() + + local module = nil + if not IsUserChoice then + if DynamicThumbstickAvailable and DevMovementMode == Enum.DevTouchMovementMode.DynamicThumbstick then + module = DynamicThumbstickModule + isJumpEnabled = true + elseif DevMovementMode == Enum.DevTouchMovementMode.Thumbstick then + module = ThumbstickModule + isJumpEnabled = true + elseif DevMovementMode == Enum.DevTouchMovementMode.Thumbpad then + module = ThumbpadModule + isJumpEnabled = true + elseif DevMovementMode == Enum.DevTouchMovementMode.DPad then + module = DPadModule + isJumpEnabled = false + elseif DevMovementMode == Enum.DevTouchMovementMode.Scriptable then + module = nil + end + else + if DynamicThumbstickAvailable and UserMovementMode == Enum.TouchMovementMode.DynamicThumbstick then + module = DynamicThumbstickModule + isJumpEnabled = true + elseif UserMovementMode == Enum.TouchMovementMode.Default or UserMovementMode == Enum.TouchMovementMode.Thumbstick then + module = ThumbstickModule + isJumpEnabled = true + elseif UserMovementMode == Enum.TouchMovementMode.Thumbpad then + module = ThumbpadModule + isJumpEnabled = true + elseif UserMovementMode == Enum.TouchMovementMode.DPad then + module = DPadModule + isJumpEnabled = false + end + end + return module +end + +local function setJumpModule(isEnabled) + if not isEnabled then + TouchJumpModule:Disable() + elseif ControlState.Current == ControlModules.Touch then + TouchJumpModule:Enable() + end +end + +local function setClickToMove() + if DevMovementMode == Enum.DevTouchMovementMode.ClickToMove or DevMovementMode == Enum.DevComputerMovementMode.ClickToMove or + UserMovementMode == Enum.ComputerMovementMode.ClickToMove or UserMovementMode == Enum.TouchMovementMode.ClickToMove then + if lastInputType == Enum.UserInputType.Touch then + ClickToMoveTouchControls = ControlState.Current + end + elseif ClickToMoveTouchControls then + ClickToMoveTouchControls:Disable() + ClickToMoveTouchControls = nil + end +end + +ControlModules.Touch = {} +ControlModules.Touch.Current = nil +ControlModules.Touch.LocalPlayerChangedCon = nil +ControlModules.Touch.GameSettingsChangedCon = nil + +function ControlModules.Touch:RefreshControlStyle() + if ControlModules.Touch.Current then + ControlModules.Touch.Current:Disable() + end + setJumpModule(false) + TouchJumpModule:Disable() + ControlModules.Touch:Enable() +end +function ControlModules.Touch:DisconnectEvents() + if ControlModules.Touch.LocalPlayerChangedCon then + ControlModules.Touch.LocalPlayerChangedCon:disconnect() + ControlModules.Touch.LocalPlayerChangedCon = nil + end + if ControlModules.Touch.GameSettingsChangedCon then + ControlModules.Touch.GameSettingsChangedCon:disconnect() + ControlModules.Touch.GameSettingsChangedCon = nil + end +end +function ControlModules.Touch:Enable() + DevMovementMode = LocalPlayer.DevTouchMovementMode + IsUserChoice = DevMovementMode == Enum.DevTouchMovementMode.UserChoice + if IsUserChoice then + UserMovementMode = GameSettings.TouchMovementMode + end + + local newModuleToEnable = getTouchModule() + if newModuleToEnable then + setClickToMove() + setJumpModule(isJumpEnabled) + + newModuleToEnable:Enable() + ControlModules.Touch.Current = newModuleToEnable + + if isJumpEnabled then TouchJumpModule:Enable() end + end + + -- This being within the above if statement was causing issues with ClickToMove, which isn't a module within this script. + ControlModules.Touch:DisconnectEvents() + ControlModules.Touch.LocalPlayerChangedCon = LocalPlayer:GetPropertyChangedSignal("DevTouchMovementMode"):connect(function() + ControlModules.Touch:RefreshControlStyle() + end) + ControlModules.Touch.GameSettingsChangedCon = GameSettings:GetPropertyChangedSignal("TouchMovementMode"):connect(function() + ControlModules.Touch:RefreshControlStyle() + end) +end +function ControlModules.Touch:Disable() + ControlModules.Touch:DisconnectEvents() + + local newModuleToDisable = getTouchModule() + + if newModuleToDisable == ThumbstickModule or + newModuleToDisable == DPadModule or + newModuleToDisable == ThumbpadModule or + newModuleToDisable == DynamicThumbstickModule then + newModuleToDisable:Disable() + setJumpModule(false) + TouchJumpModule:Disable() + end +end + +local function getKeyboardModule() + -- NOTE: Click to move still uses keyboard. Leaving cases in case this ever changes. + local whichModule = nil + if not IsUserChoice then + if DevMovementMode == Enum.DevComputerMovementMode.KeyboardMouse then + whichModule = keyboardModule + elseif DevMovementMode == Enum.DevComputerMovementMode.ClickToMove then + whichModule = keyboardModule + end + else + if UserMovementMode == Enum.ComputerMovementMode.KeyboardMouse or UserMovementMode == Enum.ComputerMovementMode.Default then + whichModule = keyboardModule + elseif UserMovementMode == Enum.ComputerMovementMode.ClickToMove then + whichModule = keyboardModule + end + end + + return whichModule +end + +ControlModules.Keyboard = {} +function ControlModules.Keyboard:RefreshControlStyle() + ControlModules.Keyboard:Disable() + ControlModules.Keyboard:Enable() +end +function ControlModules.Keyboard:Enable() + DevMovementMode = LocalPlayer.DevComputerMovementMode + IsUserChoice = DevMovementMode == Enum.DevComputerMovementMode.UserChoice + if IsUserChoice then + UserMovementMode = GameSettings.ComputerMovementMode + end + + local newModuleToEnable = getKeyboardModule() + if newModuleToEnable then + newModuleToEnable:Enable() + end + + ControlModules.Keyboard:DisconnectEvents() + ControlModules.Keyboard.LocalPlayerChangedCon = LocalPlayer.Changed:connect(function(property) + if property == 'DevComputerMovementMode' then + ControlModules.Keyboard:RefreshControlStyle() + end + end) + + ControlModules.Keyboard.GameSettingsChangedCon = GameSettings.Changed:connect(function(property) + if property == 'ComputerMovementMode' then + ControlModules.Keyboard:RefreshControlStyle() + end + end) +end +function ControlModules.Keyboard:DisconnectEvents() + if ControlModules.Keyboard.LocalPlayerChangedCon then + ControlModules.Keyboard.LocalPlayerChangedCon:disconnect() + ControlModules.Keyboard.LocalPlayerChangedCon = nil + end + if ControlModules.Keyboard.GameSettingsChangedCon then + ControlModules.Keyboard.GameSettingsChangedCon:disconnect() + ControlModules.Keyboard.GameSettingsChangedCon = nil + end +end +function ControlModules.Keyboard:Disable() + ControlModules.Keyboard:DisconnectEvents() + local newModuleToDisable = getKeyboardModule() + if newModuleToDisable then + newModuleToDisable:Disable() + end +end + +ControlModules.VRNavigation = {} + +function ControlModules.VRNavigation:Enable() + VRNavigationModule:Enable() +end + +function ControlModules.VRNavigation:Disable() + VRNavigationModule:Disable() +end + +-- not used, but needs to be required +local VehicleController = require(script.MasterControl:WaitForChild('VehicleController')) + + +--[[ Initialization/Setup ]]-- +local function createTouchGuiContainer() + if TouchGui then TouchGui:Destroy() end + + -- Container for all touch device guis + TouchGui = Instance.new('ScreenGui') + TouchGui.Name = "TouchGui" + TouchGui.ResetOnSpawn = false + TouchGui.Parent = PlayerGui + + TouchControlFrame = Instance.new('Frame') + TouchControlFrame.Name = "TouchControlFrame" + TouchControlFrame.Size = UDim2.new(1, 0, 1, 0) + TouchControlFrame.BackgroundTransparency = 1 + TouchControlFrame.Parent = TouchGui + + ThumbstickModule:Create(TouchControlFrame) + DPadModule:Create(TouchControlFrame) + ThumbpadModule:Create(TouchControlFrame) + TouchJumpModule:Create(TouchControlFrame) + DynamicThumbstickModule:Create(TouchControlFrame) +end + +--[[ Settings Changed Connections ]]-- +LocalPlayer.Changed:connect(function(property) + if lastInputType == Enum.UserInputType.Touch and property == 'DevTouchMovementMode' then + ControlState:SwitchTo(ControlModules.Touch) + elseif UserInputService.KeyboardEnabled and property == 'DevComputerMovementMode' then + ControlState:SwitchTo(ControlModules.Keyboard) + end +end) + +GameSettings.Changed:connect(function(property) + if not IsUserChoice then return end + if property == 'TouchMovementMode' or property == 'ComputerMovementMode' then + UserMovementMode = GameSettings[property] + if property == 'TouchMovementMode' then + ControlState:SwitchTo(ControlModules.Touch) + elseif property == 'ComputerMovementMode' then + ControlState:SwitchTo(ControlModules.Keyboard) + end + end +end) + +--[[ Touch Events ]]-- +UserInputService.Changed:connect(function(property) + if property == 'ModalEnabled' then + IsModalEnabled = UserInputService.ModalEnabled + + if lastInputType == Enum.UserInputType.Touch then + if ControlState.Current == ControlModules.Touch and IsModalEnabled then + ControlState:SwitchTo(nil) + elseif ControlState.Current == nil and not IsModalEnabled then + ControlState:SwitchTo(ControlModules.Touch) + end + end + end +end) + +BindableEvent_OnFailStateChanged = MasterControl:GetClickToMoveFailStateChanged() + +if BindableEvent_OnFailStateChanged then + BindableEvent_OnFailStateChanged.Event:connect(function(isOn) + if lastInputType == Enum.UserInputType.Touch and ClickToMoveTouchControls then + if isOn then + ControlState:SwitchTo(ClickToMoveTouchControls) + else + ControlState:SwitchTo(nil) + end + end + end) +end + +local switchToInputType = function(newLastInputType) + lastInputType = newLastInputType + + if VRService.VREnabled then + ControlState:SwitchTo(ControlModules.VRNavigation) + return + end + + if lastInputType == Enum.UserInputType.Touch then + ControlState:SwitchTo(ControlModules.Touch) + elseif lastInputType == Enum.UserInputType.Keyboard or + lastInputType == Enum.UserInputType.MouseButton1 or + lastInputType == Enum.UserInputType.MouseButton2 or + lastInputType == Enum.UserInputType.MouseButton3 or + lastInputType == Enum.UserInputType.MouseWheel or + lastInputType == Enum.UserInputType.MouseMovement then + ControlState:SwitchTo(ControlModules.Keyboard) + elseif lastInputType == Enum.UserInputType.Gamepad1 or + lastInputType == Enum.UserInputType.Gamepad2 or + lastInputType == Enum.UserInputType.Gamepad3 or + lastInputType == Enum.UserInputType.Gamepad4 then + ControlState:SwitchTo(ControlModules.Gamepad) + end +end + +if IsTouchDevice then + createTouchGuiContainer() +end + +MasterControl:Init() + +UserInputService.GamepadDisconnected:connect(function(gamepadEnum) + local connectedGamepads = UserInputService:GetConnectedGamepads() + if #connectedGamepads > 0 then return end + + if not VRService.VREnabled then + if UserInputService.KeyboardEnabled then + ControlState:SwitchTo(ControlModules.Keyboard) + elseif IsTouchDevice then + ControlState:SwitchTo(ControlModules.Touch) + end + end +end) + +UserInputService.GamepadConnected:connect(function(gamepadEnum) + if not VRService.VREnabled then + ControlState:SwitchTo(ControlModules.Gamepad) + end +end) + +switchToInputType(UserInputService:GetLastInputType()) +UserInputService.LastInputTypeChanged:connect(switchToInputType) + +VRService:GetPropertyChangedSignal("VREnabled"):Connect(function() + if VRService.VREnabled then + ControlState:SwitchTo(ControlModules.VRNavigation) + end +end) \ No newline at end of file diff --git a/rojo/MainModule/src/StarterPlayerScripts/DevInfo.client.lua b/rojo/MainModule/src/StarterPlayerScripts/DevInfo.client.lua new file mode 100644 index 0000000..704132f --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/DevInfo.client.lua @@ -0,0 +1,16 @@ +--local WT = "!gniyalp rof uoy knahT .ojnabelbixelf ro 0302remaG_xolboR ,noitanibmoCdraobyeK :elpoep gniwollof eht ot enil siht retfa detneserp sgol rorre yna troper esaelP" +local NewWT = "!gniyalp rof uoy knahT .puorg %q eht ot enil siht retfa ro tahc MWF eht ni detneserp sgol rorre yna troper esaelP" + +print([[ + +███████╗██╗░░░░██╗███╗░░░███╗ +██╔════╝██║░░░░██║████╗░████║ +█████╗░░██║░█╗░██║██╔████╔██║ +██╔══╝░░██║███╗██║██║╚██╔╝██║ +██║░░░░░╚███╔███╔╝██║░╚═╝░██║ +╚═╝░░░░░░╚══╝╚══╝░╚═╝░░░░░╚═╝]]) +--warn(WT:reverse()) +warn(string.format(NewWT, "laiciffO MWF"):reverse()) + + +task.defer(script.Destroy, script) diff --git a/rojo/MainModule/src/StarterPlayerScripts/FPSCap.client.lua b/rojo/MainModule/src/StarterPlayerScripts/FPSCap.client.lua new file mode 100644 index 0000000..e34f7c6 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/FPSCap.client.lua @@ -0,0 +1,12 @@ +local RunService = game:GetService("RunService") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local GetFPS = ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("GetSetting"):InvokeServer("FPS") +local MaxFPS = 30 + +if GetFPS then + while true do + local t0 = tick() + RunService.Heartbeat:Wait() + repeat until (t0 + 1/MaxFPS) < tick() + end +end \ No newline at end of file diff --git a/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Explosions.lua b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Explosions.lua new file mode 100644 index 0000000..a53f9f9 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Explosions.lua @@ -0,0 +1,31 @@ +local module = {} + +--Init +local Debris = game:GetService("Debris") +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local CurrentCamera = workspace.CurrentCamera + +local CurrentTimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value + +function module:OldifyExplosion(Explosion : Explosion): () + if Explosion.Visible then + Explosion.Visible = false + + if CurrentTimePeriod <= 1 then + return + end + + local explosionVisual: SphereHandleAdornment = Instance.new("SphereHandleAdornment") + explosionVisual.Color3 = Color3.fromRGB(255, 0, 0) + explosionVisual.Radius = Explosion.BlastRadius * 0.75 + explosionVisual.CFrame = CFrame.new(Explosion.Position) + explosionVisual.Adornee = workspace.Terrain + explosionVisual.Parent = CurrentCamera + + explosionVisual.Visible = true + Debris:AddItem(explosionVisual, Explosion.BlastRadius * 0.032) + end +end + +return module diff --git a/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Humanoid.lua b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Humanoid.lua new file mode 100644 index 0000000..0e8bb4f --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Humanoid.lua @@ -0,0 +1,185 @@ +local Players = game:GetService("Players") +local LocalPlayer = Players.LocalPlayer + +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local CustomCamera = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("CustomCamera")); +local CustomFont = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("CustomFont")) +local CurrentTimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value +local IsSolo = ReplicatedStorage:WaitForChild("Solo") +local Color3Team = CurrentTimePeriod < 8 + +task.spawn(function() + local IsDisplayNames = ReplicatedStorage:WaitForChild("Protocols"):WaitForChild("GetSetting"):InvokeServer("DisplayNames") + LocalPlayer:SetAttribute("ShowDisplayNames", IsDisplayNames) +end) + +local Humanoid = {} + +function Humanoid:ApplyHealthBar(humanoid: Humanoid): () + local HumanoidParent: Instance? = humanoid.Parent + + if HumanoidParent then + local CurrentHead: Instance? = HumanoidParent:FindFirstChild("Head") + + if CurrentHead and CurrentHead:IsA("Part") then + local Connections = {} + + -- If just somehow an extra one slipped through + local GrabbedExtra = CurrentHead:FindFirstChildOfClass("BillboardGui") + + if GrabbedExtra then + GrabbedExtra:Destroy() + end + + humanoid.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None + humanoid.HealthDisplayType = Enum.HumanoidHealthDisplayType.AlwaysOff + + --if not IsSolo.Value then + local Overhead = script.Overhead:Clone() + + local Healthbar = Overhead.HealthBarContainer + local Nametag = Overhead.TextLabel + local NametagTextStrokeTransparency = Nametag.TextStrokeTransparency + + local IsPlayer: Player? = Players:GetPlayerFromCharacter(HumanoidParent) + + Nametag.Text = HumanoidParent.Name + + Healthbar.Bar.Size = UDim2.new(humanoid.Health / humanoid.MaxHealth, 0, 0, 7) + Healthbar.Visible = (humanoid.MaxHealth > 0) + + if IsPlayer then + local TheresDisplay = LocalPlayer:GetAttribute("ShowDisplayNames") + Overhead.PlayerToHideFrom = IsPlayer + + if TheresDisplay == nil then + local DisplayConnection + DisplayConnection = LocalPlayer:GetAttributeChangedSignal("ShowDisplayNames"):Connect(function() + local TheresDisplay = LocalPlayer:GetAttribute("ShowDisplayNames") + + if TheresDisplay then + Nametag.Text = IsPlayer.DisplayName + end + + local FindInConnections = table.find(Connections, DisplayConnection) + + if FindInConnections then + table.remove(Connections, FindInConnections) + + DisplayConnection:Disconnect() + DisplayConnection = nil + end + end) + + table.insert(Connections, DisplayConnection) + elseif TheresDisplay then + Nametag.Text = IsPlayer.DisplayName + end + + if CurrentTimePeriod >= 6 then + if IsPlayer.Team then + local isColor3 = Color3Team and IsPlayer.Team:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and IsPlayer.Team:GetAttribute("Color3") or IsPlayer.Team.TeamColor.Color + + if not IsPlayer.Neutral then + Nametag.TextColor3 = TeamColor + --Nametag.TextColor3 = IsPlayer.Team.TeamColor.Color + end + end + + table.insert(Connections, IsPlayer:GetPropertyChangedSignal("Neutral"):Connect(function() + if IsPlayer.Team then + if IsPlayer.Neutral then + Nametag.TextColor3 = Color3.fromRGB(255, 255, 255) + else + local isColor3 = Color3Team and IsPlayer.Team:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and IsPlayer.Team:GetAttribute("Color3") or IsPlayer.Team.TeamColor.Color + + --Nametag.TextColor3 = IsPlayer.Team.TeamColor.Color + Nametag.TextColor3 = TeamColor + end + end + end)) + + table.insert(Connections, IsPlayer:GetPropertyChangedSignal("Team"):Connect(function() + if IsPlayer.Team then + if not IsPlayer.Neutral then + local isColor3 = Color3Team and IsPlayer.Team:GetAttribute("Color3") ~= nil + local TeamColor = isColor3 and IsPlayer.Team:GetAttribute("Color3") or IsPlayer.Team.TeamColor.Color + + Nametag.TextColor3 = TeamColor + --Nametag.TextColor3 = IsPlayer.Team.TeamColor.Color + end + end + end)) + end + end + + Overhead.Parent = CurrentHead + Overhead.Size = UDim2.new(0, Nametag.TextBounds.X * 2, 0, 14) + CustomCamera:AddBillboard(Overhead); + + if CurrentTimePeriod < 8 then + CustomFont.displayString(Nametag.Text, Nametag.TextBounds.Y + 4, Nametag, NametagTextStrokeTransparency) + else + Nametag.Font = Enum.Font.Cartoon + end + + table.insert(Connections, Overhead.AncestryChanged:Connect(function(child: Instance, parent: Instance): () + for _, v in pairs(Connections) do + v:Disconnect() + end + + + + if parent then + local GetHumanoid = parent:FindFirstChildOfClass("Humanoid") + + if GetHumanoid then + self:ApplyHealthBar(GetHumanoid) + else + Overhead:Destroy() + end + end + end)) + + table.insert(Connections, humanoid.AncestryChanged:Connect(function(child: Instance, parent: Instance): () + if (not parent) or (not humanoid:IsDescendantOf(HumanoidParent)) then + Overhead:Destroy() + end + end)) + + table.insert(Connections, humanoid.HealthChanged:Connect(function(health: number): () + Healthbar.Bar.Size = UDim2.new(health / humanoid.MaxHealth, 0, 0, 7) + end)) + + table.insert(Connections, humanoid:GetPropertyChangedSignal("MaxHealth"):Connect(function(): () + Healthbar.Bar.Size = UDim2.new(humanoid.Health / humanoid.MaxHealth, 0, 0, 7) + Healthbar.Visible = (humanoid.MaxHealth > 0) + end)) + + table.insert(Connections, HumanoidParent:GetPropertyChangedSignal("Name"):Connect(function(): () + Nametag.Text = HumanoidParent.Name + + --if HumanoidParent:GetAttribute("FakeName") then + -- Nametag.Text = HumanoidParent:GetAttribute("FakeName") + --end + + --if CurrentTimePeriod < 8 then + -- CustomFont.displayString(Nametag.Text, Nametag.TextBounds.Y + 4, Nametag, NametagTextStrokeTransparency) + --end + end)) + + table.insert(Connections, Nametag:GetPropertyChangedSignal("Text"):Connect(function(): () + Overhead.Size = UDim2.new(0, Nametag.TextBounds.X * 2, 0, 14) + + if CurrentTimePeriod < 8 then + CustomFont.displayString(Nametag.Text, Nametag.TextBounds.Y + 4, Nametag, NametagTextStrokeTransparency) + end + end)) + end + end +end + +return Humanoid diff --git a/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Humanoid.meta.json b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Humanoid.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Humanoid.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Replacements.lua b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Replacements.lua new file mode 100644 index 0000000..6dc64cf --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Replacements.lua @@ -0,0 +1,107 @@ +local Replacements = {} + +local Humanoid = require(script.Parent.Humanoid) + +local BODY_PART_NAMES: {string} = { + ["Left Arm"] = true, + ["Left Leg"] = true, + ["Right Arm"] = true, + ["Right Leg"] = true, + ["Torso"] = true, +} + +local SoundsToOld = { + ["rbxasset://sounds/uuhhh.wav"] = "rbxassetid://1033209269" +} + +function Replacements:TintColor(Part : BasePart): () + Part.Color = BrickColor.new(Part.Color).Color + + local randomAmount: number = 6 / 255 + local random: Random = Random.new() + local hue: number, saturation: number, value: number = Part.Color:ToHSV() + + Part.Color = Color3.fromHSV(hue, math.clamp(random:NextNumber(saturation - randomAmount * 1.0, saturation + randomAmount * 1.0), 0, 1), math.clamp(random:NextNumber(value - randomAmount * 0.5, value + randomAmount * 0.5), 0, 1)) +end + +function Replacements:Unbevel(Model : Model): () + for _, Object in pairs(Model:GetChildren()) do + local BodyPart = BODY_PART_NAMES[Object.Name] + + if BodyPart then + local BlockMesh = Instance.new("SpecialMesh") + BlockMesh.MeshType = Enum.MeshType.Brick + BlockMesh.Parent = Object + end + end +end + +function Replacements:HeadHumanoidCheck(Part : BasePart): () + if Part.Name == "Head" and Part.Parent then + local HasHumanoid = Part.Parent:FindFirstChildOfClass("Humanoid") + local AlreadyApplied = Part:FindFirstChildOfClass("BillboardGui") + + if HasHumanoid and not AlreadyApplied then + Humanoid:ApplyHealthBar(HasHumanoid) + end + end +end + +function Replacements:HeadMesh(Mesh: SpecialMesh): () + local Part : Instance? = Mesh.Parent + + if Part and Part:IsA("BasePart") and Mesh.MeshType == Enum.MeshType.Head then + Mesh.MeshId = "rbxassetid://7390281327" + + local OldMeshScale = Mesh.Scale + + if Part.Size.X > Part.Size.Z then + Mesh.Scale = Vector3.new(Part.Size.Z * OldMeshScale.Z, Part.Size.Y * OldMeshScale.Y, Part.Size.Z * OldMeshScale.Z) + else + Mesh.Scale = Vector3.new(Part.Size.X * OldMeshScale.Z, Part.Size.Y * OldMeshScale.Y, Part.Size.X * OldMeshScale.Z) + end + + local Conns = {} -- HANDLES STUFF, GOOD GOING KEY + table.insert(Conns, Part:GetPropertyChangedSignal("Size"):Connect(function() + if Part.Size.X > Part.Size.Z then + Mesh.Scale = Vector3.new(Part.Size.Z * OldMeshScale.Z, Part.Size.Y * OldMeshScale.Y, Part.Size.Z * OldMeshScale.Z) + else + Mesh.Scale = Vector3.new(Part.Size.X * OldMeshScale.Z, Part.Size.Y * OldMeshScale.Y, Part.Size.X * OldMeshScale.Z) + end + + OldMeshScale = Mesh.Scale + end)) + + table.insert(Conns, Mesh:GetPropertyChangedSignal("MeshType"):Connect(function() + if Mesh.MeshType ~= Enum.MeshType.Head and not (Mesh.MeshType == Enum.MeshType.FileMesh and Mesh.MeshId == "rbxassetid://7390281327") then + for _, v in pairs(Conns) do + v:Disconnect() + end + end + end)) + + table.insert(Conns, Part.AncestryChanged:Connect(function(Child, Parent) + if not Parent then + for _, v in pairs(Conns) do + v:Disconnect() + end + end + end)) + end +end + +function Replacements:OldifySound(Sound: Sound): () + if (not SoundsToOld[Sound.SoundId]) then + return + end + + Sound.SoundId = SoundsToOld[Sound.SoundId] +end + +function Replacements:FaceTexture(Decal: Decal): () + if Decal.Texture == "rbxasset://textures/face.png" then + Decal.Texture = "rbxassetid://11945029012" + end +end + +return Replacements diff --git a/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/SkyElements.lua b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/SkyElements.lua new file mode 100644 index 0000000..4978e41 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/SkyElements.lua @@ -0,0 +1,538 @@ +local module = {} + +--Init: +local RunService = game:GetService("RunService") +local Lighting = game:GetService("Lighting") +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local CurrentTimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value +local HeldSky = script.PlainSky + +local sunRayRaycast = RaycastParams.new() +sunRayRaycast.FilterDescendantsInstances = {workspace.CurrentCamera} +sunRayRaycast.FilterType = Enum.RaycastFilterType.Blacklist -- 5/28/2023: bro I aint switching to Exclude + +--moonHolder.CFrame = CFrame.new(sunPos) +--moonHolder.Position = (sunPos:Cross(moonPos).Unit * 2000) + (workspace.CurrentCamera.CFrame.Position) +--moonHolder.Position = Vector3.new(4748.924, 2565.836, 4768.066) + workspace.CurrentCamera.CFrame.Position + +--Flare Config: +type LensFlareConfiguration = { + scale: number, + texture: string, + transparency: number, +} + +type Lense = { + attachment0: Attachment?, + attachment1: Attachment?, + beam: Beam?, + distance: number, + color: Color3, + radius: number, +} + +local lensFlareNode: Part = Instance.new("Part") +lensFlareNode.Name = "LensFlareNode" +lensFlareNode.Anchored = true +lensFlareNode.CanCollide = false +lensFlareNode.CanQuery = false +lensFlareNode.CanTouch = false +lensFlareNode.Locked = true +lensFlareNode.Transparency = 1 +lensFlareNode.Parent = workspace.CurrentCamera + +local sunAdorn = script.SunAdorn +local lastClockTime: number = nil + +local lensFlareConfiguration: LensFlareConfiguration = { + scale = 1 / 8; + texture = "rbxasset://textures/whiteCircle.png"; + transparency = 0.9; +} + +local defaultSkyValues = { + MoonAngularSize = 0, + MoonTextureId = "", + StarCount = 0, + SunAngularSize = 21, + SunTextureId = "rbxassetid://6958593179", + CelestialBodiesShown = true, +} + +local LENSES: {Lense} = + { + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB(200, 255, 200), + distance = 0.000, + radius = 1.00, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB( 0, 255, 0), + distance = 0.200, + radius = 0.50, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB(255, 0, 0), + distance = 0.225, + radius = 0.30, + }; + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB(255, 170, 0), + distance = 0.250, + radius = 1.50, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB(255, 170, 0), + distance = 0.250, + radius = 3.00, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB( 0, 255, 0), + distance = 0.300, + radius = 0.50, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB( 0, 255, 0), + distance = 0.600, + radius = 0.20, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB( 0, 255, 0), + distance = 0.650, + radius = 0.40, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB(255, 0, 0), + distance = 0.780, + radius = 0.20, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB( 0, 255, 0), + distance = 0.900, + radius = 0.25, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB( 63, 63, 63), + distance = 1.200, + radius = 0.15, + }, + { + attachment0 = nil, + attachment1 = nil, + beam = nil, + color = Color3.fromRGB( 63, 63, 63), + distance = 1.500, + radius = 0.15, + }, + } + +--Flare Functions: +local function asVector2(vector3: Vector3, ...): (Vector2, any) + -- Roblox likes to kill my OCD. + return Vector2.new(vector3.X, vector3.Y), ... +end + +--local function isSunOccluded(sunDir: Vector3): () +-- local origin = workspace.CurrentCamera.CFrame.Position + (workspace.CurrentCamera.CFrame.LookVector * 2) +-- local ray = Ray.new(origin,origin + (sunDir * 10e6)) +-- local ignore = {} +-- local occluded = false + +-- if sunDir:Dot(workspace.CurrentCamera.CFrame.LookVector) > 0 then +-- while true do +-- local hit,pos = workspace:FindPartOnRayWithIgnoreList(ray,ignore) +-- if hit then +-- local t = hit.Transparency + hit.LocalTransparencyModifier +-- if t <= 0 then +-- occluded = true +-- break +-- else +-- table.insert(ignore,hit) +-- end +-- else +-- break +-- end +-- end +-- end + +-- return occluded +--end + +-- replication of getDepthBufferValue from G3D's source code (specifically in Sky.cpp) +local function getDepthBufferValue() + local sunDir = Lighting:GetSunDirection() + local cameraObject = workspace.CurrentCamera + local cameraCFrame = cameraObject.CFrame + local visible = 0 + local rays = 0 + local cameraPosition = nil + + if sunDir:Dot(cameraCFrame.LookVector) > 0 then + local realSize = cameraObject:WorldToViewportPoint(cameraCFrame.Position + sunDir) + local vec, inView = asVector2(cameraObject:WorldToViewportPoint(sunDir * 10e6)) + + if inView then + cameraPosition = cameraObject:ViewportPointToRay(realSize.X, realSize.Y).Origin + + for dx = -1, 1 do + for dy = -1, 1 do + local viewPort = cameraObject:ViewportPointToRay( + math.round(realSize.X + dx * 15), + math.round(realSize.Y + dy * 15) + ) + + rays += 1 + local cast = workspace:Raycast(viewPort.Origin, viewPort.Direction * 5000, sunRayRaycast) + + if not cast then + visible += 1 + end + end + end + end + end + + return (visible / rays), cameraPosition +end + +local function createLenseBeam(lense: Lense, id: number): Beam + local radius: number = lense.radius * lensFlareConfiguration.scale + + local attachment0: Attachment = Instance.new("Attachment") + attachment0.Name = id .. "_A0" + attachment0.Parent = lensFlareNode + lense.attachment0 = attachment0 + + local attachment1: Attachment = Instance.new("Attachment") + attachment1.Name = id .. "_A1" + attachment1.Parent = lensFlareNode + lense.attachment1 = attachment1 + + local beam: Beam = Instance.new("Beam") + beam.Attachment0 = attachment0 + beam.Attachment1 = attachment1 + beam.Color = ColorSequence.new(lense.color) + beam.LightEmission = 1 + beam.Name = tostring(id) + beam.Texture = lensFlareConfiguration.texture + beam.TextureSpeed = 0 + beam.Width0 = radius + beam.Width1 = radius + beam.Parent = lensFlareNode + + lense.beam = beam + + return beam +end + +local function updateLensFlare(): () + local vpSize: Vector2 = workspace.CurrentCamera.ViewportSize + local moonDir: Vector3 = Lighting:GetMoonDirection() + local sunDir: Vector3 = Lighting:GetSunDirection() + local sunWrldSpace: Vector3 = sunDir * 10e6 + local sunScrnSpace: Vector2, inView: boolean = asVector2(workspace.CurrentCamera:WorldToViewportPoint(sunWrldSpace)) + local sunScrnSpaceInv: Vector2 = workspace.CurrentCamera.ViewportSize - sunScrnSpace + local amount, position = getDepthBufferValue() + local enabled = (amount > 0.01 and sunDir.Y > -.1) + --local enabled = (position ~= nil) + + for i: number, lense: Lense in ipairs(LENSES) do + local beam = lense.beam or createLenseBeam(lense, i) + + local squareRoot = math.sqrt(math.max(0, sunDir.Y * 4)) + local transparencyEquation = 0.04 * squareRoot + local finalTransparency = 1 - transparencyEquation + + beam.Transparency = NumberSequence.new(finalTransparency) + beam.Enabled = enabled + + if enabled then + local radius: number = lense.radius * lensFlareConfiguration.scale + local lenseSP: Vector2 = sunScrnSpaceInv:Lerp(sunScrnSpace, lense.distance) + local lenseWP: Vector3 = workspace.CurrentCamera:ViewportPointToRay(lenseSP.X, lenseSP.Y, 1).Origin + local lenseCF: CFrame = CFrame.new(lenseWP, lenseWP - sunDir) + + if lense.attachment0 and lense.attachment1 then + lense.attachment0.CFrame = lenseCF * CFrame.new(-radius / 2, 0, 0) + lense.attachment1.CFrame = lenseCF * CFrame.new(radius / 2, 0, 0) + end + end + end +end + +local moonHolder = Instance.new("Part") +moonHolder.Transparency = 1 +moonHolder.CanCollide = false +moonHolder.Anchored = true +moonHolder.CanTouch = false +moonHolder.CanQuery = false +moonHolder.Locked = true +moonHolder.Parent = workspace.CurrentCamera +moonHolder.Name = "FWM_LEGACY_MOON" + +local moonTextureHolder: BillboardGui = Instance.new("BillboardGui") +moonTextureHolder.ClipsDescendants = false +moonTextureHolder.LightInfluence = 0 +moonTextureHolder.Name = "Interface" +moonTextureHolder.Size = UDim2.new(0, 75, 0, 75) +moonTextureHolder.Parent = moonHolder + +local moonTexture: ImageLabel = Instance.new("ImageLabel") +moonTexture.BackgroundTransparency = 1 +moonTexture.Image = "rbxassetid://8753438296" +moonTexture.Name = "Texture" +moonTexture.Rotation = -65 +moonTexture.Size = UDim2.new(1, 0, 1, 0) +moonTexture.ResampleMode = Enum.ResamplerMode.Pixelated +moonTexture.Parent = moonTextureHolder + +local stars = {} +local nightLegacy = Instance.new("Part") +nightLegacy.Name = "FWM_LEGACY_NIGHT" +nightLegacy.Transparency = 1 +nightLegacy.CanCollide = false +nightLegacy.Anchored = true +nightLegacy.CanTouch = false +nightLegacy.CanQuery = false +nightLegacy.Locked = true +nightLegacy.Parent = workspace.CurrentCamera +nightLegacy.Position = Vector3.zero + +local function moonUpdate(): () + local currentCamera = workspace.CurrentCamera + local cameraCFrame = currentCamera.CFrame + + local sunPos = Lighting:GetSunDirection() + local moonPos = Lighting:GetMoonDirection() + local crossEquation = moonPos:Cross(-sunPos) + + local moonActualPosition = moonPos:Cross(moonPos:Cross(Vector3.zAxis)).Unit + local moonTransparency = math.clamp(moonActualPosition.Y * 4, 0, 1) + + moonHolder.CFrame = CFrame.new(crossEquation.Unit * 2500, sunPos) + cameraCFrame.Position + Vector3.new(0, 150, 4000).Unit * 2000 + moonTexture.ImageTransparency = moonTransparency +end + +--local Ratio; +--local Size; +--local function can_see_target(lp) +-- local r = Size.X/Size.Y; +-- local h = -math.min(lp.z,0)*Ratio; +-- local w = r*h; +-- local corner = Vector3.new(-w, h, lp.z); +-- local relative = lp - corner; +-- local sx = relative.X / (w*2); +-- local sy = -relative.Y / (h*2); +-- return -lp.Z > 0 and sx >=0 and sx <= 1 and sy >=0 and sy <= 1; +--end + +local CurrentCamera = workspace.CurrentCamera; + +local function handleStars(): () + local sunPos = Lighting:GetSunDirection() + local moonPos = Lighting:GetMoonDirection() + local currentClockTime = Lighting.ClockTime + local starsClamp = math.clamp(sunPos.Y * 10, 0, 1) + + --Ratio = math.tan(math.rad(CurrentCamera.FieldOfView/2)); + --Size = CurrentCamera.ViewportSize; + + --if moonPos.Y < -0.3 then + -- nightLegacy.Parent = nil + -- return + --end + + local cameraCFrame = CurrentCamera.CFrame; + nightLegacy.CFrame = CFrame.new(cameraCFrame.Position) + * CFrame.lookAt(Vector3.zero, sunPos) + + if lastClockTime == currentClockTime then + return + end + + lastClockTime = currentClockTime + + --local invCameraMatrix = cameraCFrame.Rotation:inverse(); + --local matrix = invCameraMatrix * nightLegacy.CFrame.Rotation; + for position, starframe in stars do + starframe.StarFrame.BackgroundTransparency = starsClamp + end +end + +local function updateSunRay(): () + local sunDir = Lighting:GetSunDirection() + local amount, position = getDepthBufferValue() + local currentCamera = workspace.CurrentCamera + + if sunDir.X < 0 or sunDir.Y < -.1 or (not position) then + sunAdorn.Parent = nil + + return + end + + local occulusionAttenuation = 1 - ((2 * amount - 1) ^ 2) + local equationForSun = occulusionAttenuation * 0.4 * math.clamp(1 - sunDir.Y * 2 / math.sqrt(2), 0, 1) + local finalEquation = 1 - equationForSun + + sunAdorn.Parent = currentCamera + sunAdorn.SunRayTexture.Transparency = NumberSequence.new(finalEquation) + sunAdorn.CFrame = CFrame.new(position, currentCamera.CFrame.Position) +end + +local function otherSkyBoxes(): boolean + for i, v in pairs(Lighting:GetChildren()) do + if v:IsA("Sky") and not v:GetAttribute("FWMTexture") then + return true + end + end + + return false +end + +local function getFWMSky(): () + local findName = Lighting:FindFirstChild("PlainSky") + + if not findName then + return + end + + for i, v in pairs(Lighting:GetChildren()) do + local isFWMSky = v:GetAttribute("FWMTexture") + + if v:IsA("Sky") and isFWMSky then + return v + end + end +end + +local function initializeAlreadyExisting(alreadyExist: Sky): () + local isOfficialTexture = alreadyExist:GetAttribute("FWMTexture") + + if alreadyExist:IsA("Sky") and (not isOfficialTexture) and alreadyExist.StarCount > 0 then + for propertys, values in defaultSkyValues do + alreadyExist[propertys] = values + end + end +end + +local function registerSkyBox(newSkybox: Sky) + if newSkybox:IsA("Sky") then + local theresOthers = otherSkyBoxes() + + -- roblox added StarCount in like the 2010s and every skybox made before that had had their StarCount set to 3000 + if newSkybox.StarCount > 0 then + for propertys, values in defaultSkyValues do + newSkybox[propertys] = values + end + end + + if theresOthers then + local grabbedSky = getFWMSky() + + if grabbedSky then + task.defer(function() + HeldSky.Parent = script + end) + end + end + end +end + +local function unregisterSkyBox(removedSkybox: Sky) + local isOfficialTexture = removedSkybox:GetAttribute("FWMTexture") + + if removedSkybox:IsA("Sky") and not isOfficialTexture then + local findOthers = otherSkyBoxes() + + if findOthers or (not HeldSky) then + return + end + + task.defer(function() + HeldSky.Parent = Lighting + end) + end +end + +local function skyboxHandler(): () + local getSky = Lighting:FindFirstChildOfClass("Sky") + + if not getSky then + HeldSky.Parent = Lighting + end + + if CurrentTimePeriod >= 8 then + for i, v in pairs(Lighting:GetChildren()) do + initializeAlreadyExisting(v) + end + + Lighting.ChildAdded:Connect(registerSkyBox) + Lighting.ChildRemoved:Connect(unregisterSkyBox) + end +end + +function module:InitializeElements() + skyboxHandler() + + RunService:BindToRenderStep("updateLensFlare", 201, updateLensFlare) + RunService:BindToRenderStep("moonUpdate", 201, moonUpdate) + + if CurrentTimePeriod >= 7 then + RunService:BindToRenderStep("updateSunRay", 201, updateSunRay) + + for i = 1, 750 do + local newStar = script.FWM_STAR:Clone() + + local sizeAmt = math.random(1, 3) + newStar.Size = UDim2.new(0, sizeAmt, 0, sizeAmt) + newStar.StudsOffsetWorldSpace = Vector3.new(math.random(-1000, 1000), math.random(-1000, 1000), math.random(-1000, 1000)).Unit * 5000 + newStar.Parent = nightLegacy + newStar.Adornee = nightLegacy + + --stars[newStar.StudsOffset] = newStar.StarFrame; + table.insert(stars, newStar) + end + + RunService:BindToRenderStep("handleStars", 201, handleStars) + + --if CurrentTimePeriod >= 8 then + -- skyboxHandler() + --end + end +end + +return module \ No newline at end of file diff --git a/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/SkyElements.meta.json b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/SkyElements.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/SkyElements.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Surfaces.lua b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Surfaces.lua new file mode 100644 index 0000000..76f0803 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Surfaces.lua @@ -0,0 +1,341 @@ +-- GAMES UNITE +local module = {} + +local SurfaceTextures = { + [Enum.SurfaceType.Studs] = "rbxassetid://1068388907", + [Enum.SurfaceType.Inlet] = "rbxassetid://1068388840", + [Enum.SurfaceType.Weld] = "rbxassetid://3447813050", + [Enum.SurfaceType.Glue] = "rbxassetid://3527578761", +} + +local CylinderSides = { + Enum.NormalId.Left, + Enum.NormalId.Right +} + +local SurfaceNormals = { + ["TopSurface"] = Enum.NormalId.Top, + ["BottomSurface"] = Enum.NormalId.Bottom, + ["BackSurface"] = Enum.NormalId.Back, + ["FrontSurface"] = Enum.NormalId.Front, + ["RightSurface"] = Enum.NormalId.Right, + ["LeftSurface"] = Enum.NormalId.Left +} + +local BlacklistedNormals = { + [Enum.MeshType.Head] = { + [Enum.NormalId.Top] = true, + [Enum.NormalId.Bottom] = true, + [Enum.NormalId.Back] = true, + [Enum.NormalId.Front] = true, + [Enum.NormalId.Right] = true, + [Enum.NormalId.Left] = true + }, + + [Enum.MeshType.Wedge] = { + [Enum.NormalId.Top] = true + }, + + [Enum.MeshType.FileMesh] = { + [Enum.NormalId.Top] = true, + [Enum.NormalId.Bottom] = true, + [Enum.NormalId.Back] = true, + [Enum.NormalId.Front] = true, + [Enum.NormalId.Right] = true, + [Enum.NormalId.Left] = true + } +} + +local function GetOffsets(BasePart : BasePart) + return{ + ["TopSurface"] = CFrame.Angles(math.rad(-90), 0, 0) * CFrame.new(0, 0, BasePart.Size.Y / 2), + ["BottomSurface"] = CFrame.Angles(math.rad(-90), 0, 0) * CFrame.new(0, 0, -BasePart.Size.Y / 2), + ["LeftSurface"] = CFrame.Angles(0, math.rad(90), 0) * CFrame.new(0, 0, -BasePart.Size.X / 2), + ["RightSurface"] = CFrame.Angles(0, math.rad(90), 0) * CFrame.new(0, 0, BasePart.Size.X / 2), + ["FrontSurface"] = CFrame.Angles(0, 0, 0) * CFrame.new(0, 0, -BasePart.Size.Z / 2), + ["BackSurface"] = CFrame.Angles(0, 0, 0) * CFrame.new(0, 0, BasePart.Size.Z / 2), + } +end + +local function GrabTextures(BasePart : BasePart) + local ReturnedData = {} + + for _, v in pairs(BasePart:GetChildren()) do + if v:GetAttribute("FWMTexture") then + table.insert(ReturnedData, v) + end + end + + return ReturnedData +end + +local function GetValidSpecialMesh(BasePart: BasePart): SpecialMesh? + if BasePart:FindFirstChildOfClass("SpecialMesh") then + for _, v in pairs(BasePart:GetChildren()) do + if v:IsA("SpecialMesh") and not v:GetAttribute("FWMTexture") then + return v + end + end + end + + return nil +end + +local function ApplyPlus(BasePart: BasePart) + local NewMesh = script.CylinderMesh:Clone() + NewMesh.Parent = BasePart + + for _, v in pairs(CylinderSides) do + local PlusSide = script.CylinderPlus:Clone() + PlusSide.Face = v + PlusSide.Parent = BasePart + end +end + +local function ShineBasedOffMesh(BasePart : BasePart, Mesh : SpecialMesh?): () + if Mesh and Mesh.TextureId ~= "" then + BasePart.MaterialVariant = "" + BasePart.Material = Enum.Material.Brick + else + BasePart.Material = Enum.Material.SmoothPlastic + BasePart.MaterialVariant = (BasePart.Reflectance < 0.01 and "Shiny") or "" + end +end + +local function HandleSurfacesFromMesh(BasePart : BasePart, HasMesh : SpecialMesh): () + local Type = HasMesh.MeshType + local MeshTexture = HasMesh.TextureId + local GetTextures = GrabTextures(BasePart) + + ShineBasedOffMesh(BasePart, HasMesh) + + if BlacklistedNormals[Type] then + for _, v in pairs(GetTextures) do + if v:IsA("Texture") then + local GetSurface = string.gsub(v.Name, "LegacyTextureVisual_", "") + v.Texture = SurfaceTextures[BasePart[GetSurface]] or "" + + if BlacklistedNormals[Type][v.Face] and v.Texture ~= "" then + v.Texture = "" + end + end + end + end +end + +local function DrawSurfaces(BasePart : BasePart, HasMesh : SpecialMesh?): () + local AdornmentsOffsets = GetOffsets(BasePart) + local GetTextures = GrabTextures(BasePart) + + local FocusedMesh = HasMesh + local MeshConnection = nil + + local ShapeUpdating = false + + local Connections = {} + + if BasePart:IsA("Part") and BasePart:GetAttribute("Cylinder") == true then + ApplyPlus(BasePart) + end + + for Surface, Normal in pairs(SurfaceNormals) do + local SurfaceType = BasePart[Surface] + local SurfaceUpdating = false + + local Texture = Instance.new("Texture") + Texture.Name = "LegacyTextureVisual_"..Surface + Texture.Texture = SurfaceTextures[SurfaceType] or "" + Texture.StudsPerTileU = 2 + Texture.StudsPerTileV = 4 + Texture.Transparency = BasePart.Transparency + .2 + Texture.LocalTransparencyModifier = BasePart.LocalTransparencyModifier + Texture.Face = Normal + Texture.ZIndex = -1 + Texture:SetAttribute("FWMTexture", true) + Texture.Parent = BasePart + + local MotorHinge = Instance.new("CylinderHandleAdornment") + MotorHinge.CFrame = AdornmentsOffsets[Surface] + MotorHinge.Name = "LegacyTextureVisual_"..Surface + MotorHinge.Height = 1.01 + MotorHinge.Radius = 0.21 + MotorHinge.Color3 = Color3.fromRGB(255, 255, 0) + MotorHinge.AlwaysOnTop = true + MotorHinge.Visible = (SurfaceType == Enum.SurfaceType.Motor) + MotorHinge.Adornee = BasePart + MotorHinge:SetAttribute("FWMTexture", true) + MotorHinge.Parent = BasePart + + local MotorHingeBack = Instance.new("CylinderHandleAdornment") + MotorHingeBack.CFrame = AdornmentsOffsets[Surface] + MotorHingeBack.Name = MotorHinge.Name.."_Background" + MotorHingeBack.Height = 0.251 + MotorHingeBack.Radius = 0.41 + MotorHingeBack.Color3 = Color3.fromRGB(70, 70, 70) + MotorHingeBack.AlwaysOnTop = true + MotorHingeBack.Visible = MotorHinge.Visible + MotorHingeBack.Adornee = BasePart + MotorHingeBack.Parent = MotorHinge + + local Hinge = Instance.new("CylinderHandleAdornment") + Hinge.CFrame = AdornmentsOffsets[Surface] + Hinge.Name = "LegacyTextureVisual_"..Surface + Hinge.Height = 1.01 + Hinge.Radius = 0.21 + Hinge.Color3 = Color3.fromRGB(255, 255, 0) + Hinge.AlwaysOnTop = true + Hinge.Visible = (SurfaceType == Enum.SurfaceType.Hinge) + Hinge.Adornee = BasePart + Hinge:SetAttribute("FWMTexture", true) + Hinge.Parent = BasePart + + table.insert(Connections, BasePart:GetPropertyChangedSignal(Surface):Connect(function() + Texture.Texture = SurfaceTextures[BasePart[Surface]] or "" + + Hinge.Visible = BasePart[Surface] == Enum.SurfaceType.Hinge + MotorHinge.Visible = BasePart[Surface] == Enum.SurfaceType.Motor + MotorHingeBack.Visible = MotorHinge.Visible + + if FocusedMesh then + HandleSurfacesFromMesh(BasePart, FocusedMesh) + end + end)) + end + + table.insert(Connections, BasePart:GetPropertyChangedSignal("Reflectance"):Connect(function() + ShineBasedOffMesh(BasePart, FocusedMesh) + end)) + + table.insert(Connections, BasePart:GetPropertyChangedSignal("Size"):Connect(function() + local GetTextures = GrabTextures(BasePart) + local GetOffsets = GetOffsets(BasePart) + + for _, v in pairs(GetTextures) do + if v:IsA("CylinderHandleAdornment") then + local SurfaceType = string.gsub(v.Name, "LegacyTextureVisual_", "") + + if GetOffsets[SurfaceType] then + v.CFrame = GetOffsets[SurfaceType] + + local GetBackground = v:FindFirstChild(v.Name.."_Background") + + if not GetBackground then + continue + end + + GetBackground.CFrame = v.CFrame + end + end + end + end)) + + table.insert(Connections, BasePart:GetPropertyChangedSignal("Transparency"):Connect(function() + local GetTextures = GrabTextures(BasePart) + + for _, v in pairs(GetTextures) do + if v:IsA("Texture") then + v.Transparency = BasePart.Transparency + .2 + end + end + end)) + + table.insert(Connections, BasePart:GetPropertyChangedSignal("LocalTransparencyModifier"):Connect(function() + local GetTextures = GrabTextures(BasePart) + + for _, v in pairs(GetTextures) do + if v:IsA("Texture") then + v.LocalTransparencyModifier = BasePart.LocalTransparencyModifier + end + end + end)) + + table.insert(Connections, BasePart.ChildAdded:Connect(function(child) + if child:IsA("SpecialMesh") and not child:GetAttribute("FWMTexture") then + if MeshConnection then + MeshConnection:Disconnect() + end + + FocusedMesh = child + + MeshConnection = FocusedMesh:GetPropertyChangedSignal("MeshType"):Connect(function() + HandleSurfacesFromMesh(BasePart, FocusedMesh) + end) + + HandleSurfacesFromMesh(BasePart, FocusedMesh) + end + end)) + + table.insert(Connections, BasePart.ChildRemoved:Connect(function(child) + if child:IsA("SpecialMesh") and not child:GetAttribute("FWMTexture") then + if MeshConnection then + MeshConnection:Disconnect() + end + + local SecondChance = GetValidSpecialMesh(BasePart) + + if SecondChance then + FocusedMesh = SecondChance + + MeshConnection = FocusedMesh:GetPropertyChangedSignal("MeshType"):Connect(function() + HandleSurfacesFromMesh(BasePart, FocusedMesh) + end) + + return + end + + FocusedMesh = nil + MeshConnection = nil + + ShineBasedOffMesh(BasePart, FocusedMesh) + end + end)) + + table.insert(Connections, BasePart.AncestryChanged:Connect(function(child, parent) + if not parent then + for _, v in pairs(Connections) do + v:Disconnect() + end + + if MeshConnection then + MeshConnection:Disconnect() + MeshConnection = nil + end + end + end)) + + if FocusedMesh then + MeshConnection = FocusedMesh:GetPropertyChangedSignal("MeshType"):Connect(function() + HandleSurfacesFromMesh(BasePart, FocusedMesh) + end) + + HandleSurfacesFromMesh(BasePart, FocusedMesh) + end +end + +local function ApplySurfaces(BasePart: BasePart): () + local FocusedMesh = GetValidSpecialMesh(BasePart) + DrawSurfaces(BasePart, FocusedMesh) +end + +function module:ApplySurfaceTextures(BasePart: BasePart): () + BasePart.Material = Enum.Material.SmoothPlastic + BasePart.CastShadow = false + + -- OOPS LOLOOLOLO completely forgot to add an "else" statement to things like this + if BasePart.Reflectance < 0.01 then + BasePart.MaterialVariant = "Shiny" + else + BasePart.MaterialVariant = "" + end + + -- a small price to pay for salvation... + local GetExisting = GrabTextures(BasePart) + + for _, v in pairs(GetExisting) do + v:Destroy() + end + + ApplySurfaces(BasePart) +end + +return module \ No newline at end of file diff --git a/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Surfaces.meta.json b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Surfaces.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/Surfaces.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/init.client.lua b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/init.client.lua new file mode 100644 index 0000000..de8eb8a --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipeline/init.client.lua @@ -0,0 +1,47 @@ +--!strict +--[[ + FWM 2022 + + Handles initializing the graphics pipeline. + GAMES UNITE!!! GAME UNITE!!!!!! + + TODO: Handle shape changing in surfaces script +]] + +--Init: +local Humanoid = require(script.Humanoid) +local Explosions = require(script.Explosions) +local Surfaces = require(script.Surfaces) +local SkyElements = require(script.SkyElements) +local Replacements = require(script.Replacements) + +--Functions: +local function Process(Child: any): () + if Child:IsA("BasePart") then + Surfaces:ApplySurfaceTextures(Child) + Replacements:TintColor(Child) + Replacements:HeadHumanoidCheck(Child) + elseif Child:IsA("Humanoid") then + Humanoid:ApplyHealthBar(Child) + Replacements:Unbevel(Child.Parent) + elseif Child:IsA("Explosion") then + Explosions:OldifyExplosion(Child) + elseif Child:IsA("SpecialMesh") then + Replacements:HeadMesh(Child) + elseif Child:IsA("Decal") then + Replacements:FaceTexture(Child) + elseif Child:IsA("Sound") then + Replacements:OldifySound(Child) + end +end + +--Hookup: +SkyElements:InitializeElements() + +for _, v in pairs(workspace:GetDescendants()) do + Process(v) +end + +workspace.DescendantAdded:Connect(function(Child : any): () + Process(Child) +end) diff --git a/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipelineNEW.client.lua b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipelineNEW.client.lua new file mode 100644 index 0000000..ea08da1 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/GraphicsPipelineNEW.client.lua @@ -0,0 +1,112 @@ +--[[ + + FWM Official, 2023 + A good graphics pipeline + +]]-- + +local Players = game:GetService("Players") +local Lighting = game:GetService("Lighting") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local Debris = game:GetService("Debris") +local TeleportService = game:GetService("TeleportService") + +-- Important Values, shouldn't ever be changed in run time +local IsSolo = ReplicatedStorage:WaitForChild("Solo").Value +local CurrentTimePeriod = ReplicatedStorage:WaitForChild("TimePeriod").Value + +-- Booleans to make life completely easier +-- Time Periods +local IsEras = CurrentTimePeriod > 8 -- Eras era also includes Color3 teams, wow! +local ShowExplosions = CurrentTimePeriod > 1 + +-- Settings +local DisplayNames = TeleportService:GetTeleportSetting("DisplayNames") + +-- Important Tables +local SoundsToOld = { + ["rbxasset://sounds/uuhhh.wav"] = "rbxassetid://1033209269" +} + +local DecalsToOld = { + ["rbxasset://textures/face.png"] = "rbxassetid://11945029012" +} + +local BodyPartNames = { + ["Left Arm"] = true, + ["Left Leg"] = true, + ["Right Arm"] = true, + ["Right Leg"] = true, + ["Torso"] = true +} + +-- Variables +local CurrentCamera = workspace.CurrentCamera + +-- Functions that'll handle each of their Classes +local function ExplosionCreated(Explosion) + local PriorVisible = Explosion.Visible + Explosion.Visible = false + + if (not ShowExplosions) then + return + end + + local explosionVisual: SphereHandleAdornment = Instance.new("SphereHandleAdornment") + explosionVisual.Color3 = Color3.fromRGB(255, 0, 0) + explosionVisual.Radius = Explosion.BlastRadius * 0.75 + explosionVisual.CFrame = CFrame.new(Explosion.Position) + explosionVisual.Adornee = workspace.Terrain + + explosionVisual.Parent = CurrentCamera + explosionVisual.Visible = PriorVisible + + Debris:AddItem(explosionVisual, Explosion.BlastRadius * 0.033) +end + +local function PartCreated(Part) + +end + +local function MeshCreated(SpecialMesh) + +end + +local function TextureCreated(Texture) + +end + +local function HumanoidCreated(Humanoid) + +end + +local function SoundCreated(Sound) + +end + +-- Main Setup +local ClassesToFunctions = { + ["Explosion"] = tr, + ["Part"] = PartCreated, + ["SpecialMesh"] = MeshCreated, + ["Decal"] = TextureCreated, + ["Texture"] = TextureCreated, + ["Humanoid"] = HumanoidCreated, + ["Sound"] = SoundCreated +} + +local function MainNewInstance(NewInstance) + local IsClass = ClassesToFunctions[NewInstance.ClassName] + + if (not IsClass) then + return + end + + IsClass(NewInstance) +end + +for Index, Object in workspace:GetDescendants() do + MainNewInstance(Object) +end + +workspace.DescendantAdded:Connect(MainNewInstance) \ No newline at end of file diff --git a/rojo/MainModule/src/StarterPlayerScripts/RbxCharacterAnimations/Character.lua b/rojo/MainModule/src/StarterPlayerScripts/RbxCharacterAnimations/Character.lua new file mode 100644 index 0000000..add2f49 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/RbxCharacterAnimations/Character.lua @@ -0,0 +1,185 @@ +local Players = game:GetService("Players"); +local States = {}; +for _, state in script.Parent.States:GetChildren() do + States[state.Name] = require(state); +end + +local Character = {}; +Character.__index = Character; + +local all_motors = { + "Right Shoulder"; + "Left Shoulder"; + "Right Hip"; + "Left Hip"; +}; +local function get_motors(where) + local motors = {}; + local out = {}; + for _, name in all_motors do + local motor = where:WaitForChild(name); + local data = { + MaxVelocity = 0.1; + C0 = motor.C0; + DesiredAngle = 0; + CurrentAngle = 0; + }; + motors[name:gsub(' ','')] = data; + out[motor] = data; + end + return motors, out; +end + +function Character.new(character) + local env, motors = get_motors(character:WaitForChild("Torso")); + env.character = character; + env.states = States; + env.motors = motors; + return setmetatable(env, Character):init(); +end + +function Character:destroy() + if(self.animConnection)then + self.animConnection:Disconnect(); + end + + for _, conn in self.connections do + conn:Disconnect(); + end + + self:disconnect(); +end + +local fmt = "%s is not a valid state"; + +function Character:change_state(to) + if(not States[to])then + return; + end + self.state = States[to]; + self.state(self, 0); +end + +function Character:update_tool(dt) + if(not self.tool)then + return; + end + + local toolAnim = self.toolAnim; + if(self.toolClock 0.1 then + sound.Playing = true + stopPlayingLoopedSounds(sound) + else + stopPlayingLoopedSounds() + end + playingLoopedSounds[sound] = true + end, + + [Enum.HumanoidStateType.Seated] = function() + stopPlayingLoopedSounds() + end, + + [Enum.HumanoidStateType.Dead] = function() + stopPlayingLoopedSounds() + playSound(sounds.Died) + end, + } + + -- updaters for looped sounds + local loopedSoundUpdaters = { + [sounds.Climbing] = function(dt, sound, vel) + sound.Playing = vel.Magnitude > 0.1 + end, + + [sounds.FreeFalling] = function(dt, sound, vel) + if vel.Magnitude > 75 then + sound.Volume = math.clamp(sound.Volume + 0.9*dt, 0, 1) + else + sound.Volume = 0 + end + end, + + [sounds.Running] = function(dt, sound, vel) + sound.Playing = vel.Magnitude > 0.5 and humanoid.MoveDirection.Magnitude > 0.5 + end, + } + + -- state substitutions to avoid duplicating entries in the state table + local stateRemap = { + [Enum.HumanoidStateType.RunningNoPhysics] = Enum.HumanoidStateType.Running, + } + + local activeState = stateRemap[humanoid:GetState()] or humanoid:GetState() + + if activeState ~= Enum.HumanoidStateType.None and stateTransitions[activeState] then + stateTransitions[activeState]() + end + + local stateChangedConn = humanoid.StateChanged:Connect(function(_, state) + state = stateRemap[state] or state + + if state ~= activeState then + local transitionFunc = stateTransitions[state] + + if transitionFunc then + transitionFunc() + end + + activeState = state + end + end) + + local steppedConn = RunService.Stepped:Connect(function(time, deltaTime) + -- update looped sounds on stepped + for sound in pairs(playingLoopedSounds) do + local updater = loopedSoundUpdaters[sound] + + if updater then + updater(deltaTime, sound, rootPart.AssemblyLinearVelocity) + end + end + end) + + local humanoidAncestryChangedConn + local rootPartAncestryChangedConn + local characterAddedConn + + local function terminate() + stateChangedConn:Disconnect() + steppedConn:Disconnect() + humanoidAncestryChangedConn:Disconnect() + rootPartAncestryChangedConn:Disconnect() + characterAddedConn:Disconnect() + end + + humanoidAncestryChangedConn = humanoid.AncestryChanged:Connect(function(_, parent) + if not parent then + terminate() + end + end) + + rootPartAncestryChangedConn = rootPart.AncestryChanged:Connect(function(_, parent) + if not parent then + terminate() + end + end) + + characterAddedConn = player.CharacterAdded:Connect(terminate) +end + +local function playerAdded(player) + local function characterAdded(character) + -- Avoiding memory leaks in the face of Character/Humanoid/RootPart lifetime has a few complications: + -- * character deparenting is a Remove instead of a Destroy, so signals are not cleaned up automatically. + -- ** must use a waitForFirst on everything and listen for hierarchy changes. + -- * the character might not be in the dm by the time CharacterAdded fires + -- ** constantly check consistency with player.Character and abort if CharacterAdded is fired again + -- * Humanoid may not exist immediately, and by the time it's inserted the character might be deparented. + -- * RootPart probably won't exist immediately. + -- ** by the time RootPart is inserted and Humanoid.RootPart is set, the character or the humanoid might be deparented. + + if not character.Parent then + waitForFirst(character.AncestryChanged, player.CharacterAdded) + end + + if player.Character ~= character or not character.Parent then + return + end + + local humanoid = character:FindFirstChildOfClass("Humanoid") + while character:IsDescendantOf(game) and not humanoid do + waitForFirst(character.ChildAdded, character.AncestryChanged, player.CharacterAdded) + humanoid = character:FindFirstChildOfClass("Humanoid") + end + + if player.Character ~= character or not character:IsDescendantOf(game) then + return + end + + -- must rely on HumanoidRootPart naming because Humanoid.RootPart does not fire changed signals + local rootPart = character:FindFirstChild("Head") + while character:IsDescendantOf(game) and not rootPart do + waitForFirst(character.ChildAdded, character.AncestryChanged, humanoid.AncestryChanged, player.CharacterAdded) + rootPart = character:FindFirstChild("Head") + end + + if rootPart and humanoid:IsDescendantOf(game) and character:IsDescendantOf(game) and player.Character == character then + initializeSoundSystem(player, humanoid, rootPart) + end + end + + if player.Character then + characterAdded(player.Character) + end + player.CharacterAdded:Connect(characterAdded) +end + +Players.PlayerAdded:Connect(playerAdded) +for _, player in ipairs(Players:GetPlayers()) do + playerAdded(player) +end \ No newline at end of file diff --git a/rojo/MainModule/src/StarterPlayerScripts/init.meta.json b/rojo/MainModule/src/StarterPlayerScripts/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/StarterPlayerScripts/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/rojo/MainModule/src/init.lua b/rojo/MainModule/src/init.lua new file mode 100644 index 0000000..994f685 --- /dev/null +++ b/rojo/MainModule/src/init.lua @@ -0,0 +1,96 @@ +--!strict +local Lighting = game:GetService("Lighting") +local Players = game:GetService("Players") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local ServerScriptService = game:GetService("ServerScriptService") +local ServerStorage = game:GetService("ServerStorage") +local SoundService = game:GetService("SoundService") +local StarterGui = game:GetService("StarterGui") +local StarterPack = game:GetService("StarterPack") +local StarterPlayer = game:GetService("StarterPlayer") +local MaterialService = game:GetService("MaterialService") +local RunService = game:GetService("RunService") +local MaterialService = game:GetService("MaterialService") +local ReplicatedFirst = game:GetService("ReplicatedFirst") + +local MainModule = {} + +local directories: { [Instance] : Instance } = { + --[script.Lighting] = Lighting, + [script.ReplicatedStorage] = ReplicatedStorage, + --[script.ReplicatedFirst] = ReplicatedFirst, + --[script.StarterGui] = StarterGui, + [script.ServerScriptService] = ServerScriptService, + [script.ServerStorage] = ServerStorage, + [script.Soundscape] = SoundService, + [script.StarterCharacterScripts] = StarterPlayer.StarterCharacterScripts, + [script.StarterPlayer] = StarterPlayer, + [script.StarterPlayerScripts] = StarterPlayer.StarterPlayerScripts, + [script.MaterialService] = MaterialService, +} + +function MainModule:load(month : string?, year : number?) + local startTime: number = os.clock() + + local grabbedYear = year or 2006 + local grabbedMonth = month or "November" + local TimePeriods = require(script.ReplicatedStorage.Modules.TimePeriods) + + -- Double check + if not TimePeriods[string.format("%s %s", grabbedMonth, tostring(grabbedYear))] then + grabbedYear = 2006 + grabbedMonth = "November" + + print("[FRAMEWORK]: Fixing invalid Time Period option (setting to November 2006)") + end + + -- Is the game a solo or public server? To make sure we do not interfere with Team Test, an :IsStudio check is required! + if game.PrivateServerId ~= "" and not RunService:IsStudio() then + script.ReplicatedStorage.Solo.Value = true + end + + script.ReplicatedStorage.TimePeriod.Value = TimePeriods[string.format("%s %s", grabbedMonth, tostring(grabbedYear))] + + -- Add scripts to their respective directories: + for folder: Instance, destination: Instance in pairs(directories) do + for _: number, item: Instance in pairs(folder:GetChildren()) do + item.Parent = destination + end + end + + -- Replace tools with HopperBin based on Command type: + for _: number, tool: Instance in ipairs(StarterPack:GetChildren()) do + local hopperBins = ServerStorage.HopperBins + local hasAttribute = tool:GetAttribute("Command") + + if not hasAttribute then + print(tool.Name.." does not have a Command attribute assigned! (Ignore if the object is a Tool)") + + continue + end + + local newHopperBin: Instance? = hopperBins:FindFirstChild(tool:GetAttribute("Command"), false) + + -- If the Command is ScriptHopper, then don't replace anything. + if tool:GetAttribute("Command") ~= "ScriptHopper" and newHopperBin then + newHopperBin:Clone().Parent = tool.Parent + + tool:Destroy() + else + tool.Parent = ServerStorage.Reserve + end + end + + -- A bit stanky way to fix sorting for ScriptHopper tools. + for _: number, reservedTool: Instance in ipairs(ServerStorage.Reserve:GetChildren()) do + reservedTool.Parent = StarterPack + end + + local endTime: number = os.clock() + local timeElapsed: number = math.floor((endTime - startTime) * 1000) + + print("[FRAMEWORK]: Loaded in " .. timeElapsed .. "ms") + print(string.format("[FRAMEWORK]: The time period of this game is %s %s", grabbedMonth, tostring(grabbedYear))) +end + +return MainModule diff --git a/rojo/MainModule/src/init.meta.json b/rojo/MainModule/src/init.meta.json new file mode 100644 index 0000000..1025b06 --- /dev/null +++ b/rojo/MainModule/src/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file