#npc rotation and push away

1 messages · Page 1 of 1 (latest)

knotty crescent
#

im tryinbg to make the npc rotate to face what angle im coming from and then push me away when i walk up to them

( I HAVE THE PUSH AND STUN, JUST NEED ROTATION )

#

the code

#

ping me when you help

jade fulcrum
#

To have rotation

#

U just

#

Set it's cframe

#

As 2nd argument is lookat

#

So just update cframe

knotty crescent
#

how do i do that

#

can u rewrite it for me @jade fulcrum

jade fulcrum
#

Just

knotty crescent
#

y

jade fulcrum
#

Simple

knotty crescent
#

how do i do that

#

is it this line

#

local targetCFrame = CFrame.new(npcHRP.Position, Vector3.new(hrp.Position.X, npcHRP.Position.Y, hrp.Position.Z))
npcHRP.CFrame = npcHRP.CFrame:Lerp(targetCFrame, ROTATE_SPEED * deltaTime)

jade fulcrum
#

If you wrote the script

#

U will know

#

I litteraly have u whole ass code

knotty crescent
#

can u just help

jade fulcrum
#

No

knotty crescent
#

y

jade fulcrum
knotty crescent
#

ur weird

jade fulcrum
#

And u used ai

#

Or free models

knotty crescent
#

its ai

jade fulcrum
knotty crescent
#

its not fixing it

#

just tell me the issue

jade fulcrum
lyric canopy
#

try this

lyric canopy
knotty crescent
#

ty

lyric canopy
#

should be instead of trhis

knotty crescent
#

so replace this with

#

this

#

local targetCFrame = CFrame.new(npcHRP.Position, hrp.Position)
npcHRP.CFrame = npcHRP.CFrame:Lerp(targetCFrame, ROTATE_SPEED * deltaTime)

lyric canopy
#
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local councilFolder = workspace:WaitForChild("StudentCouncil") -- folder with NPCs

local DETECTION_RANGE = 3  -- how close to trigger push/stun
local PUSH_FORCE = 50      -- strength of push
local STUN_TIME = 1        -- seconds stunned
local ROTATE_SPEED = 5     -- higher = faster rotation

local stunnedPlayers = {}

RunService.Heartbeat:Connect(function(deltaTime)
    for _, player in pairs(Players:GetPlayers()) do
        local character = player.Character
        if character and character:FindFirstChild("HumanoidRootPart") and character:FindFirstChild("Humanoid") then
            local hrp = character.HumanoidRootPart
            local humanoid = character.Humanoid

            for _, npc in pairs(councilFolder:GetChildren()) do
                if npc:IsA("Model") and npc:FindFirstChild("HumanoidRootPart") then
                    local npcHRP = npc.HumanoidRootPart
                    local distance = (hrp.Position - npcHRP.Position).Magnitude

                    if distance <= DETECTION_RANGE then
                        -- Smooth horizontal rotation toward player
                        local lookAtPos = Vector3.new(hrp.Position.X, npcHRP.Position.Y, hrp.Position.Z)
                        local targetCFrame = CFrame.new(npcHRP.Position, lookAtPos)
                        npcHRP.CFrame = npcHRP.CFrame:Lerp(targetCFrame, ROTATE_SPEED * deltaTime)

                        -- Push + Stun
                        if not stunnedPlayers[player] then
                            stunnedPlayers[player] = true

                            -- Push using BodyVelocity
                            local pushDir = (hrp.Position - npcHRP.Position).Unit
                            local bv = Instance.new("BodyVelocity")
                            bv.MaxForce = Vector3.new(1e5, 0, 1e5)
                            bv.Velocity = pushDir * PUSH_FORCE
                            bv.P = 3000
                            bv.Parent = hrp
                            game:GetService("Debris"):AddItem(bv, 0.2)

                            -- Stun player
                            local oldWalk = humanoid.WalkSpeed
                            local oldJump = humanoid.JumpPower
                            humanoid.WalkSpeed = 0
                            humanoid.JumpPower = 0

                            task.delay(STUN_TIME, function()
                                humanoid.WalkSpeed = oldWalk
                                humanoid.JumpPower = oldJump
                                stunnedPlayers[player] = nil
                            end)
                        end
                    end
                end
            end
        end
    end
end)
knotty crescent
#

i just put that in

lyric canopy
#

you can avoid this using a guard clause btw

lyric canopy
knotty crescent
#

but they dont like rotate

#

like if i approach from behind

#

theyre supposed to turn around and face me and push

#

as soon as i make contact

lyric canopy
#

hmm alright 1 sec

#
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local councilFolder = workspace:WaitForChild("StudentCouncil") -- folder with NPCs

local DETECTION_RANGE = 50   -- how close to trigger push/stun (changed to 50)
local PUSH_FORCE = 50        -- strength of push
local STUN_TIME = 1          -- seconds stunned
local ROTATE_SPEED = 5       -- higher = faster rotation

local stunnedPlayers = {}

RunService.Heartbeat:Connect(function(deltaTime)
    -- Iterate through each NPC in the folder
    for _, npc in pairs(councilFolder:GetChildren()) do
        if npc:IsA("Model") and npc:FindFirstChild("HumanoidRootPart") then
            local npcHRP = npc.HumanoidRootPart
            local closestPlayer = nil
            local minDistance = DETECTION_RANGE + 1 -- Initialize with a value larger than the range

            -- Loop through all players to find the closest one to the current NPC
            for _, player in pairs(Players:GetPlayers()) do
                local character = player.Character
                if character and character:FindFirstChild("HumanoidRootPart") and character:FindFirstChild("Humanoid") then
                    local hrp = character.HumanoidRootPart
                    local distance = (hrp.Position - npcHRP.Position).Magnitude

                    -- Check if the player is within range and is closer than the current closest
                    if distance <= DETECTION_RANGE and distance < minDistance then
                        minDistance = distance
                        closestPlayer = player
                    end
                end
            end

            -- If a closest player was found within the detection range, apply the effects
            if closestPlayer then
                local character = closestPlayer.Character
                local hrp = character.HumanoidRootPart
                local humanoid = character.Humanoid

                -- Smooth horizontal rotation toward the closest player
                local lookAtPos = Vector3.new(hrp.Position.X, npcHRP.Position.Y, hrp.Position.Z)
                local targetCFrame = CFrame.new(npcHRP.Position, lookAtPos)
                npcHRP.CFrame = npcHRP.CFrame:Lerp(targetCFrame, ROTATE_SPEED * deltaTime)

                -- Push + Stun the player if they aren't already stunned
                if not stunnedPlayers[closestPlayer] then
                    stunnedPlayers[closestPlayer] = true

                    -- Push using BodyVelocity
                    local pushDir = (hrp.Position - npcHRP.Position).Unit
                    local bv = Instance.new("BodyVelocity")
                    bv.MaxForce = Vector3.new(1e5, 0, 1e5)
                    bv.Velocity = pushDir * PUSH_FORCE
                    bv.P = 3000
                    bv.Parent = hrp
                    game:GetService("Debris"):AddItem(bv, 0.2)

                    -- Stun player by setting their speed to 0
                    local oldWalk = humanoid.WalkSpeed
                    local oldJump = humanoid.JumpPower
                    humanoid.WalkSpeed = 0
                    humanoid.JumpPower = 0

                    -- Restore the player's speed after the stun duration
                    task.delay(STUN_TIME, function()
                        humanoid.WalkSpeed = oldWalk
                        humanoid.JumpPower = oldJump
                        stunnedPlayers[closestPlayer] = nil
                    end)
                end
            end
        end
    end
end)
knotty crescent
#

still no

#

the detection range is how close you have to be to push

#

can i js add u to studio

lyric canopy
#

yeah "gabeisvibing" i cant test rn but when i can ill have a look

knotty crescent
#

kk

#

addde

#

added

knotty crescent
#

gabe

#

its eraa

lyric canopy
knotty crescent
#

got shut down

#

bc i had no license

lyric canopy
#

oh for assets

#

riip

knotty crescent
#

yup

lapis garnet
#

How is blud s1

#

Oh nvm

mortal swan
lyric canopy
#

@knotty crescent you didnt add me to the experience i dont think

#

also i think you should add it so

  • they look at you from say 50 studs
  • but push you at say 10 studs
#

im not sure if that was your issue but currently when i run your code they will only face me when they also push me

#
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Debris = game:GetService("Debris")

local npcModel = script.Parent
if not npcModel:IsA("Model") then return end

local npcRoot = npcModel:FindFirstChild("HumanoidRootPart")
if not npcRoot then return end

--// Configuration
local FACE_DISTANCE = 50          -- NPC rotates within this distance
local PUSH_DISTANCE = 10          -- npc pushes if within this distance
local PUSH_FORCE = 50             -- strength of the push
local STUN_DURATION = 1           -- seconds player is stunned the player is stunned
local ROTATION_SPEED = 5          -- How quickly NPC rotates to face player

local stunnedPlayers = {}

local function faceTarget(npcRootPart, targetPosition, deltaTime)
    local flatTarget = Vector3.new(targetPosition.X, npcRootPart.Position.Y, targetPosition.Z)
    local targetCFrame = CFrame.new(npcRootPart.Position, flatTarget)
    npcRootPart.CFrame = npcRootPart.CFrame:Lerp(targetCFrame, ROTATION_SPEED * deltaTime)
end

local function pushPlayer(playerRoot, npcRootPart)
    local pushVector = playerRoot.Position - npcRootPart.Position
    if pushVector.Magnitude <= 0.1 then return end 

    local attachment = Instance.new("Attachment")
    attachment.Parent = playerRoot

    local linearVelocity = Instance.new("LinearVelocity")
    linearVelocity.Attachment0 = attachment
    linearVelocity.MaxForce = math.huge
    linearVelocity.VectorVelocity = pushVector.Unit * PUSH_FORCE
    linearVelocity.Parent = playerRoot

    Debris:AddItem(attachment, 0.2)
    Debris:AddItem(linearVelocity, 0.2)
end


local function stunPlayer(humanoid, player)
    if stunnedPlayers[player] then return end 
    stunnedPlayers[player] = true

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

    humanoid.WalkSpeed = 0
    humanoid.JumpPower = 0

    task.delay(STUN_DURATION, function()
        if humanoid then
            humanoid.WalkSpeed = originalWalkSpeed
            humanoid.JumpPower = originalJumpPower
        end
        stunnedPlayers[player] = nil
    end)
end

RunService.Heartbeat:Connect(function(deltaTime)
    local nearestPlayer = nil
    local nearestDistance = FACE_DISTANCE + 1

    for _, player in ipairs(Players:GetPlayers()) do
        local character = player.Character
        if not character then continue end

        local playerRoot = character:FindFirstChild("HumanoidRootPart")
        local humanoid = character:FindFirstChild("Humanoid")
        if not (playerRoot and humanoid) then continue end

        local distance = (playerRoot.Position - npcRoot.Position).Magnitude
        if distance <= FACE_DISTANCE and distance < nearestDistance then
            nearestDistance = distance
            nearestPlayer = player
        end
    end

    if not nearestPlayer then return end

    local nearestCharacter = nearestPlayer.Character
    local nearestRoot = nearestCharacter:FindFirstChild("HumanoidRootPart")
    local nearestHumanoid = nearestCharacter:FindFirstChild("Humanoid")
    if not (nearestRoot and nearestHumanoid) then return end

    faceTarget(npcRoot, nearestRoot.Position, deltaTime)

    if nearestDistance <= PUSH_DISTANCE then
        pushPlayer(nearestRoot, npcRoot)
        stunPlayer(nearestHumanoid, nearestPlayer)
    end
end)
#

put it into multiple functions to make the flow easier to read

#

made it so they will turn at you in a certain range and push you in another certain range

#

you can config pretty easily

#

this is specifically for one NPC but you can add your folder logic in the Heartbeat function