Skip to content

Adding Custom Pocket items

AgentCucco edited this page Jan 27, 2021 · 4 revisions

Adding custom pocket items can be either easy or hard, depending on whether or not you plan on making them unique to your mod like Capsules, or a mod friendly one like Syringes.

  • Note: Make sure you do all this while in an if Encyclopedia then check, to prevent errors.

Adding a new pocket item for your own type.

Helper function

The first step is to make a function to facilitate the process, let's use Capsules as an example.

function Encyclopedia.AddCapsule(itemTab)
  Encyclopedia.AddPocketItem(itemTab, "capsules")
end

Adding your pocket items.

Once you have the helper function, adding the new pocket items is very easy.

Encyclopedia.AddCapsule({
  ID = Card.CARD_DAMAGE_CAPSULE,
  WikiDesc = var, -- Their EID description table entry
  Sprite = Encyclopedia.RegisterSprite("gfx/ui/ui_cardspills.anm2", "Pills", 1, "gfx/items/pick ups/capsule_damage.png")
})

Adding a new global pocket item used by more mods.

Helper functions.

The first step is to make a function to facilitate the process, let's use Syringes as an example. In this thread I'll just assume you want to autogenerate mod names as well. Note that Syringes behave like pills and are a very different to cards, syringes use up only 13 different cards, but can yield up to 28 (without mods) unique effects, and many more with mods, such like pills.

Grabbing the mod names.

Note than in order to successfully grab all mod names automatically, for items that were registered for your mod, your mod needs to load first than them.

local LastModLoaded = "Unknown Mod"
local registerModOld = Isaac.RegisterMod -- Stores the old RegisterMod()
local function registerModNew(ref, modName, apiVersion)
  -- Checks for errors, so that RegisterMod() issues don't get redirect to your mod. 
  local registeredCorrectly, returned = pcall(registerModOld, ref, modName, apiVersion)

  if registeredCorrectly then
    LastModLoaded = modName -- Store the most recent loaded mod.
  
    return returned -- Copy as is.
  else
    error(returned, 2) -- Copy as is.
  end 
end
Isaac.RegisterMod = registerModNew

Store the modded names when they register a new item from your mod.

You can probably add this inside the original function, but I personally thing it looks cleaner this way (remember to add this only inside the if Encyclopedia then check.)

Encyclopedia.TrackerTables.syringes = {} -- This add the entry directly in Encyclopedia, it's linked to the ``etype`` variable used in ``AddPocketItem()``
Encyclopedia.TrackerTables.syringesNames = {} -- Same here.
local NUM_SYRINGES = #M_SYR.EFF_TAB + 1 -- Grab the maximum amount of custom items at the time your mod is loaded.
local MaxSyringe = NUM_SYRINGES - 1 -- The start point for mods.
local oldSyringeRegister = M_SYR.GetSyringeIdByName
local function newSyringeRegister(name)
  local SyringeID = oldSyringeRegister(name) -- Call the original function.
  
  if not M_SYR.EFF_TAB[SyringeID] then -- If the ID has not yet been registered.
    Encyclopedia.TrackerTables.syringesNames[SyringeID] = LastModLoaded
    MaxSyringe = MaxSyringe + 1
  end
  
  return SyringeID -- Follow internal code.
end
M_SYR.GetSyringeIdByName = newSyringeRegister

Custom Add function.

Unlike Capsules where you could've just used AddPocketItem() with an etype instead of making your own function, in this case you require making the function to handle all of the little details of your custom pocket item.

function Encyclopedia.AddSyringe(itemTab)
  local Syringe = M_SYR.EFF_TAB[itemTab.ID] -- Get the item from your main effect table.
  itemTab.Name = Syringe.Name
  itemTab.WikiDesc = itemTab.WikiDesc or Encyclopedia.EIDtoWiki(Syringe.EIDDescription)
  itemTab.ID = SyringeColors.ClearSyringe
  itemTab.ModName = itemTab.ModName or LastModLoaded -- Make sure you give a ModName when registering your own, to not have them display "Unknown Mod"
  
  -- General Syringes stuff.
  local Duration = math.floor((Syringe.Duration / 30) * 100) / 100
  if Syringe.Exclusive and Syringe.Type == M_SYR.TYPES.Negative then
    Duration = math.floor((Syringe.Duration / 60) * 100) / 100
  end
  if Duration % 1 == 0 then Duration = math.floor(Duration) end
  itemTab.Description = "Lasts for " .. Duration .. " seconds"

  -- Grab a specific sprite given the syringe attributes.
  if not itemTab.Spr then
    if Syringe.Type == M_SYR.TYPES.Positive then
      if Syringe.Exclusive then
        itemTab.Spr = Encyclopedia.RegisterSprite("gfx/encyclopedia.syringes.anm2", "Unicorn Syringe")
      else
        itemTab.Spr = Encyclopedia.RegisterSprite("gfx/encyclopedia.syringes.anm2", "Green Syringe")
      end
    elseif Syringe.Type == M_SYR.TYPES.Negative then
      if Syringe.Exclusive then
        itemTab.Spr = Encyclopedia.RegisterSprite("gfx/encyclopedia.syringes.anm2", "Black Syringe")
      else
        itemTab.Spr = Encyclopedia.RegisterSprite("gfx/encyclopedia.syringes.anm2", "Red Syringe")
      end
    elseif Syringe.Type == M_SYR.TYPES.Neutral then
      itemTab.Spr = Encyclopedia.RegisterSprite("gfx/encyclopedia.syringes.anm2", "Yellow Syringe")
    end
  end
  
  -- SyringeID added at last to ensure it's stored properly.
  Encyclopedia.AddPocketItem(itemTab, "syringes").SyringeID = Syringe.ID
end

Hijack the autogeneration function.

You want to hijack the Encyclopedia autogeneration function to successfully autogenerate modded custom items.

  • Note that this only applies if your item follows a similar behavior to pills or syringes. For normal cards you'd have to still replace the original function, but in a different way.
local oldAutogeneration = Encyclopedia.AutogenerateUnknownItems
local function newAutogeneration()
  local Generate = oldAutogeneration()
  
  if Generate then
    for i = NUM_SYRINGES, MaxSyringe do -- Iterate from the last original syringe, to the last modded syringe.
      if not Encyclopedia.TrackerTables.syringes[i] then -- If it hasn't been generated.
        local item = M_SYR.EFF_TAB[i]
        
        if item then -- Failsafe in case the syringe was never added to the Effect table.
          local desc = item.EIDDescription
          local modName = Encyclopedia.TrackerTables.syringesNames[i] or "unknown mod"
          
          if desc then
            desc = Encyclopedia.EIDtoWiki(desc)
          end
          
          Encyclopedia.AddSyringe({
            Class = "autogenerated",
            ID = i,
            WikiDesc = desc,
            SubClass = modName,
            ModName = modName,
          })
        end
      end
    end
    
    return true -- Continue internal logic.
  end
end
Encyclopedia.AutogenerateUnknownItems = newAutogeneration

If your custom item uses pooling (similar to pills or syringes).

If your custom item is similar to pills or syringes in this regard, you WILL REQUIRE a StatusFunc display function.

local function UpdateSyringeStatus(self)
  local syringe = M_SYR.CurrentIDPool[self.ItemId] -- Gets the item from your mod's table.
  local Known = M_SYR.CurrentRunPool[syringe.Index].Known

  for i, item in pairs(Encyclopedia.pocketitemsTable.syringes.allinternal) do -- Iterates over all, hidden and not, syringes.
    if item.SyringeID == syringe.Syringe.ID then
      if Known then -- If it's revealed, return the real syringe.
        self.Name = item.Name
        self.Desc = item.Desc
        self.WikiDesc = item.WikiDesc
        
        return self
      else
        return -- Continue internal code.
      end
    end
  end
end

Adding the custom items.

Once you have all of the helper functions down, all that's left is following the next steps to ensure they work properly.

Overwriting the original cards (if a pooling system is used).

If your custom items behave similar to pills or syringes, you will need to overwrite the original cards used to pool them.

-- Do this for all of your custom items.
Encyclopedia.AddCard({ -- ClearSyringe
  Class = "syringes",
  ID = SyringeColors.ClearSyringe,
  Name = "Unknown Syringe",
  Description = "???",
  Hide = true, -- So it doesn't appear in the cards menu.
  StatusFunc = UpdateSyringeStatus,
  Spr = Encyclopedia.RegisterSprite("gfx/encyclopedia.syringes.anm2", "Clear Syringe"),
})

Adding your own custom items to the Encyclopedia.

Once you have the autogeneration system done, you can finally add your custom items to it.

-- Repeat for all.
Encyclopedia.AddSyringe({ -- 1.DPSBoost
	Class = "syringes",
	ID = M_SYR.TOT_SYR.DPSBoost,
	WikiDesc = SyringesWiki.DPSBoost,
	ModName = SyrMod.ModName,
})
Encyclopedia.AddSyringe({ -- 2.LuckBoost
	Class = "syringes",
	ID = M_SYR.TOT_SYR.LuckBoost,
	WikiDesc = SyringesWiki.LuckBoost,
	ModName = SyrMod.ModName,
})

Clone this wiki locally