So basically, I made this npc so that it charges at you and beats you to death, while using pathfinding and stuff which is why I’m using a pathfinding module. It works relatively smoothly and alright up until around 30 of them. This code is inside of a spawn function in a module script so it’s all in one place and any server script and spawn an enemy.
I’m just trying to see if I can change things in the code so that it does what it already does but better, and I also want to make it less laggy and be able to handle more
local ServerStorage = game:GetService("ServerStorage")
local SimplePath = require(ServerStorage.SimplePath)
local RaycastHitbox = require(ServerStorage:WaitForChild("RaycastHitboxV4"))
local spawnMarker = ServerStorage:FindFirstChild("spawnMarker")
function BehaviorHandler:SpawnDwarf(x,y,z)
local Thread = coroutine.create(function()
--some variables
local character = game.ServerStorage.Enemies:FindFirstChild("Dwarf"):Clone()
local human = character:WaitForChild("Humanoid")
local OldHealth = human.Health
local myHRP = character:WaitForChild("HumanoidRootPart")
local assets = character:FindFirstChild("Assets")
--spawn markers so i see where they're gonna spawn
local clone = spawnMarker:Clone()
clone.Position = Vector3.new(x, spawnMarker.Position.Y,z)
clone.Parent = workspace
task.wait(3)
character:SetPrimaryPartCFrame(CFrame.new(Vector3.new(x,y,z)))
character.Parent = workspace.Enemies
clone:Destroy()
--more variables
local Path = SimplePath.new(character)
local HitboxRight = RaycastHitbox.new(character:WaitForChild("RightHand"))
local HitboxLeft = RaycastHitbox.new(character:WaitForChild("LeftHand"))
local DamageParticle = assets:WaitForChild("DamageParticle")
local attack1Sound = assets:WaitForChild("Attack1Sound")
local hitSound = assets:WaitForChild("HitSound")
local attack1 = assets:WaitForChild("Attack1")
local attack2 = assets:WaitForChild("Attack2")
local attack1Track = human:LoadAnimation(attack1)
local attack2Track = human:LoadAnimation(attack2)
local Damage = 15
local mainWalkSpeed = 32
local attackSpeed = 0.3
local attackCooldown = 0.5
local lastAttack = 2
local attackDistance = 8
local faceDistance = 25
local db = true
local timeCount = 0
local timeCountOfLastAttack = 0
--setting network ownership
if myHRP:CanSetNetworkOwnership() then
myHRP:SetNetworkOwner(nil)
end
--functions
local function Attack()
local attackThread = coroutine.create(function()
if db then
db = false
--human.WalkSpeed = mainWalkSpeed/2
attack1Sound:Play()
if lastAttack == 2 then
lastAttack = 1
attack1Track:Play()
HitboxRight:HitStart()
task.wait(attackSpeed)
HitboxRight:HitStop()
human.WalkSpeed = mainWalkSpeed
db = true
else
lastAttack = 2
attack2Track:Play()
HitboxLeft:HitStart()
task.wait(attackSpeed)
HitboxLeft:HitStop()
human.WalkSpeed = mainWalkSpeed
db = true
end
end
end)
coroutine.resume(attackThread)
end
local target = nil
local function findTarget()
local tempTarget = nil
local maxDist = 1000
for i,v in pairs(workspace:GetDescendants()) do
if v:IsA("Humanoid") then
local PotEnemyChar = v.Parent
if PotEnemyChar.Parent ~= workspace.Enemies and PotEnemyChar.Parent ~= workspace.Passive then
local enemyHRP = PotEnemyChar:FindFirstChild("HumanoidRootPart")
local dist = (enemyHRP.Position - myHRP.Position).Magnitude
if dist < maxDist and v.Health > 0 then
maxDist = dist
tempTarget = enemyHRP
end
end
end
end
target = tempTarget
end
--hit detection
HitboxRight.OnHit:Connect(function(hit, humanoid)
if humanoid.Parent ~= character and humanoid.Parent.Parent ~= workspace.Enemies and humanoid.Parent.Parent ~= workspace.Passive then
local clone = DamageParticle:Clone()
humanoid:TakeDamage(Damage)
hitSound:Play()
clone.Parent = hit
clone:Emit(50)
game:GetService("Debris"):AddItem(clone, 1)
end
end)
HitboxLeft.OnHit:Connect(function(hit, humanoid)
if humanoid.Parent ~= character and humanoid.Parent.Parent ~= workspace.Enemies and humanoid.Parent.Parent ~= workspace.Passive then
local clone = DamageParticle:Clone()
humanoid:TakeDamage(Damage)
hitSound:Play()
clone.Parent = hit
clone:Emit(50)
game:GetService("Debris"):AddItem(clone, 1)
end
end)
--main
while task.wait(.1) do
if human.Health == 0 then
break
end
timeCount = timeCount + 0.1
if human.Health > 0 then
findTarget()
if target then
local futurePos = target.Position + (target.Velocity / 3)
Path:Run(futurePos)
if (target.Position - myHRP.Position).Magnitude <= attackDistance and timeCount - timeCountOfLastAttack >= attackCooldown then
Attack()
timeCountOfLastAttack = timeCount
end
end
end
--no use for this yet
human:GetPropertyChangedSignal("Health"):Connect(function()
if human.Health < OldHealth then
OldHealth = human.Health
end
end)
--remove body on death
human.Died:Connect(function()
game:GetService("Debris"):AddItem(character, 10)
end)
end
end)
coroutine.resume(Thread)
end