How to make something not repeat something if it's already doing it?

I am working on a pvz game and i’ve just programed the Peashooter’s function but whenever a new zombie steps on the sidewalk, it generates a new stream of peas for that zombie (view below) i need to find a way to make it so that it only uses the same stream of peas it’s currently using on every zombie that touches the sidewalk until they are all killed and start shooting again when a new zombie touches the sidewalk i would also appreciate if someone could help me figure out how to code it so that it only shoots in whatever lane (1-5 or bigger) it is in.
robloxapp-20250126-1844227.wmv (630.1 KB)

2 Likes

I recommend making the peashooters shoot in the same frequency while the lane isn’t empty. It shouldn’t shoot depending on how many zombies there are, but shoot depending on if there are zombies in the lane it is shooting. Also, could you show the script when you post on the Scripting Support category? Would be nice :slight_smile:

Kind of a late reply now that I think about it…

1 Like

here’s the coding: I had ai write it since i have very little coding experience:

local TweenService = game:GetService(“TweenService”)
local Peashooter = script.Parent
local Humanoid = Peashooter:FindFirstChildOfClass(“Humanoid”)
local Animator = Humanoid:FindFirstChildOfClass(“Animator”)
local PeaTemplate = workspace:FindFirstChild(“Pea”)
local Sidewalk = workspace:FindFirstChild(“SIdewalk”)
local ShootInterval = 1.5
local Damage = 20
local ShootingAnimationId = “rbxassetid://108587954936313”
local IdleAnimationId = “rbxassetid://71646474698213” – Replace with actual idle animation asset ID

local activeZombies = {}
local isShooting = false – Flag to track if Peashooter is currently shooting

– Associate each Peashooter with a specific lane
local lane = Peashooter:FindFirstChild(“Lane”) – Assuming each Peashooter has a child named “Lane” indicating its lane

local function playAnimation()
local idleAnimation = Instance.new(“Animation”)
idleAnimation.AnimationId = IdleAnimationId
local idleTrack = Animator:LoadAnimation(idleAnimation)
idleTrack.Looped = true
idleTrack:Play()

local shootingAnimation = Instance.new("Animation")
shootingAnimation.AnimationId = ShootingAnimationId
local shootingTrack = Animator:LoadAnimation(shootingAnimation)
shootingTrack.Looped = true
shootingTrack:Play()

end

local function animateHeadAndParts()
local head = Peashooter:FindFirstChild(“FakeHead”)
local hole = Peashooter:FindFirstChild(“Hole”)
local mouth = Peashooter:FindFirstChild(“Mouth”)
if head and hole and mouth then
local originalHeadSize = head.Size
local targetHeadSize = originalHeadSize + Vector3.new(0, 0, originalHeadSize.Z)

    local originalHoleSize = hole.Size
    local targetHoleSize = originalHoleSize + Vector3.new(0, 0, originalHoleSize.Z * 1.1)  -- Expand along Z-axis

    local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut)
    local headTween = TweenService:Create(head, tweenInfo, {Size = targetHeadSize})
    local mouthTween = TweenService:Create(mouth, tweenInfo, {CFrame = mouth.CFrame * CFrame.new(0, 0, 1)})
    local holeTween = TweenService:Create(hole, tweenInfo, {Size = targetHoleSize})

    headTween:Play()
    mouthTween:Play()
    holeTween:Play()

    headTween.Completed:Connect(function()
        local returnHeadTween = TweenService:Create(head, tweenInfo, {Size = originalHeadSize})
        local returnHoleTween = TweenService:Create(hole, tweenInfo, {Size = originalHoleSize})
        returnHeadTween:Play()
        returnHoleTween:Play()
    end)
end

end

local function blink()
local eyes = Peashooter:FindFirstChild(“Eyes”)
local blink1 = Peashooter:FindFirstChild(“Blink 1”)
local blink2 = Peashooter:FindFirstChild(“Blink 2”)
if eyes and blink1 and blink2 then
eyes.Transparency = 1
blink1.Transparency = 0
task.wait(0.1)
blink1.Transparency = 1
blink2.Transparency = 0
task.wait(0.1)
blink2.Transparency = 1
eyes.Transparency = 0
end
end

local function shootPea(zombieHumanoid)
if not PeaTemplate then
print(“PeaTemplate not found”)
return
end
local pea = PeaTemplate:Clone()
local mouth = Peashooter:FindFirstChild(“Mouth”)
if mouth and zombieHumanoid then
print(“Shooting pea at zombie”)
pea.CFrame = mouth.CFrame
pea.Parent = workspace

    local direction = mouth.CFrame.LookVector  -- Use the direction the mouth is facing
    local bodyVelocity = Instance.new("BodyVelocity")
    bodyVelocity.Velocity = direction * 50
    bodyVelocity.MaxForce = Vector3.new(1e5, 1e5, 1e5)
    bodyVelocity.Parent = pea

    pea.Touched:Connect(function(hit)
        if hit:IsDescendantOf(zombieHumanoid.Parent) then
            local zombieHumanoid = hit.Parent:FindFirstChildOfClass("Humanoid")
            if zombieHumanoid then
                zombieHumanoid:TakeDamage(Damage)
                pea:Destroy()
            end
        end
    end)

    task.delay(5, function()
        if pea and pea.Parent then
            pea:Destroy()
        end
    end)
end
blink()  -- Blink whenever the Peashooter shoots

end

local function onSidewalkTouched(other)
local humanoid = other.Parent:FindFirstChildOfClass(“Humanoid”)
if humanoid and other.Parent.Name == “Zombie” then
print(“Zombie detected on sidewalk”)
if not activeZombies[humanoid] then
activeZombies[humanoid] = true
if not isShooting then
isShooting = true
task.spawn(function()
while next(activeZombies) do
animateHeadAndParts() – Call animation once per cycle
for zombieHumanoid in pairs(activeZombies) do
if zombieHumanoid.Health > 0 then
shootPea(zombieHumanoid)
else
activeZombies[zombieHumanoid] = nil
end
end
task.wait(ShootInterval)
end
isShooting = false
end)
end
end
else
print(“Touched by non-zombie or incorrect humanoid”)
end
end

local function checkLaneForZombies()
if lane then
local zombiesInLane = lane:GetChildren()
local hasZombies = false
for _, zombie in ipairs(zombiesInLane) do
if zombie:IsA(“Model”) and zombie:FindFirstChildOfClass(“Humanoid”) then
hasZombies = true
activeZombies[zombie:FindFirstChildOfClass(“Humanoid”)] = true
end
end
if not hasZombies then
print("No zombies in lane: " … lane.Name)
– Logic to stop shooting if no zombies are detected
activeZombies = {}
isShooting = false
end
end
end

Sidewalk.Touched:Connect(onSidewalkTouched)
playAnimation()

– Periodically check the specific lane for zombies
task.spawn(function()
while true do
checkLaneForZombies()
task.wait(2) – Check every 2 seconds
end
end)

– Randomly blink at intervals
task.spawn(function()
while true do
task.wait(math.random(5, 10)) – Randomly wait between 5 to 10 seconds
blink()
end
end)

Hey im just gona say it might takes days to debug this script from how long it is

The AI here has associated every peashooter with a specific lane. Wouldn’t it be easier to just throw projectiles at the enemies going through a straight line starting from the peashooter?

…And if you insist on making a Threepeater, you could just make it fabricate 3 projectiles and lead two of them to the adjacent lanes.

What I could understand from this is that the peashooter makes peas specifically made for zombies. This causes it to have it make peas at intervals disconnected from the peashooter themselves, and actually parents it to the zombie. Make it so that it only shoots peas while it has detected a zombie in front of it, and just make it start shooting.

TL;DR: The AI overcomplicated the process, so just make the peashooter shoot when it detects a zombie in front of it. Doesn’t have to be whatever advanced stuff the AI was trying to do :sweat_smile:

i don’t know how to i have very little scripting experience

i would have to rewrite the code wouldn’t i? I’d appreciate help doing so

Yup, unfortunately. I might be able to fix it if you give me a photo of the explorer though, but I don’t consider myself a good programmer all that much either. Usually I write about 50 lines of code at most so I’m kinda underexperienced too lol

example of an explorer photo:
Ekran görüntüsü 2024-08-13 102819

pea