Stolen Realm
Install with App

Details

Latest version
1.0.4
Last Updated
First Uploaded
Downloads
118
Likes
0
Size
115KB
Dependants

Categories

Changelog — BetterFont

Publication dates use ISO 8601 (BRT, UTC−03:00); undated older headings do not assert a release date. CHG-REV documentation audit: 2026-10-16. These repository corrections do not modify previously published ZIPs.

1.0.4 — Unreleased

  • Added the README source/contribution block linking to https://github.com/DefRuivo/stolenRealmMods for source code, issues, contributions and forks.
  • Documentation release: no new font-rendering behaviour. The plugin reports the new package version.

1.0.3 — 2026-10-07

Documentation release; no new font-rendering behaviour over 1.0.2. The source version literal was bumped; this is not a claim that every byte outside that literal is identical between two compiled assemblies.

  • The build instructions were wrong about the deploy. They said that a bare dotnet build would also copy the mod into the mod-manager profile. That is no longer true: the deploy is opt-in — a bare dotnet build installs nothing, and only -p:DeployToBepInEx=true copies the DLL into <profile>\BepInEx\plugins\BetterFont\. The README now says it correctly.
  • Marcos verificáveis (commits): primeira distribuição documentada em 5a13c64; preservação de estilo e filtro de patches em 6cdd448, 254c9a2 e 8c90483; transporte entre shaders e diagnóstico em 2a93297/634e88b; BF-5 em 27b5e69; bump documental 1.0.3 em 0d33ef3.
  • Why a text fix needs a new version: a published version is immutable, so the README that travels inside the package cannot be corrected afterwards. Fixing it for whoever downloads the package means publishing a new one — and the code is untouched.

1.0.2

O BF-1 recusava exatamente o caso que ele existe para consertar: os textos de combate. O gate do "não dá para reproduzir" barrava por variante de shader diferente e o texto ficava intocado.

  • BF-5 — do not invent a shadow the original shader did not draw (commit 27b5e69, 2026-10-02; already in the 1.0.2 source, not a new 1.0.3 feature). _UnderlayColor.a > 0 alone no longer means the underlay is active. SombraDesenhada checks the underlay keywords or nonzero offset/dilate in the effect gate and style copy. This prevents the extra thick shadow on Select Attributes. The scan summary also reports the actual escape switch instead of always saying it is on.
  • Transporte entre VARIANTES de shader (o conserto principal). A fonte serifada é criada com TextMeshPro/Mobile/Distance Field (ShaderUtilities.ShaderRef_MobileSDF, no CreateFontAssetInstance) e os alvos de combate do jogo rodam em TextMeshPro/Distance Field Overlay (PlayerInfoWindow.playerName, BossHealthbar.BossName) e TextMeshPro/Distance Field (Surface) (DiceVisualSetup.DiceNumbers) — medido EM JOGO e versionado em tools/fixtures/bf-shaders-em-jogo.log (cópia verbatim da saída do CAP-1; o original, em scratch/, não é versionado — o .gitignore ignora scratch/). As propriedades de estilo existem nas duas variantes (conferido nos shaders serializados do próprio jogo, Stolen Realm_Data/resources.assets — os objetos de shader TMP do jogo estão nesse arquivo, não no sharedassets0.assets, que a versão anterior deste CHANGELOG citava: _FaceColor, _FaceDilate, _OutlineWidth/_OutlineSoftness/_OutlineColor, _UnderlayColor/_UnderlayOffsetX/Y/_UnderlayDilate/_UnderlaySoftness, _VertexOffsetX/Y, _WeightNormal/_WeightBold, _ClipRect, _MaskSoftnessX/Y e as keywords OUTLINE_ON/UNDERLAY_ON/UNDERLAY_INNER/GLOW_ON/BEVEL_ON): o que muda é a variante, não o conjunto. Shader diferente deixou de ser recusa e passou a ser cópia best-effort propriedade por propriedade (HasProperty antes de cada Set, como no resto do arquivo), com a variante de origem -> destino escrita no log e o que a variante nova não expuser em "não transportados".
  • Ordem da falha-segura. A fonte era trocada antes da cópia: uma exceção em CopiarEstilo/UpdateMeshPadding deixava o texto com a fonte trocada e o estilo pela metade — a meia cópia que este conserto diz evitar. Agora a troca de fonte e o transporte são uma operação só, e qualquer falha reverte (ReverterTexto: fonte e material originais de volta, padding recalculado). A varredura conta e loga os revertidos (REVERTIDO (...), no resumo da varredura também).
  • Buracos de propriedade fechados (medidos pela revisão):
    • UNDERLAY_INNER transportado (sombra "inner" não vira mais "outer" calada) — e registrado quando a variante nova pode não declará-lo (keyword de shader não se confere por HasProperty).
    • MASK_SOFT/MASK_HARD/MASK_TEX + _ClipRect (e _MaskSoftnessX/_MaskSoftnessY) transportados: texto mascarado/rolável não perde mais o recorte ao ganhar material novo. O TMP desta versão já liga MASK_SOFT no EnableMasking; as keywords ficam registradas porque só valem se o shader novo as declarar.
    • _VertexOffsetX/_VertexOffsetY transportados.
    • _WeightNormal/_WeightBold registrados (não copiados): são parâmetro da fonte/atlas, como _GradientScale — quem manda é a fonte nova, e o valor da origem aparece no log quando difere. Antes não eram nem copiados nem logados.
  • O gate olha o EFEITO no material, não a classificação do texto. Antes o portão só valia para estilizado && PreservarEstilo: texto não classificado cujo material da própria fonte traz _FaceTex/GLOW_ON/BEVEL_ON era trocado e perdia o efeito, e com PreservarEstilo=false o portão era pulado inteiro. Agora TemEfeitoNoMaterial decide se há o que proteger e a conferência roda sempre — o único desfecho dela é deixar aquele texto intacto, com o motivo nomeado no log.
  • Falso positivo que teria mantido o defeito de pé: _FaceTex/_BumpMap contavam como "em uso" só por existirem — e o default dessas propriedades no shader é a textura embutida white/bump do Unity, que GetTexture devolve diferente de null. Com o shader destravado, o gate recusaria os textos de combate de novo, por esse motivo. TexturaDeEfeito distingue default de textura real (instâncias embutidas whiteTexture/normalTexture/blackTexture/grayTexture, nome e tamanho).
  • Diagnóstico que serve para conferir em combate: a linha [diag] ganhou o antes/depois da variante de shader (shader='X' -> 'Y'), um campo de registros (o que fica fora de propósito E o motivo) e o texto pulado/revertido não é mais apresentado como convertido. Com LogDiagnosticoEstilo=true sai também uma linha com o catálogo do material da fonte nova (shader e quais propriedades do transporte ele expõe).
  • Os dois tetos do diagnóstico, consertados (BF-2R). Esta versão saiu com "rotina para nos 120 e linha de efeito com teto próprio de 300", e uma revisão independente mostrou que nenhum dos dois fazia o que prometia: o deEfeito era tirado do conteúdo da linha, e copiados nunca vem vazio num texto convertido (as cores de face existem nos dois shaders) — ou seja, toda linha era contada como "de efeito" e o teto de 120 era inalcançável; e os contadores eram da sessão, então a varredura de boot (o log do dono mede 406 e 484 textos numa passada) gastava os 300 antes da cena de combate — a linha que o dono liga o diagnóstico para ler não saía. Agora a classificação é explícita (quem chama diz se o material daquele texto carrega efeito, em vez de o teto se decidir pelo texto do log) e o orçamento é POR CENA: OrcamentoDoDiagnosticoPorCena zera os dois contadores quando a cena ativa muda (e escreve no log que zerou). Com isso a linha do texto de combate sai mesmo com centenas de textos antes, na mesma sessão — a prova é tools/testes/testes/puros/t_bf_diag_orcamento.py, com a escala real de uma varredura lida de tools/fixtures/bf-varredura-em-jogo.log (nunca digitada), rodada também contra o modelo do defeito.
  • O pulado pelo ESCAPE também é linha de diagnóstico — e NÃO é "de efeito" (BF-3). Faltava justamente a config em que o dono está (PularTextosEstilizados=true): o texto estilizado é pulado antes do portão, e o call site do escape contava esse pulo no teto de efeito (deEfeito=true fixo). Com a chave ligada a varredura pula ~484 textos numa passada (o log do dono mede 484 e 624 — tools/fixtures/bf-varredura-em-jogo.log), então o teto de 300 se esgotava antes da linha de combate — que, nessa config, é justamente um pulado. Agora a classificação é de três vias (TipoLinhaDiag: rotina / efeito / escape) e o pulado pelo escape tem teto próprio (TetoDiagEscape, dimensionado pelo log versionado — maior varredura 640 textos, 624 pulados; ver o item do FIX-8 abaixo — com folga): ele deixa de consumir o orçamento de efeito, e o de efeito fica reservado a quem tem efeito no material. O teste mede também a escala REAL de textos com efeito no boot (tools/fixtures/bf-efeito-no-boot.json: 365 de 488 — era esse número que o teste antigo digitava como 5) e prova a linha de combate saindo nas duas configs (default e a do dono).
  • A conta do teto do escape foi refeita (FIX-8) — a projeção de 773 era falsa, e o 900 NÃO é necessário. O TetoDiagEscape subiu de 700 para 900 no FIX-6 com a conta "793 objetos × a fração de pulo = 773 pulados". As duas pernas daquela conta eram falsas. (1) O denominador estava errado: a fração de pulo não é sobre o total da varredura, porque o texto que já está na serifa nem chega ao escape (o if (t.font == _serifFont) continue; vem antes). Na maior varredura versionada (tools/fixtures/bf-varredura-em-jogo.log: 640 textos, 12 já na serifa, 624 pulados) a base é 640 − 12 = 628, e a fração é 624/628 = 0,9936 — não 0,975. (2) A varredura de 793 não estava versionada e não projeta pulo nenhum: esse número só existia em log de scratch/ (gitignored); ela fechou 353 convertidos + 61 intocados + 379 já na serifa = 793 exato, com ZERO pulados — e, mesmo tomando o total como base, só 793 − 379 = 414 textos chegam ao escape, que a 0,9936 dão ~411 pulados. Isto é: o teto real, pelos dados versionados, só precisa passar do maior pulo medido numa cena — 624 —, e o antigo 700 já cobria. A premissa de que "o 700 estava apertado" cai. O valor fica em 900 como folga deliberada de limite de log (não custa nada logar mais), nunca como necessidade — quem diz isso é o comentário da constante e a conta refeita em tools/testes/regras_bf.maior_pulado_medido() (nada digitado).
  • Doc corrigida (era FALSA): "com o .cfg ausente/ilegível volta ao conservador". Chave ausente não é caso especial: o BepInEx cria a entrada com o default do Bind (false para PularTextosEstilizados) e o caminho novo vale — conferido no ConfigFile.Bind de BepInEx 5.4.23. O conservador só entra quando ler/criar a entrada falha (getter seguro devolvendo true), e isso agora está dito no README, no config e no comentário do código.
  • Versão 1.0.2 porque a 1.0.1 já estava publicada; a antiga nota usava 01/10/2026 sem explicitar fuso, e não é tomada aqui como data de publicação auditada. Nada muda no acoplamento: zero referências a outro mod (nome, GUID ou artefato) no código — o README cita o BetterCombatText de propósito, para explicar a convivência entre os dois, e isso é desejado (o que não pode é o código conhecer o outro mod).

1.0.1

Defeito corrigido (relatado pelo dono): trocar a fonte apagava o estilo e a coloração do jogo — visível principalmente em combate.

  • Causa (confirmada no IL do TMP): em TextMeshPro, texto.font = novaFonte não troca só o tipo de letra — o LoadFontAsset() do TMP descarta o material em uso e passa a usar o material do asset novo (TextMeshProUGUI.LoadFontAsset → m_sharedMaterial = m_fontAsset.material). Como cor de face, contorno e sombra vivem no material, a troca da 1.0.0 (linha t.font = _serifFont;) jogava fora o estilo — os materiais estilizados do jogo (... SDF - Drop Shadow/Outline, Title Font ... SDF Material) não eram reproduzidos.
  • Conserto: antes de trocar a fonte, o material em uso é capturado (fontSharedMaterial) e as propriedades de estilo são transportadas para o material por componente da fonte nova (fontMaterial — instância daquele texto; nada é escrito no material compartilhado nem no material do font asset): _FaceColor, _FaceDilate, _OutlineWidth/_OutlineSoftness/_OutlineColor, _UnderlayColor/_UnderlayOffsetX/_UnderlayOffsetY/_UnderlayDilate/_UnderlaySoftness, mais as keywords OUTLINE_ON/UNDERLAY_ON quando estavam ativas. Todo Set é precedido de HasProperty.
  • Não transportado de propósito: atlas/textura e _GradientScale/_TextureWidth/_TextureHeight (pertencem à fonte nova), texturas de face (_FaceTex), bevel (_BumpMap) e as keywords GLOW_ON/BEVEL_ON — quando existirem, o log de diagnóstico diz o que ficou de fora.
  • Novo config Estilo/PreservarEstilo (padrão true): liga/desliga o transporte do estilo.
  • Novo config Estilo/PularTextosEstilizados (na primeira versão desta 1.0.1, padrão true): textos com material próprio (títulos, números de combate) não trocam de fonte — visual intacto; só não ganham a serifa. Em BF-1 esta chave virou o ESCAPE do comportamento antigo e o padrão passou a false — ver a seção do BF-1 abaixo.
  • Novo config Diagnostico/LogDiagnosticoEstilo (padrão false): log por texto (objeto, fonte, material compartilhado, shader, o que foi copiado e o que não pôde ser) — para conferir e fechar dúvida.
  • UpdateMeshPadding() após ligar contorno/sombra (sem isso o contorno é cortado na borda do mesh).
  • README: seção do defeito/conserto, tabela de configuração e a convivência com outros mods que estilizam texto (o mecanismo do material clonado por componente e por que ele deixa de ser um caso à parte).

Conserto NA CAUSA: a fonte é trocada E o efeito de material é preservado (BF-1, nesta mesma 1.0.1)

  • Defeito (relatado pelo dono, 30/09): com os dois mods de estilização ligados, os textos de combate ficavam na fonte ORIGINAL enquanto o resto da interface ficava serifada — interface inconsistente. A causa era a própria proteção da 1.0.1: EhEstilizado chamava de "estilizado" todo texto cujo material em uso não é o material da sua fonte e mandava pular o texto. Quem aplica contorno/halo clonando o material por componente (é o mecanismo correto, exigido para não escrever no material compartilhado) deixava o texto exatamente nessa condição — e o BetterFont passava a ignorá-lo.
  • Conserto na causa, genérico e sem acoplar mod nenhum: o texto estilizado passa a trocar de fonte, e os efeitos que já estavam no material anterior daquele texto (cor de face _FaceColor/_FaceDilate, contorno _OutlineWidth/_OutlineSoftness/_OutlineColor + OUTLINE_ON, sombra _UnderlayColor/_UnderlayOffsetX/_UnderlayOffsetY/_UnderlayDilate/_UnderlaySoftness + UNDERLAY_ON) são reaplicados no material por componente da fonte nova (fontMaterial), com UpdateMeshPadding() para o contorno/sombra não serem cortados na borda do mesh. A regra é uma só — "o que estava no material anterior daquele texto continua lá" —, então vale para qualquer mod que tenha aplicado efeito antes, não para um caso específico. Nenhuma linha deste mod cita, referencia ou conhece outro mod.
  • Ordem indiferente entre os mods: efeito aplicado antes é transportado pelo BetterFont; efeito aplicado depois clona o material já serifado e o mantém. Não há corrida nem ordem obrigatória.
  • Falha-segura (EstiloTransportavel): só se troca a fonte de um texto estilizado se o efeito em uso puder ser reproduzido com fidelidade no material novo. Reprova (e aí o texto não é tocado, exatamente o comportamento de hoje) quando o efeito depende de textura de face (_FaceTex), de bevel (_BumpMap), das keywords GLOW_ON/BEVEL_ON, de um shader diferente do material da fonte serifada, ou de contorno/sombra que o material novo não expõe. Uma cópia parcial sairia pior que não mexer; em dúvida (incluindo exceção na conferência), não estiliza. A recusa por shader diferente foi REMOVIDA na 1.0.2 (BF-2): era ela que deixava os textos de combate de fora — variante diferente virou cópia best-effort. A conferência também deixou de olhar a classificação do texto e passou a olhar o efeito presente no material.
  • Reversível por config: Estilo/PularTextosEstilizados continua existindo e agora é o escape — com true, o texto com material próprio fica 100% intocado (o comportamento antigo). O padrão virou false porque era ele que produzia a interface inconsistente; os padrões dos outros dois (PreservarEstilo = true, LogDiagnosticoEstilo = false) não mudaram.
    • Correção (BF-2) do texto que estava aqui: esta seção dizia "Com o .cfg ausente/ilegível (getter seguro), o escape vale como ligado — ou seja, cai no comportamento conservador". A frase era falsa e foi retirada daqui (a conclusão fica, a causa errada sai): chave (ou arquivo) .cfg ausente NÃO cai no conservador — o BepInEx cria a entrada com o default do Bind (false) e o caminho novo vale; o conservador só entra se ler/criar a entrada falhar (getter seguro devolvendo true).
  • Log de resumo da varredura passou a separar os três desfechos: convertidos (efeitos transportados), pulados pelo escape e intocados por efeito não transportável — é por ele que se vê, sem abrir o jogo, se algum texto saiu do caminho novo.

Correção do aplicador de ganchos (também nesta 1.0.1)

  • A troca do PatchAll() por aplicação gancho a gancho (que entrou nesta versão) veio acompanhada de um filtro de classe de gancho que exigia [HarmonyPrefix]/[HarmonyPostfix] no método. Este mod declara o gancho pela convenção de nome do Harmony (LocalizeFontTrigger.Postfix), que o Harmony aceita exatamente como o atributo — o filtro recusava a única classe de patch: o mod carregava, logava "carregado." e não aplicava gancho nenhum (o silêncio parecendo sucesso; era o defeito A-1 da REV-2, em 4 mods).
  • O filtro agora exige só [HarmonyPatch] no TIPO — o mesmo conjunto de classes que o PatchAll() processava. Medido invocando o filtro real da DLL construída: 1 de 1 classe de patch aceita e 1 método de gancho dentro (antes: 0 de 1). Em todo o projeto, os 4 mods afetados passaram de 0/14 para 14/14 classes de patch aceitas.
  • Esta 1.0.1 não tinha sido publicada (a versão no ar era a 1.0.0, que carrega os dois defeitos): a correção do estilo e a do aplicador entram nesta mesma build, e é ela que foi para a Thunderstore — por isso o número não sobe de novo. No caminho feliz nada muda: o conjunto de ganchos aplicados é o mesmo.
  • Também nesta versão, do mesmo endurecimento: o Config.Bind ganhou guarda (BindSeguro, com try/catch e o default documentado valendo em caso de falha) e o Update() do plugin ficou protegido no ponto da chamada — um .cfg inválido não derruba mais o mod.

Historical dependency decision (1.0.1 package)

  • dependencies: BepInEx-BepInExPack-5.4.2305 — só. Este manifest não declara o DefRuivo_StolenRealmMods-BetterCombatText (era o que ele declarava no pacote antigo deste 1.0.1).
  • A dependência entre os dois é UMA DIREÇÃO: BetterCombatText 0.1.0 → BetterFont 1.0.1 — o BetterCombatText é quem devolve o estilo (contorno/sombra) nos textos de combate que a troca de fonte, sozinha, não preserva, e é ele que declara a referência. O caminho de volta foi removido no commit ac0210f.
  • Por que a mão dupla não sobe (provado no código da Thunderstore): no upload a plataforma resolve cada referência (DependencyField usa PackageReferenceValidator(resolve=True)) e recusa a que não existe, com No matching package found for reference. Com os dois lados se referenciando, cada lado apontava para uma versão inédita (este 1.0.1 e o BetterCombatText 0.1.0, nenhuma das duas no ar) — não havia ordem de envio válida: quem subisse primeiro falhava. Foi por isso que a direção única substituiu a mão dupla, e não por preferência.
  • Ordem de envio que funciona: o BetterFont 1.0.1 (este pacote, sem a dependência de volta) sobe primeiro; depois sobe o BetterCombatText 0.1.0 declarando o BetterFont 1.0.1 — a mesma ordem registrada em release/mods.json.
  • Hipótese histórica, não release futura: em 2026-09-30 cogitou-se um BetterFont 1.0.2 com dependência de volta. Isso não foi adotado: a 1.0.2 e a 1.0.3 existem e o manifest atual do BetterFont continua declarando só BepInEx. Não há versão futura prometida por esta nota.
  • O zip desta 1.0.1 na Release (pack-2026-09-30) é o pacote com a direção única: o asset antigo (com a mão dupla no manifest) foi substituído em 30/09/2026.

1.0.0

Primeira versão publicada.

  • Troca a fonte renderizada do jogo por uma serifada — Times New Roman, com fallback para Georgia / Liberation Serif — aplicada a todos os textos TMP, inclusive telas que abrem depois (level up, tooltips, menus).
  • A fonte original do jogo entra como fallback do asset serifado, então ícones e símbolos que a Times não tem continuam renderizando (sem quadradinhos).
  • A aplicação é preguiçosa e com throttle: o updater é criado na primeira UI viva (gatilho em OptionsManager.Localize), porque um GameObject criado no Awake do plugin é destruído pelo jogo na primeira carga de cena. A varredura roda com tempo real, então funciona mesmo com timeScale = 0 (menus).
  • Sem qualquer alteração de gameplay.
Thunderstore development is made possible with ads. Please consider making an exception to your adblock.