diff --git a/descriptions/ab+/en_us.lua b/descriptions/ab+/en_us.lua index e2dff692..1195b2c4 100644 --- a/descriptions/ab+/en_us.lua +++ b/descriptions/ab+/en_us.lua @@ -16,7 +16,7 @@ EID.descriptions[languageCode].custom = {} -- table for custom entity descriptio EID.descriptions[languageCode].languageName = "English" -- Fonts to be used with this language pack -EID.descriptions[languageCode].fonts = {{name="default", lineHeight=11}, {name="inverted", lineHeight=11}, {name="borderless", lineHeight=11}} +EID.descriptions[languageCode].fonts = {{name="default", lineHeight=11, textboxWidth = 115}, {name="inverted", lineHeight=11, textboxWidth = 115}, {name="borderless", lineHeight=11, textboxWidth = 115}} ---------- Collectibles ---------- EID.descriptions[languageCode].collectibles={ diff --git a/descriptions/ab+/ko_kr.lua b/descriptions/ab+/ko_kr.lua index 61f10899..6abc9acc 100644 --- a/descriptions/ab+/ko_kr.lua +++ b/descriptions/ab+/ko_kr.lua @@ -29,7 +29,7 @@ EID.descriptions[languageCode].languageName = "Korean" korean_galmoori9, korean_galmoori11 is added for community request. ]] -EID.descriptions[languageCode].fonts = {{name="korean_hcrdotum", lineHeight=11}, {name="korean_lanapixel", lineHeight=12}, {name="korean_soyakkoma", lineHeight=13}, {name="korean_soyakkoma_borderless", lineHeight=13}, {name="korean_soyakkoma_inverted", lineHeight=13}, {name="korean_soyanon", lineHeight=12}, {name="korean_galmoori9", lineHeight=12}, {name="korean_galmoori11", lineHeight=14}} +EID.descriptions[languageCode].fonts = {{name="korean_hcrdotum", lineHeight=11, textboxWidth = 115}, {name="korean_lanapixel", lineHeight=12, textboxWidth = 115}, {name="korean_soyakkoma", lineHeight=13, textboxWidth = 115}, {name="korean_soyakkoma_borderless", lineHeight=13, textboxWidth = 115}, {name="korean_soyakkoma_inverted", lineHeight=13, textboxWidth = 115}, {name="korean_soyanon", lineHeight=12, textboxWidth = 115}, {name="korean_galmoori9", lineHeight=12, textboxWidth = 115}, {name="korean_galmoori11", lineHeight=14, textboxWidth = 115}} ---------- Collectibles ---------- EID.descriptions[languageCode].collectibles={ diff --git a/descriptions/ab+/zh_cn.lua b/descriptions/ab+/zh_cn.lua index 778ef20b..97072791 100644 --- a/descriptions/ab+/zh_cn.lua +++ b/descriptions/ab+/zh_cn.lua @@ -16,7 +16,7 @@ EID.descriptions[languageCode].custom = {} -- table for custom entity descriptio EID.descriptions[languageCode].languageName = "Chinese" -- Fonts to be used with this languagepack -EID.descriptions[languageCode].fonts = {{name = "default_cn", lineHeight = 14}} +EID.descriptions[languageCode].fonts = {{name = "default_cn", lineHeight = 14, textboxWidth = 150}} ---------- Collectibles ---------- EID.descriptions[languageCode].collectibles={ diff --git a/descriptions/rep/en_us.lua b/descriptions/rep/en_us.lua index c167926b..4b13572f 100644 --- a/descriptions/rep/en_us.lua +++ b/descriptions/rep/en_us.lua @@ -971,22 +971,22 @@ EID.descriptions[languageCode].GlitchedItemText = { [0] = "Damage", "Fire Rate", "Shot Speed", "Range", "Speed", "Tear Effects", "Tear Color", "Flight", "Attack Type", "Familiars", "Luck", "Size", "Color", "Chest Contents", [16] = "All Stats", -- Attribute triggers - chain = "{{ColorCyan}}Then:{{CR}} ", - active = "{{ColorCyan}}On use:#", - pickup_collected = "{{ColorCyan}}When you collect a pickup:#", --chance to? - enemy_kill = "{{ColorCyan}}On kill, chance to:#", - damage_taken = "{{ColorCyan}}When you take damage:#", --chance to? - entity_spawned = "When a {{ColorCyan}}{T1}{{CR}} is spawned:#", - tear_fire = "{{ColorCyan}}When you fire a tear, chance to:#", - enemy_hit = "{{ColorCyan}}On hitting an enemy, chance to:#", - room_clear = "{{ColorCyan}}On room clear:#", --chance to? + chain = "Then:{{CR}} ", + active = "On use:#", + pickup_collected = "When you collect a pickup:#", --chance to? + enemy_kill = "On kill, chance to:#", + damage_taken = "When you take damage:#", --chance to? + entity_spawned = "When a {T1} is spawned:#", + tear_fire = "When you fire a tear, chance to:#", + enemy_hit = "On hitting an enemy, chance to:#", + room_clear = "On room clear:#", --chance to? -- Attribute effects area_damage = "Deal {1} damage in an area around you", add_temporary_effect = "Gain {1} for the room", - convert_entities = "Convert all {{ColorGray}}{1}{{CR}} in the room to {{ColorGray}}{2}{{CR}}", + convert_entities = "Convert all {1} in the room to {2}", use_active_item = "Use {1}", - spawn_entity = "Spawn a {{ColorGray}}{1}{{CR}}", + spawn_entity = "Spawn a {1}", fart = "Fart with size {1}", -- Generic entity names not obtained from entities2.xml diff --git a/eid_api.lua b/eid_api.lua index 9c0ea8dd..12c05697 100644 --- a/eid_api.lua +++ b/eid_api.lua @@ -530,11 +530,7 @@ end -- Generates a string with the defined pixel-length using a custom 1px wide character -- This will only work for this specific custom font function EID:generatePlaceholderString(length) - local placeholder = "" - for i = 1, length do - placeholder = placeholder .. "¤" - end - return placeholder + return string.rep("¤", length) end -- Returns the inlineIcon object of a given Iconstring @@ -720,29 +716,103 @@ end -- Fits a given string to a specific width -- returns the string as a table of lines -function EID:fitTextToWidth(str, textboxWidth) +function EID:fitTextToWidth(str, textboxWidth, breakUtf8Chars) local formatedLines = {} local curLength = 0 - local text = "" - for word in string.gmatch(str, "([^%s]+)") do - local colorFiltered = EID:filterColorMarkup(word, EID:getTextColor()) - local filteredWord = "" - for _, filtered in ipairs(colorFiltered) do - filteredWord = filteredWord .. filtered[1] - end - local strFiltered, spriteTable = EID:filterIconMarkup(filteredWord, 0, 0) - local wordLength = EID:getStrWidth(strFiltered) + local text = {} - if curLength + wordLength <= textboxWidth or curLength < 12 then - text = text .. word .. " " - curLength = curLength + wordLength - else - table.insert(formatedLines, text) - text = word .. " " - curLength = wordLength + local cursor = 1 + local word_begin_index = 1 + + local byte = string.byte -- for speed up + local sub = string.sub + local byte_space = string.byte(' ') + + while cursor <= #str do + -- ascii word: 0x0xxxxxxx + -- utf8 word (sequence): 0x11xxxxxx 0x10xxxxxx 0x10xxxxxx ... 0x10xxxxxx + -- see https://en.wikipedia.org/wiki/UTF-8 + -- we can only break after space, or before 0x11xxxxxx + local can_break_after_cursor = false + local cur, next = byte(str,cursor), byte(str,cursor+1) + if + -- cond#1: we can break at the end of string + cursor == #str or + -- cond#2: we can break after space + cur == byte_space or + -- handle utf8 characters + (breakUtf8Chars and( + -- cond#3: we can break if the next character is 0x11xxxxxx + ((next & 0xC0) == 0xC0) or + -- cond#4: we can also break if the current is 0x10xxxxxx while the next is ascii but not space + (((cur & 0xC0) == 0x80) and (next~= byte_space and (next & 0x80) == 0x00)) + )) + then + --[[ + -------------------ascii only--------------- + word will be separated by spaces. + wordA |wordB |wordC |^%@&Q%#^&#@!! |aksldj + ↑ + cond#2 + we may break after every space. + spaces | | | | | |woops + ↑ + cond#2 + -------------------UTF8 only---------------- + word is 0x11xxxxxx followed by several 0x10xxxxxx until the next 0x11xxxxxx (not included) + 你|好|,|世|界|!|↑|↑|↑|↑ + ↑ + cond#3 + byte data of a word: + [0x11xxxxxx,0x10xxxxxx,0x10xxxxxx, (next is 0x11xxxxxx, cond#3)] + --------------------ascii->utf8------------ + utf8 word must start with 0x11xxxxxx, so cond#3 split before it. + word|世|界 + | ↑ + ↑ cond#3 + cond#3 + + world |means |世|界 + ↑ + cond#2 + -------------------utf8->ascii-------------- + 世|界|是|world + | ↑ + ↑ cond#4 + cond#3 + 世|界|是 |world + | ↑ + ↑ cond#2 + cond#3 + ]] + + -- we can break after str[cursor] + local word = sub(str, word_begin_index, cursor) + + local colorFiltered = EID:filterColorMarkup(word, EID:getTextColor()) + local filteredWord = {} + for _, filtered in ipairs(colorFiltered) do + table.insert(filteredWord, filtered[1]) + end + local strFiltered, spriteTable = EID:filterIconMarkup(table.concat(filteredWord), 0, 0) + local wordLength = EID:getStrWidth(strFiltered) + + if curLength + wordLength <= textboxWidth or curLength < 12 then + table.insert(text, word) + curLength = curLength + wordLength + else + table.insert(formatedLines, table.concat(text)) + text = { word } + curLength = wordLength + end + + -- next word starts here + word_begin_index = cursor + 1 end + cursor = cursor + 1 end - table.insert(formatedLines, text) + + table.insert(formatedLines, table.concat(text)) return formatedLines end @@ -1041,6 +1111,7 @@ function EID:fixDefinedFont() end EID.Config["FontType"] = EID.descriptions[curLang].fonts[1].name EID.lineHeight = EID.descriptions[curLang].fonts[1].lineHeight + EID.Config["TextboxWidth"] = EID.descriptions[curLang].fonts[1].textboxWidth return true end diff --git a/eid_data.lua b/eid_data.lua index 9e8e699e..2cc6dc9e 100644 --- a/eid_data.lua +++ b/eid_data.lua @@ -498,3 +498,7 @@ EID.GoldenTrinketData = { -- Lil Clot, Swallowed M80, The Twins (default text), Cricket Leg (17%, 1 in 6), Apollyon's Best Friend, Broken Glasses [176] = 1, [178] = {t={50},mult=2}, [183] = 0, [185] = 17, [186] = 1, [187] = {t={50,50}, mult=2}, } + +EID.BreakUtf8CharsLanguage = { + ['zh_cn'] = true +} diff --git a/eid_tmtrainer.lua b/eid_tmtrainer.lua index eb81f2e1..383af69f 100644 --- a/eid_tmtrainer.lua +++ b/eid_tmtrainer.lua @@ -20,6 +20,18 @@ local logLocation = os.getenv("SYSTEMDRIVE") .. "/Users/" .. os.getenv("USERNAME local logFound = false local logCursor = 0 +local triggerColors = { + chain = "{{ColorSilver}}", + active = "{{ColorLime}}", + pickup_collected = "{{ColorYellow}}", + enemy_kill = "{{ColorRed}}", + damage_taken = "{{ColorRed}}", + entity_spawned = "", + tear_fire = "{{ColorCyan}}", + enemy_hit = "{{ColorEIDError}}", + room_clear = "{{ColorOrange}}", +} + local function entityToName(e, plural) local localizedNames = EID:getDescriptionEntry("GlitchedItemText") -- -1 is often used as an "any of this type", even if there's only one of that type, so converting it to 0 can help find names @@ -31,7 +43,7 @@ local function entityToName(e, plural) if name == e then Isaac.DebugString("No name found for " .. e .. " (could be modded)") elseif plural then name = name .. localizedNames["pluralize"] end - return name + return "{{ColorGray}}" .. name .. "{{CR}}" end local function parseEffectLine(raw) @@ -77,7 +89,7 @@ local function parseEffectLine(raw) local localizedNames = EID:getDescriptionEntry("GlitchedItemText") local eidString = "" - if effectTrigger ~= lastEffectTrigger then eidString = eidString .. (localizedNames[effectTrigger] or (effectTrigger .. "#")) end + if effectTrigger ~= lastEffectTrigger then eidString = eidString .. triggerColors[effectTrigger] .. (localizedNames[effectTrigger] or (effectTrigger .. "#")) end if printEffect then eidString = eidString .. (localizedNames[effectType] or fullEffect) .. "#" end for k,v in ipairs(triggerReplacements) do eidString = string.gsub(eidString, "{T" .. k .. "}", v) end for k,v in ipairs(replacements) do eidString = string.gsub(eidString, "{" .. k .. "}", v) end @@ -87,8 +99,11 @@ local function parseEffectLine(raw) end local function CheckLogForItems(_) - if not EID.Config["DisplayGlitchedItemInfo"] or not logFound or game:GetFrameCount() % 5 ~= 0 or not EID:PlayersHaveCollectible(CollectibleType.COLLECTIBLE_TMTRAINER) then return end - + -- Check log.txt every 5 frames if there's a collectible we haven't read the data for yet + -- (Should work well for Corrupted Data) + if game:GetFrameCount() % 5 ~= 0 or not EID.Config["DisplayGlitchedItemInfo"] or not logFound or + Isaac.GetItemConfig():GetCollectible(maxNumber - spawnedItems - 1) == nil then return end + local numEffects = 0 local itemScore = 0 local eidDesc = "" diff --git a/main.lua b/main.lua index 8dd1c69e..2cf00409 100644 --- a/main.lua +++ b/main.lua @@ -323,10 +323,15 @@ if REPENTANCE then EID:AddCallback(ModCallbacks.MC_POST_PICKUP_INIT, EID.postPickupInit, PickupVariant.PICKUP_COLLECTIBLE) function EID:CheckPedestalIndex(entity) - -- Only pedestals with indexes that were present at room load can be flip pedestals; fixes shop restock machines - if EID.flipItemPositions[curRoomIndex] and EID.flipItemPositions[curRoomIndex][entity.InitSeed] and entity.Index > EID.flipMaxIndex then - EID.flipItemPositions[curRoomIndex][entity.InitSeed] = nil - entity:GetData()["EID_FlipItemID"] = nil + -- Only pedestals with indexes that were present at room load can be flip pedestals + -- Fixes shop restock machines and Diplopia... mostly. At least while you're in the room. + if entity:GetData()["EID_FlipItemID"] and entity.Index > EID.flipMaxIndex then + local curRoomIndex = game:GetLevel():GetCurrentRoomIndex() + local gridPos = game:GetRoom():GetGridIndex(entity.Position) + local flipEntry = EID.flipItemPositions[curRoomIndex] and EID.flipItemPositions[curRoomIndex][entity.InitSeed] + -- only wipe the data if the grid index matches (so Diplopia pedestals don't) + if flipEntry and gridPos == flipEntry[2] then EID.flipItemPositions[curRoomIndex][entity.InitSeed] = nil end + entity:GetData()["EID_FlipItemID"] = nil end end EID:AddCallback(ModCallbacks.MC_POST_PICKUP_UPDATE, EID.CheckPedestalIndex, PickupVariant.PICKUP_COLLECTIBLE) @@ -512,7 +517,7 @@ function EID:printBulletPoints(description, renderPos) local textScale = Vector(EID.Scale, EID.Scale) description = EID:replaceShortMarkupStrings(description) for line in string.gmatch(description, "([^#]+)") do - local formatedLines = EID:fitTextToWidth(line, textboxWidth) + local formatedLines = EID:fitTextToWidth(line, textboxWidth, EID.BreakUtf8CharsLanguage[EID.Config["Language"]]) local textColor = EID:getTextColor() for i, lineToPrint in ipairs(formatedLines) do -- render bulletpoint diff --git a/mod_config_menu.lua b/mod_config_menu.lua index 26204ef4..695fdd56 100644 --- a/mod_config_menu.lua +++ b/mod_config_menu.lua @@ -1014,6 +1014,7 @@ if MCMLoaded then OnChange = function(currentNum) EID.Config["FontType"] = fontNames[currentNum] EID.lineHeight = fonts[currentNum].lineHeight + EID.Config["TextboxWidth"] = fonts[currentNum].textboxWidth EID:fixDefinedFont() local fontFile = EID.Config["FontType"] or "default" EID:loadFont(EID.modPath .. "resources/font/eid_"..fontFile..".fnt")