diff --git a/main.lua b/main.lua index d7d0bf5..5757e6b 100644 --- a/main.lua +++ b/main.lua @@ -1,3 +1,4 @@ +-- Formatted using lua-format local modname = "DeadGod Helper" local mod = RegisterMod(modname, 1) local math = require("math") @@ -7,150 +8,160 @@ local savegen = include("save") local save = savegen:new() local json = include("json") local DEBUG = false +local getgamedata = Isaac.GetPersistentGameData -- Repentogon exclusive mod.font = Font() mod.font:Load("font/terminus.fnt") function mod:isCurseBlind() - return mod.game:GetLevel():GetCurses() & LevelCurse.CURSE_OF_BLIND > 0 + return mod.game:GetLevel():GetCurses() & LevelCurse.CURSE_OF_BLIND > 0 end function mod.isIdNotTakenAlready(id) - -- Always returns seen if on a challenge - if Isaac.GetChallenge()~=0 then return false end + if id > 0 then + -- Always returns seen if on a challenge + if Isaac.GetChallenge() ~= 0 then return false end - if id>=1 and id<=save.settings.maxid then - return not save.seen[id] - end - if id>save.settings.maxid and save.settings.showonmodded then - local itemconfig = Isaac.GetItemConfig():GetCollectible(id) - if itemconfig then - local name = itemconfig.Name - return not save.seenmodded[name] - end - end + -- Check using REPENTOGON + if getgamedata then + if getgamedata():IsItemInCollection(id) then + if not save.seen[id] then + save:touchid(id) + mod:save() + end + return false + end + end - return false + if id <= save.settings.maxid then return not save.seen[id] end + + if id > save.settings.maxid and save.settings.showonmodded then + local itemconfig = Isaac.GetItemConfig():GetCollectible(id) + if itemconfig then + local name = itemconfig.Name + return not save.seenmodded[name] + end + end + + return false + else + return false -- Don't show on empty pedestals + end end function mod.registerTouched(id) - -- Only register when not on a challenge - if Isaac.GetChallenge()==0 then - if id>=1 and id<=save.settings.maxid then - save:touchid(id) - end - if id >=save.settings.maxid then - -- Modded item, save them by name - -- (as IDs are choosen manually by the game, and may vary when changing mods) - local itemconfig = Isaac.GetItemConfig():GetCollectible(id) - if itemconfig then - local name = itemconfig.Name - save:touchname(name) - end - end + -- Only register when not on a challenge + if Isaac.GetChallenge() == 0 then + if id >= 1 and id <= save.settings.maxid then save:touchid(id) end + if id >= save.settings.maxid then + -- Modded item, save them by name + -- (as IDs are choosen manually by the game, and may vary when changing mods) + local itemconfig = Isaac.GetItemConfig():GetCollectible(id) + if itemconfig then + local name = itemconfig.Name + save:touchname(name) + end + end - -- Save - mod:save() - end + -- Save + mod:save() + end end -- Used to check if EID's description should be modified function mod.shouldBeModified(descObj) - -- Taken from https://github.com/wofsauge/External-Item-Descriptions/wiki/Description-Modifiers - -- if entity is a piedestal - if descObj.ObjType == 5 and descObj.ObjVariant == 100 then - -- Check if item was not already taken in this savefile - -- And if item is non-modded (id<= Mom's ring ID) - local id = descObj.ObjSubType - return mod.isIdNotTakenAlready(id) - end + -- Taken from https://github.com/wofsauge/External-Item-Descriptions/wiki/Description-Modifiers + -- if entity is a piedestal + if descObj.ObjType == 5 and descObj.ObjVariant == 100 then + -- Check if item was not already taken in this savefile + -- And if item is non-modded (id<= Mom's ring ID) + local id = descObj.ObjSubType + return mod.isIdNotTakenAlready(id) + end end -- Used to modify EID's description function mod.modifierCallback(descObj) - if save.settings.eid then - local str = "#{{Collectible}} Not picked up yet!#" - if descObj.ObjSubType>save.settings.maxid then - str = "#{{Trinket}} Not picked up yet!#" - end - descObj.Description = str..descObj.Description - end - return descObj + if save.settings.eid then + local str = "#{{Collectible}} Not picked up yet!#" + if descObj.ObjSubType > save.settings.maxid then + str = "#{{Trinket}} Not picked up yet!#" + end + descObj.Description = str .. descObj.Description + end + return descObj end -- Used to detect when an item is picked up function mod:update() - for i=0, mod.game:GetNumPlayers()-1 do - local player = mod.game:GetPlayer(i) - local data = player:GetData() - local item = player.QueuedItem.Item - if data._deadgodlastid and data._deadgodlastcount and data._deadgodlastid>0 then - if item==nil then -- Finished animation - if player:GetCollectibleNum(data._deadgodlastid)>data._deadgodlastcount then -- Have it on me - -- Then I just picked it up, yay - mod.registerTouched(data._deadgodlastid) - if DEBUG then - mod.print("> "..tostring(data._deadgodlastid).."\n") - end - data._deadgodlastid = 0 - data._deadgodlastcount = 0 - end end - end - if item and item:IsCollectible() then - data._deadgodlastid = item.ID - data._deadgodlastcount = player:GetCollectibleNum(item.ID) - end - end + for i = 0, mod.game:GetNumPlayers() - 1 do + local player = mod.game:GetPlayer(i) + local data = player:GetData() + local item = player.QueuedItem.Item + if data._deadgodlastid and data._deadgodlastcount and + data._deadgodlastid > 0 then + if item == nil then -- Finished animation + if player:GetCollectibleNum(data._deadgodlastid) > + data._deadgodlastcount then -- Have it on me + -- Then I just picked it up, yay + mod.registerTouched(data._deadgodlastid) + if DEBUG then + mod.print("> " .. tostring(data._deadgodlastid) .. "\n") + end + data._deadgodlastid = 0 + data._deadgodlastcount = 0 + end + end + end + if item and item:IsCollectible() then + data._deadgodlastid = item.ID + data._deadgodlastcount = player:GetCollectibleNum(item.ID) + end + end end -- Used to draw the ! sign function mod:PickupDrawCallback(pickupEntity, _) - if save.settings.visual and (not mod:isCurseBlind() or save.settings.showonblind)then - if pickupEntity.Variant==PickupVariant.PICKUP_COLLECTIBLE then - if mod.isIdNotTakenAlready(pickupEntity.SubType) then - local v = Isaac.WorldToScreen(pickupEntity.Position + pickupEntity.SpriteOffset) - local color = KColor(0.98,0.93,0.55,1) - if pickupEntity.SubType > save.settings.maxid then - -- Modded item - color = KColor(0.68,0.88,1,1) - end - mod.font:DrawString("!", v.X-1, v.Y-52+math.sin(mod.game:GetFrameCount()/10)*2, color , 2, true) - end - end - end + if save.settings.visual and + (not mod:isCurseBlind() or save.settings.showonblind) then + if pickupEntity.Variant == PickupVariant.PICKUP_COLLECTIBLE then + if mod.isIdNotTakenAlready(pickupEntity.SubType) then + local v = Isaac.WorldToScreen( + pickupEntity.Position + pickupEntity.SpriteOffset) + local color = KColor(0.98, 0.93, 0.55, 1) + if pickupEntity.SubType > save.settings.maxid then + -- Modded item + color = KColor(0.68, 0.88, 1, 1) + end + mod.font:DrawString("!", v.X - 1, v.Y - 52 + + math.sin(mod.game:GetFrameCount() / 10) * + 2, color, 2, true) + end + end + end end function mod:newrun() - if mod:HasData() then - local data = mod:LoadData() - if DEBUG then - mod.print(data.."\n") - end - save = savegen:new() - save:load(json, data) - else - save = savegen:new() - end - local c = 0 - for _,v in ipairs(save.seen) do - if v then c = c+1 end - end - mod.print(modname.." loaded, "..c.." vanilla items seen") - if save.settings.showonmodded then - local c = 0 - for _,v in pairs(save.seenmodded) do - if v then - c = c + 1 - end - end - mod.print(", "..tostring(c).." modded") - end - mod.print(".\n") + if mod:HasData() then + local data = mod:LoadData() + if DEBUG then mod.print(data .. "\n") end + save = savegen:new() + save:load(json, data) + else + save = savegen:new() + end + local c = 0 + for _, v in ipairs(save.seen) do if v then c = c + 1 end end + mod.print(modname .. " loaded, " .. c .. " vanilla items seen") + if save.settings.showonmodded then + local c = 0 + for _, v in pairs(save.seenmodded) do if v then c = c + 1 end end + mod.print(", " .. tostring(c) .. " modded") + end + mod.print(".\n") 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_STARTED, mod.newrun) @@ -159,86 +170,66 @@ mod:AddCallback(ModCallbacks.MC_POST_UPDATE, mod.update) mod:AddCallback(ModCallbacks.MC_POST_PICKUP_RENDER, mod.PickupDrawCallback) if EID then - EID:addDescriptionModifier( - modname, - mod.shouldBeModified, - mod.modifierCallback - ) + EID:addDescriptionModifier(modname, mod.shouldBeModified, + mod.modifierCallback) end if ModConfigMenu then - ModConfigMenu.AddSetting( - modname, -- This should be unique for your mod - nil, - { - Type = ModConfigMenu.OptionType.BOOLEAN, - CurrentSetting = function() - return save.settings.eid - end, - Display = function() - return "Show in EID: " .. (save.settings.eid and "on" or "off") - end, - OnChange = function(b) - save.settings.eid = b - mod:save() - end, - } - ) - ModConfigMenu.AddSetting( - modname, -- This should be unique for your mod - nil, - { - Type = ModConfigMenu.OptionType.BOOLEAN, - CurrentSetting = function() - return save.settings.visual - end, - Display = function() - return "Show on pedestals: " .. (save.settings.visual and "on" or "off") - end, - OnChange = function(b) - save.settings.visual = b - mod:save() - end, - } - ) + ModConfigMenu.AddSetting(modname, -- This should be unique for your mod + nil, { + Type = ModConfigMenu.OptionType.BOOLEAN, + CurrentSetting = function() return save.settings.eid end, + Display = function() + return "Show in EID: " .. (save.settings.eid and "on" or "off") + end, + OnChange = function(b) + save.settings.eid = b + mod:save() + end + }) + ModConfigMenu.AddSetting(modname, -- This should be unique for your mod + nil, { + Type = ModConfigMenu.OptionType.BOOLEAN, + CurrentSetting = function() return save.settings.visual end, + Display = function() + return "Show on pedestals: " .. + (save.settings.visual and "on" or "off") + end, + OnChange = function(b) + save.settings.visual = b + mod:save() + end + }) - ModConfigMenu.AddSetting( - modname, -- This should be unique for your mod - nil, - { - Type = ModConfigMenu.OptionType.BOOLEAN, - CurrentSetting = function() - return save.settings.showonmodded - end, - Display = function() - return "Also track modded items: " .. (save.settings.showonmodded and "on" or "off") - end, - OnChange = function(b) - save.settings.showonmodded = b - if b==false then - -- Reset modded items - save.seenmodded = {} - end - mod:save() - end, - } - ) + ModConfigMenu.AddSetting(modname, -- This should be unique for your mod + nil, { + Type = ModConfigMenu.OptionType.BOOLEAN, + CurrentSetting = function() return save.settings.showonmodded end, + Display = function() + return "Also track modded items: " .. + (save.settings.showonmodded and "on" or "off") + end, + OnChange = function(b) + save.settings.showonmodded = b + if b == false then + -- Reset modded items + save.seenmodded = {} + end + mod:save() + end + }) - ModConfigMenu.AddSetting( - modname, -- This should be unique for your mod - nil, - { - Type = ModConfigMenu.OptionType.BOOLEAN, - CurrentSetting = function() - return save.settings.showonblind - end, - Display = function() - return "Show while having Curse Of The Blind: " .. (save.settings.showonblind and "on" or "off") - end, - OnChange = function(b) - save.settings.showonblind = b - mod:save() - end, - } - ) + ModConfigMenu.AddSetting(modname, -- This should be unique for your mod + nil, { + Type = ModConfigMenu.OptionType.BOOLEAN, + CurrentSetting = function() return save.settings.showonblind end, + Display = function() + return "Show while having Curse Of The Blind: " .. + (save.settings.showonblind and "on" or "off") + end, + OnChange = function(b) + save.settings.showonblind = b + mod:save() + end + }) end diff --git a/metadata.xml b/metadata.xml index 422b936..a59dc24 100644 --- a/metadata.xml +++ b/metadata.xml @@ -3,7 +3,7 @@ DeadGod Helper deadgod helper 2985754961 - Spot missing items! + Spot missing items! 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. @@ -16,7 +16,7 @@ It is also compatible with Mod Config Menu, if you want to toggle things (such a 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. -Turns out EID already has 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 +Turns out EID already have 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 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.