CCCPaste

Hiddendevs application, Interesting

--!strict

--Services
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--Modules
local Helper = require(ReplicatedStorage.Packages.Helper)
local Fusion = require(ReplicatedStorage.Packages.Fusion)
local FusionTypes = require(ReplicatedStorage.Packages._Index["[email protected]"].fusion.Types)

--Vars
local Player = game.Players.LocalPlayer :: Player
local PlayerGui = Player.PlayerGui
local Database = Player:WaitForChild("Database")
local Peek = Fusion.peek

--Constants
local LEFT_ACCEL = Vector3.new(20, 2, 30) --Smoke effect velocity when going LEFT
local RIGHT_ACCEL = Vector3.new(-20, 2, 30) --Smoke effect velocity when going RIGHT
local VELOCITY_MAG = 1000 --Side movement velocity
local DrainageTick = 0.1 --Control bar drain

--Types
export type Class = {
    Character: Model?,
    HRP: BasePart?,
    LinearVelocity: LinearVelocity?,
    Smoke: ParticleEmitter?,
    Init: boolean,
    Input: RBXScriptConnection,
    LastTimeRedirected: number?,
    
    Scope: FusionTypes.Scope,
    ScopeValues: {
        Control: FusionTypes.Value?
    },
}

local module = {}

function module.new(character)
    local self = {}
    
    self.Character = character
    self.HRP = nil
    self.LinearVelocity = nil
    self.Smoke = nil
    self.Init = false
    self.Input = nil
    self.LastTimeRedirected = nil
    
    self.ScopeValues = {
        Control = nil
    }
    self.Scope = nil

    return self
end

function module:Init(class: Class): ()
    if class.Init then warn("Inited before: fail") return end
    
    class.HRP = class.Character:WaitForChild("HumanoidRootPart")
    if not class.HRP then warn('Init failed, not rootpart') return end
   
    class.Init = true
    
    --Velocity
    class.LinearVelocity = Instance.fromExisting(script.LinearVelocity)
    if not class.LinearVelocity then warn("Failed creating velocity") return end
    class.LinearVelocity.Parent = class.HRP
    local VelocityAttachment = Instance.new("Attachment", class.HRP)
    VelocityAttachment.Name = "Director"
    class.LinearVelocity.Attachment0 = VelocityAttachment
    
    --Smoke effect
    local SmokeAttachment = ReplicatedStorage.Templates.Assets.Effects.ControlSmoke:Clone()
    SmokeAttachment.Parent = class.HRP
    class.Smoke = SmokeAttachment:FindFirstChild("ParticleEmitter") :: ParticleEmitter
    if not class.Smoke then warn("Failed creating smoke effect") return end
    class.Smoke.Enabled = false
    
    module:InitInterface( class )
    module:HandleInput( class )
end

function module:InitInterface(class: Class)
    local Scope = Fusion:scoped()
    class.Scope = Scope
    
    local ControlValue = Database.Upgrades.Control :: NumberValue
    local Limit = 20 * ( ControlValue.Value * 0.1 + 1)
    local Control = Scope:Value( Limit ) :: FusionTypes.Value
    
    class.ScopeValues.Control = Control

    local RoundMoney = PlayerGui:WaitForChild("Money"):WaitForChild("RoundMoney")
    local ControlGui = PlayerGui:WaitForChild("ControlBar")
    RoundMoney.Visible = true
    ControlGui.Enabled = true

    local ControlFill = ControlGui.Bar.Fill :: Frame
    local SizeCompute = Scope:Computed(function(use)
        return UDim2.fromScale( use(Control) :: number / Limit , 1)
    end)
    
    Scope:Hydrate(ControlFill) {
        Size = SizeCompute
    }
end

function module:HandleInput(class: Class): ()
    
    local Control = class.ScopeValues.Control :: FusionTypes.Value
    
    local function ShrinkControlUI()
        Control:set( Peek(Control) :: number - DrainageTick )
    end
    
    class.Input = game:GetService("RunService").PostSimulation:Connect(function(deltaTimeSim: number)
        local current_direction = nil

        if UserInputService:IsKeyDown(Enum.KeyCode.A) then
            current_direction = "Left"
        end
        if UserInputService:IsKeyDown(Enum.KeyCode.D) then
            current_direction = "Right"
        end

        if current_direction then
            ShrinkControlUI()
        end

        if Peek(Control) :: number > 0 then
            module:SetDirection(class, current_direction)
        else
            module:SetDirection(class, nil)
        end
    end)
end

function module:SetDirection(class: Class, direction: string?): ()
    if not class.Character then return end
    if not class.LinearVelocity then return end
    if not class.Smoke then return end
    
    if direction == nil then
        class.Smoke.Enabled = false
        class.LinearVelocity.Enabled = false
    else
        class.Smoke.Enabled = true
        class.LinearVelocity.Enabled = true
        
        if module.LastTimeRedirected then
            local Past = os.time() - module.LastTimeRedirected
            if Past > 5 then
                Helper:Play("Air")
            end
        else
            Helper:Play("Air")
        end
        module.LastTimeRedirected = os.time()
    end
    
    if direction == "Left" then
        class.Smoke.Acceleration = LEFT_ACCEL
        class.LinearVelocity.VectorVelocity = Vector3.new(-VELOCITY_MAG,0,0)
    elseif direction == "Right" then
        class.Smoke.Acceleration = RIGHT_ACCEL
        class.LinearVelocity.VectorVelocity = Vector3.new(VELOCITY_MAG,0,0)
    end
end

function module:Destroy(class: Class): ()
    if class.LinearVelocity then
        class.LinearVelocity:Destroy()
        class.LinearVelocity = nil
    end

    if class.HRP then
        local attachment = class.HRP:FindFirstChild("Director")
        if attachment then
            attachment:Destroy()
        end
    end
    
    if class.Scope then
        class.Scope.doCleanup()
    end

    if class.Input then
        class.Input:Disconnect()
    end
    
    local RoundMoney = PlayerGui:WaitForChild("Money"):WaitForChild("RoundMoney")
    RoundMoney.Visible = false
    
    class.Character = nil
    class.HRP = nil
    class.Init = false
end


return module