I have an issue where I need to set these variables only once in a repeating function.
I’m sorry if I don’t make any sense but I don’t know how to precisely describe this problem, its just so obscure and weird that I don’t have words for it.
Here is a video showcasing the issue, only one of the AIs attack at a time
And here is the attack script, it gets called multiple times per second.
local RunOnce = false
local MeleeDB = false
local NPCHitbox
function AI.Melee(humrp,hum,NPC,target,WalkAnim,Team,AttackType)
if MeleeDB == false then
MeleeDB = true
WalkAnim:Stop()
NPC:SetPrimaryPartCFrame(CFrame.new(NPC.HumanoidRootPart.Position,target.HumanoidRootPart.Position))
--local AnimId = 'rbxassetid://6932293833'
local AttackAnim = hum:LoadAnimation(Anims.Attack)
local Damage = 15
local delay = 1
if RunOnce == false then
RunOnce = true
NPCHitbox = RaycastHitbox.new(NPC['Right Arm'])
NPCHitbox:SetPoints(NPC['Right Arm'],{Vector3.new(0,0,1),Vector3.new(-1,1,3),Vector3.new(-3.5,1,3)})
end
AttackAnim:Play()
NPCHitbox:HitStart()
NPCHitbox.OnHit:Connect(function(hit,humanoid)
if humanoid.Parent.Name ~= NPC.Name and not humanoid:FindFirstAncestor(Team) then
humanoid:TakeDamage(Damage)
end
end)
coroutine.wrap(function()
AttackAnim.Stopped:Wait()
NPCHitbox:HitStop()
task.wait(delay)
MeleeDB = false
WalkAnim:Play()
end)()
end
end
Here is the entire script
local Players = game:GetService('Players')
local RunService = game:GetService('RunService')
local PathfindingService = game:GetService('PathfindingService')
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local RaycastHitbox = require(ReplicatedStorage.RaycastHitboxV4)
local maxDistance = math.huge
local Anims = script.Parent.R6Anims
local AI = {}
AI.__index = AI
function AI.new(NPC,WalkAnim,AttackType)
spawn(function()
local Team = NPC.Parent.Name
local NPCProperties = setmetatable({},AI)
local hum = NPC.Humanoid
local humrp = NPC.HumanoidRootPart
local WalkAnim = hum:LoadAnimation(WalkAnim)
NPCProperties.Model = NPC
NPCProperties.Humanoid = hum
NPCProperties.humrp = humrp
--Pathfinding
NPC.PrimaryPart:SetNetworkOwner(nil)
local CoreOfFactory = workspace.CentreOfFactory
local function findTarget()
local team
if Team == 'Allies' then
team = workspace.Enemies:GetChildren()
else
team = workspace.Allies:GetChildren()
end
local MaxDistance = 200
local nearestTarget
for _,enemy in pairs(team) do
if enemy then
if enemy.Humanoid.Health > 0 then
local target = enemy
local distance = (humrp.Position - target.HumanoidRootPart.Position).Magnitude
if distance < MaxDistance then
nearestTarget = target
MaxDistance = distance
end
end
end
end
return nearestTarget
end
local function agro()
repeat task.wait(0.05)
local target = findTarget()
if target and target.HumanoidRootPart then
local distance = (humrp.Position - target.HumanoidRootPart.Position).Magnitude
if distance <= 3 then
WalkAnim:Stop()
if AttackType == 'Melee' then
AI[AttackType](humrp,hum,NPC,target,WalkAnim,Team)
end
else
local targetVel = target.PrimaryPart.Velocity
local leadBy = 7
local lead
if targetVel.Magnitude < 0.1 then
lead = Vector3.new(0, 0, 0)
else
lead = targetVel.Unit * leadBy
end
hum:MoveTo(target.PrimaryPart.Position + lead)
end
end
until target == nil or target.Humanoid.Health == 0 or (humrp.Position - target.HumanoidRootPart.Position).Magnitude > maxDistance
end
local function walkToCore()
local path = PathfindingService:CreatePath()
local success, errorMessage = pcall(function()
path:ComputeAsync(humrp.Position, CoreOfFactory.Position)
end)
WalkAnim:Play()
if success and path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
for _,waypoint in pairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
hum:ChangeState(Enum.HumanoidStateType.Jumping)
end
if findTarget() and (humrp.Position - findTarget().HumanoidRootPart.Position).Magnitude < maxDistance then
agro()
end
hum:MoveTo(waypoint.Position)
hum.MoveToFinished:Wait()
end
end
WalkAnim:Stop()
end
walkToCore()
end)
end
local RunOnce = false
local MeleeDB = false
local NPCHitbox
function AI.Melee(humrp,hum,NPC,target,WalkAnim,Team,AttackType)
if MeleeDB == false then
MeleeDB = true
WalkAnim:Stop()
NPC:SetPrimaryPartCFrame(CFrame.new(NPC.HumanoidRootPart.Position,target.HumanoidRootPart.Position))
--local AnimId = 'rbxassetid://6932293833'
local AttackAnim = hum:LoadAnimation(Anims.Attack)
local Damage = 15
local delay = 1
if RunOnce == false then
RunOnce = true
NPCHitbox = RaycastHitbox.new(NPC['Right Arm'])
NPCHitbox:SetPoints(NPC['Right Arm'],{Vector3.new(0,0,1),Vector3.new(-1,1,3),Vector3.new(-3.5,1,3)})
end
AttackAnim:Play()
NPCHitbox:HitStart()
NPCHitbox.OnHit:Connect(function(hit,humanoid)
if humanoid.Parent.Name ~= NPC.Name and not humanoid:FindFirstAncestor(Team) then
humanoid:TakeDamage(Damage)
end
end)
coroutine.wrap(function()
AttackAnim.Stopped:Wait()
NPCHitbox:HitStop()
task.wait(delay)
MeleeDB = false
WalkAnim:Play()
end)()
end
end
return AI
Here is the server script which calls the module
local RunService = game:GetService('RunService')
local Players = game:GetService('Players')
local PathfindingService = game:GetService('PathfindingService')
local AI = require(script.AI)
Players.PlayerAdded:Connect(function(plr)
plr.CharacterAdded:Connect(function(char)
char.AncestryChanged:wait()
game:GetService("RunService").Stepped:wait()
char.Parent = workspace.Allies
end)
end)
AI.new(workspace.Enemies["Fast Zombie"],script.R6Anims.walk.WalkAnim,'Melee')
AI.new(workspace.Allies.Noob,script.R6Anims.walk.WalkAnim,'Melee')
Please help, i’ve been at this for 3 days now, spending around an hour each time trying to figure out what is happening, I tried making bool values, I tried putting the variables inside of the function, I tried including a debounce before the function is called, and much more, if you need any extra information, I can provide.