admin管理员组

文章数量:1410725

I've applied for the Luau role on the HiddenDevs website five times, but I keep getting rejected. I'm feeling really frustrated and would love some guidance on how to overcome this obstacle.

Each time, the feedback I receive is that my comments should explain how the code works, not what it does, and that I need better code structure. I want to improve these aspects, but I'm struggling to understand exactly how to do that.

Could anyone provide advice or examples on how to write better explanatory comments and improve my code structure to meet the role requirements?

Here’s my latest script:

local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local torso = character:WaitForChild("Torso")
local characterHead = character:WaitForChild("Head")
local humanoid = character:WaitForChild("Humanoid")

local animator = humanoid:WaitForChild("Animator")

-- services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Debris = game:GetService("Debris")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local ContextActionService = game:GetService("ContextActionService")
local SoundService = game:GetService("SoundService")

-- Remotes
local damageServerRemote = ReplicatedStorage:WaitForChild("Damage server")
local stunServerRemote = ReplicatedStorage:WaitForChild("stunServer")
local stunStatusChanged = ReplicatedStorage:WaitForChild("stunStatusChanged")
local playEnemyAnimationRemote = ReplicatedStorage:WaitForChild("playEnemyAnimation")
local ragdollServerRemote = ReplicatedStorage:WaitForChild("ragdoll server")
local knockbackServerRemote = ReplicatedStorage:WaitForChild("knockbackServer")
local punchEffectRemote = ReplicatedStorage:WaitForChild("punchEffectRemote")

-- animations
local punchAnimations = ReplicatedStorage:WaitForChild("punch animations")

local punchAnim1 = ReplicatedStorage["punch animations"].punch1
local punchAnim2 = ReplicatedStorage["punch animations"].punch2
local punchAnim3 = ReplicatedStorage["punch animations"].punch3
local punchAnim4 = ReplicatedStorage["punch animations"].punch4
local slamAnim = ReplicatedStorage["special animations"].slam
local uppercutAnim = ReplicatedStorage["special animations"]["upper cut"]

local punchAnimationTracks = {
    animator:LoadAnimation(punchAnim1),
    animator:LoadAnimation(punchAnim2),
    animator:LoadAnimation(punchAnim3),
    animator:LoadAnimation(punchAnim4)
}
local slamAnimTrack = animator:LoadAnimation(slamAnim)
local uppercutAnimTrack = animator:LoadAnimation(uppercutAnim)

-- sounds
local blockSound = SoundService["blocking effect sound"]
local punchSwingSound = SoundService["pre punch swing (1)"]
local punchSound = SoundService["punch 2"]
local slamSound = SoundService["slam sound"]

-- Game variables

local isAttacking = false
local currentPunchPosition = 1
local currentHitPosition = 1
local stunDuration = 2
local ragdollDuration = 2
local maxCombo = 4
local punchCooldown = 2  -- Set cooldown time for resetting combo

local lastHitMissed = false

local originalWalkSpeed = humanoid.WalkSpeed
local originalJumpPower = humanoid.JumpPower
local originalJumpHeight = humanoid.JumpHeight

local hitboxPart = Instance.new("Part")
hitboxPart.Name = "hitboxPart"
hitboxPart.Massless = true
hitboxPart.Size = Vector3.new(4, 7, 4.1)
hitboxPart.Transparency = 1
hitboxPart.Color = Color3.new(1, 0.235294, 0.4)
hitboxPart.CanCollide = false
hitboxPart.Parent = ReplicatedStorage

local hitboxPartClone = hitboxPart:Clone()

local punchEffect = ReplicatedStorage.Sphere

local WeldConstraint = Instance.new("WeldConstraint")
local weldConstraint = Instance.new("WeldConstraint")

local overlapParams = OverlapParams.new()
overlapParams.FilterType = Enum.RaycastFilterType.Exclude
overlapParams.FilterDescendantsInstances = {character, workspace.Baseplate}

local raycastParams = RaycastParams.new()

local function ragdollChar(enemyCharacter, enemyHumanoid)
    task.defer(function()
        local EnemyRP = enemyCharacter.HumanoidRootPart

        if Players:GetPlayerFromCharacter(enemyCharacter) then --if its a player

            ragdollServerRemote:FireServer(enemyCharacter, enemyHumanoid, "replacejoints")
            task.wait(2)
            ragdollServerRemote:FireServer(enemyCharacter, enemyHumanoid, "unreplacejoints")
        else --if its not a player

            ragdollServerRemote:FireServer(enemyCharacter, enemyHumanoid, "dummyreplacejoints")     
            task.delay(2,function()

                ragdollServerRemote:FireServer(enemyCharacter, enemyHumanoid, "dummyunreplacejoints")   
            end)
        end
    end)
end

local function spaceButtonHold(actionName, inputState, inputDetails)
    if inputState == Enum.UserInputState.Begin then
        spacePressed = true

    elseif inputState == Enum.UserInputState.End then
        spacePressed = false
    end
    return Enum.ContextActionResult.Pass
end

ContextActionService:BindAction("specialTrigger", spaceButtonHold, true, Enum.KeyCode.Space)

local function hitboxSet()
    hitboxPartClone.CFrame = torso.CFrame * CFrame.new(0, 2, -2)
    weldConstraint.Part0 = torso
    weldConstraint.Part1 = hitboxPartClone
    weldConstraint.Parent = torso
end

local function hitboxDeploy()
    hitboxPartClone.Parent = workspace
    task.wait(0.15)
    hitboxPartClone.Parent = ReplicatedStorage
end

local overLapDuration = 0.3 -- duration for how long the function hitdetection will keep detecting
local playerDetected = false


local knockbackMultiplier
-- function to knockback 
local function hitPush(direction, closeUp) 

    if closeUp then
        knockbackMultiplier = 0.1
    else
        knockbackMultiplier = 0.8
    end

    local linearVelocity = Instance.new("LinearVelocity")
    local attachment0 = Instance.new("Attachment")

    linearVelocity.MaxForce = math.huge
    linearVelocity.ForceLimitsEnabled = true
    linearVelocity.ForceLimitMode = Enum.ForceLimitMode.Magnitude
    --linearVelocity.RelativeTo = Enum.ActuatorRelativeTo.World
    linearVelocity.Attachment0 = attachment0
    linearVelocity.Enabled = true
    linearVelocity.Parent = torso
    attachment0.Parent = torso
    linearVelocity.VectorVelocity = direction * torso.AssemblyMass * knockbackMultiplier

    Debris:AddItem(linearVelocity, 0.15)
    Debris:AddItem(attachment0, 0.15)

end

local lastHit = 0
local lastClicked = 0
local function resetNoPunchTwoSeconds()
    task.spawn(function()
        while true do
            task.wait(0.1)
            if tick() - lastClicked >= punchCooldown and not mousePressed then 
                --print("2 seconds passed, currentpunchposition reset")
                currentPunchPosition = 1
            end
        end
    end)
end

local function resetNoHitTwoSeconds()
    task.spawn(function()
        while true do
            task.wait(0.1)
            if tick() - lastHit >= punchCooldown and not mousePressed then
                --print("2 seconds passed, currenthitposition reset")
                currentHitPosition = 1
            end
        end
    end)
end

local isPlayingHold = false
local isPlayingClick = false

--local currentTrack
local direction
local enemyMass

local differenceDirection
local dotProduct = 0


local function updateDotProduct(characterHead, enemyCharacterHead) -- to know when the block gets broke
    if not characterHead or not enemyCharacterHead then return end
    local enemyToCharacterDirection = (characterHead.Position - enemyCharacterHead.Position).Unit
    local enemyLookVector = enemyCharacterHead.CFrame.LookVector
    dotProduct = enemyLookVector:Dot(enemyToCharacterDirection)
end

local function handleBlocking(enemyCharacter)
    if enemyCharacter:GetAttribute("Blocking") then
        if dotProduct < 0.5 then
            print("behind player or sideways.")
            return false
        else
            print("in front and he's blocking.")
            -- play block sound
            return true
        end
    end
    return false
end
-- Adjust movement restrictions for M1 chain
local function applyMovementRestrictions()
    humanoid.WalkSpeed = 8
    humanoid.JumpPower = 0
    humanoid.JumpHeight = 0


end

local function restoreMovement()
    humanoid.WalkSpeed = 16
    humanoid.JumpPower = 50
    humanoid.JumpHeight = 7.2
end


local runConnection1
local function handleCloseUpPush(enemyTorso)
    runConnection1 = RunService.Heartbeat:Connect(function()
        local distance = (enemyTorso.Position - torso.Position).Magnitude

        if distance < 2.5 then
            closeUp = true
        else
            closeUp = false
        end

    end)
end

local runConnection
local runConnection2
local function handleClosingConnections(markerConnections)
    for _, connection in ipairs(markerConnections) do
        connection:Disconnect()
    end
    if runConnection1 and runConnection then
        runConnection1:Disconnect()
        runConnection:Disconnect()
    end
end
local falling

local function stunPlayer(currentPunchPosition)
    character:SetAttribute("Stunned", true)
    humanoid.WalkSpeed = 0
    humanoid.JumpPower = 0
    humanoid.JumpHeight = 0

    local stunDuration = 4

    task.delay(stunDuration, function()
        humanoid.WalkSpeed = originalWalkSpeed
        humanoid.JumpPower = originalJumpPower
        humanoid.JumpHeight = originalJumpHeight
        character:SetAttribute("Stunned", false)
        lastHitMissed = false
    end)

end
local function handleMissedLastPunch()
    if currentPunchPosition == maxCombo then
        lastHitMissed = true
        print("lastHitMissed is true", lastHitMissed, currentPunchPosition)
        stunPlayer()
    else
        lastHitMissed = false
    end

end

local markerConnections = {}

local function onPrePunchMarker(enemyCharacter, differenceDirection, currentTrack)
    -- function onPrePunchMarker()
    local enemyHumanoid = enemyCharacter:FindFirstChild("Humanoid")
    table.insert(markerConnections, currentTrack:GetMarkerReachedSignal("prepunch"):Connect(function()
        hitPush(differenceDirection, closeUp)

        if not (currentHitPosition == maxCombo) then
            playEnemyAnimationRemote:FireServer(currentHitPosition, enemyHumanoid)
            currentHitPosition += 1
            lastHit = tick()
        else
            currentHitPosition = 1
        end
    end))
end

local function onPunchMarker(enemyCharacter, currentTrack, special)
    local enemyHumanoid = enemyCharacter:WaitForChild("Humanoid")
    table.insert(markerConnections, currentTrack:GetMarkerReachedSignal("punch"):Connect(function()
        if currentPunchPosition == maxCombo then
            ragdollChar(enemyCharacter, enemyHumanoid)
        end

        if special == "slam" then
            slamSound:Play()
        else
            punchSound:Play()
        end

        damageServerRemote:FireServer(enemyCharacter, 3)
        stunServerRemote:FireServer(enemyCharacter, stunDuration)
        knockbackServerRemote:FireServer(enemyCharacter, special)

    end))
end

local function determinePunchType(falling)
    local special, track
    if currentPunchPosition == maxCombo then
        print("Current punch is at max combo")
        if falling then
            track = slamAnimTrack
            special = "slam"
        elseif spacePressed then
            track = uppercutAnimTrack
            special = "uppercut"
        else
            track = punchAnimationTracks[currentPunchPosition]
            special = "m1Last" -- Last punch in combo for heavy knockback
            print("Last combo track:", track)
        end
    else
        track = punchAnimationTracks[currentPunchPosition]
        special = "m1" -- Regular punch in the sequence
    end
    -- Safety check for nil track
    if not track then
        warn("No animation track found for position: " .. tostring(currentPunchPosition))
        return nil, nil -- Return nil to indicate failure
    end
    return special, track
end

local function updateCurrentPunchPosition()
    
    if currentPunchPosition == maxCombo then
        currentPunchPosition = 1
    else
        currentPunchPosition += 1
    end
end


-- Function to detect if a player got hit by hitbox
local function hitDetection(callback)
    local hitPlayers = {} -- Table to store detected players
    local connection
    local timeElapsed = 0

    connection = RunService.Heartbeat:Connect(function(deltaTime)
        timeElapsed += deltaTime
        local hitParts = workspace:GetPartsInPart(hitboxPartClone, overlapParams)

        for _, part in hitParts do
            if part.Name == "Torso" then
                local enemyCharacter = part.Parent
                if not hitPlayers[enemyCharacter] then
                    hitPlayers[enemyCharacter] = true
                    print("You've hit a player: ", enemyCharacter.Name)
                end
            end
        end

        if timeElapsed >= overLapDuration or next(hitPlayers) then
            connection:Disconnect()
            if not next(hitPlayers) then
                callback(false)
            else
                callback(hitPlayers)
            end
        end
    end)
end

-- Global variables
local enemyCharacter
local enemyPlayer
local enemyTorso
local enemyHumanoid
local enemyCharacterHead
local mouseHeldDuration = 0.4
local isAnimationPlaying = false
local special, currentTrack

-- Helper functions to break down executePunchSequence
local function setupPunch(isPunchHold)
    isAnimationPlaying = true
    isAttacking = true
    punchSwingSound:Play()

    if isPunchHold then
        applyMovementRestrictions()
    elseif not lastHitMissed then
        applyMovementRestrictions()
    end

    runConnection = RunService.RenderStepped:Connect(function()
        falling = torso.AssemblyLinearVelocity.Y < 0
    end)
end

local function playPunchAnimation()
    special, currentTrack = determinePunchType(falling)
    currentTrack:Play()
end

local function setupHitbox()
    hitboxSet()
    hitboxDeploy()
end

local function setupEnemyVariables(character)
    enemyCharacter = character
    enemyPlayer = Players:GetPlayerFromCharacter(enemyCharacter)
    enemyTorso = enemyCharacter:WaitForChild("Torso")
    enemyHumanoid = enemyCharacter:WaitForChild("Humanoid")
    enemyCharacterHead = enemyCharacter:WaitForChild("Head")
end

local function handleHitEffects(differenceDirection)
    punchEffectRemote:FireServer(enemyTorso)
    handleCloseUpPush(enemyTorso)
    if handleBlocking(enemyCharacter) and special ~= "slam" then
        blockSound:Play()
        return false
    end
    onPrePunchMarker(enemyCharacter, differenceDirection, currentTrack)
    onPunchMarker(enemyCharacter, currentTrack, special)
    return true
end

local function processEnemyHit(character)
    lastHitMissed = false
    setupEnemyVariables(character)

    local direction = torso.CFrame.LookVector
    local differenceDirection = (enemyTorso.Position - torso.Position).Unit
    raycastParams.FilterType = Enum.RaycastFilterType.Exclude
    raycastParams.FilterDescendantsInstances = {enemyCharacter}

    local shouldContinue = handleHitEffects(differenceDirection)
    if shouldContinue then
        runConnection2 = RunService.RenderStepped:Connect(function()
            updateDotProduct(characterHead, enemyCharacterHead)
        end)
    end
end

local function handleHitDetectionResult(hitPlayers)
    if not hitPlayers then
        print("No one is hit with your punch.")
        return
    end

    for character, _ in hitPlayers do
        processEnemyHit(character)
    end
end

local function cleanupPunch(isPunchHold)
    currentTrack.Stopped:wait()
    isAnimationPlaying = false
    handleClosingConnections(markerConnections)

    if not isPunchHold then
        task.delay(0.10, function()
            if not mousePressed and not lastHitMissed then
                restoreMovement()
            end
            isAttacking = false
        end)
    end
    print(currentPunchPosition)
    updateCurrentPunchPosition()
end

local function executePunchSequence(isPunchHold)
    setupPunch(isPunchHold)
    playPunchAnimation()
    setupHitbox()
    hitDetection(handleHitDetectionResult)
    cleanupPunch(isPunchHold)
end

-- Mouse input handling
local function handleMouseBegin()
    if character:GetAttribute("Stunned") then return end
    mousePressed = true
    timePressed = tick()

    if not isPlayingClick and not isPlayingHold and humanoid then
        isPlayingClick = true
        resetNoPunchTwoSeconds()
        resetNoHitTwoSeconds()
        lastClicked = tick()

        executePunchSequence(false)

        isPlayingClick = false
    end
    print(isPlayingClick)
end

local function handleMouseEnd()
    mousePressed = false
    print(isPlayingClick)

    if currentTrack and isAnimationPlaying then
        currentTrack.Stopped:Wait()
    end
    restoreMovement()
end

local function mouseButtonHold(actionName, inputState, inputDetails)
    if inputState == Enum.UserInputState.Begin then
        handleMouseBegin()
    elseif inputState == Enum.UserInputState.End then
        handleMouseEnd()
    end
end

ContextActionService:BindAction("normalPunch", mouseButtonHold, true, Enum.UserInputType.MouseButton1)

-- Continuous punching handler
task.spawn(function()
    while true do
        task.wait(0.1)
        if mousePressed and not isPlayingClick and not character:GetAttribute("Stunned") then
            local pressDuration = tick() - timePressed
            if pressDuration >= mouseHeldDuration then
                print("holding")
                isPlayingHold = true
                resetNoPunchTwoSeconds()
                resetNoHitTwoSeconds()
                executePunchSequence(true)
                if not mousePressed then
                    isPlayingHold = false
                end
            end
        end
    end
end)

For reference, here are the Luau role requirements:

Luau Scripter Requirements: Luau Scripter

A minimum of 200 lines of Roblox Luau code in a single script (excluding empty/ blank lines and comment lines). Only Pastebin, GitHub and Hastebin are permitted. You must demonstrate a broad understanding of Roblox and programming logic. You must show broad understanding of Roblox API. We suggest using CFrame math, physics, metatables, open-source libraries, etc. The code must be well written and efficient, with proper utilization of functions and methods. Code must be well presented in order to maintain readability. There must be appropriate comments to demonstrate an understanding of the provided code. A demo game demonstrating the functionality of the script must be provided. Ensure that your code is well-optimized and avoid any unnecessary components/ extra lines. Roblox place must be owned by you, or you must be specifically credited in the game description. Alternatively, credits are allowed on an external page (like Roblox Devforum) if this external page is linked in the game description. Avoid the following: Irrelevant blocks of code. Several modules/ scripts combined together to meet the line requirement.

If anyone has tips, examples, or feedback on my script, I’d really appreciate it! Thanks in advance.

I've applied for the Luau role on the HiddenDevs website five times, but I keep getting rejected. I'm feeling really frustrated and would love some guidance on how to overcome this obstacle.

Each time, the feedback I receive is that my comments should explain how the code works, not what it does, and that I need better code structure. I want to improve these aspects, but I'm struggling to understand exactly how to do that.

Could anyone provide advice or examples on how to write better explanatory comments and improve my code structure to meet the role requirements?

Here’s my latest script: https://pastebin/ZZibpy4c

local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local torso = character:WaitForChild("Torso")
local characterHead = character:WaitForChild("Head")
local humanoid = character:WaitForChild("Humanoid")

local animator = humanoid:WaitForChild("Animator")

-- services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Debris = game:GetService("Debris")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local ContextActionService = game:GetService("ContextActionService")
local SoundService = game:GetService("SoundService")

-- Remotes
local damageServerRemote = ReplicatedStorage:WaitForChild("Damage server")
local stunServerRemote = ReplicatedStorage:WaitForChild("stunServer")
local stunStatusChanged = ReplicatedStorage:WaitForChild("stunStatusChanged")
local playEnemyAnimationRemote = ReplicatedStorage:WaitForChild("playEnemyAnimation")
local ragdollServerRemote = ReplicatedStorage:WaitForChild("ragdoll server")
local knockbackServerRemote = ReplicatedStorage:WaitForChild("knockbackServer")
local punchEffectRemote = ReplicatedStorage:WaitForChild("punchEffectRemote")

-- animations
local punchAnimations = ReplicatedStorage:WaitForChild("punch animations")

local punchAnim1 = ReplicatedStorage["punch animations"].punch1
local punchAnim2 = ReplicatedStorage["punch animations"].punch2
local punchAnim3 = ReplicatedStorage["punch animations"].punch3
local punchAnim4 = ReplicatedStorage["punch animations"].punch4
local slamAnim = ReplicatedStorage["special animations"].slam
local uppercutAnim = ReplicatedStorage["special animations"]["upper cut"]

local punchAnimationTracks = {
    animator:LoadAnimation(punchAnim1),
    animator:LoadAnimation(punchAnim2),
    animator:LoadAnimation(punchAnim3),
    animator:LoadAnimation(punchAnim4)
}
local slamAnimTrack = animator:LoadAnimation(slamAnim)
local uppercutAnimTrack = animator:LoadAnimation(uppercutAnim)

-- sounds
local blockSound = SoundService["blocking effect sound"]
local punchSwingSound = SoundService["pre punch swing (1)"]
local punchSound = SoundService["punch 2"]
local slamSound = SoundService["slam sound"]

-- Game variables

local isAttacking = false
local currentPunchPosition = 1
local currentHitPosition = 1
local stunDuration = 2
local ragdollDuration = 2
local maxCombo = 4
local punchCooldown = 2  -- Set cooldown time for resetting combo

local lastHitMissed = false

local originalWalkSpeed = humanoid.WalkSpeed
local originalJumpPower = humanoid.JumpPower
local originalJumpHeight = humanoid.JumpHeight

local hitboxPart = Instance.new("Part")
hitboxPart.Name = "hitboxPart"
hitboxPart.Massless = true
hitboxPart.Size = Vector3.new(4, 7, 4.1)
hitboxPart.Transparency = 1
hitboxPart.Color = Color3.new(1, 0.235294, 0.4)
hitboxPart.CanCollide = false
hitboxPart.Parent = ReplicatedStorage

local hitboxPartClone = hitboxPart:Clone()

local punchEffect = ReplicatedStorage.Sphere

local WeldConstraint = Instance.new("WeldConstraint")
local weldConstraint = Instance.new("WeldConstraint")

local overlapParams = OverlapParams.new()
overlapParams.FilterType = Enum.RaycastFilterType.Exclude
overlapParams.FilterDescendantsInstances = {character, workspace.Baseplate}

local raycastParams = RaycastParams.new()

local function ragdollChar(enemyCharacter, enemyHumanoid)
    task.defer(function()
        local EnemyRP = enemyCharacter.HumanoidRootPart

        if Players:GetPlayerFromCharacter(enemyCharacter) then --if its a player

            ragdollServerRemote:FireServer(enemyCharacter, enemyHumanoid, "replacejoints")
            task.wait(2)
            ragdollServerRemote:FireServer(enemyCharacter, enemyHumanoid, "unreplacejoints")
        else --if its not a player

            ragdollServerRemote:FireServer(enemyCharacter, enemyHumanoid, "dummyreplacejoints")     
            task.delay(2,function()

                ragdollServerRemote:FireServer(enemyCharacter, enemyHumanoid, "dummyunreplacejoints")   
            end)
        end
    end)
end

local function spaceButtonHold(actionName, inputState, inputDetails)
    if inputState == Enum.UserInputState.Begin then
        spacePressed = true

    elseif inputState == Enum.UserInputState.End then
        spacePressed = false
    end
    return Enum.ContextActionResult.Pass
end

ContextActionService:BindAction("specialTrigger", spaceButtonHold, true, Enum.KeyCode.Space)

local function hitboxSet()
    hitboxPartClone.CFrame = torso.CFrame * CFrame.new(0, 2, -2)
    weldConstraint.Part0 = torso
    weldConstraint.Part1 = hitboxPartClone
    weldConstraint.Parent = torso
end

local function hitboxDeploy()
    hitboxPartClone.Parent = workspace
    task.wait(0.15)
    hitboxPartClone.Parent = ReplicatedStorage
end

local overLapDuration = 0.3 -- duration for how long the function hitdetection will keep detecting
local playerDetected = false


local knockbackMultiplier
-- function to knockback 
local function hitPush(direction, closeUp) 

    if closeUp then
        knockbackMultiplier = 0.1
    else
        knockbackMultiplier = 0.8
    end

    local linearVelocity = Instance.new("LinearVelocity")
    local attachment0 = Instance.new("Attachment")

    linearVelocity.MaxForce = math.huge
    linearVelocity.ForceLimitsEnabled = true
    linearVelocity.ForceLimitMode = Enum.ForceLimitMode.Magnitude
    --linearVelocity.RelativeTo = Enum.ActuatorRelativeTo.World
    linearVelocity.Attachment0 = attachment0
    linearVelocity.Enabled = true
    linearVelocity.Parent = torso
    attachment0.Parent = torso
    linearVelocity.VectorVelocity = direction * torso.AssemblyMass * knockbackMultiplier

    Debris:AddItem(linearVelocity, 0.15)
    Debris:AddItem(attachment0, 0.15)

end

local lastHit = 0
local lastClicked = 0
local function resetNoPunchTwoSeconds()
    task.spawn(function()
        while true do
            task.wait(0.1)
            if tick() - lastClicked >= punchCooldown and not mousePressed then 
                --print("2 seconds passed, currentpunchposition reset")
                currentPunchPosition = 1
            end
        end
    end)
end

local function resetNoHitTwoSeconds()
    task.spawn(function()
        while true do
            task.wait(0.1)
            if tick() - lastHit >= punchCooldown and not mousePressed then
                --print("2 seconds passed, currenthitposition reset")
                currentHitPosition = 1
            end
        end
    end)
end

local isPlayingHold = false
local isPlayingClick = false

--local currentTrack
local direction
local enemyMass

local differenceDirection
local dotProduct = 0


local function updateDotProduct(characterHead, enemyCharacterHead) -- to know when the block gets broke
    if not characterHead or not enemyCharacterHead then return end
    local enemyToCharacterDirection = (characterHead.Position - enemyCharacterHead.Position).Unit
    local enemyLookVector = enemyCharacterHead.CFrame.LookVector
    dotProduct = enemyLookVector:Dot(enemyToCharacterDirection)
end

local function handleBlocking(enemyCharacter)
    if enemyCharacter:GetAttribute("Blocking") then
        if dotProduct < 0.5 then
            print("behind player or sideways.")
            return false
        else
            print("in front and he's blocking.")
            -- play block sound
            return true
        end
    end
    return false
end
-- Adjust movement restrictions for M1 chain
local function applyMovementRestrictions()
    humanoid.WalkSpeed = 8
    humanoid.JumpPower = 0
    humanoid.JumpHeight = 0


end

local function restoreMovement()
    humanoid.WalkSpeed = 16
    humanoid.JumpPower = 50
    humanoid.JumpHeight = 7.2
end


local runConnection1
local function handleCloseUpPush(enemyTorso)
    runConnection1 = RunService.Heartbeat:Connect(function()
        local distance = (enemyTorso.Position - torso.Position).Magnitude

        if distance < 2.5 then
            closeUp = true
        else
            closeUp = false
        end

    end)
end

local runConnection
local runConnection2
local function handleClosingConnections(markerConnections)
    for _, connection in ipairs(markerConnections) do
        connection:Disconnect()
    end
    if runConnection1 and runConnection then
        runConnection1:Disconnect()
        runConnection:Disconnect()
    end
end
local falling

local function stunPlayer(currentPunchPosition)
    character:SetAttribute("Stunned", true)
    humanoid.WalkSpeed = 0
    humanoid.JumpPower = 0
    humanoid.JumpHeight = 0

    local stunDuration = 4

    task.delay(stunDuration, function()
        humanoid.WalkSpeed = originalWalkSpeed
        humanoid.JumpPower = originalJumpPower
        humanoid.JumpHeight = originalJumpHeight
        character:SetAttribute("Stunned", false)
        lastHitMissed = false
    end)

end
local function handleMissedLastPunch()
    if currentPunchPosition == maxCombo then
        lastHitMissed = true
        print("lastHitMissed is true", lastHitMissed, currentPunchPosition)
        stunPlayer()
    else
        lastHitMissed = false
    end

end

local markerConnections = {}

local function onPrePunchMarker(enemyCharacter, differenceDirection, currentTrack)
    -- function onPrePunchMarker()
    local enemyHumanoid = enemyCharacter:FindFirstChild("Humanoid")
    table.insert(markerConnections, currentTrack:GetMarkerReachedSignal("prepunch"):Connect(function()
        hitPush(differenceDirection, closeUp)

        if not (currentHitPosition == maxCombo) then
            playEnemyAnimationRemote:FireServer(currentHitPosition, enemyHumanoid)
            currentHitPosition += 1
            lastHit = tick()
        else
            currentHitPosition = 1
        end
    end))
end

local function onPunchMarker(enemyCharacter, currentTrack, special)
    local enemyHumanoid = enemyCharacter:WaitForChild("Humanoid")
    table.insert(markerConnections, currentTrack:GetMarkerReachedSignal("punch"):Connect(function()
        if currentPunchPosition == maxCombo then
            ragdollChar(enemyCharacter, enemyHumanoid)
        end

        if special == "slam" then
            slamSound:Play()
        else
            punchSound:Play()
        end

        damageServerRemote:FireServer(enemyCharacter, 3)
        stunServerRemote:FireServer(enemyCharacter, stunDuration)
        knockbackServerRemote:FireServer(enemyCharacter, special)

    end))
end

local function determinePunchType(falling)
    local special, track
    if currentPunchPosition == maxCombo then
        print("Current punch is at max combo")
        if falling then
            track = slamAnimTrack
            special = "slam"
        elseif spacePressed then
            track = uppercutAnimTrack
            special = "uppercut"
        else
            track = punchAnimationTracks[currentPunchPosition]
            special = "m1Last" -- Last punch in combo for heavy knockback
            print("Last combo track:", track)
        end
    else
        track = punchAnimationTracks[currentPunchPosition]
        special = "m1" -- Regular punch in the sequence
    end
    -- Safety check for nil track
    if not track then
        warn("No animation track found for position: " .. tostring(currentPunchPosition))
        return nil, nil -- Return nil to indicate failure
    end
    return special, track
end

local function updateCurrentPunchPosition()
    
    if currentPunchPosition == maxCombo then
        currentPunchPosition = 1
    else
        currentPunchPosition += 1
    end
end


-- Function to detect if a player got hit by hitbox
local function hitDetection(callback)
    local hitPlayers = {} -- Table to store detected players
    local connection
    local timeElapsed = 0

    connection = RunService.Heartbeat:Connect(function(deltaTime)
        timeElapsed += deltaTime
        local hitParts = workspace:GetPartsInPart(hitboxPartClone, overlapParams)

        for _, part in hitParts do
            if part.Name == "Torso" then
                local enemyCharacter = part.Parent
                if not hitPlayers[enemyCharacter] then
                    hitPlayers[enemyCharacter] = true
                    print("You've hit a player: ", enemyCharacter.Name)
                end
            end
        end

        if timeElapsed >= overLapDuration or next(hitPlayers) then
            connection:Disconnect()
            if not next(hitPlayers) then
                callback(false)
            else
                callback(hitPlayers)
            end
        end
    end)
end

-- Global variables
local enemyCharacter
local enemyPlayer
local enemyTorso
local enemyHumanoid
local enemyCharacterHead
local mouseHeldDuration = 0.4
local isAnimationPlaying = false
local special, currentTrack

-- Helper functions to break down executePunchSequence
local function setupPunch(isPunchHold)
    isAnimationPlaying = true
    isAttacking = true
    punchSwingSound:Play()

    if isPunchHold then
        applyMovementRestrictions()
    elseif not lastHitMissed then
        applyMovementRestrictions()
    end

    runConnection = RunService.RenderStepped:Connect(function()
        falling = torso.AssemblyLinearVelocity.Y < 0
    end)
end

local function playPunchAnimation()
    special, currentTrack = determinePunchType(falling)
    currentTrack:Play()
end

local function setupHitbox()
    hitboxSet()
    hitboxDeploy()
end

local function setupEnemyVariables(character)
    enemyCharacter = character
    enemyPlayer = Players:GetPlayerFromCharacter(enemyCharacter)
    enemyTorso = enemyCharacter:WaitForChild("Torso")
    enemyHumanoid = enemyCharacter:WaitForChild("Humanoid")
    enemyCharacterHead = enemyCharacter:WaitForChild("Head")
end

local function handleHitEffects(differenceDirection)
    punchEffectRemote:FireServer(enemyTorso)
    handleCloseUpPush(enemyTorso)
    if handleBlocking(enemyCharacter) and special ~= "slam" then
        blockSound:Play()
        return false
    end
    onPrePunchMarker(enemyCharacter, differenceDirection, currentTrack)
    onPunchMarker(enemyCharacter, currentTrack, special)
    return true
end

local function processEnemyHit(character)
    lastHitMissed = false
    setupEnemyVariables(character)

    local direction = torso.CFrame.LookVector
    local differenceDirection = (enemyTorso.Position - torso.Position).Unit
    raycastParams.FilterType = Enum.RaycastFilterType.Exclude
    raycastParams.FilterDescendantsInstances = {enemyCharacter}

    local shouldContinue = handleHitEffects(differenceDirection)
    if shouldContinue then
        runConnection2 = RunService.RenderStepped:Connect(function()
            updateDotProduct(characterHead, enemyCharacterHead)
        end)
    end
end

local function handleHitDetectionResult(hitPlayers)
    if not hitPlayers then
        print("No one is hit with your punch.")
        return
    end

    for character, _ in hitPlayers do
        processEnemyHit(character)
    end
end

local function cleanupPunch(isPunchHold)
    currentTrack.Stopped:wait()
    isAnimationPlaying = false
    handleClosingConnections(markerConnections)

    if not isPunchHold then
        task.delay(0.10, function()
            if not mousePressed and not lastHitMissed then
                restoreMovement()
            end
            isAttacking = false
        end)
    end
    print(currentPunchPosition)
    updateCurrentPunchPosition()
end

local function executePunchSequence(isPunchHold)
    setupPunch(isPunchHold)
    playPunchAnimation()
    setupHitbox()
    hitDetection(handleHitDetectionResult)
    cleanupPunch(isPunchHold)
end

-- Mouse input handling
local function handleMouseBegin()
    if character:GetAttribute("Stunned") then return end
    mousePressed = true
    timePressed = tick()

    if not isPlayingClick and not isPlayingHold and humanoid then
        isPlayingClick = true
        resetNoPunchTwoSeconds()
        resetNoHitTwoSeconds()
        lastClicked = tick()

        executePunchSequence(false)

        isPlayingClick = false
    end
    print(isPlayingClick)
end

local function handleMouseEnd()
    mousePressed = false
    print(isPlayingClick)

    if currentTrack and isAnimationPlaying then
        currentTrack.Stopped:Wait()
    end
    restoreMovement()
end

local function mouseButtonHold(actionName, inputState, inputDetails)
    if inputState == Enum.UserInputState.Begin then
        handleMouseBegin()
    elseif inputState == Enum.UserInputState.End then
        handleMouseEnd()
    end
end

ContextActionService:BindAction("normalPunch", mouseButtonHold, true, Enum.UserInputType.MouseButton1)

-- Continuous punching handler
task.spawn(function()
    while true do
        task.wait(0.1)
        if mousePressed and not isPlayingClick and not character:GetAttribute("Stunned") then
            local pressDuration = tick() - timePressed
            if pressDuration >= mouseHeldDuration then
                print("holding")
                isPlayingHold = true
                resetNoPunchTwoSeconds()
                resetNoHitTwoSeconds()
                executePunchSequence(true)
                if not mousePressed then
                    isPlayingHold = false
                end
            end
        end
    end
end)

For reference, here are the Luau role requirements:

Luau Scripter Requirements: Luau Scripter

A minimum of 200 lines of Roblox Luau code in a single script (excluding empty/ blank lines and comment lines). Only Pastebin, GitHub and Hastebin are permitted. You must demonstrate a broad understanding of Roblox and programming logic. You must show broad understanding of Roblox API. We suggest using CFrame math, physics, metatables, open-source libraries, etc. The code must be well written and efficient, with proper utilization of functions and methods. Code must be well presented in order to maintain readability. There must be appropriate comments to demonstrate an understanding of the provided code. A demo game demonstrating the functionality of the script must be provided. Ensure that your code is well-optimized and avoid any unnecessary components/ extra lines. Roblox place must be owned by you, or you must be specifically credited in the game description. Alternatively, credits are allowed on an external page (like Roblox Devforum) if this external page is linked in the game description. Avoid the following: Irrelevant blocks of code. Several modules/ scripts combined together to meet the line requirement.

If anyone has tips, examples, or feedback on my script, I’d really appreciate it! Thanks in advance.

Share Improve this question asked Mar 5 at 19:44 yousef mashayekhyousef mashayekh 1
Add a comment  | 

1 Answer 1

Reset to default 0

From my perspective, here are some tips that I think would help

For the comments part, you shouldn't state the obvious. For example, you shouldn't put a comments on variables that already describe themselves by the name.

local punchCooldown = 2  -- Set cooldown time for resetting combo

And for this code block, you didn't add any comments

local function spaceButtonHold(actionName, inputState, inputDetails)
    if inputState == Enum.UserInputState.Begin then
        spacePressed = true

    elseif inputState == Enum.UserInputState.End then
        spacePressed = false
    end
    return Enum.ContextActionResult.Pass
end

You should describe what it does. Instead of saying what the code does, work on why it's there and how it works.
Here's a better version

-- Listens for the Space button, handling space presses and releases.
-- It's used for clarifying if the space button is pressed or not to avoid lots of redundant functions.
local function spaceButtonHold(actionName, inputState, inputDetails)
    if inputState == Enum.UserInputState.Begin then
        spacePressed = true

    elseif inputState == Enum.UserInputState.End then
        spacePressed = false
    end
    return Enum.ContextActionResult.Pass
end

To make your code more optimized or have "better readability", try putting some variables in tables.
Change this:

local originalWalkSpeed = humanoid.WalkSpeed
local originalJumpPower = humanoid.JumpPower
local originalJumpHeight = humanoid.JumpHeight

To this:

local originalStats = {
    WalkSpeed = humanoid.WalkSpeed,
    JumpPower = humanoid.JumpPower,
    JumpHeight = humanoid.JumpHeight
}

本文标签: optimizationNeed Help Improving Code Comments amp Structure for Luau Role ApplicationStack Overflow