Merge branch 'wofsauge:master' into master

This commit is contained in:
wakaba (aka. 미카) authored and GitHub committed 2022-03-07 11:16:35 +09:00
commit 87e7261a62
12 files changed
+557 -282

No files matched your search

+4 -4
View File
@@ -58,9 +58,9 @@ EID.descriptions[languageCode].collectibles={
{"36", "The Poop", "Spawns one poop and knocks back enemies#Can be placed next to a pit and destroyed with a bomb to make a bridge"},
{"37", "Mr. Boom", "Drops a large bomb below the player which deals 110 damage"},
{"38", "Tammy's Head", "Fires 10 tears in a circle around Isaac"},
{"39", "Mom's Bra", "Freeze all enemies in the current room for 4 secs"},
{"39", "Mom's Bra", "Freeze all enemies in the current room for 4 seconds"},
{"40", "Kamikaze!", "Causes an explosion at the players location#Deals 40 damage"},
{"41", "Mom's Pad", "Fears all enemies in the current room for 5 secs"},
{"41", "Mom's Pad", "Fears all enemies in the current room for 5 seconds"},
{"42", "Bob's Rotten Head", "Throwable poison bomb"},
{"43", "", "<item does not exist>"},
{"44", "Teleport!", "Teleports Isaac into a random room except I AM ERROR rooms"},
@@ -77,7 +77,7 @@ EID.descriptions[languageCode].collectibles={
{"55", "Mom's Eye", "50% chance to shoot a tear backwards#100% chance at 2 Luck"},
{"56", "Lemon Mishap", "Drop a pool of lemonade#Deals 66 contact damage per second"},
{"57", "Distant Admiration", "Mid-range fly orbital#Deals 75 contact damage per second"},
{"58", "Book of Shadows", "Invincibility for 10 secs"},
{"58", "Book of Shadows", "Invincibility for 10 seconds"},
{"59", "", "<item does not exist>"},
{"60", "The Ladder", "Walk over small gaps"},
{"61", "", "<item does not exist>"},
@@ -85,7 +85,7 @@ EID.descriptions[languageCode].collectibles={
{"63", "The Battery", "Active items can now be charged up twice"},
{"64", "Steam Sale", "-50% on shop items#Getting this item two times will make everything free"},
{"65", "Anarchist Cookbook", "Spawn 6 troll bombs near the center of the room"},
{"66", "The Hourglass", "Slow down enemies for 8 secs"},
{"66", "The Hourglass", "Slow down enemies for 8 seconds"},
{"67", "Sister Maggy", "Normal tear familiar#Deals 3.5 damage per tear"},
{"68", "Technology", "Tears are now lasers"},
{"69", "Chocolate Milk", "Chargeable tears#↑ Up to 400% Damage#↓ Tears down"},
+24 -4
View File
@@ -62,7 +62,10 @@ local dynamicSpriteCache = {} -- used to store sprite objects of collectible ico
function EID:addCollectible(id, description, itemName, language)
itemName = itemName or nil
language = language or "en_us"
EID.descriptions[language].custom["5.100." .. id] = {id, itemName, description, EID._currentMod}
modName = EID._currentMod
-- Glitched Items exception so they don't have a mod name
if id > 4294960000 then modName = nil end
EID.descriptions[language].custom["5.100." .. id] = {id, itemName, description, modName}
end
-- Adds a description for a trinket. Optional parameters: itemName, language
@@ -708,7 +711,7 @@ function EID:renderIcon(spriteObj, posX, posY, callback, animName, animFrame)
end
if EID.CachingDescription then
table.insert(EID.CachedIcons, {spriteObj, posX, posY, callback, animName, animFrame})
table.insert(EID.CachedIcons[#EID.CachedIcons], {spriteObj, posX, posY, callback, animName, animFrame})
end
spriteObj:Render(Vector(posX, posY), nullVector, nullVector)
@@ -901,7 +904,7 @@ function EID:renderString(str, position, scale, kcolor)
EID:renderInlineIcons(spriteTable, position.X + offsetX, position.Y)
EID.font:DrawStringScaledUTF8(strFiltered, position.X + offsetX, position.Y, scale.X, scale.Y, textPart[2], 0, false)
if EID.CachingDescription then
table.insert(EID.CachedStrings, {strFiltered, position.X + offsetX, position.Y, textPart[2], textPart[4], EID.Config["Transparency"]})
table.insert(EID.CachedStrings[#EID.CachedStrings], {strFiltered, position.X + offsetX, position.Y, textPart[2], textPart[4], EID.Config["Transparency"]})
end
offsetX = offsetX + EID:getStrWidth(strFiltered) * scale.X
end
@@ -959,7 +962,7 @@ function EID:PlayersHaveCollectible(collectibleID)
for i = 0, game:GetNumPlayers() - 1 do
local player = Isaac.GetPlayer(i)
if player:HasCollectible(collectibleID) then
return true
return true, player
end
end
return false
@@ -1407,3 +1410,20 @@ function EID:removeIgnoredEntity(entityType, entityVariant, entitySubType)
EID.IgnoredEntities[entityType.."."..entityVariant.."."..entitySubType] = nil
end
end
-- Returns if this is a frame we should refresh our descriptions
function EID:RefreshThisFrame()
if EID.GameRenderCount % (60 / EID.Config["RefreshRate"]) == 0 then
return true
end
return false
end
-- Returns true if any player is pressing the given button (you can also specify any of the input functions)
function EID:PlayersActionPressed(button, inputFunc)
inputFunc = inputFunc or Input.IsActionPressed
for k,_ in pairs(EID.controllerIndexes) do
if inputFunc(button, k) then return true end
end
return false
end
+41 -38
View File
@@ -84,7 +84,7 @@ local pickupIDLookup = {
local function IsTaintedCain()
-- this check is necessary for tracking Bag usage since Tainted Cain's pocket bag works differently than everyone else's
return EID.player:GetPlayerType() == 23
return EID.bagPlayer:GetPlayerType() == 23
end
local componentShifts = {
@@ -597,15 +597,15 @@ end)
local holdCounter = 0
local function trackBagHolding()
if not IsTaintedCain() then return end
local isCardHold = Input.IsActionPressed(ButtonAction.ACTION_PILLCARD, EID.player.ControllerIndex)
local animationName = EID.player:GetSprite():GetAnimation()
local isCardHold = Input.IsActionPressed(ButtonAction.ACTION_PILLCARD, EID.bagPlayer.ControllerIndex)
local animationName = EID.bagPlayer:GetSprite():GetAnimation()
if isCardHold and string.match(animationName, "PickupWalk") and #EID.BagItems>=8 then
holdCounter = holdCounter + 1
if holdCounter < 30 then
icount = EID.player:GetCollectibleCount()
icount = EID.bagPlayer:GetCollectibleCount()
end
else
if isCardHold and holdCounter >= 30 and (string.match(animationName, "Walk") and not string.match(animationName, "Pickup") or (EID.player:GetCollectibleCount() ~= icount)) then
if isCardHold and holdCounter >= 30 and (string.match(animationName, "Walk") and not string.match(animationName, "Pickup") or (EID.bagPlayer:GetCollectibleCount() ~= icount)) then
EID.BagItems = {}
else
holdCounter = 0
@@ -629,7 +629,7 @@ local function shiftBagContent()
end
-- only Tainted Cain's consumable slot bag can have its ingredients shifted
local function detectBagContentShift()
if Input.IsActionTriggered(ButtonAction.ACTION_DROP, EID.player.ControllerIndex) and IsTaintedCain() then
if Input.IsActionTriggered(ButtonAction.ACTION_DROP, EID.bagPlayer.ControllerIndex) and IsTaintedCain() then
shiftBagContent()
end
end
@@ -712,7 +712,7 @@ local function getHotkeyString()
local hideDesc = EID:getDescriptionEntry("CraftingHideKey")
local previewDesc = EID:getDescriptionEntry("CraftingPreviewKey")
local controllerEnabled = EID.player.ControllerIndex > 0
local controllerEnabled = EID.bagPlayer.ControllerIndex > 0
local hideKey = HotkeyToString[EID.Config["CraftingHideKey"]]
local hideButton = controllerEnabled and ControllerToString[EID.Config["CraftingHideButton"]]
local previewKey = HotkeyToString[EID.Config["CraftingResultKey"]]
@@ -858,7 +858,8 @@ local function RecipeCrunchCoroutine()
EID.RefreshBagTextbox = true
end
function EID:handleBagOfCraftingRendering()
-- Called 60 times a second so we can read input properly
function EID:handleBagOfCraftingUpdating()
-- reset our calculated recipes when the game seed changes
local curSeed = game:GetSeeds():GetStartSeed()
if (curSeed ~= lastSeedUsed) then
@@ -875,36 +876,34 @@ function EID:handleBagOfCraftingRendering()
detectBagContentShift()
if EID.GameRenderCount % 2 == 0 then checkForPickups() end
-- load the function we need for Show Recipes as Groups / 8 Icons
local tableToCraftingIconsFunc = EID.tableToCraftingIconsMerged
if EID.Config["BagOfCraftingDisplayIcons"] then tableToCraftingIconsFunc = EID.tableToCraftingIconsFull end
-- Check for Hide/Preview hotkeys; prevent them from triggering while in MCM
if not ModConfigMenu or not ModConfigMenu.IsVisible then
if Input.IsButtonTriggered(EID.Config["CraftingHideKey"], 0) or Input.IsButtonTriggered(EID.Config["CraftingHideButton"], EID.player.ControllerIndex) then
if Input.IsButtonTriggered(EID.Config["CraftingHideKey"], 0) or Input.IsButtonTriggered(EID.Config["CraftingHideButton"], EID.bagPlayer.ControllerIndex) then
craftingIsHidden = not craftingIsHidden
end
if Input.IsButtonTriggered(EID.Config["CraftingResultKey"], 0) or Input.IsButtonTriggered(EID.Config["CraftingResultButton"], EID.player.ControllerIndex) then
if Input.IsButtonTriggered(EID.Config["CraftingResultKey"], 0) or Input.IsButtonTriggered(EID.Config["CraftingResultButton"], EID.bagPlayer.ControllerIndex) then
showCraftingResult = not showCraftingResult
end
end
end
-- Called when needed based on EID.Config["RefreshRate"]
function EID:handleBagOfCraftingRendering()
-- Determine if we should display anything at all
if ((EID.isHidden or craftingIsHidden) and EID.MCMCompat_isDisplayingEIDTab ~= "Crafting") or game.Challenge == Challenge.CHALLENGE_CANTRIPPED then
return
return false
elseif not EID:RefreshThisFrame() then
return false
elseif EID.Config["BagOfCraftingHideInBattle"] then
if Isaac.CountBosses() > 0 or Isaac.CountEnemies() > 0 then
return
return false
end
end
if EID.Config["DisplayBagOfCrafting"] == "never" then
elseif EID.Config["DisplayBagOfCrafting"] == "never" then
return false
end
if EID.Config["DisplayBagOfCrafting"] == "hold" and not string.find(EID.player:GetSprite():GetAnimation(), "PickupWalk") then
elseif EID.Config["DisplayBagOfCrafting"] == "hold" and not string.find(EID.bagPlayer:GetSprite():GetAnimation(), "PickupWalk") then
return false
end
if game:GetRoom():GetFrameCount() < 2 then
elseif game:GetRoom():GetFrameCount() < 2 then
return false
end
@@ -922,7 +921,7 @@ function EID:handleBagOfCraftingRendering()
EID:appendToDescription(descriptionObj,"#" .. backupDesc .. "#{{Collectible" .. backupResult .. "}} " ..
backupObjName .. "#{{Blank}} " .. tabText)
end
EID:printDescription(descriptionObj)
EID:addDescriptionToPrint(descriptionObj)
return true
end
-- if we're in Preview Only mode, then we have nothing more to do
@@ -981,16 +980,20 @@ function EID:handleBagOfCraftingRendering()
local customDescObj = EID:getDescriptionObj(5, 100, 710)
customDescObj.Description = ""
-- load the function we need for Show Recipes as Groups / 8 Icons
local tableToCraftingIconsFunc = EID.tableToCraftingIconsMerged
if EID.Config["BagOfCraftingDisplayIcons"] then tableToCraftingIconsFunc = EID.tableToCraftingIconsFull end
-- Pickups Only / No Recipes Mode display
if EID.Config["BagOfCraftingDisplayMode"] == "Pickups Only" then
EID:appendToDescription(customDescObj, getHotkeyString())
EID:appendToDescription(customDescObj, getFloorItemsString(false, roomItems))
EID:printDescription(customDescObj)
EID:addDescriptionToPrint(customDescObj)
return true
elseif EID.Config["BagOfCraftingDisplayMode"] == "No Recipes" then
if not EID.RefreshBagTextbox and prevDesc ~= "" and not EID.OptionChanged then
EID:appendToDescription(customDescObj, prevDesc)
EID:printDescription(customDescObj)
EID:addDescriptionToPrint(customDescObj)
return true
end
@@ -1013,7 +1016,7 @@ function EID:handleBagOfCraftingRendering()
if (bestQuality > bagQuality) then prevDesc = prevDesc .. bestQualityDesc .. " " .. bestQuality .. "#{{Blank}} " .. tableToCraftingIconsFunc(self,mostValuableBag, true) .. "#" .. bestResult .. "#" end
EID:appendToDescription(customDescObj, prevDesc)
EID:printDescription(customDescObj)
EID:addDescriptionToPrint(customDescObj)
return true
end
@@ -1064,35 +1067,35 @@ function EID:handleBagOfCraftingRendering()
end
local prevOffset = bagOfCraftingOffset
if Input.IsActionPressed(EID.Config["BagOfCraftingToggleKey"], EID.player.ControllerIndex) then
EID.player.ControlsCooldown = 2
if Input.IsActionTriggered(ButtonAction.ACTION_SHOOTDOWN, EID.player.ControllerIndex) then
if Input.IsActionPressed(EID.Config["BagOfCraftingToggleKey"], EID.bagPlayer.ControllerIndex) then
EID.bagPlayer.ControlsCooldown = 2
if Input.IsActionTriggered(ButtonAction.ACTION_SHOOTDOWN, EID.bagPlayer.ControllerIndex) then
bagOfCraftingOffset = math.min(numResults-(numResults%EID.Config["BagOfCraftingResults"]), bagOfCraftingOffset + EID.Config["BagOfCraftingResults"])
downHeld = Isaac.GetTime()
elseif Input.IsActionTriggered(ButtonAction.ACTION_SHOOTUP, EID.player.ControllerIndex) then
elseif Input.IsActionTriggered(ButtonAction.ACTION_SHOOTUP, EID.bagPlayer.ControllerIndex) then
bagOfCraftingOffset = math.max(0, bagOfCraftingOffset - EID.Config["BagOfCraftingResults"])
upHeld = Isaac.GetTime()
--lock the current results so you can actually do a recipe that you've scrolled down to without losing it
elseif Input.IsActionTriggered(ButtonAction.ACTION_SHOOTLEFT, EID.player.ControllerIndex) then
elseif Input.IsActionTriggered(ButtonAction.ACTION_SHOOTLEFT, EID.bagPlayer.ControllerIndex) then
EID.RefreshBagTextbox = true
if (lockedResults == nil) then lockedResults = queryString
else lockedResults = nil end
--refresh the recipes
elseif Input.IsActionTriggered(ButtonAction.ACTION_SHOOTRIGHT, EID.player.ControllerIndex) then
elseif Input.IsActionTriggered(ButtonAction.ACTION_SHOOTRIGHT, EID.bagPlayer.ControllerIndex) then
if (lockedResults == nil) then
refreshNextTick = true
end
end
--scroll pages quickly if the button is held
if Input.IsActionPressed(ButtonAction.ACTION_SHOOTDOWN, EID.player.ControllerIndex) and Isaac.GetTime() - downHeld > 750 then
if Input.IsActionPressed(ButtonAction.ACTION_SHOOTDOWN, EID.bagPlayer.ControllerIndex) and Isaac.GetTime() - downHeld > 750 then
bagOfCraftingOffset = math.min(numResults-(numResults%EID.Config["BagOfCraftingResults"]), bagOfCraftingOffset + EID.Config["BagOfCraftingResults"])
downHeld = Isaac.GetTime() - 700
elseif Input.IsActionPressed(ButtonAction.ACTION_SHOOTUP, EID.player.ControllerIndex) and Isaac.GetTime() - upHeld > 750 then
elseif Input.IsActionPressed(ButtonAction.ACTION_SHOOTUP, EID.bagPlayer.ControllerIndex) and Isaac.GetTime() - upHeld > 750 then
bagOfCraftingOffset = math.max(0, bagOfCraftingOffset - EID.Config["BagOfCraftingResults"])
upHeld = Isaac.GetTime() - 700
end
--reset bag contents when holding Use Pill/Card
if Input.IsActionPressed(ButtonAction.ACTION_PILLCARD, EID.player.ControllerIndex) then
if Input.IsActionPressed(ButtonAction.ACTION_PILLCARD, EID.bagPlayer.ControllerIndex) then
resetBagCounter = resetBagCounter + 1
if resetBagCounter > 120 then
EID.BagItems = {}
@@ -1108,7 +1111,7 @@ function EID:handleBagOfCraftingRendering()
if not EID.RefreshBagTextbox and prevDesc ~= "" and bagOfCraftingOffset == prevOffset and not EID.OptionChanged then
EID:appendToDescription(customDescObj, prevDesc)
EID:printDescription(customDescObj)
EID:addDescriptionToPrint(customDescObj)
return true
end
@@ -1173,6 +1176,6 @@ function EID:handleBagOfCraftingRendering()
end
EID:appendToDescription(customDescObj, prevDesc)
EID:printDescription(customDescObj)
EID:addDescriptionToPrint(customDescObj)
return true
end
+26 -4
View File
@@ -76,6 +76,11 @@ EID.UserConfig = {
-- Hide the descriptions when in battle
-- Default = false
["HideInBattle"] = false,
-- How many times a second that EID checks for what objects are close to the player
-- Lowering this number can help if you experience frame drops while descriptions are on-screen
-- Please use a factor of 60! (1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60)
-- Default: 30
["RefreshRate"] = 30,
-- Toggle obstruction based hiding, when the player has flight
-- Default = true
["DisableObstructionOnFlight"] = true,
@@ -83,6 +88,19 @@ EID.UserConfig = {
-- Current warnings are: Achievements are locked, outdated game version, and potentially having inaccurate modded Bag of Crafting recipes
-- Default = false
["DisableStartOfRunWarnings"] = false,
---------- Co-op / Multiple Descriptions -----------
-- Allow P2/P3/P4 to display descriptions when in Co-op mode
-- Default = true
["CoopDescriptions"] = true,
-- Allow the paired player of certain characters in Repentance (Esau, Tainted Forgotten's bone pile) to display descriptions
-- Default = false
["PairedPlayerDescriptions"] = false,
-- Display a description for every object within range of you, instead of just the closest
-- Default = false
["DisplayAllNearby"] = false,
-- Any descriptions displayed beyond the first one will use the "Local" display mode
---------- Display Modes -----------
@@ -209,8 +227,8 @@ EID.UserConfig = {
-- Note: The --luadebug launch option is required for more detailed glitched item descriptions
-- This option allows mods to have access to your files and should be turned on at your own risk!
-- Without --luadebug, you still can see the effect the item will have on your Hearts, and what stats it might modify
-- Default = true
["DisplayGlitchedItemInfo"] = true,
-- Default = false
["DisplayGlitchedItemInfo"] = false,
---------- Sacrifice Room ----------
@@ -304,7 +322,7 @@ EID.UserConfig = {
["CraftingResultButton"] = -1,
---------- Mouse Controls ------------
---------- Save Game Options ------------
-- Savegame which should be used for savegame specific features (for example: Item Collection page progress)
-- Possible values: 0,1,2,3
@@ -398,8 +416,12 @@ EID.DefaultConfig = {
["HideButton"] = -1,
["InitiallyHidden"] = false,
["HideInBattle"] = false,
["RefreshRate"] = 30,
["DisableObstructionOnFlight"] = true,
["DisableStartOfRunWarnings"] = false,
["CoopDescriptions"] = true,
["PairedPlayerDescriptions"] = false,
["DisplayAllNearby"] = false,
["DisableOnCurse"] = true,
["DisableOnAltPath"] = true,
["DisableOnAprilFoolsChallenge"] = true,
@@ -427,7 +449,7 @@ EID.DefaultConfig = {
["DisplayPillInfoOptions?"] = true,
["DisplayObstructedPillInfo"] = false,
["ShowUnidentifiedPillDescriptions"] = false,
["DisplayGlitchedItemInfo"] = true,
["DisplayGlitchedItemInfo"] = false,
["DisplaySacrificeInfo"] = true,
["DisplayDiceInfo"] = true,
["DisplayBagOfCrafting"] = "always",
+5 -2
View File
@@ -65,6 +65,8 @@ local function TabCallback(descObj)
EID.inModifierPreview = true
local descEntry = EID:getDescriptionObj(5, 100, EID.TabPreviewID)
EID.inModifierPreview = false
descEntry.Entity = descObj.Entity
EID.TabPreviewID = 0
return descEntry
end
@@ -498,9 +500,10 @@ local function EIDConditionsAB(descObj)
end
EID:addDescriptionModifier("EID Afterbirth+", EIDConditionsAB, nil)
-- should this be done differently so that mods can add tab previews?
-- should this be done differently so that mods can add tab previews? (tab conditions is done last, but would be done before callbacks mods add, maybe tab should be checked in EID:getDescriptionObj
local function TabConditions(descObj)
if EID.player and Input.IsActionPressed(ButtonAction.ACTION_MAP, EID.player.ControllerIndex) and not EID.inModifierPreview then return true end
if EID:PlayersActionPressed(ButtonAction.ACTION_MAP) and not EID.inModifierPreview then return true end
EID.TabPreviewID = 0
return false
end
+4 -1
View File
@@ -75,7 +75,10 @@ local function parseEffectLine(raw)
if (i ~= #words) then name = name .. " " end
end
replacements[1] = "{{Collectible" .. Isaac.GetItemIdByName(name) .. "}} " .. name
replacements[1] = name
if (Isaac.GetItemIdByName(name) > 0) then
replacements[1] = "{{Collectible" .. Isaac.GetItemIdByName(name) .. "}} " .. name
end
elseif effectType == "convert_entities" then
replacements[1] = "{{ColorGray}}" .. entityToName(words[6], true) .. "{{CR}}"
replacements[2] = "{{ColorGray}}" .. entityToName(words[8])
+404 -225
View File
@@ -9,10 +9,15 @@ local game = Game()
require("eid_config")
EID.Config = EID.UserConfig
EID.Config.Version = "3.2" -- note: changing this will reset everyone's settings to default!
EID.ModVersion = "4.21"
EID.ModVersion = "4.22"
EID.DefaultConfig.Version = EID.Config.Version
EID.isHidden = false
EID.player = nil
EID.player = nil -- The primary Player Entity of Player 1
EID.players = {} -- Both Player Entities of Player 1 if applicable (includes Esau, T.Forgotten)
EID.coopMainPlayers = {} -- The primary Player Entity for each controller being used
EID.coopAllPlayers = {} -- Every Player Entity (includes Esau, T.Forgotten)
EID.controllerIndexes = {} -- A table to map each controller index to their player number for coloring indicators
EID.isMultiplayer = false -- Used to color P1's highlight/outline indicators (single player just uses white)
-- general variables
EID.PositionModifiers = {}
@@ -33,6 +38,7 @@ EID.CollectedItems = {}
EID.IgnoredEntities = {}
local pathsChecked = {}
local altPathItemChecked = {}
local alwaysUseLocalMode = false -- set to true after drawing a non-local mode description this frame
EID.GameUpdateCount = 0
EID.GameRenderCount = 0
@@ -434,20 +440,87 @@ end
---------------------------------------------------------------------------
---------------------------Printing Functions------------------------------
local previousDesc = ""
local previousRenderPos = Vector.Zero
EID.previousDescs = {}
EID.CachingDescription = false
EID.CachedIcons = {}
EID.CachedStrings = {}
EID.CachedIndicators = {}
EID.CachedRenderPoses = {}
EID.descriptionsToPrint = {}
EID.entitiesToPrint = {}
function EID:printDescription(desc)
function EID:addDescriptionToPrint(desc)
if desc.Entity and EID.entitiesToPrint[GetPtrHash(desc.Entity)] then return end
table.insert(EID.descriptionsToPrint, desc)
if desc.Entity then EID.entitiesToPrint[GetPtrHash(desc.Entity)] = true end
end
function EID:printDescriptions(useCached)
EID.CachingDescription = false
if not useCached then
-- Test if we should print our cached descriptions or not
-- Did an option change, or it's a different number of descriptions?
if #EID.descriptionsToPrint ~= #EID.previousDescs or EID.OptionChanged or EID.MCM_OptionChanged then
EID:printNewDescriptions()
return
end
-- Do the description entities match, and the description texts match?
for i,newDesc in ipairs(EID.descriptionsToPrint) do
local oldDesc = EID.previousDescs[i]
if newDesc.Description ~= oldDesc.Description or (newDesc.Entity and oldDesc.Entity and GetPtrHash(newDesc.Entity) ~= GetPtrHash(oldDesc.Entity)) then
EID:printNewDescriptions()
return
end
end
end
-- Print our cached descriptions
for i,indicator in ipairs(EID.CachedIndicators) do
EID:renderIndicator(indicator[1], indicator[2])
end
for i,oldDesc in ipairs(EID.previousDescs) do
EID:printDescription(oldDesc, i)
end
end
function EID:printNewDescriptions()
EID.CachingDescription = true
EID.CachedIcons = {}
EID.CachedStrings = {}
EID.CachedRenderPoses = {}
EID.previousDescs = {}
for i,newDesc in ipairs(EID.descriptionsToPrint) do
if newDesc.Description == "UnidentifiedPill" then
if EID:renderUnidentifiedPill(newDesc.Entity) ~= false then
table.insert(EID.previousDescs, newDesc)
end
elseif newDesc.Description == "QuestionMark" then
if EID:renderQuestionMark(newDesc.Entity) ~= false then
table.insert(EID.previousDescs, newDesc)
end
elseif EID:printDescription(newDesc) ~= false then
table.insert(EID.previousDescs, newDesc)
end
end
EID.CachingDescription = false
end
function EID:printDescription(desc, cachedID)
EID:PositionLocalMode(desc.Entity)
-- Do not print this description if it has to be drawn in the top-left and we've already drawn a top-left desc this frame
if EID.CurrentScaleType == "Size" then
if alwaysUseLocalMode then return false
else alwaysUseLocalMode = true end
end
local renderPos = EID:getTextPosition()
EID.CachingDescription = false
if previousDesc == desc.Description and not EID.OptionChanged and not EID.MCM_OptionChanged then
local localModeDiff = renderPos - previousRenderPos
--print(cachedID)
if cachedID then
local localModeDiff = renderPos - EID.CachedRenderPoses[cachedID]
-- Drawing our currently saved description
for _,icon in ipairs(EID.CachedIcons) do
for _,icon in ipairs(EID.CachedIcons[cachedID]) do
-- set inline icon to specific frame
if icon[6] >= 0 then
icon[1]:SetFrame(icon[5], icon[6])
@@ -459,7 +532,7 @@ function EID:printDescription(desc)
end
EID:renderIcon(icon[1], icon[2] + localModeDiff.X, icon[3] + localModeDiff.Y, icon[4])
end
for i,str in ipairs(EID.CachedStrings) do
for _,str in ipairs(EID.CachedStrings[cachedID]) do
-- check for func (Rainbow, Blink, Fade), reset the color's Alpha to EID.Config["Transparency"] if func
if str[5] then
str[4].Alpha = str[6]
@@ -469,12 +542,9 @@ function EID:printDescription(desc)
end
return
else
-- Drawing a new description
EID.CachingDescription = true
EID.CachedIcons = {}
EID.CachedStrings = {}
previousDesc = desc.Description
previousRenderPos = Vector(renderPos.X, renderPos.Y)
table.insert(EID.CachedIcons, {})
table.insert(EID.CachedStrings, {})
table.insert(EID.CachedRenderPoses, Vector(renderPos.X, renderPos.Y))
end
local textScale = Vector(EID.Scale, EID.Scale)
@@ -667,13 +737,49 @@ end
---------------------------------------------------------------------------
---------------------------Handle Rendering--------------------------------
function EID:renderQuestionMark()
function EID:renderQuestionMark(entity)
EID:PositionLocalMode(entity)
if EID.CurrentScaleType == "Size" then
if alwaysUseLocalMode then return false
else alwaysUseLocalMode = true end
end
EID.IconSprite:Play("CurseOfBlind")
local pos = EID:getTextPosition()
if EID.CachingDescription then
table.insert(EID.CachedStrings, {})
table.insert(EID.CachedIcons, {})
table.insert(EID.CachedRenderPoses, Vector(pos.X, pos.Y))
end
EID:renderIcon(EID.IconSprite, pos.X + 5 * EID.Scale, pos.Y + 5 * EID.Scale, nil, "CurseOfBlind", 0)
end
function EID:renderIndicator(entity)
function EID:renderUnidentifiedPill(entity)
EID:PositionLocalMode(entity)
if EID.CurrentScaleType == "Size" then
if alwaysUseLocalMode then return false
else alwaysUseLocalMode = true end
end
local pillColor = entity.SubType
if pillColor >= 2049 then
pillColor = pillColor - 2048
end
local pos = EID:getTextPosition()
if EID.CachingDescription then
table.insert(EID.CachedStrings, {})
table.insert(EID.CachedIcons, {})
table.insert(EID.CachedRenderPoses, Vector(pos.X, pos.Y))
end
EID:renderString(
"{{Pill"..pillColor.."}} "..EID:getDescriptionEntry("unidentifiedPill"),
pos,
Vector(EID.Scale, EID.Scale),
EID:getErrorColor()
)
end
-- RGB colors for each player's highlights (Red, Blue, Green, Yellow)
local playerRGB = { {1,0.6,0.6}, {0.5,0.75,1}, {0.5,1,0.75}, {0.9, 0.9, 0.5} }
function EID:renderIndicator(entity, playerNum)
if EID.Config["Indicator"] == "none" then
return
end
@@ -708,20 +814,25 @@ function EID:renderIndicator(entity)
-- Don't apply sprite.Color changes to Effects (Dice Floors, Card Reading Portals), use Arrow instead
if EID.Config["Indicator"] == "arrow" or entity.Type == 1000 then
ArrowSprite:Update()
ArrowSprite:Render(arrowPos, nullVector, nullVector)
ArrowSprite:RenderLayer(playerNum-1, arrowPos, nullVector, nullVector)
else
local colorMult = {1,1,1}
if EID.isMultiplayer then colorMult = playerRGB[playerNum] end
if EID.Config["Indicator"] == "blink" then
local c = 255 - math.floor(255 * ((entity.FrameCount % 40) / 40))
sprite.Color = Color(1, 1, 1, 1, c/repDiv, c/repDiv, c/repDiv)
local r, g, b = math.floor(c*colorMult[1]), math.floor(c*colorMult[2]), math.floor(c*colorMult[3])
sprite.Color = Color(1, 1, 1, 1, r/repDiv, g/repDiv, b/repDiv)
EID:renderEntity(entity, sprite, entityPos)
sprite.Color = Color(1, 1, 1, 1, 0, 0, 0)
else
if EID.Config["Indicator"] == "border" then
if EID.Config["Indicator"] == "highlight" then
local c = 255 - math.floor(255 * ((entity.FrameCount % 40) / 40))
sprite.Color = Color(1, 1, 1, 1, c/repDiv, c/repDiv, c/repDiv)
elseif EID.Config["Indicator"] == "highlight" then
sprite.Color = Color(1, 1, 1, 1, 255/repDiv, 255/repDiv, 255/repDiv)
local r, g, b = math.floor(c*colorMult[1]), math.floor(c*colorMult[2]), math.floor(c*colorMult[3])
sprite.Color = Color(1, 1, 1, 1, r/repDiv, g/repDiv, b/repDiv)
elseif EID.Config["Indicator"] == "border" then
local c = 255
local r, g, b = math.floor(c*colorMult[1]), math.floor(c*colorMult[2]), math.floor(c*colorMult[3])
sprite.Color = Color(1, 1, 1, 1, r/repDiv, g/repDiv, b/repDiv)
end
EID:renderEntity(entity, sprite, entityPos + Vector(0, 1))
EID:renderEntity(entity, sprite, entityPos + Vector(0, -1))
@@ -738,7 +849,7 @@ end
function EID:PositionLocalMode(entity)
-- don't use Local Mode for descriptions without an entity (or dice floors)
if EID.Config["DisplayMode"] == "local" and entity and entity.Variant ~= EffectVariant.DICE_FLOOR then
if (EID.Config["DisplayMode"] == "local" or alwaysUseLocalMode) and entity and entity.Variant ~= EffectVariant.DICE_FLOOR then
EID.Scale = EID.Config["LocalModeSize"]
EID.CurrentScaleType = "LocalModeSize"
local textBoxWidth = EID.Config["LocalModeCentered"] and tonumber(EID.Config["TextboxWidth"])/2 * EID.Scale or -30
@@ -809,12 +920,50 @@ function EID:handleHoverHUD()
end
function EID:setPlayer()
local p = Isaac.GetPlayer(0)
if REPENTANCE and p:GetPlayerType() == PlayerType.PLAYER_THEFORGOTTEN_B then
EID.player = p:GetOtherTwin() or p
else
EID.player = p
local numPlayers = game:GetNumPlayers()
-- Old simple setPlayer, to reduce runtime in single player
if numPlayers == 1 or not EID.Config["CoopDescriptions"] then
local p = Isaac.GetPlayer(0)
if REPENTANCE and p:GetPlayerType() == PlayerType.PLAYER_THEFORGOTTEN_B then
EID.player = p:GetOtherTwin() or p
else
EID.player = p
end
EID.players = { EID.player, REPENTANCE and EID.player:GetOtherTwin() }
EID.coopMainPlayers = { EID.player }
EID.coopAllPlayers = EID.players
EID.controllerIndexes[p.ControllerIndex] = 1
return
end
-- Get our primary player, our list of all players, and a list of the primary player for each controller
EID.coopAllPlayers = {} -- all player characters in order
EID.coopMainPlayers = {} -- the primary player character from each controller
EID.controllerIndexes = {} -- simple table to map each controller index to P1/P2/P3/P4 (since index 0 could be P2)
local currentPlayerNum = 1
for i = 0, numPlayers - 1 do
local player = Isaac.GetPlayer(i)
-- Don't include player entities with a parent (Strawman / Soul of Jacob and Esau)
if player.Parent == nil then
local newIndex = not EID.controllerIndexes[player.ControllerIndex]
-- Tainted Soul is treated as the primary player for Tainted Forgotten, so swap them
if REPENTANCE and (player:GetPlayerType() == PlayerType.PLAYER_THEFORGOTTEN_B
or player:GetPlayerType() == PlayerType.PLAYER_THESOUL_B) then
player = player:GetOtherTwin() or player
end
table.insert(EID.coopAllPlayers, player)
if newIndex then
table.insert(EID.coopMainPlayers, player)
EID.controllerIndexes[player.ControllerIndex] = currentPlayerNum
currentPlayerNum = currentPlayerNum + 1
end
end
end
EID.player = EID.coopAllPlayers[1]
-- second entry will be nil if no twin or AB+ (REPENTANCE = nil)
EID.players = { EID.player, REPENTANCE and EID.player:GetOtherTwin() }
EID.isMultiplayer = #EID.coopMainPlayers > 1
end
---------------------------------------------------------------------------
@@ -853,7 +1002,7 @@ function EID:onGameUpdate()
end
-- Remove Crane Game item data if it's giving the prize out
if REPENTANCE and EID.GameUpdateCount % 15 == 0 then
if REPENTANCE and EID.GameUpdateCount % 10 == 0 then
for _, crane in ipairs(Isaac.FindByType(6, 16, -1, true, false)) do
if EID.CraneItemType[tostring(crane.InitSeed)] then
if crane:GetSprite():IsPlaying("Prize") then
@@ -990,6 +1139,7 @@ local searchPartitions = EntityPartition.FAMILIAR + EntityPartition.ENEMY + Enti
EID.lastDescriptionEntity = nil
EID.lastDist = 0
EID.OptionChanged = false
EID.bagPlayer = nil
local function onRender(t)
-- Increases by 60 per second, ignores pauses
@@ -997,9 +1147,20 @@ local function onRender(t)
EID.OptionChanged = EID.MCM_OptionChanged
EID.MCM_OptionChanged = false
EID:resumeCoroutines()
ArrowSprite:Update()
EID:setPlayer()
if REPENTANCE then
local hasBag, bagPlayer = EID:PlayersHaveCollectible(710)
if hasBag then
EID.bagPlayer = bagPlayer
EID:handleBagOfCraftingUpdating()
end
end
EID.isDisplaying = false
EID:setPlayer()
EID.descriptionsToPrint = {}
EID.entitiesToPrint = {}
alwaysUseLocalMode = false
-- Do not check our hotkeys while a tab that can modify the hotkey is open
if EID.MCMCompat_isDisplayingEIDTab ~= "Visuals" then
-- scale key must be handled before resetting to non-local mode
@@ -1008,7 +1169,6 @@ local function onRender(t)
EID.isHidden = not EID.isHidden
end
end
EID:PositionLocalMode() -- default to non-local mode to fix MCM / Bag errors
EID.TabPreviewID = 0
-- If MCM is open, don't show anything unless we're in a tab labeled as "Visuals" or "Crafting"
@@ -1016,6 +1176,7 @@ local function onRender(t)
return
end
-- Handle descriptions that display regardless of player position
checkStartOfRunWarnings()
checkPosModifiers()
EID:renderMCMDummyDescription()
@@ -1034,222 +1195,240 @@ local function onRender(t)
return
end
if REPENTANCE and EID.player:HasCollectible(710) then
local success = EID:handleBagOfCraftingRendering()
-- If the Bag of Crafting did rendering, don't display any other description
if success then
return
end
-- This is not a frame we should check for new descriptions; just print our cached ones
if not EID:RefreshThisFrame() then
EID:printDescriptions(true)
return
end
-- If we're in the Crafting options tab, the only rendering we want to happen is the Bag of Crafting
if EID.MCMCompat_isDisplayingEIDTab == "Crafting" then return end
EID.lastDescriptionEntity = nil
EID.lastDist = 10000
local searchGroups = {}
local sourcePos = EID.player.Position
EID.CachedIndicators = {}
if EID.Config["EnableMouseControls"] then
local hudDescription = EID:handleHoverHUD()
if hudDescription then
EID:printDescription(hudDescription)
return
EID:addDescriptionToPrint(hudDescription)
end
end
table.insert(searchGroups, Isaac.FindInRadius(sourcePos, tonumber(EID.Config["MaxDistance"])*40, searchPartitions))
for k,_ in pairs(EID.effectList) do
table.insert(searchGroups, Isaac.FindByType(EntityType.ENTITY_EFFECT, k, -1, true, false))
-- Decide how many player entities we're checking
-- Primary P1 only, P1 + Esau, primary all controllers, or all controllers + Esaus
local playerSearch = { EID.player }
if EID.Config["CoopDescriptions"] then
if EID.Config["PairedPlayerDescriptions"] then playerSearch = EID.coopAllPlayers
else playerSearch = EID.coopMainPlayers end
elseif EID.Config["PairedPlayerDescriptions"] then
playerSearch = EID.players
end
for _, entitySearch in ipairs(searchGroups) do
for i, entity in ipairs(entitySearch) do
if EID:hasDescription(entity) and entity.FrameCount > 0 then
local diff = entity.Position:__sub(sourcePos)
-- break ties with the render offset (for Mega Chest double collectibles)
if diff:Length() == EID.lastDist and entity:GetData()["EID_RenderOffset"] then
diff = diff + entity:GetData()["EID_RenderOffset"]
-- Check for descriptions to print per player
for i,player in ipairs(playerSearch) do
local displayedDesc = false
-- Check if this player has the Bag of Crafting
local craftingSuccess = false
if REPENTANCE and player:HasCollectible(710) then
craftingSuccess = EID:handleBagOfCraftingRendering()
if craftingSuccess then
displayedDesc = true
end
end
-- If we're in the Crafting options tab, the only rendering we want to happen is the Bag of Crafting preview
if EID.MCMCompat_isDisplayingEIDTab == "Crafting" then
if craftingSuccess then
EID:printDescription(EID.descriptionsToPrint[#EID.descriptionsToPrint])
return
end
if i == #playerSearch then return end
end
if not displayedDesc or EID.Config["DisplayAllNearby"] then
-- Searching for the closest describable entity to this player
EID.lastDescriptionEntity = nil
EID.lastDist = 10000
local searchGroups = {}
local sourcePos = player.Position
local inRangeEntities = {}
table.insert(searchGroups, Isaac.FindInRadius(sourcePos, tonumber(EID.Config["MaxDistance"])*40, searchPartitions))
for k,_ in pairs(EID.effectList) do
table.insert(searchGroups, Isaac.FindByType(EntityType.ENTITY_EFFECT, k, -1, true, false))
end
for _, entitySearch in ipairs(searchGroups) do
for i, entity in ipairs(entitySearch) do
if EID:hasDescription(entity) and entity.FrameCount > 0 and not EID.entitiesToPrint[GetPtrHash(entity)] then
table.insert(inRangeEntities, entity)
local diff = entity.Position:__sub(sourcePos)
-- break ties with the render offset (for Mega Chest double collectibles)
if diff:Length() == EID.lastDist and entity:GetData()["EID_RenderOffset"] then
diff = diff + entity:GetData()["EID_RenderOffset"]
end
if diff:Length() < EID.lastDist then
EID.lastDescriptionEntity = entity
EID.lastDist = diff:Length()
end
end
end
if diff:Length() < EID.lastDist then
EID.lastDescriptionEntity = entity
EID.lastDist = diff:Length()
end
if EID.Config["DisplayAllNearby"] then
-- make the closest entity the first to get drawn
table.insert(inRangeEntities, 1, EID.lastDescriptionEntity)
else
-- we only want to describe the closest entity
inRangeEntities = { EID.lastDescriptionEntity }
end
-- Only display the indicator for the primary (closest / crafting) description
if EID.lastDescriptionEntity and not displayedCrafting then
EID:renderIndicator(EID.lastDescriptionEntity, EID.controllerIndexes[player.ControllerIndex] or 1)
table.insert(EID.CachedIndicators, {EID.lastDescriptionEntity, EID.controllerIndexes[player.ControllerIndex]})
end
for _,closest in ipairs(inRangeEntities) do
--Handle GetData Entities (specific)
if EID.Config["EnableEntityDescriptions"] and EID:getEntityData(closest, "EID_Description") then
local desc = EID:getEntityData(closest, "EID_Description")
local origDesc = EID:getDescriptionObjByEntity(closest)
if type(desc) == "table" then
origDesc.Description = desc.Description or origDesc.Description
origDesc.Name = desc.Name or origDesc.Name
origDesc.Transformation = desc.Transformation or origDesc.Transformation
else
origDesc.Description = desc
end
EID:addDescriptionToPrint(origDesc)
-- Handle Glitched Items
elseif closest.Type == 5 and closest.Variant == 100 and closest.SubType > 4294960000 then
local glitchedObj = EID:getDescriptionObj(closest.Type, closest.Variant, closest.SubType, closest)
local glitchedDesc = EID:getXMLDescription(closest.Type, closest.Variant, closest.SubType)
-- force the default glitchy description if option is off
if not EID.Config["DisplayGlitchedItemInfo"] then
glitchedObj.Description = glitchedDesc
-- grab the Item Config info if eid_tmtrainer.lua hasn't taken care of it, and it hasn't been done before
elseif not debug and glitchedObj.Description == glitchedDesc then
EID:addCollectible(closest.SubType, EID:CheckGlitchedItemConfig(closest.SubType) .. glitchedDesc)
glitchedObj = EID:getDescriptionObj(closest.Type, closest.Variant, closest.SubType, closest)
end
EID:addDescriptionToPrint(glitchedObj)
-- Handle Dice Room Floor
elseif closest.Type == 1000 and closest.Variant == 76 then
EID:addDescriptionToPrint(EID:getDescriptionObj(closest.Type, closest.Variant, closest.SubType+1, closest))
-- Handle Card Reading Portals
elseif closest.Type == 1000 and closest.Variant == 161 and closest.SubType <= 2 then
local subtypeToCard = {18, 5, 19}
-- Reuse the descriptions of The Emperor/Stars/Moon, so no localization needed
local descriptionObj = EID:getDescriptionObj(5, 300, subtypeToCard[closest.SubType+1], closest)
-- Card Reading's name
descriptionObj.Name = EID:getObjectName(5, 100, 660)
EID:addDescriptionToPrint(descriptionObj)
-- Handle Crane Game
elseif closest.Type == 6 and closest.Variant == 16 then
if EID.CraneItemType[tostring(closest.InitSeed)] then
if EID:getEntityData(closest, "EID_DontHide") ~= true then
if (EID:hasCurseBlind() and EID.Config["DisableOnCurse"]) or (game.Challenge == Challenge.CHALLENGE_APRILS_FOOL and EID.Config["DisableOnAprilFoolsChallenge"]) then
EID:addDescriptionToPrint({ Description = "QuestionMark", Entity = closest})
end
end
local collectibleID = EID.CraneItemType[tostring(closest.InitSeed)]
local descriptionObj = EID:getDescriptionObj(5, 100, collectibleID, closest)
EID:addDescriptionToPrint(descriptionObj)
end
elseif closest.Variant == 110 then
--Handle Broken Shovel
local descriptionObj = EID:getDescriptionObj(5, 100, 550, closest)
EID:addDescriptionToPrint(descriptionObj)
elseif closest.Variant == PickupVariant.PICKUP_TRINKET then
--Handle Trinkets
local descriptionObj = EID:getDescriptionObjByEntity(closest)
EID:addDescriptionToPrint(descriptionObj)
elseif closest.Variant == PickupVariant.PICKUP_COLLECTIBLE then
--Handle Collectibles
if EID:getEntityData(closest, "EID_DontHide") ~= true then
if (EID:hasCurseBlind() and not closest:ToPickup().Touched and EID.Config["DisableOnCurse"] and not isDeathCertRoom) or (EID.Config["DisableOnAltPath"] and not closest:ToPickup().Touched and EID:IsAltChoice(closest)) or (game.Challenge == Challenge.CHALLENGE_APRILS_FOOL and EID.Config["DisableOnAprilFoolsChallenge"]) then
EID:addDescriptionToPrint({ Description = "QuestionMark", Entity = closest})
end
end
local descriptionObj = EID:getDescriptionObjByEntity(closest)
EID:addDescriptionToPrint(descriptionObj)
elseif closest.Variant == PickupVariant.PICKUP_TAROTCARD then
--Handle Cards & Runes
if (not EID.Config["DisplayObstructedCardInfo"] or not EID.Config["DisplayObstructedSoulstoneInfo"]) and closest.FrameCount < 3 then
-- small delay when having obstruction enabled & entering the room to prevent spoilers
--return
end
if EID:getEntityData(closest, "EID_DontHide") ~= true then
local isSoulstone = closest.SubType >= 81 and closest.SubType <= 97
local hideinShop = closest:ToPickup():IsShopItem() and ((not isSoulstone and not EID.Config["DisplayCardInfoShop"]) or (isSoulstone and not EID.Config["DisplaySoulstoneInfoShop"]))
local isOptionsSpawn = REPENTANCE and not EID.Config["DisplayCardInfoOptions?"] and closest:ToPickup().OptionsPickupIndex > 0
local obstructed = ((not isSoulstone and not EID.Config["DisplayObstructedCardInfo"]) or
(not EID.Config["DisplayObstructedSoulstoneInfo"] and isSoulstone)) and
(not pathsChecked[closest.InitSeed] and not attemptPathfind(closest))
if isOptionsSpawn or hideinShop or obstructed or (REPENTANCE and game.Challenge == Challenge.CHALLENGE_CANTRIPPED) then
EID:addDescriptionToPrint({ Description = "QuestionMark", Entity = closest})
end
end
local descriptionObj = EID:getDescriptionObjByEntity(closest)
EID:addDescriptionToPrint(descriptionObj)
elseif closest.Variant == PickupVariant.PICKUP_PILL then
--Handle Pills
if not EID.Config["DisplayObstructedPillInfo"] and closest.FrameCount < 3 then
-- small delay when having obstruction enabled & entering the room to prevent spoilers
--return
end
if EID:getEntityData(closest, "EID_DontHide") ~= true then
local hideinShop = closest:ToPickup():IsShopItem() and not EID.Config["DisplayPillInfoShop"]
local isOptionsSpawn = REPENTANCE and not EID.Config["DisplayPillInfoOptions?"] and closest:ToPickup().OptionsPickupIndex > 0
local obstructed = not EID.Config["DisplayObstructedPillInfo"] and
(not pathsChecked[closest.InitSeed] and not attemptPathfind(closest))
if isOptionsSpawn or hideinShop or obstructed then
EID:addDescriptionToPrint({ Description = "QuestionMark", Entity = closest})
end
end
local pillColor = closest.SubType
local pool = game:GetItemPool()
local identified = pool:IsPillIdentified(pillColor)
if REPENTANCE and pillColor % PillColor.PILL_GIANT_FLAG == PillColor.PILL_GOLD then identified = true end
if (identified or EID.Config["ShowUnidentifiedPillDescriptions"]) then
local descEntry = EID:getDescriptionObj(closest.Type, closest.Variant, pillColor, closest)
EID:addDescriptionToPrint(descEntry)
else
EID:addDescriptionToPrint({ Description = "UnidentifiedPill", Entity = closest})
end
elseif EID.Config["EnableEntityDescriptions"] then
--Handle Entities (omni)
local descriptionEntry = EID:getDescriptionObjByEntity(closest)
if descriptionEntry~=nil then
EID:addDescriptionToPrint(descriptionEntry)
end
end
end
end
end
local closest = EID.lastDescriptionEntity
-- if no entity in range, display Sacrifice Room information
if EID.lastDist / 40 > tonumber(EID.Config["MaxDistance"]) then
-- if no entities to display, display Sacrifice Room information
-- it will be last priority for the main spot if DisplayAllNearby is on
if #EID.descriptionsToPrint == 0 or EID.Config["DisplayAllNearby"] then
if game:GetRoom():GetType() == RoomType.ROOM_SACRIFICE and EID.Config["DisplaySacrificeInfo"] then
local curRoomIndex = game:GetLevel():GetCurrentRoomIndex()
local curCounter = EID.sacrificeCounter[curRoomIndex] or 1
local sacrificeDesc = EID:getDescriptionObj(-999, -1, curCounter)
sacrificeDesc.Name = sacrificeDesc.Name.." ("..curCounter.."/12)"
EID:printDescription(sacrificeDesc)
end
return
end
if closest == nil then
return
end
EID.isDisplaying = true
--Handle Indicators
EID:renderIndicator(closest)
--Position the description under the entity in Local Mode
EID:PositionLocalMode(closest)
--Handle GetData Entities (specific)
if EID.Config["EnableEntityDescriptions"] and EID:getEntityData(closest, "EID_Description") then
local desc = EID:getEntityData(closest, "EID_Description")
local origDesc = EID:getDescriptionObjByEntity(closest)
if type(desc) == "table" then
origDesc.Description = desc.Description or origDesc.Description
origDesc.Name = desc.Name or origDesc.Name
origDesc.Transformation = desc.Transformation or origDesc.Transformation
else
origDesc.Description = desc
end
EID:printDescription(origDesc)
return
end
-- Handle Glitched Items
if closest.Type == 5 and closest.Variant == 100 and closest.SubType > 4294960000 then
local glitchedObj = EID:getDescriptionObj(closest.Type, closest.Variant, closest.SubType)
local glitchedDesc = EID:getXMLDescription(closest.Type, closest.Variant, closest.SubType)
-- force the default glitchy description if option is off
if not EID.Config["DisplayGlitchedItemInfo"] then
glitchedObj.Description = glitchedDesc
-- grab the Item Config info if eid_tmtrainer.lua hasn't taken care of it, and it hasn't been done before
elseif not debug and glitchedObj.Description == glitchedDesc then
EID:addCollectible(closest.SubType, EID:CheckGlitchedItemConfig(closest.SubType) .. glitchedDesc)
glitchedObj = EID:getDescriptionObj(closest.Type, closest.Variant, closest.SubType)
end
EID:printDescription(glitchedObj)
return
-- Handle Dice Room Floor
elseif closest.Type == 1000 and closest.Variant == 76 then
EID:printDescription(EID:getDescriptionObj(closest.Type, closest.Variant, closest.SubType+1, closest))
return
-- Handle Card Reading Portals
elseif closest.Type == 1000 and closest.Variant == 161 and closest.SubType <= 2 then
local subtypeToCard = {18, 5, 19}
-- Reuse the descriptions of The Emperor/Stars/Moon, so no localization needed
local descriptionObj = EID:getDescriptionObj(5, 300, subtypeToCard[closest.SubType+1], closest)
-- Card Reading's name
descriptionObj.Name = EID:getObjectName(5, 100, 660)
EID:printDescription(descriptionObj)
return
-- Handle Crane Game
elseif closest.Type == 6 and closest.Variant == 16 then
if EID.CraneItemType[tostring(closest.InitSeed)] then
if EID:getEntityData(closest, "EID_DontHide") ~= true then
if (EID:hasCurseBlind() and EID.Config["DisableOnCurse"]) or (game.Challenge == Challenge.CHALLENGE_APRILS_FOOL and EID.Config["DisableOnAprilFoolsChallenge"]) then
EID:renderQuestionMark()
return
end
end
local collectibleID = EID.CraneItemType[tostring(closest.InitSeed)]
local descriptionObj = EID:getDescriptionObj(5, 100, collectibleID, closest)
EID:printDescription(descriptionObj)
return
EID:addDescriptionToPrint(sacrificeDesc)
end
end
if closest.Variant == 110 then
--Handle Broken Shovel
local descriptionObj = EID:getDescriptionObj(5, 100, 550, closest)
EID:printDescription(descriptionObj)
elseif closest.Variant == PickupVariant.PICKUP_TRINKET then
--Handle Trinkets
local descriptionObj = EID:getDescriptionObjByEntity(closest)
EID:printDescription(descriptionObj)
elseif closest.Variant == PickupVariant.PICKUP_COLLECTIBLE then
--Handle Collectibles
if EID:getEntityData(closest, "EID_DontHide") ~= true then
if (EID:hasCurseBlind() and not closest:ToPickup().Touched and EID.Config["DisableOnCurse"] and not isDeathCertRoom) or (EID.Config["DisableOnAltPath"] and not closest:ToPickup().Touched and EID:IsAltChoice(closest)) or (game.Challenge == Challenge.CHALLENGE_APRILS_FOOL and EID.Config["DisableOnAprilFoolsChallenge"]) then
EID:renderQuestionMark()
return
end
end
local descriptionObj = EID:getDescriptionObjByEntity(closest)
EID:printDescription(descriptionObj)
elseif closest.Variant == PickupVariant.PICKUP_TAROTCARD then
--Handle Cards & Runes
if (not EID.Config["DisplayObstructedCardInfo"] or not EID.Config["DisplayObstructedSoulstoneInfo"]) and closest.FrameCount < 3 then
-- small delay when having obstruction enabled & entering the room to prevent spoilers
return
end
if EID:getEntityData(closest, "EID_DontHide") ~= true then
local isSoulstone = closest.SubType >= 81 and closest.SubType <= 97
local hideinShop = closest:ToPickup():IsShopItem() and ((not isSoulstone and not EID.Config["DisplayCardInfoShop"]) or (isSoulstone and not EID.Config["DisplaySoulstoneInfoShop"]))
local isOptionsSpawn = REPENTANCE and not EID.Config["DisplayCardInfoOptions?"] and closest:ToPickup().OptionsPickupIndex > 0
local obstructed = ((not isSoulstone and not EID.Config["DisplayObstructedCardInfo"]) or
(not EID.Config["DisplayObstructedSoulstoneInfo"] and isSoulstone)) and
(not pathsChecked[closest.InitSeed] and not attemptPathfind(closest))
if isOptionsSpawn or hideinShop or obstructed or (REPENTANCE and game.Challenge == Challenge.CHALLENGE_CANTRIPPED) then
EID:renderQuestionMark()
return
end
end
local descriptionObj = EID:getDescriptionObjByEntity(closest)
EID:printDescription(descriptionObj)
elseif closest.Variant == PickupVariant.PICKUP_PILL then
--Handle Pills
if not EID.Config["DisplayObstructedPillInfo"] and closest.FrameCount < 3 then
-- small delay when having obstruction enabled & entering the room to prevent spoilers
return
end
if EID:getEntityData(closest, "EID_DontHide") ~= true then
local hideinShop = closest:ToPickup():IsShopItem() and not EID.Config["DisplayPillInfoShop"]
local isOptionsSpawn = REPENTANCE and not EID.Config["DisplayPillInfoOptions?"] and closest:ToPickup().OptionsPickupIndex > 0
local obstructed = not EID.Config["DisplayObstructedPillInfo"] and
(not pathsChecked[closest.InitSeed] and not attemptPathfind(closest))
if isOptionsSpawn or hideinShop or obstructed then
EID:renderQuestionMark()
return
end
end
local pillColor = closest.SubType
local pool = game:GetItemPool()
local identified = pool:IsPillIdentified(pillColor)
if REPENTANCE and pillColor % PillColor.PILL_GIANT_FLAG == PillColor.PILL_GOLD then identified = true end
if (identified or EID.Config["ShowUnidentifiedPillDescriptions"]) then
local descEntry = EID:getDescriptionObj(closest.Type, closest.Variant, pillColor, closest)
EID:printDescription(descEntry)
else
if pillColor >= 2049 then
pillColor = pillColor - 2048
end
EID:renderString(
"{{Pill"..pillColor.."}} "..EID:getDescriptionEntry("unidentifiedPill"),
EID:getTextPosition(),
Vector(EID.Scale, EID.Scale),
EID:getErrorColor()
)
end
elseif EID.Config["EnableEntityDescriptions"] then
--Handle Entities (omni)
local descriptionEntry = EID:getDescriptionObjByEntity(closest)
if descriptionEntry~=nil then
EID:printDescription(descriptionEntry)
return
end
end
EID:printDescriptions()
end
EID:AddCallback(ModCallbacks.MC_POST_RENDER, onRender)
+6 -2
View File
@@ -56,7 +56,6 @@ This mod displays detailed information about all items, trinkets, cards, runes a
[th]KOREAN[/th]
[th]CHINESE[/th]
[th]JAPANESE[/th]
[th]CZECH[/th]
[/tr]
[tr]
[td]by Jake[/td]
@@ -66,6 +65,11 @@ This mod displays detailed information about all items, trinkets, cards, runes a
[td]by Blackcreamtea, 미카[/td]
[td]by Xheepey87, frto027[/td]
[td]by prefab[/td]
[/tr]
[tr]
[th]CZECH[/th]
[/tr]
[tr]
[td]by domcizzz[/td]
[/tr]
[/table]
@@ -109,7 +113,7 @@ https://moddingofisaac.com/mod/1079/external-item-descriptions
- prefab for the incredible [b]Japanese[/b] language pack
- domcizzz for the cool [b]Czech[/b] language pack
- [url=https://steamcommunity.com/id/whytefang/]adc[/url] for creating an awesome new Languagepack and providing ideas for new functionalities</description>
<version>4.21</version>
<version>4.22</version>
<visibility>Public</visibility>
<tag id="Lua"/>
<tag id="Items"/>
+13 -2
View File
@@ -356,7 +356,9 @@ if MCMLoaded then
-- maxDistance
local distances = {1, 1.5, 2, 3, 4, 5, 6, 7, 8, 9, 10}
EID:AddScrollSetting("General", "MaxDistance", "Max Distance", distances, {label = " Grids",
infoText = "Distance to the object until descriptions are displayed."})
infoText = "Distance to the object until descriptions are displayed"})
EID:AddBooleanSetting("General", "DisplayAllNearby", "Display All Objects In Range",
{ infoText = "Descriptions besides the closest one will be shown using the Local display mode" })
--------Reset to default
MCM.AddSpace("EID", "General")
@@ -383,6 +385,15 @@ if MCMLoaded then
---------------------------------------------------------------------------
---------------------------------Display-----------------------------------
local refreshRateSteps = {1, 2, 3, 4, 6, 10, 12, 15, 20, 30, 60}
EID:AddScrollSetting("Display", "RefreshRate", "Description Refresh Rate", refreshRateSteps,
{infoText = "How many times per second that EID updates what description to show"})
EID:AddBooleanSetting("Display", "CoopDescriptions", "Co-op Player Descriptions",
{infoText = "Allow Players 2, 3, and 4 to display descriptions in Co-op"})
EID:AddBooleanSetting("Display", "PairedPlayerDescriptions", "Paired Player Descriptions", {repOnly = true,
infoText = "Allow paired characters like Esau and Tainted Forgotten's bone pile to display descriptions"})
MCM.AddSpace("EID", "Display")
-- Simple toggles of what descriptions the user wants displayed
EID:AddBooleanSetting("Display", "DisplayItemInfo", "Collectible Infos", {displayingTab = ""})
EID:AddBooleanSetting("Display", "DisplayTrinketInfo", "Trinket Infos")
@@ -406,7 +417,7 @@ if MCMLoaded then
EID:AddBooleanSetting("Display", "SpindownDiceDisplayID", "Display IDs",
{repOnly = true, infoText = "Display IDs for Spindown Dice results"})
-- Display names for Spindown Dice results
EID:AddBooleanSetting("Display", "SpindownDiceDisplayName", "Display names",
EID:AddBooleanSetting("Display", "SpindownDiceDisplayName", "Display Names",
{repOnly = true, infoText = "Display names for Spindown Dice results"})
-- Spindown Dice skip locked items
EID:AddBooleanSetting("Display", "SpindownDiceSkipLocked", "Skip Locked Items",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

+30
View File
@@ -6,6 +6,9 @@
</Spritesheets>
<Layers>
<Layer Name="1" Id="0" SpritesheetId="0"/>
<Layer Name="2" Id="1" SpritesheetId="0"/>
<Layer Name="3" Id="2" SpritesheetId="0"/>
<Layer Name="4" Id="3" SpritesheetId="0"/>
</Layers>
<Nulls/>
<Events/>
@@ -217,6 +220,33 @@
<Frame XPosition="0" YPosition="-12" XPivot="7" YPivot="8" XCrop="72" YCrop="82" Width="16" Height="16" XScale="90" YScale="110" Delay="12" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="0" XPivot="7" YPivot="8" XCrop="72" YCrop="82" Width="16" Height="16" XScale="100" YScale="100" Delay="1" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
</LayerAnimation>
<LayerAnimation LayerId="1" Visible="true">
<Frame XPosition="0" YPosition="0" XPivot="7" YPivot="8" XCrop="72" YCrop="66" Width="16" Height="16" XScale="100" YScale="100" Delay="9" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-7" XPivot="7" YPivot="8" XCrop="72" YCrop="66" Width="16" Height="16" XScale="90" YScale="110" Delay="8" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-12" XPivot="7" YPivot="8" XCrop="72" YCrop="66" Width="16" Height="16" XScale="120" YScale="110" Delay="7" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-15" XPivot="7" YPivot="8" XCrop="72" YCrop="66" Width="16" Height="16" XScale="100" YScale="100" Delay="6" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-12" XPivot="7" YPivot="8" XCrop="72" YCrop="66" Width="16" Height="16" XScale="110" YScale="100" Delay="5" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-12" XPivot="7" YPivot="8" XCrop="72" YCrop="66" Width="16" Height="16" XScale="90" YScale="110" Delay="12" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="0" XPivot="7" YPivot="8" XCrop="72" YCrop="66" Width="16" Height="16" XScale="100" YScale="100" Delay="1" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
</LayerAnimation>
<LayerAnimation LayerId="2" Visible="true">
<Frame XPosition="0" YPosition="0" XPivot="7" YPivot="8" XCrop="72" YCrop="50" Width="16" Height="16" XScale="100" YScale="100" Delay="9" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-7" XPivot="7" YPivot="8" XCrop="72" YCrop="50" Width="16" Height="16" XScale="90" YScale="110" Delay="8" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-12" XPivot="7" YPivot="8" XCrop="72" YCrop="50" Width="16" Height="16" XScale="120" YScale="110" Delay="7" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-15" XPivot="7" YPivot="8" XCrop="72" YCrop="50" Width="16" Height="16" XScale="100" YScale="100" Delay="6" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-12" XPivot="7" YPivot="8" XCrop="72" YCrop="50" Width="16" Height="16" XScale="110" YScale="100" Delay="5" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-12" XPivot="7" YPivot="8" XCrop="72" YCrop="50" Width="16" Height="16" XScale="90" YScale="110" Delay="12" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="0" XPivot="7" YPivot="8" XCrop="72" YCrop="50" Width="16" Height="16" XScale="100" YScale="100" Delay="1" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
</LayerAnimation>
<LayerAnimation LayerId="3" Visible="true">
<Frame XPosition="0" YPosition="0" XPivot="7" YPivot="8" XCrop="72" YCrop="34" Width="16" Height="16" XScale="100" YScale="100" Delay="9" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-7" XPivot="7" YPivot="8" XCrop="72" YCrop="34" Width="16" Height="16" XScale="90" YScale="110" Delay="8" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-12" XPivot="7" YPivot="8" XCrop="72" YCrop="34" Width="16" Height="16" XScale="120" YScale="110" Delay="7" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-15" XPivot="7" YPivot="8" XCrop="72" YCrop="34" Width="16" Height="16" XScale="100" YScale="100" Delay="6" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-12" XPivot="7" YPivot="8" XCrop="72" YCrop="34" Width="16" Height="16" XScale="110" YScale="100" Delay="5" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="-12" XPivot="7" YPivot="8" XCrop="72" YCrop="34" Width="16" Height="16" XScale="90" YScale="110" Delay="12" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
<Frame XPosition="0" YPosition="0" XPivot="7" YPivot="8" XCrop="72" YCrop="34" Width="16" Height="16" XScale="100" YScale="100" Delay="1" Visible="true" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="true"/>
</LayerAnimation>
</LayerAnimations>
<NullAnimations/>
<Triggers/>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB