Is this npc code decent?

Trying to make NPCs at the moment and I’m trying to make a system that lets me assign different actions or none when the player interacts with them. I came up with something that works, however, it’s kind of clunky.

This is the code that runs when the game starts that sets up every NPC the biggest flaw I can see with this is it will be difficult to manage if I decide to add a lot of NPCs. Right now there are only 4 so it’s not that much of a problem.

-- different actions we can assign to an npc
local callbacks = {
    ["openMenu"] = function(menuName)
        print(menuName)
    end,
    ["dialogue"] = function(...)
        print("DIALOGUE")
    end,
}

-- assigning above callbacks and now data (i.e: name of frame to open for the openMenu callback) to name of npc
local npc = {
    ["StoreNPC"] = {callbacks.openMenu,"Store"}
}

-- creating the npc with above data
for _, instance in pairs(CollectionService:GetTagged("NPC")) do
    NPCTest.new(instance,npc[instance.Name])
end

This is what creates a new npc object.

function NPC.new(model,args)
	local self = setmetatable({},NPC)
	
	local function makeCollider(root)
		local part = Instance.new("Part")
		part.Shape = Enum.PartType.Ball
		part.Size = Vector3.new(RADIUS,RADIUS,RADIUS)
		part.Anchored = true
		part.CanCollide = false 
		part.CFrame = model:FindFirstChild("HumanoidRootPart").CFrame
		part.Transparency = 0.5
		Util:WeldParts(part,root)	
		part.Parent = root
		
		return part
	end

	self.model = model
	self.root = model:FindFirstChild("HumanoidRootPart")
	self.collider = makeCollider(self.root)
	self.zone = Zone.new(self.collider)
	
	if args and #args ~= 0 then
		self.callback = args[1]
		self.arg2 = args[2]

	end

	self.zone.localPlayerEntered:Connect(function()
		self:onColliderTriggered()
	end)
	
	return self
end

--TODO: set a bool variable to true and if the player presses the interact key while variable is true call the Interact() method
function NPC:onColliderTriggered()
	if typeof(self.callback) ~= "function" then print("this npc doesn't do anything") return end
	self.callback(self.arg2)
end
1 Like

uhmm not bad dude pretty decent

use bindableEvent.

NPC.Event:Fire(‘openMenu’)

Pretty good, but keeping the actions of all your npcs in one script would probably get overwhelming. I would add a modulescript parented to each npc model that contains the actions and data for that npc, and then the npc object can require the modulescript and access the callbacks from there (it would be easier to manage, but it might affect performance slightly).

It also looks like each npc can only have 1 callback, which might be bad if you want to create more complex npcs.