also, some weird bug where the client dosent finish the tween beforethe server teleports it. Heres a video:

hers the code:

```
--!native
local module = {}
local ServerStorage = game:GetService("ServerStorage")
--local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
--local PhysicsService = game:GetService("PhysicsService")
local moveremote = ReplicatedStorage:WaitForChild("tweenenemy")
local Players = game:GetService("Players")
module.spawn = function(name: string, waypointfolder: Folder, exit, spawns: CFrame, boss: BoolValue)
local offset = math.random(-1, 1)
local model: Model = ServerStorage.Enemies:FindFirstChild(name):Clone()
model:PivotTo(spawns + Vector3.new(offset, 0, 0))
if boss then
ReplicatedStorage.AddHealthBar:FireAllClients(name, model.Health.Value, model.Health.Value)
end
--for _,parts:BasePart in pairs(model) do
-- if parts:IsA("BasePart") then
-- parts.CollisionGroup = "Enemies"
-- end
--end
model.Parent = Workspace:FindFirstChild(ReplicatedStorage.Map.Value).enemies
--local health = model.health
--health:GetPropertyChangedSignal("Value"):Connect(function()
-- if health.Value == 0 then
-- model:Destroy()
-- end
--end)
model.PrimaryPart:SetNetworkOwner(nil)
local enemySpeed = model.speed.value
--model.speed:GetPropertyChangedSignl("Value"):Connect(function()
-- enemySpeed = model.speed.Value
--end)
local _, size = model:GetBoundingBox()
for index = 1, #waypointfolder:GetChildren() - 2 do
local node = waypointfolder[index]
local finished = false
local distance = (node.Position + Vector3.new(offset, size.Y / 2, 0) - model.PrimaryPart.Position).Magnitude
local movethread = task.spawn(function()
local movementgoal = {
CFrame = CFrame.lookAlong(
node.Position + Vector3.new(offset, size.Y / 2, 0),
model.PrimaryPart.CFrame.LookVector
),
}
ReplicatedStorage.tweenenemy:FireAllClients(model, distance / enemySpeed, movementgoal)
task.wait(distance / enemySpeed)
model.PrimaryPart.CFrame = CFrame.lookAlong(
node.Position + Vector3.new(offset, size.Y / 2, 0),
model.PrimaryPart.CFrame.LookVector
)
finished = true
end)
local speed: IntValue = model:WaitForChild("speed")
local changedthread = nil
local speedChanged = nil
speedChanged = speed:GetPropertyChangedSignal("Value"):Connect(function()
if movethread then
task.cancel(movethread)
movethread = nil
end
if changedthread then
task.cancel(changedthread)
changedthread = nil
end
enemySpeed = model.speed.value
distance = (node.Position + Vector3.new(offset, size.Y / 2, 0) - model.PrimaryPart.Position).Magnitude
print(
"newspeed: "
.. tostring(enemySpeed)
.. " "
.. "newdistance: "
.. tostring(distance)
.. " "
.. "newtime: "
.. " "
.. tostring(distance / enemySpeed)
)
changedthread = task.spawn(function()
print("updating tweens")
local movementgoal = {
CFrame = CFrame.lookAlong(
node.Position + Vector3.new(offset, size.Y / 2, 0),
model.PrimaryPart.CFrame.LookVector
),
}
ReplicatedStorage.tweenenemy:FireAllClients(model, distance / enemySpeed, movementgoal)
task.wait(distance / enemySpeed)
model.PrimaryPart.CFrame = CFrame.lookAlong(
node.Position + Vector3.new(offset, size.Y / 2, 0),
model.PrimaryPart.CFrame.LookVector
)
finished = true
end)
end)
repeat
task.wait()
until finished == true
speedChanged:Disconnect()
local rotationgoal = {
CFrame = CFrame.lookAlong(model.PrimaryPart.Position, node.CFrame.LookVector),
}
local rotation
ReplicatedStorage.tweenenemy:FireAllClients(model, 0.05, rotationgoal)
task.wait(0.05)
if not model then
break
end
model.PrimaryPart.CFrame = CFrame.lookAlong(model.PrimaryPart.Position, node.CFrame.LookVector)
end
if model then
local node = exit
local finished = false
local distance = (node.Position + Vector3.new(offset, size.Y / 2, 0) - model.PrimaryPart.Position).Magnitude
local movethread = task.spawn(function()
local movementgoal = {
CFrame = CFrame.lookAlong(
node.Position + Vector3.new(offset, size.Y / 2, 0),
model.PrimaryPart.CFrame.LookVector
),
}
ReplicatedStorage.tweenenemy:FireAllClients(model, distance / enemySpeed, movementgoal)
task.wait(distance / enemySpeed)
model.PrimaryPart.CFrame = CFrame.lookAlong(
node.Position + Vector3.new(offset, size.Y / 2, 0),
model.PrimaryPart.CFrame.LookVector
)
finished = true
end)
local speed: IntValue = model:WaitForChild("speed")
local changedthread = nil
local speedChanged = nil
speedChanged = speed:GetPropertyChangedSignal("Value"):Connect(function()
if movethread then
task.cancel(movethread)
movethread = nil
end
if changedthread then
task.cancel(changedthread)
changedthread = nil
end
enemySpeed = model.speed.value
distance = (node.Position + Vector3.new(offset, size.Y / 2, 0) - model.PrimaryPart.Position).Magnitude
print(
"newspeed: "
.. tostring(enemySpeed)
.. " "
.. "newdistance: "
.. tostring(distance)
.. " "
.. "newtime: "
.. " "
.. tostring(distance / enemySpeed)
)
changedthread = task.spawn(function()
print("updating tweens")
local movementgoal = {
CFrame = CFrame.lookAlong(
node.Position + Vector3.new(offset, size.Y / 2, 0),
model.PrimaryPart.CFrame.LookVector
),
}
ReplicatedStorage.tweenenemy:FireAllClients(model, distance / enemySpeed, movementgoal)
task.wait(distance / enemySpeed)
model.PrimaryPart.CFrame = CFrame.lookAlong(
node.Position + Vector3.new(offset, size.Y / 2, 0),
model.PrimaryPart.CFrame.LookVector
)
finished = true
end)
end)
repeat
task.wait()
until finished == true
speedChanged:Disconnect()
ReplicatedStorage.BaseHealth.Value = math.clamp(
ReplicatedStorage.BaseHealth.Value - model.Health.Value,
0,
ReplicatedStorage.MaxBaseHealth.Value
)
model:Destroy()
end
end
return module
```

Edit: the only things i changed with the spawning is how the enemys are spawned. I made the wave system work with dual lanes, so calling the module more.