#NPC System

1 messages · Page 1 of 1 (latest)

worldly geyser
#

Alrighty I'm back!
I created this system where knights spawn once you press this textbutton in the corner and it costs the player 200 coins

the knights go around the base (which is assigned in a different script)

what's happening is the script isn't spawning the knights

for my textbutton script, i have it so that when the button is pressed it fires a remote event called BuyKnight and then it starts the other script

CURRENT SCRIPT BELOW

#
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local KnightTemplate = ReplicatedStorage:WaitForChild("Knight")
local BuyKnightEvent = ReplicatedStorage:WaitForChild("BuyKnight")
local baseFolder = workspace:WaitForChild("Bases")

-- Knight settings
local KNIGHT_COST = 200
local DETECTION_RADIUS = 15
local DAMAGE = 10
local ATTACK_COOLDOWN = 2

-- Maps userId -> their base (update this from your base assignment system)
local playerBaseMap = {}

-- Utility: Find the closest enemy player
local function findNearestEnemy(knight, ownerPlayer)
    local closestPlayer = nil
    local shortestDistance = DETECTION_RADIUS

    for _, player in pairs(Players:GetPlayers()) do
        if player ~= ownerPlayer and player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
            local distance = (knight.HumanoidRootPart.Position - player.Character.HumanoidRootPart.Position).Magnitude
            if distance < shortestDistance then
                closestPlayer = player
                shortestDistance = distance
            end
        end
    end

    return closestPlayer
end

-- Knight AI behavior
local function setupKnightAI(knight, ownerPlayer, base)
    task.spawn(function()
        local lastAttack = 0

        while knight and knight.Parent and knight:FindFirstChild("Humanoid") and knight:FindFirstChild("HumanoidRootPart") do
            local enemy = findNearestEnemy(knight, ownerPlayer)

            if enemy and enemy.Character and enemy.Character:FindFirstChild("HumanoidRootPart") then
                local targetPos = enemy.Character.HumanoidRootPart.Position
                knight.Humanoid:MoveTo(targetPos)

                local distance = (targetPos - knight.HumanoidRootPart.Position).Magnitude
chrome shuttleBOT
#

studio** You are now Level 1! **studio

worldly geyser
#
                    lastAttack = os.clock()
                    local humanoid = enemy.Character:FindFirstChildOfClass("Humanoid")
                    if humanoid then
                        humanoid:TakeDamage(DAMAGE)
                    end
                end
            else
                -- Wander near base
                local offset = Vector3.new(math.random(-10, 10), 0, math.random(-10, 10))
                local destination = base.Position + offset
                knight.Humanoid:MoveTo(destination)
            end

            wait(1)
        end
    end)
end

-- Handle player requesting to buy knight
BuyKnightEvent.OnServerEvent:Connect(function(player)
    local cash = player:FindFirstChild("leaderstats") and player.leaderstats:FindFirstChild("Cash")
    if not cash or cash.Value < KNIGHT_COST then return end

    local base = playerBaseMap[player.UserId]
    if not base then return end

    local spawnPoint = base:FindFirstChild("KnightSpawn")
    if not spawnPoint then return end

    -- Deduct cash
    cash.Value -= KNIGHT_COST

    -- Spawn the knight
    local knight = KnightTemplate:Clone()
    knight.Parent = workspace
    knight:SetPrimaryPartCFrame(spawnPoint.CFrame + Vector3.new(0, 3, 0))

    -- Activate AI
    setupKnightAI(knight, player, spawnPoint)
end)

-- Example base linking (you must call this from your base assignment script)
Players.PlayerAdded:Connect(function(player)
    repeat task.wait() until workspace:FindFirstChild("Bases")
    for _, base in pairs(baseFolder:GetChildren()) do
        if base:GetAttribute("Owner") == player.UserId then
            playerBaseMap[player.UserId] = base
            break
        end
    end
end)

Players.PlayerRemoving:Connect(function(player)
    playerBaseMap[player.UserId] = nil
end)


#

its a long script...

hoary marlin
#

Since you don't get any errors, the problem might lie in the KnightTemplate itself.

#

You had humanoid, and a HumanoidRootPart in your character?

#

Or if you had any errors, please share, it'd help narrow down the problem

chrome shuttleBOT
#

studio** You are now Level 2! **studio

hoary marlin
#

Another possibility is the BuyKnightEvent Handler has some bugs in it.

astral terrace
#

It seems like it works. But, when testing, do you lose coins, and if you put a print statement after the cloning, WILL it clone?

astral terrace
#

Definitely a bug with the buying process then; if it doesn't take away coins it's not an issue with the spawning part.