From Moondust Wiki
(Redirected from Pnpc.lua)
Jump to navigation Jump to search
OOjs UI icon notice-destructive.svg DEPRECATED: This library has been deprecated since SMBX2 Beta 4. In this version and onwards,, npc.uid,, and npc.pidIsDirty can be accessed without needing to use this library.

Download Latest Version

pNPC is a library for getting a wrapper object for NPC class objects LunaLua, which unlike those remains valid across ticks.

For extra utility it also provides a uid and a property for user-defined data storage.


Place the file pnpc.lua in either your level's custom graphics folder for use in a level, along with a lunadll.lua file, or in the same directory as your .wld file along with a lunaworld.lua file for use throughout an entire episode.

How to use

To enable the pNPC library for a specific level, add this line to lunadll.lua:

local pNPC = API.load("pnpc");

This will load the pNPC API.

After loading we can wrap NPC objects, which gives them a data table we can read values from/write values to.

for _, npc in ipairs(myNPCs) do
    npc = pNPC.wrap(npc); -- add or get a wrapper for the NPC object

    local myData =; -- reference to the data table locally

    if myData.someVar == nil then -- check if some data variable has no value assigned to it
        myData.someVar = someValue; -- set that data variable
        -- we can set other variables as well as needed

    -- we can read and write to these data values here
    -- the NPC still has all of its fields/methods inherited from the NPC class when wrapped

Note: It is also sometimes useful when needing to initialize/reset a large number of data values to have an additional helper function to do the work.

function initMyNPCData(data)
    data.someVar = data.someValue;
    -- set more variables

Then we can call it as needed to initialize/reset these values.

for _, npc in ipairs(myNPCs) do
    npc = pNPC.wrap(npc);

    local myData =;

    if myData.someVar == nil then

    if resetCondition then

The following is a brief example that stops all goombas (in the player's section) from moving 150 ticks after they are spawned.

local pNPC = API.load("pnpc");

function onTick()
    for _, npc in ipairs(NPC.get(1, player.section)) do
        npc = pNPC.wrap(npc);

        local myData =;

        if myData.sleepCounter == nil
            myData.sleepCounter = 150;

        if myData.sleepCounter > 0 then
            myData.sleepCounter = myData.sleepCounter - 1;
            npc.dontMove = true;

External Use Functions

These are functions you will need to use the library

wrap npc
Get a wrapper around a specified NPC which will remain valid across ticks. If one already exists, it is returned, otherwise a new one is created. NPC-like Wrapper NPC

The NPC to wrap.

getExistingWrapper npc
Get a wrapper around a specified NPC which will remain valid across ticks. If one doesn't already exist, return nil. NPC-like Wrapper NPC

The NPC to find the wrapper for

The NPC Wrapper

All properties supported by LunaLua's NPC class are automatically supported.

The mem and kill methods are also supported.

There are four additional properties defined:

data A table which user-defined data associated with the NPC can be entered into
uid (read-only) A unique identifier for this NPC
pid (read-only) The persistence identifier for this NPC. If the uid is less than 0x8000, it is guaranteed to be the same as pid. Intended for debugging.
pidIsDirty (read-only) Flag to indicate that the persistence identifier is recycled. Intended for debugging.