This tank AI attacks NPCS but also attacks players. How do I add players onto the ally list on this tank AI?
local clone = script.Parent:Clone()
--Latency Fix
for i,v in ipairs(script.Parent:GetDescendants()) do
if v:IsA("BasePart") then
if v:CanSetNetworkOwnership() == true then
v:SetNetworkOwner(nil)
end
end
end
--Main body
local myHuman = script.Parent.Humanoid
local myHead = script.Parent.Head
local myTorso = script.Parent.Torso
local engine = script.Parent.Engine
local bodyBG = myTorso.BodyGyro
local status = script.Parent.Status
local bodyColor = script.Parent.TankColor
--Gun parts
local gunBackMain = script.Parent.GunBackMain
local gunBase = script.Parent.GunBase
local gunBG = gunBackMain.BodyGyro
local barrel = script.Parent.Barrel
local gunTip = script.Parent.GunBarrelTip
local gunBarrelTube = script.Parent.GunBarrelTube
local gunBarrelTube2 = script.Parent.GunBarrelTube2
local barrelWeld = script.Parent.BarrelWeld
local smokeSpot = barrel.SmokeSpot
local flash = barrel.Flash
local barrelSmoke = smokeSpot.Smoke
local allies = {script.Parent.Name, "Davarian Marine"}
--Sounds
local shootSound = barrel.Shoot
local engineSound = engine:WaitForChild("EngineNoise")
local explosionSound = engine:WaitForChild("Explosion")
local sight = 200
local detection = 3000
local failedPaths = 0
local touchedEvents = {}
local pathArgs = {
["AgentRadius"] = 16,
["AgentHeight"] = 13,
["AgentCanJump"] = false
}
local gunCool = true
local pathBlocked = false
--Inital Adjustments
engineSound:Play()
bodyBG.CFrame = myTorso.CFrame
gunBG.CFrame = gunBackMain.CFrame
barrelSmoke.Parent = nil
--Engine pitch adjuster
spawn(function()
repeat
wait(0.1)
if myTorso.Velocity.Magnitude > 5 or myTorso.RotVelocity.Magnitude > 0.1 then
game:GetService("TweenService"):Create(engineSound,TweenInfo.new(0.2),{PlaybackSpeed = 0.35}):Play()
else
game:GetService("TweenService"):Create(engineSound,TweenInfo.new(0.2),{PlaybackSpeed = 0.3}):Play()
end
until myHuman.Health < 1
end)
--Set team color
for i,v in ipairs(script.Parent:GetDescendants()) do
if v:IsA("BasePart") and v.Name ~= "Headlight" and v.Name ~= "Status" then
v.BrickColor = bodyColor.Value
end
end
function checkDist(part1,part2)
return (part1.Position - part2.Position).Magnitude
end
function checkForObstacles(direction)
for i = -13, 13, 0.5 do
local ray
if direction == "front" then
ray = Ray.new((myTorso.CFrame * CFrame.new(i,1,-16)).Position, myTorso.CFrame.LookVector * 5)
elseif direction == "back" then
ray = Ray.new((myTorso.CFrame * CFrame.new(i,0,13)).Position, -myTorso.CFrame.LookVector * 5)
elseif direction == "right" then
ray = Ray.new((myTorso.CFrame * CFrame.new(13,-0.5,i)).Position, myTorso.CFrame.RightVector * 5)
elseif direction == "left" then
ray = Ray.new((myTorso.CFrame * CFrame.new(-13,-0.5,i)).Position, -myTorso.CFrame.RightVector * 5)
else
print("Invalid direction suppled")
ray = Ray.new(Vector3.new(0,0,0),Vector3.new(0,0,0))
end
local hit,pos = workspace:FindPartOnRayWithIgnoreList(ray,{script.Parent})
if hit then
if hit:IsGrounded() or hit.Anchored then
return true
end
end
end
return false
end
--Collision detection logic
for _,v in ipairs(script.Parent:GetDescendants()) do
if v:IsA("BasePart") and v.Name ~= "Wheel" and v.Name ~= "Wheel Lip" then
local db = true
local touch = v.Touched:Connect(function(obj)
if db == true then
db = false
if obj.Parent and not obj:IsDescendantOf(script.Parent) then
local human = obj.Parent:FindFirstChild("Humanoid")
if not human and obj.Position.Y >= myTorso.Position.Y - 0.5 then
--Break small objects that are in the way
if obj:IsGrounded() and obj:GetMass() < 100 and not obj.Anchored then
obj:BreakJoints()
elseif obj:IsGrounded() or obj.Anchored then
if checkForObstacles("front") then
backaway(obj)
end
end
elseif human then
if human.Health > 0 then
for i,x in ipairs(allies) do
if obj.Parent.Name == x then
if checkForObstacles("front") then
backaway(obj)
end
break
elseif i == #allies then
if v.Velocity.Magnitude > 15 then
human:ChangeState(Enum.HumanoidStateType.Ragdoll)
human:TakeDamage(math.random(20,30))
end
end
end
end
end
wait(0.2)
db = true
end
end
end)
table.insert(touchedEvents,touch)
end
end
function changeStatus(color3)
game:GetService("TweenService"):Create(status,TweenInfo.new(1),{Color = color3}):Play()
end
function backaway(target)
pathBlocked = true
changeStatus(Color3.fromRGB(110, 153, 202)) --Medium blue status
for i = 1, 8 do
wait(0.1)
myHuman:Move(-myTorso.CFrame.LookVector)
end
myHuman:Move(Vector3.new(0,0,0))
pathBlocked = false
end
function getUnstuck()
changeStatus(Color3.fromRGB(255, 102, 204))--Pink status
if not checkForObstacles("front") then
myHuman:Move(myTorso.CFrame.LookVector)
elseif not checkForObstacles("back") then
myHuman:Move(-myTorso.CFrame.LookVector)
elseif not checkForObstacles("right") then
game:GetService("TweenService"):Create(bodyBG,TweenInfo.new(0.5),{CFrame = myTorso.CFrame * CFrame.Angles(0,math.rad(-90),0)}):Play()
wait(0.5)
myHuman:Move(myTorso.CFrame.LookVector)
elseif not checkForObstacles("left") then
game:GetService("TweenService"):Create(bodyBG,TweenInfo.new(0.5),{CFrame = myTorso.CFrame * CFrame.Angles(0,math.rad(90),0)}):Play()
wait(0.5)
myHuman:Move(myTorso.CFrame.LookVector)
end
wait(0.5)
myHuman:Move(Vector3.new(0,0,0))
end
function checkSight(target)
local ray = Ray.new(myTorso.Position,(target.Position - myTorso.Position).Unit * sight)
local hit,position = workspace:FindPartOnRayWithIgnoreList(ray,{script.Parent})
local ray2 = Ray.new(gunBackMain.Position,(target.Position - gunBackMain.Position).Unit * sight)
local hit2,position2 = workspace:FindPartOnRayWithIgnoreList(ray2,{script.Parent})
if hit and hit2 then
if hit:IsDescendantOf(target.Parent) and hit2:IsDescendantOf(target.Parent) then
return true
end
end
return false
end
function findTarget()
local dist = detection
local target = nil
local potentialTargets = {}
local seeTargets = {}
--Find potential targets
for _,v in ipairs(workspace:GetChildren()) do
local human = v:FindFirstChild("Humanoid")
local torso = v:FindFirstChild("HumanoidRootPart") or v:FindFirstChild("Torso")
if human and torso and v ~= script.Parent then
if (myTorso.Position - torso.Position).magnitude < dist and human.Health > 0 then
for i,x in ipairs(allies) do
if x == v.Name then
break
elseif i == #allies then
table.insert(potentialTargets,torso)
end
end
end
end
end
--Check potential targets for targets within sight
if #potentialTargets > 0 then
for i,v in ipairs(potentialTargets) do
if checkSight(v) then
table.insert(seeTargets,v)
end
end
end
--If we cant see any targets find a target that we can move to
if #potentialTargets > 0 and #seeTargets == 0 then
for i,v in ipairs(potentialTargets) do
if (myTorso.Position - v.Position).magnitude < dist and math.abs(myTorso.Position.Y - v.Position.Y) < 2 then
local path = game:GetService("PathfindingService"):CreatePath(pathArgs)
target = v
dist = (myTorso.Position - v.Position).magnitude
end
end
end
--If we have targets within sight target the cloest one
if #seeTargets > 0 then
dist = sight
for i,v in ipairs(seeTargets) do
if (myTorso.Position - v.Position).magnitude < dist then
target = v
dist = (myTorso.Position - v.Position).magnitude
end
end
end
return target
end
function rotate(target)
if checkDist(target,myTorso) > 1.5 then
local look = Vector3.new(target.Position.X,myTorso.Position.Y,target.Position.Z)
local lookDiff = (myTorso.CFrame.lookVector - CFrame.new(myTorso.Position,look).lookVector).Magnitude
game:GetService("TweenService"):Create(bodyBG,TweenInfo.new(lookDiff),{CFrame = CFrame.new(myTorso.Position,look)}):Play()
wait(lookDiff)
end
end
function pathToTarget(target)
pathBlocked = false
changeStatus(Color3.fromRGB(213, 115, 61)) --Neon orange status
local path = game:GetService("PathfindingService"):CreatePath(pathArgs)
path:ComputeAsync(myTorso.Position, target.Position)
local waypoints = path:GetWaypoints()
if path.Status == Enum.PathStatus.Success then
for i,v in ipairs(waypoints) do
spawn(function() rotate(v) end)
local timer = 1
local success = true
repeat
wait()
myHuman:Move(myTorso.CFrame.LookVector)
timer = timer + 1
if timer > 40 then
success = false
break
end
until checkDist(myTorso,v) < 4
if success == false or pathBlocked == true then
if pathBlocked == true then
myHuman:Move(Vector3.new(0,0,0))
wait(2)
end
break
elseif (waypoints[#waypoints].Position - target.Position).magnitude > 20 then
break
elseif not target.Parent or target.Parent.Humanoid.Health <= 0 then
break
end
if i % 5 == 0 then
if checkSight(target) and checkDist(myTorso,target) < 50 then
break
end
end
end
myHuman:Move(Vector3.new(0,0,0))
else
failedPaths = failedPaths + 1
if failedPaths > 10 then
getUnstuck()
end
end
end
function shoot(target)
if gunCool then
shootSound:Play()
local missile = Instance.new("Part")
missile.CanCollide = false
missile.Size = Vector3.new(0.4,0.4,2.5)
missile.Material = Enum.Material.Neon
missile.BrickColor = BrickColor.new("New Yeller")
missile.Touched:Connect(function(obj)
if not obj:IsDescendantOf(script.Parent) then
local human = obj.Parent:FindFirstChild("Humanoid")
if human then
human:TakeDamage(100)
for i,v in ipairs(obj.Parent:GetChildren()) do
if v:IsA("BasePart") then
local f = Instance.new("Fire",v)
f.Size = v:GetMass() / 2
game:GetService("TweenService"):Create(f,TweenInfo.new(3),{Heat = 0, Size = 0}):Play()
delay(3,function()
f.Enabled = false
game:GetService("Debris"):AddItem(f,0.5)
end)
end
end
end
if obj:GetMass() < 100 then
local f = Instance.new("Fire",obj)
f.Size = obj:GetMass() / 2
game:GetService("TweenService"):Create(f,TweenInfo.new(3),{Heat = 0, Size = 0}):Play()
delay(3,function()
f.Enabled = false
game:GetService("Debris"):AddItem(f,0.5)
end)
end
local x = Instance.new("Explosion",workspace)
x.Position = missile.Position
missile:Destroy()
game:GetService("Debris"):AddItem(x,0.5)
end
end)
missile.Parent = workspace
missile:SetNetworkOwner(nil)
missile.CFrame = barrel.CFrame
local bv = Instance.new("BodyVelocity",missile)
bv.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
bv.Velocity = barrel.CFrame.LookVector * 200
local s = Instance.new("Sound",missile)
s.Volume = 1
s.PlaybackSpeed = 1.5
s.Looped = true
s.SoundId = "rbxasset://sounds/Rocket whoosh 01.wav"
s:Play()
local s = Instance.new("Sound",missile)
s.Volume = 1
s.SoundId = "rbxassetid://142070127"
s.PlayOnRemove = true
flash.Enabled = true
delay(0.1,function()
flash.Enabled = false
end)
local a1 = Instance.new("Attachment",missile)
a1.Position = Vector3.new(0,0.2,0)
local a2 = Instance.new("Attachment",missile)
a2.Position = Vector3.new(0,-0.2,0)
local t = Instance.new("Trail",missile)
t.Attachment0 = a1
t.Attachment1 = a2
t.Color = ColorSequence.new(missile.Color)
t.WidthScale = NumberSequence.new(1,0)
t.Lifetime = 0.5
barrelSmoke.Parent = smokeSpot
game:GetService("TweenService"):Create(barrelSmoke,TweenInfo.new(0.2),{Opacity = 0.5}):Play()
gunCool = false
delay(1,function()
game:GetService("TweenService"):Create(barrelSmoke,TweenInfo.new(1),{Opacity = 0}):Play()
wait(1)
barrelSmoke.Parent = nil
gunCool = true
end)
--Give some recoil
for i=0,1,0.4 do
barrelWeld.Part1 = nil
gunBarrelTube.CFrame = gunBarrelTube.CFrame:lerp(gunBarrelTube.CFrame * CFrame.new(0,0.5,0),i)
barrelWeld.Part1 = gunBarrelTube
wait()
end
for i=0,1,0.4 do
barrelWeld.Part1 = nil
gunBarrelTube.CFrame = gunBarrelTube.CFrame:lerp(gunBarrelTube.CFrame * CFrame.new(0,-0.5,0),i)
barrelWeld.Part1 = gunBarrelTube
wait()
end
end
end
function aim(target)
changeStatus(Color3.fromRGB(255, 0, 0)) --Really red status
local lookDiff = (gunBG.CFrame.LookVector - CFrame.new(gunBackMain.CFrame.p,target.CFrame.p).LookVector).Magnitude
game:GetService("TweenService"):Create(gunBG,TweenInfo.new(lookDiff),{CFrame = CFrame.new(gunBackMain.CFrame.p,target.CFrame.p)}):Play()
end
function turretRestore()
local lookDiff = (gunBG.CFrame.LookVector - myTorso.CFrame.LookVector).Magnitude
game:GetService("TweenService"):Create(gunBG,TweenInfo.new(lookDiff),{CFrame = myTorso.CFrame}):Play()
end
function targetLocked(target)
local ray = Ray.new(gunBackMain.Position,gunBackMain.CFrame.LookVector * 200)
local hit,position = workspace:FindPartOnRayWithIgnoreList(ray,{script.Parent})
if hit then
if hit:IsDescendantOf(target.Parent) then
return true
elseif (target.Position - position).Magnitude < 7 then
return true
end
end
return false
end
local vitalParts = {"GunBase","Wheel","Wheel","Wheel","Wheel"}
local gunVitalParts = {"Barrel","GunBarrelTip","GunBarrelTube","GunBarrelTube2"}
function checkVitalParts()
local tankBits = myTorso:GetConnectedParts(true)
local vitalCount = 0
for _,v in ipairs(tankBits) do
for _,x in ipairs(vitalParts) do
if x == v.Name then
vitalCount = vitalCount + 1
break
end
end
end
if vitalCount < #vitalParts then
myHuman.Health = 0
end
local gunBits = gunBackMain:GetConnectedParts(true)
vitalCount = 0
for _,v in ipairs(gunBits) do
for _,x in ipairs(gunVitalParts) do
if x == v.Name then
vitalCount = vitalCount + 1
break
end
end
end
if vitalCount < #gunVitalParts then
myHuman.Health = 0
end
end
local oldHealth = myHuman.Health
myHuman.HealthChanged:Connect(function(health)
if health < oldHealth then
checkVitalParts()
end
end)
myHuman.Died:Connect(function()
engineSound:Stop()
explosionSound:Play()
engine.CanCollide = true
for i,v in ipairs(touchedEvents) do
v:Disconnect()
end
for i,v in ipairs(engine:GetConnectedParts()) do
v.Velocity = Vector3.new(math.random(20),math.random(5,10),math.random(20))
if math.random(20) == 1 then
local f = Instance.new("Fire",v)
f.Size = v:GetMass()
end
end
local x = Instance.new("Explosion",engine)
x.Position = engine.Position
for i,v in ipairs(script.Parent:GetDescendants()) do
if v:IsA("WeldConstraint") or v:IsA("PointLight") then
v:Destroy()
elseif v:IsA("BasePart") then
if v.Material == Enum.Material.Neon then
v.Material = Enum.Material.SmoothPlastic
end
end
end
wait(3)
for i,v in ipairs(script.Parent:GetDescendants()) do
if v:IsA("BasePart") or v:IsA("Decal") then
game:GetService("TweenService"):Create(v,TweenInfo.new(0.5),{Transparency = 1}):Play()
end
end
wait(0.5)
clone.Parent = workspace
script.Parent:Destroy()
end)
local mainTarget = nil
local targetHuman = nil
--Gun logic controller
spawn(function()
while wait(0.1) do
if mainTarget then
if checkSight(mainTarget) and checkDist(myTorso,mainTarget) > 25 then
aim(mainTarget)
if gunCool and mainTarget and targetLocked(mainTarget) and mainTarget.Parent then
shoot(mainTarget)
end
else
turretRestore()
end
else
turretRestore()
end
if myHuman.Health <= 0 then
break
end
end
end)
function main()
pathBlocked = false
if mainTarget then
if not checkSight(mainTarget) or not mainTarget.Parent then
mainTarget = nil
end
end
if not mainTarget or targetHuman.Health <= 0 then
mainTarget = findTarget()
if mainTarget then
targetHuman = mainTarget.Parent.Humanoid
end
end
if mainTarget then
--Ram target if close enough
if (myTorso.Position - mainTarget.Position).magnitude < 35 and not pathBlocked then
changeStatus(Color3.fromRGB(255, 176, 0)) --Deep orange status
rotate(mainTarget)
repeat
myHuman:Move(myTorso.CFrame.LookVector)
wait(0.1)
spawn(function() rotate(mainTarget) end)
until targetHuman.Health <= 0 or myTorso.Velocity.Magnitude < 1 or
(myTorso.Position - mainTarget.Position).Magnitude > 35 or pathBlocked
if not pathBlocked then
myHuman:Move(Vector3.new(0,0,0))
end
elseif checkDist(myTorso,mainTarget) > 120 or not checkSight(mainTarget) then
pathToTarget(mainTarget)
end
end
end
while wait(0.2) do
checkVitalParts()
if myHuman.Health <= 0 then
break
end
main()
end