I am making a gun turret which will fire bullets at any enemy aircraft that gets too close.
It works, but the body gyro rotates the entire aircraft which isn’t what I want. Help
Code:
Part = script.Parent
local model = script.Parent
local e = Instance.new('BodyGyro')
e.Parent = script.Parent
local engine = script.Parent
targets = workspace.japaneseTargets
local function destroyBullet(bullet)
bullet:Destroy()
end
local function FireGuns(target)
wait(1)
local bullet = Instance.new("Part")
bullet.Position = Part.Position
bullet.CanCollide = false
local v = Instance.new("BodyVelocity")
bullet.Orientation = Part.Orientation
bullet.Name = "JB"
v.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
v.Velocity = bullet.CFrame.LookVector * -500
v.Parent = bullet
bullet.Parent = workspace
bullet.Size = Vector3.new(1,1,1)
bullet.Material = "Neon"
bullet.BrickColor = BrickColor.new("Bright red")
delay(3,function() bullet:Destroy() end)
end
local function getTargets()
for v,t in pairs(workspace:GetDescendants()) do
local enemyPlane = t:FindFirstAncestor("USFighter")
local enemyBomber = t:FindFirstAncestor("USBomber")
local enemyHeavy = t:FindFirstAncestor("USHeavy")
if enemyPlane then
enemyPlane.Parent = targets
end
if enemyHeavy then
enemyHeavy.Parent = targets
end
if enemyBomber then
enemyBomber.Parent = targets
end
end
end
local function shoot(target)
if (script.Parent.Position - target.hemalurgicSpike.Position).magnitude < 501 then
FireGuns(target)
end
end
local function attack(target)
local origincframe = engine.BodyGyro.cframe
local dir = (script.Parent.Position - target.hemalurgicSpike.Position).unit
local spawnPos = script.Parent.Position
local pos = spawnPos + dir
engine:findFirstChild("BodyGyro").maxTorque = Vector3.new(10000,10000,10000)
engine:findFirstChild("BodyGyro").cframe = CFrame.new(pos, pos+dir)
shoot(target)
end
local function findNearestEnemy()
local target = nil
getTargets()
for i,v in pairs(targets:GetChildren()) do
if v:IsA("Model") then
local previousDistance = 99999
local distance = (script.Parent.Position - v.hemalurgicSpike.Position).magnitude
if distance < previousDistance and v.Health.Value > 0 then
previousDistance = distance
target = v
end
end
end
return target
end
local function shootAtEnemyPlanes()
wait(0.01)
local target = findNearestEnemy()
if target then
attack(target)
end
end
while true do
wait(0.01)
shootAtEnemyPlanes()
end
Using Motor6Ds or welds are usually the same thing, except Motor6Ds are used in animations and welds are more for stationary objects. Both work well for what you’re attempting to do. Basically you’d weld a part to the plane for the gun. Then make a joint part in that same area and weld the actual gun to that joint. Using CFrame:ToOrientation() you’d do what you were already doing to get the rotation to fire the gun, and get the X,Y and Z rotation and apply that to the joints weld to rotate the gun without moving the plane.
I get that this is kinda confusing and probably worded poorly so if you need more elaboration I can assist further
@hotpocket285 can I please have like an example for this? Right now I am trying to use orientation but unfortunately it always goes the wrong direction.
Code:
Part = script.Parent
local gun = script.Parent
targets = workspace.japaneseTargets
local function destroyBullet(bullet)
bullet:Destroy()
end
local function FireGuns(target)
wait(0.3)
local bullet = Instance.new("Part")
bullet.Position = gun.Position
bullet.CanCollide = false
local v = Instance.new("BodyVelocity")
bullet.Orientation = gun.Orientation
bullet.Name = "JB"
v.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
v.Velocity = bullet.CFrame.LookVector * -300
v.Parent = bullet
bullet.Parent = workspace
bullet.Size = Vector3.new(1.5,1.5,1.5)
bullet.Material = "Neon"
bullet.BrickColor = BrickColor.new("Bright red")
bullet.Touched:connect(function(part)
local plane = part:FindFirstAncestor("JapBomber")
if not plane then
bullet:Destroy()
end
end)
delay(3,function() bullet:Destroy() end)
end
local function getTargets()
for v,t in pairs(workspace:GetDescendants()) do
local enemyPlane = t:FindFirstAncestor("USFighter")
local enemyBomber = t:FindFirstAncestor("USBomber")
local enemyHeavy = t:FindFirstAncestor("USHeavy")
if enemyPlane then
enemyPlane.Parent = targets
end
if enemyHeavy then
enemyHeavy.Parent = targets
end
if enemyBomber then
enemyBomber.Parent = targets
end
end
end
local function shoot(target)
if (script.Parent.Position - target.hemalurgicSpike.Position).magnitude < 501 then
FireGuns(target)
end
end
local function attack(target)
local dir = (script.Parent.Position - target.MeshPart.Position).unit
local spawnPos = script.Parent.Position
local pos = spawnPos + dir
gun.Orientation = pos + dir
shoot(target)
end
local function findNearestEnemy()
local target = nil
getTargets()
for i,v in pairs(targets:GetChildren()) do
if v:IsA("Model") then
local previousDistance = 99999
local distance = (script.Parent.Position - v.hemalurgicSpike.Position).magnitude
if distance < previousDistance and v.Health.Value > 0 then
previousDistance = distance
target = v
end
end
end
return target
end
local function shootAtEnemyPlanes()
wait(0.01)
local target = findNearestEnemy()
if target then
attack(target)
end
end
while true do
wait(0.01)
shootAtEnemyPlanes()
end
So what you’re trying to do is get the turret to rotate to face the targets, correct? Is it an object or is it a moving vehicle? May I see what the turret you’re programming looks like? There may be an easier way to do this because I’m slightly confused of your current goal.
@hotpocket285
I have a bomber plane and it has a part named “DefensiveGun” on it’s back. I want the gun to shoot at any incoming enemy aircraft. The gun is just an invisible 1x1x1 square. I want it to fire bullets at incoming planes without turning the entire aircraft
You can leave your code the same and replace the weld with a hinge. A hinge should (in theory) let the turret rotate freely without moving the rest of the ship with it.
Using a motor6d is pretty easy once you get to know how to use it. All you need to do is get the current lookvector and find the new lookvector you want to look at. Using this method(you can look through tons of topics on the forum);
local a = Vector3.new(0,0,1) -- first position
local b = Vector3.new(0,1,0) -- second position
local angle = math.acos(a:Dot(b)/(a.Magnitude*b.Magnitude))
-- after you will need to put it into a cframe
motor6d.C0 = motor6d.C0*CFrame.Angles(0,0,angle) -- choose whatever axis depending on where you want to change it.
Part = script.Parent
local gun = script.Parent
targets = workspace.japaneseTargets
local function destroyBullet(bullet)
bullet:Destroy()
end
local function FireGuns(target)
wait(0.3)
local bullet = Instance.new("Part")
bullet.Position = gun.Position
bullet.CanCollide = false
local v = Instance.new("BodyVelocity")
bullet.Name = "JB"
v.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
v.Velocity = bullet.CFrame.LookVector * -300
v.Parent = bullet
bullet.Parent = workspace
bullet.Size = Vector3.new(1.5,1.5,1.5)
bullet.Material = "Neon"
bullet.BrickColor = BrickColor.new("Bright red")
bullet.Touched:connect(function(part)
local plane = part:FindFirstAncestor("JapBomber")
if not plane then
bullet:Destroy()
end
end)
delay(3,function() bullet:Destroy() end)
end
local function getTargets()
for v,t in pairs(workspace:GetDescendants()) do
local enemyPlane = t:FindFirstAncestor("USFighter")
local enemyBomber = t:FindFirstAncestor("USBomber")
local enemyHeavy = t:FindFirstAncestor("USHeavy")
if enemyPlane then
enemyPlane.Parent = targets
end
if enemyHeavy then
enemyHeavy.Parent = targets
end
if enemyBomber then
enemyBomber.Parent = targets
end
end
end
local function shoot(target)
if (script.Parent.Position - target.hemalurgicSpike.Position).magnitude < 501 then
FireGuns(target)
end
end
local function attack(target)
local dir = (script.Parent.Position - target.MeshPart.Position).unit
local spawnPos = script.Parent.Position
local pos = spawnPos + dir
local a = Vector3.new(pos)
local b = Vector3.new(dir)
local angle = math.acos(a:Dot(b)/(a.Magnitude*b.Magnitude))
-- after you will need to put it into a cframe
script.Parent.Motor6D.C0 = script.Parent.Motor6D.C0*CFrame.Angles(0,0,angle)
shoot(target)
end
local function findNearestEnemy()
local target = nil
getTargets()
for i,v in pairs(targets:GetChildren()) do
if v:IsA("Model") then
local previousDistance = 99999
local distance = (script.Parent.Position - v.hemalurgicSpike.Position).magnitude
if distance < previousDistance and v.Health.Value > 0 then
previousDistance = distance
target = v
end
end
end
return target
end
local function shootAtEnemyPlanes()
wait(0.01)
local target = findNearestEnemy()
if target then
attack(target)
end
end
while true do
wait(0.01)
shootAtEnemyPlanes()
end
This helps a lot actually. What I would do is clone the turret and name it something like “TurretJoint” then create a weld in the actual turret and set Part0 to the joint and Part1 to the turret. Then when you calculate your rotational angle that you’d normally put into the bodygyro. Take that CFrame and this:
local x,y,z = CFrame.new(pos, pos+dir):ToOrientation() -- Returns the entire rotational matrix of the CFrame in radians
[insertturretpartnamehere].Weld.C1 = CFrame.Angles(x,y,z)
Should rotate the turret exactly like a bodygyro but won’t alter your aircraft’s orientation as a whole. Of course you’d have to weld the Joint to the plane and remove the weld holding the turret to the plane as it’s welded to the joint now.
@hotpocket285 sorry about being annoying, but the thing says that weld is not a valid member of defensivegun which is annoying. Code:
Part = script.Parent
local gun = script.Parent
targets = workspace.japaneseTargets
local function destroyBullet(bullet)
bullet:Destroy()
end
local function FireGuns(target)
wait(1)
local bullet = Instance.new("Part")
bullet.Position = gun.Position
bullet.CanCollide = false
local v = Instance.new("BodyVelocity")
bullet.Name = "JB"
v.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
v.Velocity = bullet.CFrame.LookVector * -300
v.Parent = bullet
bullet.Parent = workspace
bullet.Size = Vector3.new(1.5,1.5,1.5)
bullet.Material = "Neon"
bullet.BrickColor = BrickColor.new("Bright red")
bullet.Touched:connect(function(part)
local plane = part:FindFirstAncestor("JapBomber")
if not plane then
bullet:Destroy()
end
end)
delay(3,function() bullet:Destroy() end)
end
local function getTargets()
for v,t in pairs(workspace:GetDescendants()) do
local enemyPlane = t:FindFirstAncestor("USFighter")
local enemyBomber = t:FindFirstAncestor("USBomber")
local enemyHeavy = t:FindFirstAncestor("USHeavy")
if enemyPlane then
enemyPlane.Parent = targets
end
if enemyHeavy then
enemyHeavy.Parent = targets
end
if enemyBomber then
enemyBomber.Parent = targets
end
end
end
local function shoot(target)
if (script.Parent.Position - target.hemalurgicSpike.Position).magnitude < 1001 then
FireGuns(target)
end
end
local function attack(target)
local dir = (script.Parent.Position - target.MeshPart.Position).unit
local spawnPos = script.Parent.Position
local pos = spawnPos + dir
local x,y,z = CFrame.new(pos, pos+dir):ToOrientation()
script.Parent.Weld.C1 = CFrame.Angles(x,y,z)
shoot(target)
end
local function findNearestEnemy()
local target = nil
getTargets()
for i,v in pairs(targets:GetChildren()) do
if v:IsA("Model") then
local previousDistance = 99999
local distance = (script.Parent.Position - v.hemalurgicSpike.Position).magnitude
if distance < previousDistance and v.Health.Value > 0 then
previousDistance = distance
target = v
end
end
end
return target
end
local function shootAtEnemyPlanes()
wait(0.01)
local target = findNearestEnemy()
if target then
attack(target)
end
end
while true do
wait(0.01)
shootAtEnemyPlanes()
end
@hotpocket285.
LOL Idk why I didn’t respond last time.
So I still have the same issue.
I have become a much stronger scripter now.
I use qPerfectionWeld and edited it so it wouldn’t effect my turret.
Turret looks like this.
So I have some welds right now in each part of the turret.
I just changed the CFrame, but it twichtches the plane each time it shoots.
wait(3.1)
local plane = script.Parent.Parent
if plane.Parent == workspace.RedPlanes then
targets = workspace.BluePlanes
bull = game:GetService("ReplicatedStorage").Ammo.JB
end
if plane.Parent == workspace.BluePlanes then
targets = workspace.BluePlanes
bull = game:GetService("ReplicatedStorage").Ammo.AB
end
local function FireGuns(angle)
for i,v in pairs(script.Parent:GetChildren()) do
if v:IsA("BasePart") and v.Name == "BulletPos" then
local bullet = bull:Clone()
bullet.Orientation = v.Orientation
bullet.Position = v.Position
bullet.Parent = workspace
wait(0.333)
end
end
end
local function findNearestEnemy()
local MaxDistance = 99999
local nearestEnemy = nil
for i, enemy in pairs(targets:GetChildren()) do
if enemy then
local distance = (plane.PrimaryPart.Position - enemy.PrimaryPart.Position).magnitude
if distance < MaxDistance and enemy.Health.Value > 0 and distance < 1500 then
nearestEnemy = enemy
MaxDistance = distance
end
end
end
return nearestEnemy
end
local function FindAngle(nearestEnemy)
local origincframe = plane.Engine.BodyGyro.cframe
local dir = (plane.PrimaryPart.Position - nearestEnemy.PrimaryPart.Position).unit
local spawnPos = plane.PrimaryPart.Position
local pos = spawnPos + dir
script.Parent.GunJoint1.CFrame = CFrame.new(pos, pos+dir)
end
while wait() do
local nearestEnemy = findNearestEnemy()
if nearestEnemy and nearestEnemy.PrimaryPart.Position.Y > script.Parent.PrimaryPart.Position.Y then
FindAngle(nearestEnemy)
FireGuns()
end
end
I know the problem it’s because every part in the turret is welded together, and turretjoint, “the black square” is welded to the plane.
When joint1’s cframe is changed, (joint1) is the circle
the whole plane’s cframe twitches,
Any idea how to fix this?
Yes, sorry about the bump but it’s still not fixed.