local ProjectileHandler = {}
local function ReturnDecimal(range)
return Random.new():NextNumber(-range, range)
end
local function Lerp(a, b, t)
return a + (b - a) * t
end
local DamageEnemy = game.ReplicatedStorage.RemoteEvents.DamageEnemy
function ProjectileHandler.Shoot(Properties, Viewmodel)
if Properties.Type == “Projectile” then
local Angle = 0
local AngleDirectionToTravel = 1
local RaycastParameters = RaycastParams.new()
RaycastParameters.FilterType = Enum.RaycastFilterType.Exclude
RaycastParameters.RespectCanCollide = true
if Properties.IsPlayerShooting then
RaycastParameters.FilterDescendantsInstances = {game.Players.LocalPlayer.Character, Viewmodel}
end
local Bullet = Instance.new("Part")
Bullet:SetAttribute("TimesRicocheted", 0)
Bullet:SetAttribute("EnemiesHit", 0)
Bullet:SetAttribute("FollowsGravity", Properties.FollowsGravity)
Bullet:SetAttribute("BulletVelocity", Vector3.new(Properties.Direction.X + ReturnDecimal(Properties.MaxInaccuracy), Properties.Direction.Y + ReturnDecimal(Properties.MaxInaccuracy), Properties.Direction.Z + ReturnDecimal(Properties.MaxInaccuracy)) * Properties.Speed)
Bullet.Name = Properties.Name or "Bullet"
Bullet.Size = Properties.Size or Vector3.new(1, 1, 1)
Bullet.Color = Properties.Color or Color3.new(0, 0, 0)
Bullet.Material = Properties.Material or Enum.Material.SmoothPlastic
Bullet.CFrame = Properties.Origin
Bullet.Parent = workspace
Bullet.CollisionGroup = "Extra"
game.CollectionService:AddTag(Properties.ExtraType)
Bullet.CastShadow = false
Bullet.AssemblyLinearVelocity = Bullet:GetAttribute("BulletVelocity")
game.Debris:AddItem(Bullet, Properties.LifeTime)
local Stepped = game:GetService("RunService").PreRender:Connect(function()
local BulletVelocity = Bullet:GetAttribute("BulletVelocity")
local CharacterCollisionRay = workspace:Blockcast(Bullet.CFrame, Bullet.Size, Bullet.AssemblyLinearVelocity.Unit * math.clamp(Properties.Speed / 25, 7, math.huge), RaycastParameters)
if Bullet:GetAttribute("FollowsGravity") == false then
Bullet.AssemblyLinearVelocity = BulletVelocity
end
Bullet.CFrame = CFrame.lookAt(Bullet.Position, Bullet.Position + Bullet.AssemblyLinearVelocity)
for i, v in pairs(game.CollectionService:GetTagged("Magnet")) do
if v:IsA("Part") and (v.Position - Bullet.Position).Magnitude < 10 then
local SawCollisionRaycast = workspace:Raycast(Bullet.Position, Bullet.AssemblyLinearVelocity.Unit * 2, RaycastParameters)
if Properties.MagneticType == "Swarm" then
Bullet:SetAttribute("BulletVelocity", Lerp(BulletVelocity, (v.Position - Bullet.Position).Unit * Properties.Speed, 0.5))
elseif Properties.MagneticType == "Circular" then
Angle += (math.clamp(Properties.Speed / 900, 0, math.huge) * AngleDirectionToTravel)
Angle = Angle % 360
print(Angle)
local NewX = v.Position.X + 8 * math.cos(Angle)
local NewZ = v.Position.Z + 8 * math.sin(Angle)
Bullet:SetAttribute("BulletVelocity", (Vector3.new(NewX, v.Position.Y, NewZ) - Bullet.Position).Unit * Properties.Speed / 2)
if SawCollisionRaycast and SawCollisionRaycast.Instance then
AngleDirectionToTravel *= -1
print(SawCollisionRaycast.Instance.Name)
wait()
end
end
end
end
if CharacterCollisionRay and CharacterCollisionRay.Instance then
if not CharacterCollisionRay.Instance.Parent:FindFirstChildOfClass("Humanoid") and Bullet:GetAttribute("TimesRicocheted") < Properties.MaxRicochets then
Bullet:SetAttribute("TimesRicocheted", Bullet:GetAttribute("TimesRicocheted") + 1)
Bullet.AssemblyLinearVelocity = Bullet.AssemblyLinearVelocity - (2 * Bullet.AssemblyLinearVelocity:Dot(CharacterCollisionRay.Normal) * CharacterCollisionRay.Normal)
Bullet:SetAttribute("BulletVelocity", BulletVelocity - (2 * BulletVelocity:Dot(CharacterCollisionRay.Normal) * CharacterCollisionRay.Normal))
else
if Properties.IsPlayerShooting and CharacterCollisionRay.Instance.Parent == (game.Players.LocalPlayer.Character or Viewmodel) then return end
if CharacterCollisionRay.Instance.Parent:FindFirstChild("Humanoid") and CharacterCollisionRay.Instance.Parent:FindFirstChild("Humanoid").Health > 0 then
local HitHumanoid = CharacterCollisionRay.Instance.Parent:FindFirstChild("Humanoid")
if Bullet:GetAttribute("EnemiesHit") and Bullet:GetAttribute("EnemiesHit") < Properties.MaxEnemiesToHit and not HitHumanoid:HasTag("BeenHit") then
Bullet:SetAttribute("EnemiesHit", Bullet:GetAttribute("EnemiesHit") + 1)
HitHumanoid:AddTag("BeenHit")
DamageEnemy:FireServer(HitHumanoid, Properties.Damage * ((Properties.LocationalDamage == true and CharacterCollisionRay.Instance:GetAttribute("WeakpointMultiplier") ~= nil) and CharacterCollisionRay.Instance:GetAttribute("WeakpointMultiplier") or 1))
task.delay(0.75, function() HitHumanoid:RemoveTag("BeenHit") end)
--Hit effects like explosions.
for i = 1, Properties.ContinuousDamage.AmountOfLoops or 1 do
Bullet.Anchored = true
DamageEnemy:FireServer(HitHumanoid, Properties.ContinuousDamage.Damage * ((Properties.LocationalDamage == true and CharacterCollisionRay.Instance:GetAttribute("WeakpointMultiplier") ~= nil) and CharacterCollisionRay.Instance:GetAttribute("WeakpointMultiplier") or 1))
task.wait(Properties.ContinuousDamage.WaitPerLoop)
end
Bullet.Anchored = false
if Bullet:GetAttribute("FollowsGravity") == true and Properties.MaxEnemiesToHit > 1 and HitHumanoid.Health > 0 and Properties.ContinuousDamage.AmountOfLoops > 0 then
Bullet.AssemblyLinearVelocity = Vector3.yAxis * Properties.Speed / 2
Bullet:SetAttribute("TimesRicocheted", Properties.MaxRicochets)
else Bullet:Destroy() end
if Bullet:GetAttribute("EnemiesHit") >= Properties.MaxEnemiesToHit then Bullet:Destroy() end
end
elseif not (game.CollectionService:HasTag(CharacterCollisionRay.Instance, "Bullet") or CharacterCollisionRay.Instance.Name == "Bullet") then
Bullet:Destroy()
end
end
end
end)
Bullet.Destroying:Connect(function()
Stepped:Disconnect()
end)
return Bullet
end
end
return ProjectileHandler
Basically i’m making a system which lets you create a bullet by sending a list of properties which the function uses. In properties, there are 3 ways bullets can interact with magnets. None: no interaction with magnets. Swarm: bullets swarm around the magnet until the magnet is destroyed and Circular: bullets spin around the magnet in a circle. what i want is for bullets to ricochet when colliding with walls and attracted by a magnet so they start rotating in the opposite direction, but i can never find the right way to detect collision. Ive tried raycasting and blockcasting, and even getting all objects tagged “Wall” and checking if the distance between the bullet and the object is less than 2, but no matter what i’ve tried it never works. is there something i’m missing?