Misc item reminder updates (#695)

* Change wisp checking

* Change selected item var

* Trinket and wisp checks

* add a simple room counter

* various changes

* update my todo list

* Gulped trinket support

* Reset selected items better

* update todo list

* add poop nuggets to pickup names

* add glyph of balance

* add a helper function for xml names

* overhaul special description modifiers

* Pandora's Box greed

* Pandora's Box tweak

* Pandora's Box overview desc

* let Card Reading Boss portal get modified

* move Strange Key to conditionals

* Update eid_conditionals.lua

* misc helper functions

* whitelists

* small text pos modifier tweaks

* wild card + glowing hourglass + void ab+

* move vurp, add wild card

* move SimpleRound

* add wild card, move simpleround, fix pill icon stuff

* Echo Chamber color

* update todo list

* starting work on The Stars? preview

* remove collectible count check; bad for tainted eden

* Tainted Laz overhaul

* fix 4.5 volt with timed pocket actives

* fix pocket active check functions

* Tainted Laz overhaul + The Stars?

* more conditionals

* Battery and bean synergies
This commit is contained in:
Buurazu authored and GitHub committed 2024-07-14 22:07:10 +02:00
1 parent 24a6a808ba
commit 9703626b71
12 files changed
+985 -383

No files matched your search

+195 -80
View File
@@ -756,7 +756,8 @@ function EID:replaceNameMarkupStrings(text)
if showIcon then iconText = "{{" .. EID:GetIconNameByVariant(entityID[2]) .. entityID[3] .. "}} " end
colorText = VariantToColorText[entityID[2]] or ""
end
name = iconText .. colorText .. EID:getObjectName(entityID[1], entityID[2], entityID[3]) .. "{{CR}}"
if entityID[2] == 70 then name = iconText .. colorText .. EID:getPillName(entityID[3], false) .. "{{CR}}"
else name = iconText .. colorText .. EID:getObjectName(entityID[1], entityID[2], entityID[3]) .. "{{CR}}" end
elseif indicator == "C" then -- Collectible
name = (showIcon and "{{Collectible"..id.."}} " or "") .. "{{ColorYellow}}" .. EID:getObjectName(5, 100, id) .. "{{CR}}"
elseif indicator == "T" then -- Trinket
@@ -837,8 +838,8 @@ function EID:createItemIconObject(str)
end
local pillID,numReplace4 = string.gsub(str, "Pill", "")
if numReplace4 > 0 and pillID ~= "" and tonumber(pillID) ~= nil then
if tonumber(pillID) > maxPillID then return EID.InlineIcons[str] or EID.InlineIcons["Pill"] end
return {"Pills", tonumber(pillID)-1, 9, 8, 0, 1, EID.CardPillSprite}
if tonumber(pillID % 2048) > maxPillID then return EID.InlineIcons[str] or EID.InlineIcons["Pill"] end
return {"Pills", tonumber(pillID % 2048)-1, 9, 8, 0, 1, EID.CardPillSprite}
end
if item == nil then
return nil
@@ -1266,14 +1267,15 @@ end
function EID:PlayersVoidedCollectible(collectibleID)
for i = 0, game:GetNumPlayers() - 1 do
local player = Isaac.GetPlayer(i)
if player:HasCollectible(477) and EID.absorbedItems[tostring(i)] and EID.absorbedItems[tostring(i)][tostring(collectibleID)] then
local playerNum = EID:getPlayerID(player, true)
if player:HasCollectible(477) and EID.absorbedItems[tostring(playerNum)] and EID.absorbedItems[tostring(playerNum)][tostring(collectibleID)] then
return true, player, i
end
end
return false
end
function EID:PlayerVoidedCollectible(player, collectibleID)
local i = EID:getPlayerID(player)
local i = EID:getPlayerID(player, true)
if player:HasCollectible(477) and EID.absorbedItems[tostring(i)] and EID.absorbedItems[tostring(i)][tostring(collectibleID)] then
return true
end
@@ -1375,6 +1377,24 @@ function EID:GetMaxCollectibleID()
return id
end
local maxTrinketID = nil
function EID:GetMaxTrinketID()
if maxTrinketID then
return maxTrinketID
end
local id = TrinketType.NUM_TRINKETS-1
local step = 16
while step > 0 do
if EID.itemConfig:GetTrinket(id+step) ~= nil then
id = id + step
else
step = step // 2
end
end
maxTrinketID = id
return id
end
function EID:DetectModdedItems()
if EID:GetMaxCollectibleID() > EID.XMLMaxItemID then
return true
@@ -1722,11 +1742,22 @@ function EID:checkPlayersForMissingItems()
end
end
function EID:getPlayerID(entityPlayer)
function EID:getPlayerID(entityPlayer, lazarusAdjust)
if not entityPlayer then return 0 end
for i = 0, game:GetNumPlayers() - 1 do
local player = Isaac.GetPlayer(i)
if GetPtrHash(player) == GetPtrHash(entityPlayer) then
-- Dead Tainted Lazarus exceptions
if lazarusAdjust and EID.isRepentance then
-- Check for Birthright to make the ghostly form use the same base ID as the main form
if player:GetMainTwin() then
if GetPtrHash(player:GetMainTwin()) ~= GetPtrHash(player) then
i = EID:getPlayerID(player:GetMainTwin())
end
end
-- Increase the ID by 666 if Dead Tainted Lazarus
if player:GetPlayerType() == 38 then i = i + 666 end
end
return i
end
end
@@ -1842,24 +1873,21 @@ EID.TransformationProgress = {}
function EID:evaluateTransformationProgress(transformation)
for i = 0, game:GetNumPlayers() - 1 do
local player = Isaac.GetPlayer(i)
EID.TransformationProgress[i] = {}
EID.TransformationProgress[i][transformation] = 0
local id = EID:getPlayerID(player, true) -- Dead Tainted Lazarus exception
EID.TransformationProgress[id] = {}
EID.TransformationProgress[id][transformation] = 0
local transformData = EID.TransformationData[transformation]
if not EID.TransformationLookup[transformation] then return end
if REPENTOGON and transformData and transformData.VanillaForm then
-- REPENTOGON lets us ignore everything else for vanilla transformation progress
EID.TransformationProgress[i][transformation] = player:GetPlayerFormCounter(transformData.VanillaForm)
EID.TransformationProgress[id][transformation] = player:GetPlayerFormCounter(transformData.VanillaForm)
elseif transformData and transformData.VanillaForm and player:HasPlayerForm(transformData.VanillaForm) then
EID.TransformationProgress[i][transformation] = transformData.NumNeeded or 3
EID.TransformationProgress[id][transformation] = transformData.NumNeeded or 3
else
local pickupHistory = EID.PlayerItemInteractions[i].pickupHistory
local pickupHistory = EID.PlayerItemInteractions[id].pickupHistory
local pillsTable = {}
-- Dead Tainted Lazarus exception
if player:GetPlayerType() == 38 then
pickupHistory = EID.PlayerItemInteractions[i].altPickupHistory or pickupHistory
end
if pickupHistory then
for j = 1, #pickupHistory do
if pickupHistory[j][1] == "pill" then
@@ -1872,38 +1900,35 @@ function EID:evaluateTransformationProgress(transformation)
end
end
local activesTable = EID.PlayerItemInteractions[i].actives
if player:GetPlayerType() == 38 then
activesTable = EID.PlayerItemInteractions[i].altActives or activesTable
end
local activesTable = EID.PlayerItemInteractions[id].actives
for entityString, _ in pairs(EID.TransformationLookup[transformation]) do
local eType, eVariant, eSubType = entityString:match("([^.]+).([^.]+).([^.]+)")
if tonumber(eType) == EntityType.ENTITY_PICKUP then
if tonumber(eVariant) == PickupVariant.PICKUP_COLLECTIBLE then
local currentCount = EID.TransformationProgress[i][transformation]
local currentCount = EID.TransformationProgress[id][transformation]
if activesTable[tostring(eSubType)] then
EID.TransformationProgress[i][transformation] = EID.TransformationProgress[i][transformation] + activesTable[tostring(eSubType)]
EID.TransformationProgress[id][transformation] = EID.TransformationProgress[id][transformation] + activesTable[tostring(eSubType)]
else
local collCount = player:GetCollectibleNum(eSubType, true)
if EID.PlayerItemInteractions[i].rerollItems then
collCount = collCount - (EID.PlayerItemInteractions[i].rerollItems[tostring(eSubType)] or 0)
if EID.PlayerItemInteractions[id].rerollItems then
collCount = collCount - (EID.PlayerItemInteractions[id].rerollItems[tostring(eSubType)] or 0)
end
EID.TransformationProgress[i][transformation] = EID.TransformationProgress[i][transformation] + collCount
EID.TransformationProgress[id][transformation] = EID.TransformationProgress[id][transformation] + collCount
-- Undo the Book of Virtues active item getting counted here
if tonumber(eSubType) == 584 and player:GetActiveItem() == 584 then
EID.TransformationProgress[i][transformation] = EID.TransformationProgress[i][transformation] - 1
EID.TransformationProgress[id][transformation] = EID.TransformationProgress[id][transformation] - 1
end
end
-- In AB+, only one copy of a given collectible is counted for trans
if not EID.isRepentance and EID.TransformationProgress[i][transformation] > currentCount + 1 then
EID.TransformationProgress[i][transformation] = currentCount + 1
if not EID.isRepentance and EID.TransformationProgress[id][transformation] > currentCount + 1 then
EID.TransformationProgress[id][transformation] = currentCount + 1
end
elseif tonumber(eVariant) == PickupVariant.PICKUP_TRINKET and player:HasTrinket(eSubType) then
EID.TransformationProgress[i][transformation] = EID.TransformationProgress[i][transformation] + player:GetTrinketMultiplier(eSubType)
EID.TransformationProgress[id][transformation] = EID.TransformationProgress[id][transformation] + player:GetTrinketMultiplier(eSubType)
elseif tonumber(eVariant) == PickupVariant.PICKUP_PILL then
if pillsTable[tostring(eSubType)] then
EID.TransformationProgress[i][transformation] = EID.TransformationProgress[i][transformation] + pillsTable[tostring(eSubType)]
EID.TransformationProgress[id][transformation] = EID.TransformationProgress[id][transformation] + pillsTable[tostring(eSubType)]
end
end
end
@@ -1941,23 +1966,25 @@ EID.RecentlyTouchedItems = {}
local hadQueuedItem = {}
function EID:evaluateQueuedItems()
for i = 0, game:GetNumPlayers() - 1 do
EID:InitItemInteractionIfAbsent(i)
local player = Isaac.GetPlayer(i)
local id = EID:getPlayerID(player, true)
EID:InitItemInteractionIfAbsent(id)
if player.QueuedItem then
-- Refresh our descriptions and grid entity list upon a queued passive item being added to a player
if not player.QueuedItem.Item and hadQueuedItem[i] then
if not player.QueuedItem.Item and hadQueuedItem[id] then
EID.ForceRefreshCache = true
EID:CheckCurrentRoomGridEntities()
end
hadQueuedItem[i] = player.QueuedItem.Item ~= nil
if EID.PlayerItemInteractions[i].LastTouch + 45 >= game:GetFrameCount() and player.QueuedItem.Item then
hadQueuedItem[id] = player.QueuedItem.Item ~= nil
if EID.PlayerItemInteractions[id].LastTouch + 45 >= game:GetFrameCount() and player.QueuedItem.Item then
return
else
EID.PlayerItemInteractions[i].LastTouch = 0
EID.PlayerItemInteractions[id].LastTouch = 0
end
if not player.QueuedItem.Touched and player.QueuedItem.Item then
EID.PlayerItemInteractions[i].LastTouch = game:GetFrameCount()
EID.PlayerItemInteractions[id].LastTouch = game:GetFrameCount()
local itemIDStr = tostring(player.QueuedItem.Item.ID)
-- Add touched active items to our transformation progress table
if player.QueuedItem.Item.Type == ItemType.ITEM_ACTIVE then
@@ -1965,24 +1992,23 @@ function EID:evaluateQueuedItems()
-- (Fixes co-op bugs, compared to only initiating it for the toucher)
for j = 0, game:GetNumPlayers() - 1 do
EID.PlayerItemInteractions[j].actives[itemIDStr] = EID.PlayerItemInteractions[j].actives[itemIDStr] or 0
EID.PlayerItemInteractions[j].altActives[itemIDStr] = EID.PlayerItemInteractions[j].altActives[itemIDStr] or 0
end
-- Dead Tainted Lazarus exceptions
local activesTable = EID.PlayerItemInteractions[i].actives
if player:GetPlayerType() == 38 then
activesTable = EID.PlayerItemInteractions[i].altActives or activesTable
EID.PlayerItemInteractions[j+666].actives[itemIDStr] = EID.PlayerItemInteractions[j+666].actives[itemIDStr] or 0
end
local activesTable = EID.PlayerItemInteractions[id].actives
EID.ForceRefreshCache = true
activesTable[itemIDStr] = activesTable[itemIDStr] + 1
elseif player.QueuedItem.Item.Type ~= ItemType.ITEM_TRINKET then
-- In AB+, Halo of Flies is counted as an active item due to inaccuracy with GetCollectibleNum
if (not EID.isRepentance and itemIDStr == "10") then
EID.PlayerItemInteractions[i].actives[itemIDStr] = EID.PlayerItemInteractions[i].actives[itemIDStr] + 1
EID.PlayerItemInteractions[id].actives[itemIDStr] = EID.PlayerItemInteractions[id].actives[itemIDStr] + 1
end
-- Put non-active item pickups into the recent item list, for printing in the Item Reminder
table.insert(EID.RecentlyTouchedItems[i], player.QueuedItem.Item.ID)
EID.ItemReminderSelectedItem = 0
local playerID = i
if EID.isRepentance and player:GetPlayerType() == 38 then playerID = playerID + 666 end
table.insert(EID.RecentlyTouchedItems[playerID], player.QueuedItem.Item.ID)
EID:ResetItemReminderSelectedItems("Passives")
EID.ItemReminderSelectedItems[#EID.ItemReminderCategories - 1] = 0
end
end
end
@@ -1991,15 +2017,17 @@ end
-- if the player ItemInteraction table doesnt exist, create it with its init values
function EID:InitItemInteractionIfAbsent(playerID)
playerID = playerID % 666 -- dead tainted lazarus exception
if not EID.PlayerItemInteractions[playerID] then
EID.PlayerItemInteractions[playerID] = { LastTouch = 0, actives = {}, altActives = {},
pickupHistory = {}, altPickupHistory = {}, rerollItems = {} }
EID.PlayerItemInteractions[playerID] = { LastTouch = 0, actives = {}, pickupHistory = {}, rerollItems = {} }
EID.PlayerItemInteractions[playerID+666] = { LastTouch = 0, actives = {}, pickupHistory = {}, rerollItems = {} }
-- in AB+, initiate Halo of Flies as an active item (collectible ID 10 is used for ALL Pretty Flies)
if not EID.isRepentance then
EID.PlayerItemInteractions[playerID].actives["10"] = 0
end
end
EID.RecentlyTouchedItems[playerID] = EID.RecentlyTouchedItems[playerID] or {}
EID.RecentlyTouchedItems[playerID+666] = EID.RecentlyTouchedItems[playerID+666] or {}
end
@@ -2051,19 +2079,33 @@ function EID:AddPickupToHistory(pickupType, effectID, player, useFlags, pillColo
if EID.isRepentance and (useFlags & UseFlag.USE_MIMIC == UseFlag.USE_MIMIC or useFlags & UseFlag.USE_NOANNOUNCER == UseFlag.USE_NOANNOUNCER) then
allowEchoChamber = false
end
local playerID = EID:getPlayerID(player)
local playerID = EID:getPlayerID(player, true)
EID:InitItemInteractionIfAbsent(playerID)
local historyTable = EID.PlayerItemInteractions[playerID].pickupHistory
-- Dead Tainted Lazarus exception
if player:GetPlayerType() == 38 then
historyTable = EID.PlayerItemInteractions[playerID].altPickupHistory or historyTable
end
-- pickupType = ["pill","card"], pillColorID, effectID, hadEchoChamberWhenUsed
table.insert(historyTable, 1, {pickupType, pillColorID, effectID, EID.isRepentance and player:HasCollectible(700) and allowEchoChamber})
end
EID.WildCardEffects = {}
EID.WildCardPillColor = {}
EID.TemporaryWildCardEffects = {} -- resets every frame
function EID:TrackWildCardEffects(effectID, player, pillColor)
local playerID = EID:getPlayerID(player, true)
-- ? Card exception; both it and the active it used are ignored by Wild Card
if effectID == "5.300.48" then
-- Blank Card using ? Card exception; Blank Card being used is still seen
if EID.TemporaryWildCardEffects[playerID] ~= "5.100.286" then EID.TemporaryWildCardEffects[playerID] = nil end
else
EID.TemporaryWildCardEffects[playerID] = effectID
EID.WildCardPillColor[playerID] = pillColor -- doesn't matter that much so just set it here
end
end
function EID:UpdateWildCardEffects()
for k,v in pairs(EID.TemporaryWildCardEffects) do EID.WildCardEffects[k] = v end
EID.TemporaryWildCardEffects = {}
end
-- Render a sprite of an entity
function EID:RenderEntity(entity, sprite, position)
if entity.Type == 5 and entity.Variant == 100 then
@@ -2087,7 +2129,7 @@ end
-- Collects items that the player got after using D4 item
function EID:CollectRerolledItemsOfPlayer(player)
if maxCollectibleID == nil then maxCollectibleID = EID:GetMaxCollectibleID() end
local playerID = EID:getPlayerID(player)
local playerID = EID:getPlayerID(player, true)
EID.PlayerItemInteractions[playerID].rerollItems = {}
for i = 1, maxCollectibleID do
local count = player:GetCollectibleNum(i, true)
@@ -2118,6 +2160,10 @@ end
function EID:GetEntityXMLName(Type, Variant, SubType)
return EID.XMLEntityNames[Type.."."..Variant] or EID.XMLEntityNames[Type.."."..Variant.."."..SubType]
end
function EID:GetEntityXMLNameByString(tvsString)
local Type, Var, Sub = EID:SplitTVS(tvsString)
return EID:GetEntityXMLName(Type, Var, Sub)
end
-- Get an item's RNG seed. We have no use for the RNG object itself because every other function it can do will advance the item's RNG, altering the game state
function EID:GetItemSeed(player, id, variant)
@@ -2177,44 +2223,90 @@ function EID:UpdateAllPlayerPassiveItems()
local listUpdatedForPlayers = {}
for i = 1, #EID.coopAllPlayers do
local player = EID.coopAllPlayers[i]
local playerNum = EID:getPlayerID(player)
if player == nil then
return listUpdatedForPlayers -- dont evaluate when bad data is present
end
-- only update if collectible number changed
local currentCollectibleCount = player:GetCollectibleCount()
if #EID.RecentlyTouchedItems[playerNum] ~= currentCollectibleCount then
-- remove items the player no longer has. reverse itteration to make deletion easier
for index = #EID.RecentlyTouchedItems[playerNum], 1, -1 do
if not player:HasCollectible(EID.RecentlyTouchedItems[playerNum][index], true) then
table.remove(EID.RecentlyTouchedItems[playerNum], index)
listUpdatedForPlayers[i] = true
end
local playerNum = EID:getPlayerID(player, true)
-- remove items the player no longer has. reverse iteration to make deletion easier
for index = #EID.RecentlyTouchedItems[playerNum], 1, -1 do
if not player:HasCollectible(EID.RecentlyTouchedItems[playerNum][index], true) then
table.remove(EID.RecentlyTouchedItems[playerNum], index)
listUpdatedForPlayers[i] = true
-- If an item earlier than our oldest item is removed (e.g. Eve sacrificial altaring her Dead Bird), reduce it
if index < EID.OldestItemIndex[playerNum] then EID.OldestItemIndex[playerNum] = EID.OldestItemIndex[playerNum] - 1 end
end
end
-- add items the player did get with non-standard methods (console command, item effects, etc...)
for _, itemID in ipairs(passives) do
if player:HasCollectible(itemID, true) then
local alreadyInList = false
for _, heldItemID in ipairs(EID.RecentlyTouchedItems[playerNum]) do
if itemID == heldItemID then
alreadyInList = true
break
end
end
if not alreadyInList then
table.insert(EID.RecentlyTouchedItems[playerNum], itemID)
listUpdatedForPlayers[i] = true
-- add items the player did get with non-standard methods (console command, item effects, etc...)
for _, itemID in ipairs(passives) do
if player:HasCollectible(itemID, true) then
local alreadyInList = false
for _, heldItemID in ipairs(EID.RecentlyTouchedItems[playerNum]) do
if itemID == heldItemID then
alreadyInList = true
break
end
end
if not alreadyInList then
table.insert(EID.RecentlyTouchedItems[playerNum], itemID)
listUpdatedForPlayers[i] = true
end
end
end
end
return listUpdatedForPlayers
end
EID.OldestItemIndex = {}
function EID:SetOldestItemIndex()
for i = 0, game:GetNumPlayers() - 1 do
EID.RecentlyTouchedItems[i] = EID.RecentlyTouchedItems[i] or {}
if EID.OldestItemIndex[i] == nil then EID.OldestItemIndex[i] = #EID.RecentlyTouchedItems[i] + 1 end
-- set up Dead Tainted Lazarus to be oldest slot 1
if EID.OldestItemIndex[i+666] == nil then EID.OldestItemIndex[i+666] = 1 end
end
end
EID.GulpedTrinkets = {}
-- Check for gulped trinkets that have been removed (e.g. perfection, walnut)
function EID:UpdateAllPlayerTrinkets()
for i = 1, #EID.coopAllPlayers do
local player = EID.coopAllPlayers[i]
if player == nil then return end
local playerNum = EID:getPlayerID(player, true)
if EID.GulpedTrinkets[playerNum] == nil then return end
-- remove items the player no longer has. reverse iteration to make deletion easier
for index = #EID.GulpedTrinkets[playerNum], 1, -1 do
if not player:HasTrinket(EID.GulpedTrinkets[playerNum][index]) then
table.remove(EID.GulpedTrinkets[playerNum], index)
end
end
end
end
EID.WispsPerPlayer = {}
-- This is automatically called shortly after main.lua sees a Lemegeton get used, and when the Item Reminder is opened
function EID:UpdateAllPlayerLemegetonWisps()
EID.WispsPerPlayer = {}
for _, wisp in ipairs(Isaac.FindByType(3, 237, -1, true, false)) do
local wispPlayer = wisp:ToFamiliar() and wisp:ToFamiliar().Player
if wispPlayer then
local playerNum = EID:getPlayerID(wispPlayer, true)
EID.WispsPerPlayer[playerNum] = EID.WispsPerPlayer[playerNum] or {}
table.insert(EID.WispsPerPlayer[playerNum], wisp)
end
end
-- Sort wisps by age (newest first), and leave just the IDs
for playerNum,wisps in pairs(EID.WispsPerPlayer) do
table.sort(wisps, function(a, b) return a.FrameCount < b.FrameCount end)
for i,v in ipairs(wisps) do wisps[i] = v.SubType end
end
end
-- Replaces Variable placeholders in string with a given value
-- Example: "My {1} message" --> "My test message"
@@ -2222,3 +2314,26 @@ function EID:ReplaceVariableStr(str, varID, newString)
if type(str) ~= "string" or newString == nil then return str end
return str:gsub("{"..varID.."}", newString)
end
-- deep table copy, copied from http://lua-users.org/wiki/CopyTable
function EID:CopyTable(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[EID:CopyTable(orig_key)] = EID:CopyTable(orig_value)
end
setmetatable(copy, EID:CopyTable(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
-- simple decimal rounding, instead of just floor or ceil
function EID:SimpleRound(num, dp)
dp = dp or 2
local mult = 10^dp
return math.floor(num * mult + 0.5)/mult
end