I had an issue with vehicles sharing network ownership that I just managed to solve with weld manipulation instead of relying on constraints. However, this has introduced some new problems:
- The turret CFrame seems correct when the vehicle spawns (image 1), but as soon as the vehicle moves to a different orientation, the CFrame becomes incorrect (image 2). It looks like it’s an issue of object space vs. world space, but I’ve tried converting
aimCFrame
both ways at every step of the process and it’s only flipped the polarity I have to turn the axes. It hasn’t actually solved the issue of the welds’ orientations being based on the vehicle being at standstill.
CLIENT SCRIPT:
character.Humanoid.Seated:Connect(function(active, seatPart)
--...
--...
elseif seatPart.Name == "TurretSeat" then
local vehicle = seatPart.Parent
local turretBarrel = vehicle.TurretBarrel
local turretBody = vehicle.TurretBody
local aimer = turretBarrel.Aimer
weldUpDown = turretBody.WeldUpDown
weldLeftRight = turretBody.WeldLeftRight
local offsetUD = weldUpDown.C0
local offsetLR = weldLeftRight.C0
local seats = getSeats(vehicle:GetChildren())
queryVehicleInfo:FireServer(vehicle)
inputStart = UIS.InputBegan:Connect(function(input, GPE)
if GPE then return end
if input.UserInputType == Enum.UserInputType.MouseButton1 and firing == false then
firing = true
while firing do
fire(vehicle, FIRE_SPEED, FIRE_RANGE, getOccupants(seats))
fireTurret:FireServer(vehicle)
task.wait(1 / FIRE_RATE)
end
end
end)
inputEnd = UIS.InputEnded:Connect(function(input, GPE)
if GPE then return end
if input.UserInputType == Enum.UserInputType.MouseButton1 then
firing = false
end
end)
sitConnection = run.RenderStepped:Connect(function()
local aimCFrame
local mousePosition = UIS:GetMouseLocation()
local mouseRay = workspace.Camera:ViewportPointToRay(mousePosition.X, mousePosition.Y)
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.FilterDescendantsInstances = {vehicle, getOccupants(seats)}
local raycastResult = workspace:Raycast(mouseRay.Origin, mouseRay.Direction * 1000, raycastParams)
if raycastResult then
aimCFrame = CFrame.lookAt(aimer.WorldPosition, raycastResult.Position)
else
aimCFrame = CFrame.new(Vector3.new(0, 0, 0), mouseRay.Direction)
end
local x, y, z = aimCFrame:ToEulerAnglesYXZ()
weldUpDown.C0 = offsetUD * CFrame.Angles(-x, 0, 0)
weldLeftRight.C0 = offsetLR * CFrame.Angles(0, y, 0)
aimTurret:FireServer(vehicle, weldUpDown.C0, weldLeftRight.C0)
end)
end
end
end)
- Since the turret now uses welds, both movement and firing are now done on the client side via remote events. However, it’s tough to properly record bullet hits because the bullet gets copied to all clients, causing multiple hits to be registered depending on the number of players. For example, a bullet that deals 50 damage server-side, with 2 players, would deal 100 damage, with 4 players 200 damage, etc. One idea I had for fixing this was to track the number of clients that a specific bullet registered hits on and only deal damage if it’s above a specific number, but I’m told this would create thousands of problems regarding different pings and StreamingEnabled. To me, the obvious, somewhat lazy solution would be only to register the bullet hit by the player who fired it, but I imagine this could be easily exploited. I would appreciate any pointers in finding a solution here; even if they’re completely abstract, I could probably translate them to code.
Please let me know if I need to provide any more information.