Merge pull request #398 from Buurazu/master
Multiple descriptions / co-op support
This commit is contained in:
9 files changed
+546
-275
No files matched your search
+24
-4
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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])
|
||||
|
||||
@@ -12,7 +12,12 @@ EID.Config.Version = "3.2" -- note: changing this will reset everyone's settings
|
||||
EID.ModVersion = "4.21"
|
||||
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)
|
||||
|
||||
+13
-2
@@ -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",
|
||||
|
||||
@@ -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 |
Reference in new issue
Block a user