Right now I am working on an NPC script and it is going well so far. I would like to know how everyone else makes the combat side of their NPC. Ex. How do you make the NPC block attacks(I mean what makes the NPC start blocking/ what conditionals do you use) I’m also curious in how you make the NPC attack. Does it wait for the player to have a break in their attacks or does it block the players attacks and then attack.
My issue is I can’t think of a way to make a blocking system for the NPC I believe it’s because of lack of experience as I have not done NPC creation before.
I’ve looked on the devforum but can not find anything really in depth about what conditionals a person uses when making their NPC.
Also I am sorry because my script is definitely not neatly sorted
local pathFind = game:GetService("PathfindingService")
local Rs = game:GetService("RunService")
local Players = game:GetService("Players")
local Ts = game:GetService("TweenService")
local trackHum = script.Parent.Humanoid
local trackTorso = script.Parent.Torso
local isAtking = false
local atkDebounce = false
local canAtk = true
local shieldBroken = false
local m1Atk = false
local bBdebounce = false
local combo = 0
local blockHits = 0
local katana = script.Parent.npcKatana
local hum = katana.Parent:WaitForChild('Humanoid')
local trackHRP = katana.Parent:WaitForChild("HumanoidRootPart")
local root = hum.Parent.PrimaryPart
trackHum.WalkSpeed = 30
--Finds plr to track
local function findTarget2()
local plrList = Players:GetPlayers()
local nearestPlayer = nil
local distance = nil
local direction = nil
local char = nil
for i,v in pairs(plrList) do
char = v.Character
if char then
local distVector = (v.Character.HumanoidRootPart.Position - root.Position)
if not nearestPlayer then
nearestPlayer = v
distance = distVector.magnitude
direction = distVector.Unit
elseif distVector.magnitude <= distance then
nearestPlayer = v
distance = distVector.magnitude
direction = distVector.Unit
end
end
end
return char,direction
end
--Checks for blocking
local function checkforBlock(target)
local block = false
local counterDebounce = false
if blockHits == 5 then
blockHits = 0
end
if target ~= nil then
if target.Parent:FindFirstChild("Blocker") ~= nil and counterDebounce == false then
counterDebounce = true
block = true
elseif target.Parent:FindFirstChild("Blocker") == nil then
block = false
end
end
return block
end
--Dmgs player depending on what combo it is on
local function DmgPlayer(combo,target)
if m1Atk == true and combo == 1 and canAtk == true then
target:TakeDamage(10.5)
canAtk = false
local tweenInfo = TweenInfo.new(.5,Enum.EasingStyle.Back,Enum.EasingDirection.Out)
local Tween = Ts:Create(target.Parent.HumanoidRootPart,tweenInfo,{Velocity = trackHRP.CFrame.LookVector * 15}):Play()
end
if m1Atk == true and combo == 2 and canAtk == true then
target:TakeDamage(12.5)
canAtk = false
local tweenInfo = TweenInfo.new(.5,Enum.EasingStyle.Back,Enum.EasingDirection.Out)
local Tween = Ts:Create(target.Parent.HumanoidRootPart,tweenInfo,{Velocity = trackHRP.CFrame.LookVector * 15}):Play()
end
if m1Atk == true and combo == 3 and canAtk == true then
target:TakeDamage(13.5)
canAtk = false
local tweenInfo = TweenInfo.new(.5,Enum.EasingStyle.Back,Enum.EasingDirection.Out)
local Tween = Ts:Create(target.Parent.HumanoidRootPart,tweenInfo,{Velocity = trackHRP.CFrame.LookVector * 15}):Play()
end
if m1Atk == true and combo == 4 and canAtk == true then
target:TakeDamage(15)
canAtk = false
local tweenInfo = TweenInfo.new(.5,Enum.EasingStyle.Back,Enum.EasingDirection.Out)
local Tween = Ts:Create(target.Parent.HumanoidRootPart,tweenInfo,{Velocity = trackHRP.CFrame.LookVector * 15}):Play()
end
end
--Delays next atk depending on combo
local function Delays()
if combo == 1 then
spawn(function()
wait(.75)
isAtking = false
end)--End Of Spawned Func
end
if combo == 2 then
spawn(function()
spawn(function()
wait(.85)
isAtking = false
end)--End Of Spawned Func
end)
end
if combo == 3 then
spawn(function()
wait(.95)
isAtking = false
end)--End Of Spawned Func
end
if combo == 4 then
combo = 0
spawn(function()
wait(1.25)
isAtking = false
end)--End Of Spawned Func
end
end--End of func
--NPC plays animation and checks if touched
local function slashM1(m1,hitbox)
m1:Play()
canAtk = true
combo = combo+1
isAtking = true
hitbox.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
local target = hit.Parent:WaitForChild("Humanoid")
if checkforBlock(target) == false and canAtk == true then
DmgPlayer(combo,target)
m1Atk = true
elseif checkforBlock(target) == true and canAtk == true then
blockHits = blockHits +1
print(blockHits)
canAtk = false
end
m1.Stopped:Wait()
canAtk = false
Delays()
end
end) -- End of Touched Event
end
--If distance is less than 7 NPC atks
local function M1(HRP,m1)
local hitbox = katana:WaitForChild("BladeHitbox")
local distance = (trackHRP.Position - HRP.Position).Magnitude
if distance <= 7 and isAtking == false then
slashM1(m1,hitbox)
end
end --End of func
local function blockBreakStun(hum)
if canAtk == true then
local tweenInfo = TweenInfo.new(.5,Enum.EasingStyle.Back,Enum.EasingDirection.Out)
local Tween = Ts:Create(hum.Parent.HumanoidRootPart,tweenInfo,{Velocity = trackHRP.CFrame.LookVector * 20}):Play()
for i,v in pairs(hum:GetPlayingAnimationTracks()) do
v:Stop()
end
hum.WalkSpeed = 0
hum:TakeDamage(15)
canAtk = false
local stun = Instance.new("BoolValue")
stun.Name = "stun"
delay(2,function()
hum.WalkSpeed = 16
stun:Destroy()
end)
end
end
--Breaks player block
local rndmNum = math.random(1,4)
local function blockBreaker(m1,hitbox)
if bBdebounce == false then
m1:Play()
canAtk = true
if canAtk == true then
hitbox.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
local target = hit.Parent:FindFirstChild("Humanoid")
if checkforBlock(target) == true then
if canAtk == true then
blockBreakStun(target)
blockHits = 0
canAtk = false
rndmNum = math.random(1,4)
end
elseif checkforBlock(target) == false then
if canAtk == true then
target:TakeDamage(15)
local tweenInfo = TweenInfo.new(.5,Enum.EasingStyle.Back,Enum.EasingDirection.Out)
local Tween = Ts:Create(hum.Parent.HumanoidRootPart,tweenInfo,{Velocity = trackHRP.CFrame.LookVector * 20}):Play()
canAtk = false
rndmNum = math.random(1,4)
end
end
end
end)
end
m1.Stopped:Wait()
bBdebounce = true
canAtk = false --cant atk after anim done
delay(5,function()
bBdebounce = false
end) --end of delay func
end --End of debounce
end --End of func
local function CombatSystem()
local char,direction = findTarget2()
local HRP = char.HumanoidRootPart
local hitbox = katana:FindFirstChild("BladeHitbox")
local anims = script:WaitForChild("Anims")
local m1 = hum:LoadAnimation(anims:WaitForChild("Kendo"))
local blockBreak = hum:LoadAnimation(anims:WaitForChild("BlocKBreak"))
local dash = hum:LoadAnimation(anims:WaitForChild("Dash"))
print(rndmNum)
if blockHits == rndmNum then
print("blockbreaker")
blockBreaker(m1,hitbox)
end
M1(HRP,m1)
end --End of function
local targetDistance = 25
local stopDistance = 10
local function checkDist(distance,torso)
if distance <= 6 then
trackHum.WalkSpeed = hum.WalkSpeed
else
trackHum.WalkSpeed = 30
local path = pathFind:CreatePath()
path:ComputeAsync(trackTorso.Position,torso.Position)
local waypoints = path:GetWaypoints()
for i,v in pairs(waypoints) do
local block = Instance.new("Part",workspace)
block.Anchored = true
block.CanCollide = false
block.Size = Vector3.new(1,1,1)
block.Shape = Enum.PartType.Ball
block.BrickColor = BrickColor.new("Yellow flip/flop")
block.Position = v.Position
trackHum:MoveTo(v.Position)
end
end
end
while wait(.1) do
root:SetNetworkOwner(nil)
local char,direction = findTarget2()
--if char == nil then
-- trackHum:MoveTo( Vector3.new(math.random(-25,5),0,math.random(0,25)))
-- trackHum.MoveToFinished:Wait(false)
-- end
if char then
local torso = char.HumanoidRootPart
local distance = (torso.Position-root.Position).magnitude
if distance <= 7 then
CombatSystem()
end
if distance <= 50 then
wait(.5)
checkDist(distance,torso)
end
end
end
this is my code rn feel free to find mistakes or things I could do better. All criticism is welcome.