The reason why I opted to disconnect the heartbeat loop is because you’ll have a memory leak if you don’t disconnect a connection when it’s no longer required
After the projectile is destroyed, the heartbeat loop no longer needs to run, which is why I’m disconnecting it whenever I’m destroying the projectile
Coincidentally I was in the process of rewriting the script, and this version uses LinearVelocity instead of BodyVelocity, and also uses threads so there’s no longer a need to worry about disconnecting connections:
local projectile = {}
local data = {
Cannonball = {
Model = projectilesFolder.Cannonball;
Damage = 1000;
Size = Vector3.new(2, 2, 2);
};
Musketball = {
Model = projectilesFolder.Musketball;
Damage = 150;
Size = Vector3.new(0.144, 0.144, 0.144);
};
GatlingBullet = {
Model = projectilesFolder.GatlingBullet;
Damage = 25;
Size = Vector3.new(0.105, 0.115, 0.205);
};
NavyBullet = {
Model = projectilesFolder.GatlingBullet;
Damage = 15;
Size = Vector3.new(0.105, 0.115, 0.205);
};
}
local function handleProjectile(projectile: BasePart, originalPosition: Vector3, ignoreList: SharedTable, damage: number, cash: IntValue)
local overlapParams = OverlapParams.new()
overlapParams.FilterDescendantsInstances = ignoreList
overlapParams.FilterType = Enum.RaycastFilterType.Exclude
while (projectile.Position - originalPosition).Magnitude < 300 do -- Change 300 to the maximum distance the projectile can travel
local part = workspace:GetPartsInPart(projectile, overlapParams)[1]
if part then
local model = part:FindFirstAncestorOfClass("Model")
if model then
local humanoid = model:FindFirstChildOfClass("Humanoid")
if humanoid then
humanoid:TakeDamage(damage)
part.Color = Color3.new(0.45, 0, 0)
cash.Value += 15
end
end
break -- If the projectile hits a part, exit out of the loop so the projectile can be destroyed
end
task.wait()
end
projectile:Destroy()
end
projectile.fire = function(plr: Player, lookVector: Vector3, projectileName: string, position: Vector3, speed: number, spread: number, ignoreList: SharedTable)
if not data[projectileName] then return end
local projectile = data[projectileName].Model:Clone()
projectile.Position = position
projectile.Parent = workspace.Projectiles
projectile:SetNetworkOwner(plr)
local attachment = Instance.new("Attachment", projectile)
local linearVelocity = Instance.new("LinearVelocity") -- Replaces BodyVelocity
linearVelocity.Attachment0 = attachment
linearVelocity.ForceLimitsEnabled = false -- Use the maximum force required to reach the desired speed
linearVelocity.VectorVelocity = lookVector * speed
linearVelocity.Parent = projectile
task.spawn(handleProjectile, projectile, position, ignoreList, data[projectileName].Damage, plr.leaderstats.Cash)
end
return projectile