I’m trying to recreate the popular dodgeball gamemode from team fortress 2. Here’s some footage of what it looks like(not mine btw): [TF2 Dodgeball] Unleashing Chaos on the Dodgeball Court - YouTube
As you can see there is one or more rockets that will track a nearby player until they are air blasted away or they hit an object. I know the best way to handle rockets is on the server as it allows for easy sync between all clients and less things that can be exploited. The mock up I have right now is a module script that can create a rocket that follows an instances position. I used a align position for the rocket to point towards the target and a linear velocity that then goes in the direction of the rockets look vector multiplied by the speed of the rocket. Using constraints seems to be the best option as it allows for smooth movement that is handled by the server and doesn’t lag like if I tweened or lerped it. I also make sure to set the network owner to the server so no hackers can mess with the rocket. The issue I’m coming across is trying to figure out how to get accurate airblasting. I know that in tf2 when a rocket is airblasted its direction vector is oriented to go in the direction of the mouse position. I’ve tried looking online on how exactly the airblast functions in tf2 but have found nothing useful. I want it to be when its airblasted it doesn’t feel so linear and you should be able to flick the rocket with your airblast and it should affect the rockets path to the target. If anyone knows a good way to handle this or how tf2 handles your help would be greatly appreciated.
The code for my module script:
local Rocket = {}
Rocket.__index = Rocket
--Services
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Debris = game:GetService("Debris")
local TweenService = game:GetService("TweenService")
--Functions
function Rocket.new(rocketObj: BasePart | Model, parent: Instance, spawnPart: Instance, maxForce: number, responsiveness: number, rocketSpeed: number)
local newRocket = {}
setmetatable(newRocket, Rocket)
--Clone rocket object
newRocket.Rocket = rocketObj:Clone()
newRocket.Rocket.Parent = parent
newRocket.Rocket:SetNetworkOwner(nil)
newRocket.Rocket.Position = spawnPart.Position
newRocket.Rocket.Anchored = false
--Create attachment and velocitys
newRocket.Attachment = Instance.new("Attachment")
newRocket.Attachment.Parent = newRocket.Rocket
newRocket.LinearVelo = Instance.new("LinearVelocity")
newRocket.LinearVelo.Parent = newRocket.Rocket
newRocket.LinearVelo.Attachment0 = newRocket.Attachment
newRocket.LinearVelo.MaxForce = maxForce
newRocket.LinearVelo.RelativeTo = Enum.ActuatorRelativeTo.World
newRocket.LinearVelo.VelocityConstraintMode = Enum.VelocityConstraintMode.Vector
newRocket.LinearVelo.VectorVelocity = Vector3.new(0, 0, 0)
newRocket.AlignAng = Instance.new("AlignOrientation")
newRocket.AlignAng.Parent = newRocket.Rocket
newRocket.AlignAng.Mode = Enum.OrientationAlignmentMode.OneAttachment
newRocket.AlignAng.Attachment0 = newRocket.Attachment
newRocket.AlignAng.MaxAngularVelocity = maxForce
newRocket.AlignAng.MaxTorque = maxForce
newRocket.AlignAng.Responsiveness = responsiveness
newRocket.AlignAng.CFrame = spawnPart.CFrame
--Set speed and current target as start position
newRocket.Target = spawnPart
newRocket.Speed = rocketSpeed
newRocket.DefaultResponsiveness = responsiveness
return newRocket
end
function Rocket:Launch()
self.UpdateConnection = RunService.Heartbeat:Connect(function(dt)
if self.Target and self.Target.Parent ~= nil then
local collisionTable = self.Rocket:GetTouchingParts()
for index, part in pairs(collisionTable) do
if part:IsA("BasePart") then
self:Explode()
end
end
local distance = (self.Rocket.Position - self.Target.Position).Magnitude
if distance <= 5 then
self.AlignAng.Responsiveness = 200
else
self.AlignAng.Responsiveness = self.DefaultResponsiveness
end
self.AlignAng.CFrame = CFrame.lookAt(self.Rocket.Position, self.Target.Position)
self.LinearVelo.VectorVelocity = self.Rocket.CFrame.LookVector * self.Speed
end
end)
end
function Rocket:Explode()
self.Rocket:Destroy()
self:Destroy()
end
function Rocket:SetTarget(targetPart: Instance)
self.Target = targetPart
end
function Rocket:AirBlast(direction: Vector3, newTarget)
--self:SetTarget(newTarget)
end
function Rocket:AddSpeed(amount: number)
self.Speed += amount
end
function Rocket:Destroy()
if self.UpdateConnection then
self.UpdateConnection:Disconnect()
end
self = nil
end
return Rocket