Compare commits

..

No commits in common. "829576b6963cf2cea51d989ac766539d2e4cd0a8" and "821e0a93fd0b2b0b1a77c59a3313e1617bc582dc" have entirely different histories.

3 changed files with 196 additions and 212 deletions

View File

@ -1,23 +1,16 @@
# Dead God Helper # Dead God Helper
Spot missing items! A small mod for The Binding Of Isaac: Repentance!
Easily spot items that were not previously picked up on this savefile. Very useful when you're trying to get a second or third Dead God. It signals items that were not previously picked up on this savefile when you encounter them.Very useful when you're trying to get a second or third Dead God.
Now supports modded items, and integration with Repentogon!
I made it mainly for myself, because it was annoying to go back to the menu every time I encountered an item I was unsure about. I made it mainly for myself, because it was annoying to go back to the menu every time I encountered an item I was unsure about.
There's an integration with External Item Description. There's an integration with External Item Description.
It is also compatible with Mod Config Menu, if you want to toggle things (such as displaying info when on Curse Of The Blind) It is also compatible with Mod Config Menu, if you want to toggle things (such as displaying info when on Curse Of The Blind)
Mods can't access the savefile directly, so the mod tracks itself witch items are taken. This means that the first time you install it, everything will be marked as new. There's however a limitation: since (to my knowledge) there's no way to get information about seen items from the savefile, this mod takes it upon itself to track which item you picked up. (This means that when you install the mod for the first time, every item will be tagged as Unseen)
If you want to import data from your savefile, you can either use the extractor I wrote (adapting EID's one for Linux), or install Repentogon.
The extractor is available here : https://forge.chapril.org/ayte/DeadGodHelper/src/branch/main/SaveExtractor
This mod is still relevant in itself if you do not want to use external tools, or you want to track modded items ^^
Anyway, I hope that this mod will be useful to someone :) Anyway, I hope that this mod will be useful to someone :)
Source code is available at https://forge.chapril.org/ayte/DeadGodHelper (Source code is available at https://forge.chapril.org/ayte/DeadGodHelper)

167
main.lua
View File

@ -1,4 +1,3 @@
-- Formatted using lua-format
local modname = "DeadGod Helper" local modname = "DeadGod Helper"
local mod = RegisterMod(modname, 1) local mod = RegisterMod(modname, 1)
local math = require("math") local math = require("math")
@ -8,43 +7,33 @@ local savegen = include("save")
local save = savegen:new() local save = savegen:new()
local json = include("json") local json = include("json")
local DEBUG = false local DEBUG = false
local getgamedata = Isaac.GetPersistentGameData -- Repentogon exclusive
local isrepentogon = getgamedata ~= nil
mod.font = Font() mod.font = Font()
mod.font:Load("font/terminus.fnt") mod.font:Load("font/terminus.fnt")
function mod:isCurseBlind(pickupEntity) function mod:isCurseBlind()
if isrepentogon then if pickupEntity:IsBlind() then return true end end
return mod.game:GetLevel():GetCurses() & LevelCurse.CURSE_OF_BLIND > 0 return mod.game:GetLevel():GetCurses() & LevelCurse.CURSE_OF_BLIND > 0
end end
function mod.isIdNotTakenAlready(id) function mod.isIdNotTakenAlready(id)
if id > 0 then if id>=1 and id<=save.settings.maxid then
-- Always returns seen if on a challenge return not save.seen[id]
if Isaac.GetChallenge() ~= 0 then return false end end
if id>save.settings.maxid and save.settings.showonmodded then
if id > save.settings.maxid then
if save.settings.showonmodded then
local itemconfig = Isaac.GetItemConfig():GetCollectible(id) local itemconfig = Isaac.GetItemConfig():GetCollectible(id)
if itemconfig then if itemconfig then
local name = itemconfig.Name local name = itemconfig.Name
return not save.seenmodded[name] return not save.seenmodded[name]
end end
end end
else
return not save.seen[id] return false
end
else
return false -- Don't show on empty pedestals
end
end end
function mod.registerTouched(id) function mod.registerTouched(id)
-- Only register when not on a challenge if id>=1 and id<=save.settings.maxid then
if Isaac.GetChallenge() == 0 then save:touchid(id)
local shouldsave = mod.isIdNotTakenAlready(id) end
if id >= 1 and id <= save.settings.maxid then save:touchid(id) end
if id >=save.settings.maxid then if id >=save.settings.maxid then
-- Modded item, save them by name -- Modded item, save them by name
-- (as IDs are choosen manually by the game, and may vary when changing mods) -- (as IDs are choosen manually by the game, and may vary when changing mods)
@ -56,11 +45,8 @@ function mod.registerTouched(id)
end end
-- Save -- Save
if shouldsave then -- Only save if there's a change
mod:save() mod:save()
end end
end
end
-- Used to check if EID's description should be modified -- Used to check if EID's description should be modified
function mod.shouldBeModified(descObj) function mod.shouldBeModified(descObj)
@ -92,11 +78,9 @@ function mod:update()
local player = mod.game:GetPlayer(i) local player = mod.game:GetPlayer(i)
local data = player:GetData() local data = player:GetData()
local item = player.QueuedItem.Item local item = player.QueuedItem.Item
if data._deadgodlastid and data._deadgodlastcount and if data._deadgodlastid and data._deadgodlastcount and data._deadgodlastid>0 then
data._deadgodlastid > 0 then
if item==nil then -- Finished animation if item==nil then -- Finished animation
if player:GetCollectibleNum(data._deadgodlastid) > if player:GetCollectibleNum(data._deadgodlastid)>data._deadgodlastcount then -- Have it on me
data._deadgodlastcount then -- Have it on me
-- Then I just picked it up, yay -- Then I just picked it up, yay
mod.registerTouched(data._deadgodlastid) mod.registerTouched(data._deadgodlastid)
if DEBUG then if DEBUG then
@ -104,8 +88,7 @@ function mod:update()
end end
data._deadgodlastid = 0 data._deadgodlastid = 0
data._deadgodlastcount = 0 data._deadgodlastcount = 0
end end end
end
end end
if item and item:IsCollectible() then if item and item:IsCollectible() then
data._deadgodlastid = item.ID data._deadgodlastid = item.ID
@ -116,20 +99,16 @@ end
-- Used to draw the ! sign -- Used to draw the ! sign
function mod:PickupDrawCallback(pickupEntity, _) function mod:PickupDrawCallback(pickupEntity, _)
if save.settings.visual and if save.settings.visual and (not mod:isCurseBlind() or save.settings.showonblind)then
(not (mod:isCurseBlind(pickupEntity)) or save.settings.showonblind) then
if pickupEntity.Variant==PickupVariant.PICKUP_COLLECTIBLE then if pickupEntity.Variant==PickupVariant.PICKUP_COLLECTIBLE then
if mod.isIdNotTakenAlready(pickupEntity.SubType) then if mod.isIdNotTakenAlready(pickupEntity.SubType) then
local v = Isaac.WorldToScreen( local v = Isaac.WorldToScreen(pickupEntity.Position + pickupEntity.SpriteOffset)
pickupEntity.Position + pickupEntity.SpriteOffset)
local color = KColor(0.98,0.93,0.55,1) local color = KColor(0.98,0.93,0.55,1)
if pickupEntity.SubType > save.settings.maxid then if pickupEntity.SubType > save.settings.maxid then
-- Modded item -- Modded item
color = KColor(0.68,0.88,1,1) color = KColor(0.68,0.88,1,1)
end end
mod.font:DrawString("!", v.X - 1, v.Y - 52 + mod.font:DrawString("!", v.X-1, v.Y-52+math.sin(mod.game:GetFrameCount()/10)*2, color , 2, true)
math.sin(mod.game:GetFrameCount() / 10) *
2, color, 2, true)
end end
end end
end end
@ -138,90 +117,95 @@ end
function mod:newrun() function mod:newrun()
if mod:HasData() then if mod:HasData() then
local data = mod:LoadData() local data = mod:LoadData()
if DEBUG then mod.print(data .. "\n") end if DEBUG then
mod.print(data.."\n")
end
save = savegen:new() save = savegen:new()
save:load(json, data) save:load(json, data)
else else
save = savegen:new() save = savegen:new()
end end
-- Load info from repentogon if available
if isrepentogon then
for i = 1, save.settings.maxid do
if getgamedata():IsItemInCollection(i) then
mod.registerTouched(i)
end
end
end
local c = 0 local c = 0
for _, v in ipairs(save.seen) do if v then c = c + 1 end end for _,v in ipairs(save.seen) do
if v then c = c+1 end
end
mod.print(modname.." loaded, "..c.." vanilla items seen") mod.print(modname.." loaded, "..c.." vanilla items seen")
if save.settings.showonmodded then if save.settings.showonmodded then
local c = 0 local c = 0
for _, v in pairs(save.seenmodded) do if v then c = c + 1 end end for _,v in pairs(save.seenmodded) do
if v then
c = c + 1
end
end
mod.print(", "..tostring(c).." modded") mod.print(", "..tostring(c).." modded")
end end
mod.print(".\n") mod.print(".\n")
end end
function mod:save() mod:SaveData(save:dump(json)) end function mod:save()
mod:SaveData(save:dump(json))
end
mod:AddCallback(ModCallbacks.MC_POST_GAME_END, mod.save) mod:AddCallback(ModCallbacks.MC_POST_GAME_END, mod.save)
mod:AddCallback(ModCallbacks.MC_POST_GAME_STARTED, mod.newrun) mod:AddCallback(ModCallbacks.MC_POST_GAME_STARTED, mod.newrun)
if not isrepentogon then
-- Used to check for new items
mod:AddCallback(ModCallbacks.MC_POST_UPDATE, mod.update) mod:AddCallback(ModCallbacks.MC_POST_UPDATE, mod.update)
else
function mod.addCollectibleCallaback(_, id, _, _, _, _)
mod.registerTouched(id)
end
-- This is not a vanilla callback, it is from repentogon
mod:AddCallback(ModCallbacks.MC_POST_ADD_COLLECTIBLE,
mod.addCollectibleCallaback)
end
-- Used to draw indicators
mod:AddCallback(ModCallbacks.MC_POST_PICKUP_RENDER, mod.PickupDrawCallback) mod:AddCallback(ModCallbacks.MC_POST_PICKUP_RENDER, mod.PickupDrawCallback)
if EID then if EID then
EID:addDescriptionModifier(modname, mod.shouldBeModified, EID:addDescriptionModifier(
mod.modifierCallback) modname,
mod.shouldBeModified,
mod.modifierCallback
)
end end
if ModConfigMenu then if ModConfigMenu then
ModConfigMenu.AddSetting(modname, -- This should be unique for your mod ModConfigMenu.AddSetting(
nil, { modname, -- This should be unique for your mod
nil,
{
Type = ModConfigMenu.OptionType.BOOLEAN, Type = ModConfigMenu.OptionType.BOOLEAN,
CurrentSetting = function() return save.settings.eid end, CurrentSetting = function()
return save.settings.eid
end,
Display = function() Display = function()
return "Show in EID: " .. (save.settings.eid and "on" or "off") return "Show in EID: " .. (save.settings.eid and "on" or "off")
end, end,
OnChange = function(b) OnChange = function(b)
save.settings.eid = b save.settings.eid = b
mod:save() mod:save()
end end,
}) }
ModConfigMenu.AddSetting(modname, -- This should be unique for your mod )
nil, { ModConfigMenu.AddSetting(
modname, -- This should be unique for your mod
nil,
{
Type = ModConfigMenu.OptionType.BOOLEAN, Type = ModConfigMenu.OptionType.BOOLEAN,
CurrentSetting = function() return save.settings.visual end, CurrentSetting = function()
return save.settings.visual
end,
Display = function() Display = function()
return "Show on pedestals: " .. return "Show on pedestals: " .. (save.settings.visual and "on" or "off")
(save.settings.visual and "on" or "off")
end, end,
OnChange = function(b) OnChange = function(b)
save.settings.visual = b save.settings.visual = b
mod:save() mod:save()
end end,
}) }
)
ModConfigMenu.AddSetting(modname, -- This should be unique for your mod ModConfigMenu.AddSetting(
nil, { modname, -- This should be unique for your mod
nil,
{
Type = ModConfigMenu.OptionType.BOOLEAN, Type = ModConfigMenu.OptionType.BOOLEAN,
CurrentSetting = function() return save.settings.showonmodded end, CurrentSetting = function()
return save.settings.showonmodded
end,
Display = function() Display = function()
return "Also track modded items: " .. return "Also track modded items: " .. (save.settings.showonmodded and "on" or "off")
(save.settings.showonmodded and "on" or "off")
end, end,
OnChange = function(b) OnChange = function(b)
save.settings.showonmodded = b save.settings.showonmodded = b
@ -230,20 +214,25 @@ if ModConfigMenu then
save.seenmodded = {} save.seenmodded = {}
end end
mod:save() mod:save()
end end,
}) }
)
ModConfigMenu.AddSetting(modname, -- This should be unique for your mod ModConfigMenu.AddSetting(
nil, { modname, -- This should be unique for your mod
nil,
{
Type = ModConfigMenu.OptionType.BOOLEAN, Type = ModConfigMenu.OptionType.BOOLEAN,
CurrentSetting = function() return save.settings.showonblind end, CurrentSetting = function()
return save.settings.showonblind
end,
Display = function() Display = function()
return "Show while having Curse Of The Blind: " .. return "Show while having Curse Of The Blind: " .. (save.settings.showonblind and "on" or "off")
(save.settings.showonblind and "on" or "off")
end, end,
OnChange = function(b) OnChange = function(b)
save.settings.showonblind = b save.settings.showonblind = b
mod:save() mod:save()
end end,
}) }
)
end end

View File

@ -3,29 +3,31 @@
<name>DeadGod Helper</name> <name>DeadGod Helper</name>
<directory>deadgod helper</directory> <directory>deadgod helper</directory>
<id>2985754961</id> <id>2985754961</id>
<description>Spot missing items! <description>A small mod for The Binding Of Isaac: Repentance!
Easily spot items that were not previously picked up on this savefile. Very useful when you're trying to get a second or third Dead God. Easily spot items that were not previously picked up on this savefile. Very useful when you're trying to get a second or third Dead God.
Now supports modded items, and integration with Repentogon! Now supports modded items!
I made it mainly for myself, because it was annoying to go back to the menu every time I encountered an item I was unsure about. I made it mainly for myself, because it was annoying to go back to the menu every time I encountered an item I was unsure about.
There's an integration with External Item Description.
It is also compatible with Mod Config Menu, if you want to toggle things (such as displaying info when on Curse Of The Blind) It is also compatible with Mod Config Menu, if you want to toggle things (such as displaying info when on Curse Of The Blind)
Mods can't access the savefile directly, so the mod tracks itself witch items are taken. This means that the first time you install it, everything will be marked as new. Since mods can't directly access the savefile, this mod takes it upon itself to track wich items are picked up. This means that the first time you install this mod, everything will be marked as unseen.
If you want to import data from your savefile, you can either use the extractor I wrote (adapting EID's one for Linux), or install Repentogon. Turns out EID already has a some support for this, using a save extractor. If you want to go down that route, here's the link to the extractor : https://github.com/wofsauge/External-Item-Descriptions/tree/master/scripts
The extractor is available here : https://forge.chapril.org/ayte/DeadGodHelper/src/branch/main/SaveExtractor
However, EID's save extractor doesn't really work on Linux, so I made a port of it in python, in order to be more easily ran. This port is available here : https://forge.chapril.org/ayte/DeadGodHelper/src/branch/main/SaveExtractor
This port can also extract save file's info to be used for Dead God Helper.
This mod is still relevant in itself if you do not want to use external tools, or you want to track modded items ^^ This mod is still relevant in itself if you do not want to use external tools, or you want to track modded items ^^
Anyway, I hope that this mod will be useful to someone :) Anyway, I hope that this mod will be useful to someone :)
Source code is available at https://forge.chapril.org/ayte/DeadGodHelper</description> Source code is available at https://forge.chapril.org/ayte/DeadGodHelper</description>
<version>1.13</version> <version>1.11</version>
<visibility>Public</visibility> <visibility>Public</visibility>
<tag id="Items"/> <tag id="Items"/>
<tag id="Tweaks"/>
<tag id="Graphics"/> <tag id="Graphics"/>
</metadata> </metadata>