Project Zomboid

Project Zomboid

Braven's NPC Framework
 This topic has been pinned, so it's probably important
Braven  [developer] 22 Nov, 2023 @ 4:55pm
Basic Guide
Here's a simple to understand, but in-depth guide for how to make your NPCs using my framework. If you need any help, you can join my Discord server[discord.com] because it'd be much better to have a conversation there.

I ask that you subscribe to this Discussion so you don't miss out on updates. This will rarely be updated, if at all, because all of this is supposed to be future proof. However, we wouldn't want your mod(s) breaking due to an update would we?

Declaring your initial variables
You must declare a table variable that will contain all of the information regarding your NPC.
If you want to go fancy, you can even make a table of tables containing all your NPCs, or just declare various individual tables instead. Up to you.
Example: MyNPCData = { }

Handling Global Mod Data
"Global Mod Data" refers to data (Variables) that are saved in files and persist even when you leave the game. They are exclusive to each save, so you don't need to worry about a Player having multiple saves.

There is only ONE variable you MUST pay attention to here. YourVariable.FirstStart.
This is a boolean variable that determines whether this is the first time your NPC is being generated or not. It must be TRUE by default.

It is very easy to make it so your NPC data is saved. Simply make a local function that listens to when global mod data is loaded, and create / load it properly, like so:
local function initModData() MyNPCData = ModData.get("MyNPCData") if not MyNPCData then MyNPCData = ModData.create("MyNPCData") MyNPCData.FirstStart = true end end Events.OnInitGlobalModData.Add(initModData)

Generating your NPC
Now that you have all the variables ready for use, let us get to the real action.
Whenever you wish to generate an NPC (Most likely on game start), define a local table variable that will contain the properties you wish your NPC to have.

You can check a list of all the properties here, or simply read the framework code in the file BB_NPCFramework.lua.

Here's an example of a very basic properties table:
local npc_parameters = { isFemale = false, firstName = "Bob", hairstyle = "", speechColor = { R = 0.294, G = 0.325, B = 0.125 }, spawnSq = getPlayer():getSquare(), dialogueStringPrefix = "IGUI_MyNPC_", }

After declaring the variable, you must actually generate the NPC itself using these properties. To do that, simply call BB_NPCFramework.CreateNPC(), like so:
Example: MyNPCData.npc = BB_NPCFramework.CreateNPC(MyNPCData, npc_parameters)

Your NPC is now ready for usage! However, they are naked and have no real functionality.
If you want to write your very own custom behavior from the ground up, your guide ends here.
Otherwise, if you want to keep using the framework's functionality, read on.

Seting up your NPC
With your NPC generated, it is time to modify it to wear exactly what you want, and do whatever you tell it to do. Let's begin with giving it items.

To setup your character, call the function BB_NPCFramework.SetupNPC()
This function will handle loading your NPC's equipment and inventory. It will return a string "OK". If this is the first time the NPC is being generated,it will instead return a string "CUSTOMIZE".

If you want your NPC to have starting out equipment and inventory, check if the function returns "CUSTOMIZE", and then assign items to it. Here's an example:
local setupResult = BB_NPCFramework.SetupNPC(MyNPCData) if setupResult == "CUSTOMIZE" then local inventory = MyNPCData.npc:getInventory() local mainWeapon = InventoryItemFactory.CreateItem("Base.BaseballBat") if mainWeapon then inventory:AddItem(mainWeapon) MyNPCData.npc:setPrimaryHandItem(mainWeapon) MyNPCData.npc:setSecondaryHandItem(mainWeapon) MyNPCData.weaponIsRanged = true mainWeapon:getModData().equippedByBravenNPC = true -- <- NECESSARY FOR EQUIPPED ITEMS! end end }

If you want your NPC to also immediately start using all the modules provided by this mode, you can call BB_NPCFramework.SubscribeNPCToAllModules() instead of SetupNPC.

The Modules
The framework contains various separate modules that can automatically handle NPC behavior for you. You can subscribe your NPC to these modules easily by calling ModuleName.ManageNPC(). Alternatively, you can simply call BB_NPCFramework.SubscribeNPCToAllModules(), as mentioned earlier, to subscribe to ALL modules at once.

You can check a list of all the modules here[http//AAAAAAAA], or simply read the framework code in each file of the framework.

I highly recommend, and INSIST you subscribe to at least the Save, or MyLittleSave module.
This one is responsible for handling storing your NPC's persistent data, and is fully compatible with the Setup function by default.

Here's an example of subscribing to save, movement, combat, name tag and speech:
MyLittleSave.ManageNPC(MyNPCData) MyLittleMovement.ManageNPC(MyNPCData) MyLittleSpeech.ManageNPC(MyNPCData) MyLittleCombat.ManageNPC(MyNPCData) MyLittleNameDisplay.ManageNPC(MyNPCData)

You can subscribe and unsubscribe from any module easily by utilizing the ModuleName.ManageNPC() or ModuleName.RemoveNPC() functions.

NPC Death
You MUST handle and unsubscribe from ALL modules your NPC is subscribed to when they die, or errors will occur. This can easily be done by calling BB_NPCFramework.UnsubscribeNPCFromAllModules() when the NPC dies. You can also unsubscribe individually.

Here's an example of unsubscribing from the individual modules we subscribed to earlier:
local function onCharacterDeath(character) if character == MyNPCData.npc then MyLittleSave.RemoveNPC(MyNPCData) MyLittleMovement.RemoveNPC(MyNPCData) MyLittleSpeech.RemoveNPC(MyNPCData) MyLittleCombat.RemoveNPC(MyNPCData) MyLittleNameDisplay.RemoveNPC(MyNPCData) end end Events.OnCharacterDeath.Add(onCharacterDeath)

That's it! It's THAT easy! Hope you enjoyed the guide, and have fun with your amazing, custom NPCs!

Still need help?
Join my Discord server[discord.gg] now! I'm more active there and will gladly help you with any issues you might have.
Last edited by Braven; 27 Nov, 2023 @ 12:57am