Decompiled source of BetterCombatText v0.1.0

plugins/BetterCombatText/BetterCombatText.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("BetterCombatText")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Contorno/halo suave e legibilidade para o texto de combate (nomes de inimigos, rotulos de buff/debuff e o texto do dado nos eventos). Sem alteracao de gameplay.")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("BetterCombatText")]
[assembly: AssemblyTitle("BetterCombatText")]
[assembly: AssemblyVersion("0.1.0.0")]
namespace BetterCombatText;

internal sealed class Configuracao
{
	public readonly ConfigEntry<bool> Ativar;

	public readonly ConfigEntry<bool> LogDetalhado;

	public readonly ConfigEntry<bool> DiagnosticoArranque;

	public readonly EstiloTmpCfg Nomes;

	public readonly EstiloTextoLegadoCfg Rotulos;

	public readonly EstiloTmpCfg EventosDado;

	public readonly ConfigEntry<bool> EventosAtivar;

	public readonly EstiloTmpCfg NumeroDeVida;

	public readonly ConfigEntry<bool> AplicarNumeroDeVida;

	public readonly EstiloTmpCfg TooltipStatus;

	public readonly ConfigEntry<bool> TooltipAtivar;

	public Configuracao(ConfigFile cfg)
	{
		Ativar = cfg.Bind<bool>("1. Geral", "Ativar", true, "CHAVE MESTRA. Coloque false para o mod nao alterar NADA (nem material, nem fonte, nem contorno). E a unica linha que voce precisa mudar para desligar tudo.");
		LogDetalhado = cfg.Bind<bool>("1. Geral", "LogDetalhado", false, "true = escreve uma linha no LogOutput.log a cada superficie tratada (util para diagnostico). false = so o resumo de arranque e os avisos.");
		DiagnosticoArranque = cfg.Bind<bool>("1. Geral", "DiagnosticoNoArranque", true, "true (padrao) = UMA vez no arranque o mod procura os componentes alvo em cena e escreve no log a fonte, o material compartilhado e o shader de cada um — 100% leitura, nada e alterado. E por esse bloco que se sabe o que o jogo usa de verdade. Custo: uma varredura de cena por passo (5s) ate achar um alvo ou ate 240s. false = nenhuma varredura de cena acontece (custo zero) e o log so registra que o diagnostico esta desligado. Ligue para testar, desligue para jogar sem ele.");
		string sec = "2. Nomes de inimigos (combate)";
		Nomes = new EstiloTmpCfg(cfg, sec, haloAtivo: true, 0.1f, 0.6f, "000000", 0.1f, sombraAtiva: true, 0.1f, -0.1f, 0.1f, 0.5f, 0.35f, 0f);
		string sec2 = "3. Rotulos de buff/debuff (combate)";
		Rotulos = new EstiloTextoLegadoCfg(cfg, sec2, haloAtivo: true, 1f, "000000", 0.1f, sombraAtiva: true, 1f, -1f, 0.5f, negrito: true, 0f);
		string text = "4. Eventos (texto do dado)";
		EventosAtivar = cfg.Bind<bool>(text, "Ativar", true, "Liga/desliga SO o realce do texto do dado nos eventos de rolagem. Independente do resto: desligar aqui nao mexe no combate.");
		EventosDado = new EstiloTmpCfg(cfg, text, haloAtivo: true, 0.12f, 0.6f, "000000", 0.35f, sombraAtiva: true, 0.1f, -0.1f, 0.1f, 0.5f, 0.4f, 0f);
		string text2 = "5. Extra";
		AplicarNumeroDeVida = cfg.Bind<bool>(text2, "AplicarNoNumeroDeVida", false, "Opcional: aplica o mesmo halo no numero de vida que flutua sobre as unidades em combate (l.210529 Healthbar.healthbarText). Desligado por padrao — fora do pedido original.");
		NumeroDeVida = new EstiloTmpCfg(cfg, text2 + " (numero de vida)", haloAtivo: true, 0.1f, 0.6f, "000000", 0.1f, sombraAtiva: false, 0.1f, -0.1f, 0.1f, 0.5f, 0.3f, 0f);
		string text3 = "6. Tooltip de status (nome do buff/debuff)";
		TooltipAtivar = cfg.Bind<bool>(text3, "Ativar", false, "DESLIGADO por padrao. O nome do buff/debuff nao tem rotulo proprio em combate: ele so aparece no tooltip generico do jogo, e o componente que o desenha (Tooltip.Title/Description) e o MESMO dos tooltips de skill/item/powerup. Ligando, o halo tambem aparece nesses tooltips. Com false, nada e tocado.");
		TooltipStatus = new EstiloTmpCfg(cfg, text3, haloAtivo: true, 0.1f, 0.6f, "000000", 0.1f, sombraAtiva: true, 0.1f, -0.1f, 0.1f, 0.5f, 0.35f, 0f);
	}

	internal static Color HexComAlfa(string hex, float alfa)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		Color result = Color.black;
		try
		{
			string text = (hex ?? "").Trim().TrimStart('#');
			if (text.Length == 6)
			{
				int num = Convert.ToInt32(text.Substring(0, 2), 16);
				int num2 = Convert.ToInt32(text.Substring(2, 2), 16);
				int num3 = Convert.ToInt32(text.Substring(4, 2), 16);
				result = new Color((float)num / 255f, (float)num2 / 255f, (float)num3 / 255f, 1f);
			}
		}
		catch
		{
			result = Color.black;
		}
		result.a = Mathf.Clamp01(alfa);
		return result;
	}
}
internal sealed class EstiloTmpCfg
{
	public readonly ConfigEntry<bool> HaloAtivo;

	public readonly ConfigEntry<float> LarguraContorno;

	public readonly ConfigEntry<float> SuavidadeContorno;

	public readonly ConfigEntry<string> CorContornoHex;

	public readonly ConfigEntry<float> AlfaContorno;

	public readonly ConfigEntry<bool> SombraAtiva;

	public readonly ConfigEntry<float> SombraOffsetX;

	public readonly ConfigEntry<float> SombraOffsetY;

	public readonly ConfigEntry<float> SombraDilate;

	public readonly ConfigEntry<float> SombraSuavidade;

	public readonly ConfigEntry<float> AlfaSombra;

	public readonly ConfigEntry<float> TamanhoFonteExtra;

	public Color CorContorno => Configuracao.HexComAlfa(CorContornoHex.Value, AlfaContorno.Value);

	public Color CorSombra => Configuracao.HexComAlfa(CorContornoHex.Value, AlfaSombra.Value);

	public EstiloTmpCfg(ConfigFile cfg, string sec, bool haloAtivo, float largura, float suavidade, string corHex, float alfa, bool sombraAtiva, float sombraOffX, float sombraOffY, float sombraDilate, float sombraSuavidade, float alfaSombra, float tamanhoExtra)
	{
		HaloAtivo = cfg.Bind<bool>(sec, "Halo", haloAtivo, "Contorno/halo em volta das letras (material do TextMeshPro). Desligue para nao tocar no contorno.");
		LarguraContorno = cfg.Bind<float>(sec, "LarguraContorno", largura, "Espessura do contorno, em unidades de fonte SDF (_OutlineWidth). Faixa util: 0 a 0.5. 0.10 = fino; 0.25 = grosso.");
		SuavidadeContorno = cfg.Bind<float>(sec, "SuavidadeContorno", suavidade, "Borramento do contorno (_OutlineSoftness). ALTO = halo suave; baixo (0) = contorno duro. 0.5-0.8 da o efeito de 'sombreamento radial' pedido.");
		CorContornoHex = cfg.Bind<string>(sec, "CorContorno", corHex, "Cor do contorno no formato RRGGBB (sem #). Padrao 000000 = preto.");
		AlfaContorno = cfg.Bind<float>(sec, "AlfaContorno", alfa, "Opacidade do contorno, 0 a 1. PADRAO 0.10 = os 10% pedidos pelo dono.");
		SombraAtiva = cfg.Bind<bool>(sec, "Sombra", sombraAtiva, "Sombra difusa (_Underlay, o 'drop shadow' do TextMeshPro). Ligada por padrao para reforcar a leitura.");
		SombraOffsetX = cfg.Bind<float>(sec, "SombraOffsetX", sombraOffX, "Deslocamento X da sombra (-1 a 1).");
		SombraOffsetY = cfg.Bind<float>(sec, "SombraOffsetY", sombraOffY, "Deslocamento Y da sombra (-1 a 1).");
		SombraDilate = cfg.Bind<float>(sec, "SombraDilate", sombraDilate, "Engrossamento da sombra (_UnderlayDilate).");
		SombraSuavidade = cfg.Bind<float>(sec, "SombraSuavidade", sombraSuavidade, "Borramento da sombra (_UnderlaySoftness).");
		AlfaSombra = cfg.Bind<float>(sec, "AlfaSombra", alfaSombra, "Opacidade da sombra, 0 a 1.");
		TamanhoFonteExtra = cfg.Bind<float>(sec, "TamanhoFonteExtra", tamanhoExtra, "Soma no tamanho da fonte. 0 = NAO MEXE no tamanho (padrao). Valores tipicos: +0.5 a +2.");
	}
}
internal sealed class EstiloTextoLegadoCfg
{
	public readonly ConfigEntry<bool> HaloAtivo;

	public readonly ConfigEntry<float> RaioContorno;

	public readonly ConfigEntry<string> CorContornoHex;

	public readonly ConfigEntry<float> AlfaContorno;

	public readonly ConfigEntry<bool> SombraAtiva;

	public readonly ConfigEntry<float> SombraOffsetX;

	public readonly ConfigEntry<float> SombraOffsetY;

	public readonly ConfigEntry<float> AlfaSombra;

	public readonly ConfigEntry<bool> Negrito;

	public readonly ConfigEntry<float> TamanhoExtra;

	public Color CorContorno => Configuracao.HexComAlfa(CorContornoHex.Value, AlfaContorno.Value);

	public Color CorSombra => Configuracao.HexComAlfa(CorContornoHex.Value, AlfaSombra.Value);

	public EstiloTextoLegadoCfg(ConfigFile cfg, string sec, bool haloAtivo, float raio, string corHex, float alfa, bool sombraAtiva, float sombraOffX, float sombraOffY, float alfaSombra, bool negrito, float tamanhoExtra)
	{
		HaloAtivo = cfg.Bind<bool>(sec, "Halo", haloAtivo, "Contorno duro (componente Outline do Unity) nos rotulos 'x3' e no contador de turnos. ATENCAO: este texto e UI.Text legado, NAO tem fonte distance field — o contorno aqui e duro (4 copias), nunca suave. Para halo suave nestes rotulos seria preciso trocar os componentes por TextMeshPro (mudanca grande, fora do escopo deste mod).");
		RaioContorno = cfg.Bind<float>(sec, "RaioContorno", raio, "Distancia do contorno duro, em pixels da UI. 1.0 e discreto; 2.0 e bem visivel.");
		CorContornoHex = cfg.Bind<string>(sec, "CorContorno", corHex, "Cor do contorno no formato RRGGBB (sem #). Padrao 000000 = preto.");
		AlfaContorno = cfg.Bind<float>(sec, "AlfaContorno", alfa, "Opacidade de CADA uma das 4 copias do contorno duro (0 a 1). PADRAO 0.10 = os 10% pedidos. Como o contorno duro nao borra, se ficar fraco demais suba para 0.25-0.40.");
		SombraAtiva = cfg.Bind<bool>(sec, "Sombra", sombraAtiva, "Sombra dura atras do rotulo (componente Shadow). E o que mais ajuda a ler em fundo claro.");
		SombraOffsetX = cfg.Bind<float>(sec, "SombraOffsetX", sombraOffX, "Deslocamento X da sombra, em pixels.");
		SombraOffsetY = cfg.Bind<float>(sec, "SombraOffsetY", sombraOffY, "Deslocamento Y da sombra, em pixels.");
		AlfaSombra = cfg.Bind<float>(sec, "AlfaSombra", alfaSombra, "Opacidade da sombra, 0 a 1.");
		Negrito = cfg.Bind<bool>(sec, "Negrito", negrito, "Deixa os rotulos em negrito (FontStyle.Bold). Ganho de leitura grande, custo zero.");
		TamanhoExtra = cfg.Bind<float>(sec, "TamanhoFonteExtra", tamanhoExtra, "Soma no tamanho da fonte do rotulo. 0 = NAO MEXE no tamanho (padrao).");
	}
}
internal static class DiagnosticoRotina
{
	private static bool _feito;

	private static bool _falhou;

	private static bool _vidaLogada;

	private static float _proximaChecagem;

	private const float EsperaMinima = 20f;

	private const float IntervaloChecagem = 5f;

	private const float DesistirEm = 240f;

	internal static void Tentar(string origem)
	{
		if (_feito || _falhou || !Plugin.Ativo || Plugin.Cfg == null)
		{
			return;
		}
		try
		{
			if (!_vidaLogada)
			{
				_vidaLogada = true;
				Plugin.Log.LogInfo((object)("Better Combat Text: gatilho '" + origem + "' vivo (primeira chamada) — o patch esta rodando."));
			}
			if (!Plugin.Cfg.DiagnosticoArranque.Value)
			{
				_feito = true;
				Plugin.Log.LogInfo((object)"Better Combat Text: diagnostico de arranque DESLIGADO no config ('1. Geral' > DiagnosticoNoArranque = false) — nenhuma varredura de cena sera feita.");
				return;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (!(realtimeSinceStartup < 20f) && !(realtimeSinceStartup < _proximaChecagem))
			{
				_proximaChecagem = realtimeSinceStartup + 5f;
				bool flag = TemAlvoEmCena();
				if (flag || !(realtimeSinceStartup < 240f))
				{
					_feito = true;
					Plugin.Log.LogInfo((object)(flag ? "Better Combat Text: alvo encontrado em cena — diagnostico encerrado (nada mais e varrido)." : ($"Better Combat Text: nenhum componente alvo apareceu em cena ate {240f:0}s — " + "rodando o diagnostico uma unica vez (o inventario de cena ainda informa) e parando.")));
					Rodar();
				}
			}
		}
		catch (Exception ex)
		{
			_falhou = true;
			Plugin.Log.LogWarning((object)("Better Combat Text: diagnostico de arranque falhou: " + ex.GetType().Name + ": " + ex.Message));
		}
	}

	private static bool TemAlvoEmCena()
	{
		try
		{
			return Resources.FindObjectsOfTypeAll<PlayerInfoWindow>().Length != 0 || Resources.FindObjectsOfTypeAll<BossHealthbar>().Length != 0 || Resources.FindObjectsOfTypeAll<StatusIcon>().Length != 0 || Resources.FindObjectsOfTypeAll<DiceRoller>().Length != 0 || Resources.FindObjectsOfTypeAll<DiceVisualSetup>().Length != 0;
		}
		catch
		{
			return true;
		}
	}

	private static void Rodar()
	{
		Plugin.Log.LogInfo((object)"Better Combat Text: --- diagnostico de arranque (somente leitura, nada alterado) ---");
		ReportarTmp<PlayerInfoWindow>("PlayerInfoWindow.playerName (NOME DO INIMIGO no hover em combate)", Resources.FindObjectsOfTypeAll<PlayerInfoWindow>(), (Func<PlayerInfoWindow, TMP_Text>)((PlayerInfoWindow w) => (TMP_Text)(object)((!((Object)(object)w != (Object)null)) ? null : w.playerName)));
		ReportarTmp<BossHealthbar>("BossHealthbar.BossName (NOME DO INIMIGO na barra de chefe)", Resources.FindObjectsOfTypeAll<BossHealthbar>(), (Func<BossHealthbar, TMP_Text>)((BossHealthbar b) => (TMP_Text)(object)((!((Object)(object)b != (Object)null)) ? null : b.BossName)));
		ReportarTmp<Tooltip>("Tooltip.Title (nome do buff/debuff no tooltip, default DESLIGADO no config)", Resources.FindObjectsOfTypeAll<Tooltip>(), (Func<Tooltip, TMP_Text>)((Tooltip t) => (TMP_Text)(object)((!((Object)(object)t != (Object)null)) ? null : t.Title)));
		ReportarTmp<DiceRoller>("DiceRoller.ResultText (resultado do dado nos eventos)", Resources.FindObjectsOfTypeAll<DiceRoller>(), (Func<DiceRoller, TMP_Text>)((DiceRoller d) => (TMP_Text)(object)((!((Object)(object)d != (Object)null)) ? null : d.ResultText)));
		DiceVisualSetup[] array = Resources.FindObjectsOfTypeAll<DiceVisualSetup>();
		int num = 0;
		TMP_Text val = null;
		for (int num2 = 0; num2 < array.Length; num2++)
		{
			TextMeshPro[] array2 = (((Object)(object)array[num2] != (Object)null) ? array[num2].DiceNumbers : null);
			if (array2 != null)
			{
				num += array2.Length;
				if ((Object)(object)val == (Object)null && array2.Length != 0)
				{
					val = (TMP_Text)(object)array2[0];
				}
			}
		}
		if ((Object)(object)val != (Object)null)
		{
			Descrever("DiceVisualSetup.DiceNumbers (NUMERO NA FACE DO DADO)", val);
		}
		Plugin.Log.LogInfo((object)$"Better Combat Text: faces de dado (TextMeshPro) encontradas: {num} em {array.Length} DiceVisualSetup.");
		StatusIcon[] array3 = Resources.FindObjectsOfTypeAll<StatusIcon>();
		int num3 = 0;
		string text = "(nenhum componente de stack encontrado em cena)";
		foreach (StatusIcon val2 in array3)
		{
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.stackCount == (Object)null))
			{
				num3++;
				text = ((object)val2.stackCount).GetType().FullName;
			}
		}
		Plugin.Log.LogInfo((object)$"Better Combat Text: StatusIcon em cena: {array3.Length} ({num3} com stackCount).");
		Plugin.Log.LogInfo((object)("Better Combat Text: tipo REAL do rotulo de stack = '" + text + "' — " + (text.Contains("UnityEngine.UI.Text") ? "UI.Text LEGADO: halo SUAVE e impossivel ali; aplicado contorno duro + sombra + negrito." : "TextMeshPro: halo suave viavel.")));
		TextMesh[] array4 = Resources.FindObjectsOfTypeAll<TextMesh>();
		Plugin.Log.LogInfo((object)("Better Combat Text: TextMesh legado (3D) em cena: " + array4.Length + " — esse tipo (usado por DieSideAwareTextDie) NAO e tocado pelo mod; se a face do dado do seu build usar este tipo, o numero do dado fica sem efeito (nada quebra)."));
		TMP_Text[] array5 = Resources.FindObjectsOfTypeAll<TMP_Text>();
		Plugin.Log.LogInfo((object)$"Better Combat Text: total de TMP_Text em cena: {array5.Length} (so os alvos sao tocados).");
		Plugin.Log.LogInfo((object)"Better Combat Text: --- fim do diagnostico ---");
	}

	private static void ReportarTmp<T>(string rotulo, T[] donos, Func<T, TMP_Text> seletor) where T : Object
	{
		try
		{
			if (donos == null || donos.Length == 0)
			{
				Plugin.Log.LogInfo((object)("Better Combat Text: " + rotulo + ": nenhuma instancia em cena agora (normal antes de abrir a tela correspondente)."));
				return;
			}
			TMP_Text val = null;
			for (int i = 0; i < donos.Length; i++)
			{
				if (!((Object)(object)val == (Object)null))
				{
					break;
				}
				if (!((Object)(object)donos[i] == (Object)null))
				{
					try
					{
						val = seletor(donos[i]);
					}
					catch
					{
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogInfo((object)("Better Combat Text: " + rotulo + ": componente ainda nao preenchido pelo jogo."));
			}
			else
			{
				Descrever(rotulo, val);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Better Combat Text: diagnostico de '" + rotulo + "' falhou: " + ex.GetType().Name + ": " + ex.Message));
		}
	}

	private static void Descrever(string rotulo, TMP_Text alvo)
	{
		Material fontSharedMaterial = alvo.fontSharedMaterial;
		bool flag = (Object)(object)fontSharedMaterial != (Object)null && fontSharedMaterial.HasProperty("_OutlineWidth");
		Plugin.Log.LogInfo((object)("Better Combat Text: " + rotulo + " -> objeto='" + ((Object)((Component)alvo).gameObject).name + "', tipo=" + ((object)alvo).GetType().Name + ", fonte='" + (((Object)(object)alvo.font != (Object)null) ? ((Object)alvo.font).name : "(nula)") + "', material compartilhado='" + (((Object)(object)fontSharedMaterial != (Object)null) ? ((Object)fontSharedMaterial).name : "(nulo)") + "', shader='" + (((Object)(object)fontSharedMaterial != (Object)null && (Object)(object)fontSharedMaterial.shader != (Object)null) ? ((Object)fontSharedMaterial.shader).name : "(nulo)") + "', " + $"distance field (tem _OutlineWidth)={flag}"));
	}
}
[HarmonyPatch(typeof(GUIManager), "Update", new Type[] { })]
internal static class GatilhoDiagnosticoPorFrame
{
	private static void Postfix()
	{
		DiagnosticoRotina.Tentar("GUIManager.Update");
	}
}
[HarmonyPatch(typeof(OptionsManager), "Localize")]
internal static class GatilhoDiagnosticoPorLocalize
{
	private static void Postfix()
	{
		DiagnosticoRotina.Tentar("OptionsManager.Localize");
	}
}
[HarmonyPatch(typeof(BossHealthbar), "set_BossCharacter")]
internal static class PatchNomeDoChefe
{
	private static void Postfix(BossHealthbar __instance)
	{
		if (!Plugin.Ativo)
		{
			return;
		}
		try
		{
			TextStyler.AplicarTmp((TMP_Text)(object)__instance.BossName, Plugin.Cfg.Nomes, "Nomes (combate)");
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Better Combat Text: nome do chefe falhou: " + ex.GetType().Name + ": " + ex.Message));
		}
	}
}
[HarmonyPatch(typeof(PlayerInfoWindow), "ShowPlayerInfoWindow")]
internal static class PatchHoverEmCombate
{
	private static void Postfix(PlayerInfoWindow __instance)
	{
		if (!Plugin.Ativo)
		{
			return;
		}
		try
		{
			TextStyler.AplicarTmp((TMP_Text)(object)__instance.playerName, Plugin.Cfg.Nomes, "Nomes (combate)");
			AplicarStatusIcons(__instance.statusIcons);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Better Combat Text: hover de combate falhou: " + ex.GetType().Name + ": " + ex.Message));
		}
	}

	internal static void AplicarStatusIcons(StatusIcon[] icones)
	{
		if (icones != null)
		{
			for (int i = 0; i < icones.Length; i++)
			{
				PatchRotulosDeStatus.Aplicar(icones[i]);
			}
		}
	}
}
[HarmonyPatch(typeof(StatusIcon), "UpdateStatusIcon", new Type[] { })]
internal static class PatchRotulosDeStatus
{
	private static void Postfix(StatusIcon __instance)
	{
		Aplicar(__instance);
	}

	internal static void Aplicar(StatusIcon icone)
	{
		if (!Plugin.Ativo || (Object)(object)icone == (Object)null)
		{
			return;
		}
		try
		{
			EstiloTextoLegadoCfg rotulos = Plugin.Cfg.Rotulos;
			TextStyler.AplicarTextoLegado(icone.stackCount, rotulos, "Rotulos (combate)");
			TextStyler.AplicarTextoLegado(icone.turnCount, rotulos, "Rotulos (combate)");
			TextStyler.ReportarResumoRotulos();
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Better Combat Text: rotulo de status falhou: " + ex.GetType().Name + ": " + ex.Message));
		}
	}
}
[HarmonyPatch(typeof(DiceRollingManager), "RollDice", new Type[]
{
	typeof(int),
	typeof(int)
})]
internal static class PatchDadoNaFace
{
	private static void Postfix(DiceRollingManager __instance, TextMeshPro __result)
	{
		if (!Plugin.Ativo || !Plugin.Cfg.EventosAtivar.Value)
		{
			return;
		}
		try
		{
			TextStyler.AplicarTmp((TMP_Text)(object)__result, Plugin.Cfg.EventosDado, "Eventos (texto do dado)");
			DiceVisualSetup[] diceSetups = __instance.DiceSetups;
			if (diceSetups == null)
			{
				return;
			}
			for (int i = 0; i < diceSetups.Length; i++)
			{
				TextMeshPro[] array = (((Object)(object)diceSetups[i] != (Object)null) ? diceSetups[i].DiceNumbers : null);
				if (array != null)
				{
					for (int j = 0; j < array.Length; j++)
					{
						TextStyler.AplicarTmp((TMP_Text)(object)array[j], Plugin.Cfg.EventosDado, "Eventos (texto do dado)");
					}
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Better Combat Text: texto do dado falhou: " + ex.GetType().Name + ": " + ex.Message));
		}
	}
}
[HarmonyPatch(typeof(DiceRoller), "StartRollVisuals")]
internal static class PatchResultadoDoDado
{
	private static void Postfix(DiceRoller __instance)
	{
		if (!Plugin.Ativo || !Plugin.Cfg.EventosAtivar.Value)
		{
			return;
		}
		try
		{
			TextStyler.AplicarTmp((TMP_Text)(object)__instance.TargetText, Plugin.Cfg.EventosDado, "Eventos (texto do dado)");
			TextStyler.AplicarTmp((TMP_Text)(object)__instance.ResultText, Plugin.Cfg.EventosDado, "Eventos (texto do dado)");
			TextStyler.AplicarTmp((TMP_Text)(object)__instance.ModifierValueText, Plugin.Cfg.EventosDado, "Eventos (texto do dado)");
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Better Combat Text: resultado do dado falhou: " + ex.GetType().Name + ": " + ex.Message));
		}
	}
}
[HarmonyPatch(typeof(Tooltip), "ShowActionStatusTooltip", new Type[] { typeof(StatusIcon) })]
internal static class PatchTooltipDeStatus
{
	private static void Postfix(Tooltip __instance)
	{
		if (!Plugin.Ativo || !Plugin.Cfg.TooltipAtivar.Value)
		{
			return;
		}
		try
		{
			TextStyler.AplicarTmp((TMP_Text)(object)__instance.Title, Plugin.Cfg.TooltipStatus, "Tooltip de status");
			TextStyler.AplicarTmp((TMP_Text)(object)__instance.Description, Plugin.Cfg.TooltipStatus, "Tooltip de status");
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Better Combat Text: tooltip de status falhou: " + ex.GetType().Name + ": " + ex.Message));
		}
	}
}
[HarmonyPatch(typeof(Healthbar), "Update", new Type[] { })]
internal static class PatchNumeroDeVida
{
	private static void Postfix(Healthbar __instance)
	{
		if (!Plugin.Ativo || !Plugin.Cfg.AplicarNumeroDeVida.Value)
		{
			return;
		}
		try
		{
			TextStyler.AplicarTmp((TMP_Text)(object)__instance.healthbarText, Plugin.Cfg.NumeroDeVida, "Numero de vida (extra)");
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Better Combat Text: numero de vida falhou: " + ex.GetType().Name + ": " + ex.Message));
		}
	}
}
[BepInPlugin("com.gumatos.bettercombattext", "Better Combat Text", "0.1.0")]
public class Plugin : BaseUnityPlugin
{
	public const string Guid = "com.gumatos.bettercombattext";

	public const string Versao = "0.1.0";

	internal static bool Ativo;

	internal static ManualLogSource Log { get; private set; }

	internal static Configuracao Cfg { get; private set; }

	private void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		Log.LogInfo((object)"Better Combat Text 0.1.0 carregado (GUID com.gumatos.bettercombattext).");
		try
		{
			Cfg = new Configuracao(((BaseUnityPlugin)this).Config);
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Better Combat Text: falha ao ler o config — o mod NAO vai alterar nada. " + ex.GetType().Name + ": " + ex.Message));
			return;
		}
		if (!Cfg.Ativar.Value)
		{
			Ativo = false;
			Log.LogInfo((object)"Better Combat Text: DESLIGADO no config (secao '1. Geral', chave 'Ativar' = false). Nenhum patch foi aplicado — o jogo roda 100% original.");
			return;
		}
		Ativo = true;
		if (AplicarPatches() == 0)
		{
			Ativo = false;
			Log.LogError((object)"Better Combat Text: NENHUM gancho foi aplicado — o mod fica inerte nesta sessao (o jogo roda original; o motivo esta nas linhas acima).");
			return;
		}
		try
		{
			Log.LogInfo((object)("Better Combat Text: alvos dos ganchos (por TIPO, sem parametro posicional): BossHealthbar.set_BossCharacter e PlayerInfoWindow.ShowPlayerInfoWindow (nomes de inimigo), StatusIcon.UpdateStatusIcon (rotulos/stacks de buff e debuff), DiceRollingManager.RollDice e DiceRoller.StartRollVisuals (texto do dado nos eventos)" + (Cfg.AplicarNumeroDeVida.Value ? " + Healthbar.Update (numero de vida, opcional ligado)" : "") + ". Os efeitos aparecem quando cada superficie e escrita pelo jogo — abra um combate/evento para ver."));
			Log.LogInfo((object)("Better Combat Text: contorno cor=" + Cfg.Nomes.CorContornoHex.Value + " " + $"alfa={Cfg.Nomes.AlfaContorno.Value:0.###} largura={Cfg.Nomes.LarguraContorno.Value:0.###} " + $"softness={Cfg.Nomes.SuavidadeContorno.Value:0.###} sombra={Cfg.Nomes.SombraAtiva.Value}; " + $"eventos(dado) ativo={Cfg.EventosAtivar.Value}; numero de vida={Cfg.AplicarNumeroDeVida.Value}; " + $"diagnostico no arranque={Cfg.DiagnosticoArranque.Value}."));
			Log.LogInfo((object)"Better Combat Text: config em BepInEx/config/com.gumatos.bettercombattext.cfg — para desligar TUDO basta 'Ativar = false' na secao '1. Geral'.");
		}
		catch (Exception ex2)
		{
			Log.LogWarning((object)("Better Combat Text: falha ao escrever o resumo de config no log: " + ex2.GetType().Name + ": " + ex2.Message));
		}
	}

	private static int AplicarPatches()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		Harmony val = new Harmony("com.gumatos.bettercombattext");
		List<string> list = new List<string>();
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		Type[] types;
		try
		{
			types = typeof(Plugin).Assembly.GetTypes();
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Better Combat Text: nao deu para listar os tipos do mod — nenhum gancho aplicado: " + ex));
			return 0;
		}
		foreach (Type type in types)
		{
			if (EhClasseDeGancho(type))
			{
				num++;
				try
				{
					int num4 = val.CreateClassProcessor(type).Patch()?.Count ?? 0;
					num3 += num4;
					num2++;
					Log.LogInfo((object)("Better Combat Text: gancho aplicado — " + type.Name + " (" + num4 + " metodo(s) do jogo)."));
				}
				catch (Exception ex2)
				{
					list.Add(type.Name);
					Log.LogError((object)("Better Combat Text: FALHA ao aplicar o gancho " + type.Name + " — " + ex2.Message));
				}
			}
		}
		string text = "Better Combat Text: patches Harmony aplicados (" + num2 + "/" + num + " ganchos, " + num3 + " metodos do jogo).";
		if (list.Count == 0)
		{
			Log.LogInfo((object)text);
			return num2;
		}
		Log.LogError((object)(text + " GANCHOS QUE FALHARAM: " + string.Join(", ", list.ToArray()) + ". O mod continua de pe, mas o recurso que dependia deles nao existe nesta sessao."));
		return num2;
	}

	private static bool EhClasseDeGancho(Type tipo)
	{
		try
		{
			if (tipo == null || !tipo.IsClass)
			{
				return false;
			}
			return tipo.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0;
		}
		catch (Exception)
		{
			return false;
		}
	}
}
internal static class TextStyler
{
	private static readonly Dictionary<int, Material> MateriaisInstanciados = new Dictionary<int, Material>();

	private static readonly Dictionary<string, string> AvisosDados = new Dictionary<string, string>();

	private static readonly HashSet<int> TextosLegadosTratados = new HashSet<int>();

	private static readonly Dictionary<int, float> TamanhoOriginal = new Dictionary<int, float>();

	private static readonly Dictionary<int, float> TamanhoOriginalLegado = new Dictionary<int, float>();

	private static bool _resumoAplicadoSobreNomes;

	private static bool _resumoAplicadoSobreDado;

	private static readonly HashSet<string> DetalhesDados = new HashSet<string>();

	private static bool _inventarioFeito;

	private static bool _resumoRotulosFeito;

	internal static void AplicarTmp(TMP_Text tmp, EstiloTmpCfg cfg, string superficie)
	{
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)tmp == (Object)null || (!cfg.HaloAtivo.Value && !cfg.SombraAtiva.Value && cfg.TamanhoFonteExtra.Value == 0f))
		{
			return;
		}
		try
		{
			Material fontSharedMaterial = tmp.fontSharedMaterial;
			if ((Object)(object)fontSharedMaterial == (Object)null)
			{
				AvisoUma(superficie + ":sem-material", "'" + Nome(tmp) + "' nao tem fontSharedMaterial; ignorado.");
				return;
			}
			int instanceID = ((Object)tmp).GetInstanceID();
			if (MateriaisInstanciados.TryGetValue(instanceID, out var value) && (Object)(object)value != (Object)null && (Object)(object)value == (Object)(object)fontSharedMaterial)
			{
				return;
			}
			Material fontMaterial = tmp.fontMaterial;
			if ((Object)(object)fontMaterial == (Object)null)
			{
				AvisoUma(superficie + ":instancia-nula", "'" + Nome(tmp) + "': fontMaterial devolveu null; ignorado.");
				return;
			}
			MateriaisInstanciados[instanceID] = fontMaterial;
			Shader shader = fontMaterial.shader;
			string text = (((Object)(object)shader != (Object)null) ? ((Object)shader).name : "(sem shader)");
			bool flag = fontMaterial.HasProperty("_OutlineWidth");
			bool flag2 = fontMaterial.HasProperty("_UnderlaySoftness");
			if (cfg.HaloAtivo.Value)
			{
				if (flag)
				{
					fontMaterial.EnableKeyword("OUTLINE_ON");
					fontMaterial.SetColor("_OutlineColor", cfg.CorContorno);
					fontMaterial.SetFloat("_OutlineWidth", Mathf.Clamp(cfg.LarguraContorno.Value, 0f, 1f));
					fontMaterial.SetFloat("_OutlineSoftness", Mathf.Clamp(cfg.SuavidadeContorno.Value, 0f, 1f));
				}
				else
				{
					AvisoUma(superficie + ":bitmap", "'" + Nome(tmp) + "' usa o shader '" + text + "', que NAO tem _OutlineWidth (fonte bitmap, nao distance field). Halo suave IMPOSSIVEL nesta fonte; nada foi alterado nela.");
				}
			}
			if (cfg.SombraAtiva.Value)
			{
				if (flag2)
				{
					fontMaterial.EnableKeyword("UNDERLAY_ON");
					fontMaterial.SetColor("_UnderlayColor", cfg.CorSombra);
					fontMaterial.SetFloat("_UnderlayOffsetX", Mathf.Clamp(cfg.SombraOffsetX.Value, -2f, 2f));
					fontMaterial.SetFloat("_UnderlayOffsetY", Mathf.Clamp(cfg.SombraOffsetY.Value, -2f, 2f));
					fontMaterial.SetFloat("_UnderlayDilate", Mathf.Clamp(cfg.SombraDilate.Value, -1f, 1f));
					fontMaterial.SetFloat("_UnderlaySoftness", Mathf.Clamp(cfg.SombraSuavidade.Value, 0f, 1f));
				}
				else
				{
					AvisoUma(superficie + ":sem-underlay", "'" + Nome(tmp) + "' / shader '" + text + "' nao expoe _UnderlaySoftness; sombra ignorada.");
				}
			}
			AplicarTamanho(tmp, cfg.TamanhoFonteExtra.Value, instanceID);
			tmp.UpdateMeshPadding();
			((Graphic)tmp).SetVerticesDirty();
			((Graphic)tmp).SetMaterialDirty();
			if (Plugin.Cfg.LogDetalhado.Value)
			{
				Plugin.Log.LogInfo((object)("[" + superficie + "] '" + Nome(tmp) + "' tratado: shader='" + text + "' " + string.Format("df={0} halo={1} ", flag, cfg.HaloAtivo.Value ? Part(cfg.LarguraContorno) : "off") + "softness=" + Part(cfg.SuavidadeContorno) + " alfa=" + Part(cfg.AlfaContorno) + " sombra=" + (cfg.SombraAtiva.Value ? Part(cfg.AlfaSombra) : "off")));
			}
			ReportarResumo(superficie, text, cfg, flag);
			DetalharAlvo(superficie, tmp, fontSharedMaterial, text, flag);
		}
		catch (Exception ex)
		{
			AvisoUma(superficie + ":erro", "falha ao tratar '" + Nome(tmp) + "': " + ex.GetType().Name + ": " + ex.Message);
		}
	}

	private static void ReportarResumo(string superficie, string nomeShader, EstiloTmpCfg cfg, bool df)
	{
		if (!(superficie.Contains("dado") ? _resumoAplicadoSobreDado : _resumoAplicadoSobreNomes))
		{
			if (superficie.Contains("dado"))
			{
				_resumoAplicadoSobreDado = true;
			}
			else
			{
				_resumoAplicadoSobreNomes = true;
			}
			Plugin.Log.LogInfo((object)("[" + superficie + "] APLICADO em '" + superficie + "' (material instanciado POR COMPONENTE): " + $"shader='{nomeShader}', distance field={df}, contorno={Part(cfg.LarguraContorno)} " + "largura / " + Part(cfg.SuavidadeContorno) + " softness / cor " + cfg.CorContornoHex.Value + " alfa " + Part(cfg.AlfaContorno) + ", sombra=" + (cfg.SombraAtiva.Value ? "on" : "off") + " tamanho=" + ((cfg.TamanhoFonteExtra.Value == 0f) ? "intocado" : Part(cfg.TamanhoFonteExtra)) + "."));
		}
	}

	private static void AplicarTamanho(TMP_Text tmp, float extra, int id)
	{
		if (extra != 0f)
		{
			if (!TamanhoOriginal.TryGetValue(id, out var value))
			{
				value = tmp.fontSize;
				TamanhoOriginal[id] = value;
			}
			tmp.fontSize = value + extra;
		}
	}

	internal static void AplicarTextoLegado(Text txt, EstiloTextoLegadoCfg cfg, string superficie)
	{
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)txt == (Object)null || (!cfg.HaloAtivo.Value && !cfg.SombraAtiva.Value && !cfg.Negrito.Value && cfg.TamanhoExtra.Value == 0f))
		{
			return;
		}
		int instanceID = ((Object)txt).GetInstanceID();
		try
		{
			if (TextosLegadosTratados.Contains(instanceID))
			{
				return;
			}
			TextosLegadosTratados.Add(instanceID);
			Graphic[] components = ((Component)txt).gameObject.GetComponents<Graphic>();
			bool flag = components == null || components.Length == 0 || (Object)(object)components[0] == (Object)(object)txt;
			if (cfg.HaloAtivo.Value)
			{
				if (flag)
				{
					Outline val = ((Component)txt).gameObject.GetComponent<Outline>();
					if ((Object)(object)val == (Object)null)
					{
						val = ((Component)txt).gameObject.AddComponent<Outline>();
					}
					((Shadow)val).effectColor = cfg.CorContorno;
					((Shadow)val).effectDistance = new Vector2(cfg.RaioContorno.Value, cfg.RaioContorno.Value);
					((Shadow)val).useGraphicAlpha = true;
				}
				else
				{
					AvisoUma("rotulos:graphic-antes", "'" + ((Object)((Component)txt).gameObject).name + "': ha outro Graphic antes do Text no mesmo objeto; contorno NAO adicionado (mexeria no elemento errado).");
				}
			}
			if (cfg.SombraAtiva.Value && flag)
			{
				Shadow val2 = ((Component)txt).gameObject.GetComponent<Shadow>();
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = ((Component)txt).gameObject.AddComponent<Shadow>();
				}
				val2.effectColor = cfg.CorSombra;
				val2.effectDistance = new Vector2(cfg.SombraOffsetX.Value, cfg.SombraOffsetY.Value);
				val2.useGraphicAlpha = true;
			}
			if (cfg.Negrito.Value)
			{
				txt.fontStyle = (FontStyle)(txt.fontStyle | 1);
			}
			if (cfg.TamanhoExtra.Value != 0f)
			{
				if (!TamanhoOriginalLegado.TryGetValue(instanceID, out var value))
				{
					value = txt.fontSize;
					TamanhoOriginalLegado[instanceID] = value;
				}
				txt.fontSize = Mathf.Max(1, Mathf.RoundToInt(value + cfg.TamanhoExtra.Value));
			}
			if (Plugin.Cfg.LogDetalhado.Value)
			{
				Plugin.Log.LogInfo((object)("[" + superficie + "] '" + ((Object)((Component)txt).gameObject).name + "' tratado (UI.Text legado): contorno=" + (cfg.HaloAtivo.Value ? Part(cfg.RaioContorno) : "off") + "px alfa=" + Part(cfg.AlfaContorno) + ", " + string.Format("sombra={0}, negrito={1}", cfg.SombraAtiva.Value ? Part(cfg.AlfaSombra) : "off", cfg.Negrito.Value)));
			}
		}
		catch (Exception ex)
		{
			AvisoUma(superficie + ":erro", "falha ao tratar '" + ((Object)((Component)txt).gameObject).name + "': " + ex.GetType().Name + ": " + ex.Message);
		}
	}

	internal static void ReportarResumoRotulos()
	{
		if (!_resumoRotulosFeito)
		{
			_resumoRotulosFeito = true;
			EstiloTextoLegadoCfg rotulos = Plugin.Cfg.Rotulos;
			Plugin.Log.LogInfo((object)("[Rotulos de buff/debuff em combate] APLICADO nos rotulos 'xN' e contador de turnos dos icones de status (props 100% locais do objeto, nada compartilhado): contorno duro " + (rotulos.HaloAtivo.Value ? (Part(rotulos.RaioContorno) + "px") : "off") + " cor " + rotulos.CorContornoHex.Value + " alfa " + Part(rotulos.AlfaContorno) + " (4 copias), sombra=" + (rotulos.SombraAtiva.Value ? "on" : "off") + ", " + string.Format("negrito={0}, tamanho={1}. ", rotulos.Negrito.Value, (rotulos.TamanhoExtra.Value == 0f) ? "intocado" : Part(rotulos.TamanhoExtra)) + "Obs.: este texto e UI.Text legado (sem distance field) — halo SUAVE nao se aplica aqui."));
		}
	}

	private static void DetalharAlvo(string superficie, TMP_Text tmp, Material compartilhadoAntes, string nomeShader, bool df)
	{
		if (DetalhesDados.Add(superficie))
		{
			try
			{
				string text = (((Object)(object)tmp.font != (Object)null) ? ((Object)tmp.font).name : "(nula)");
				string text2 = (((Object)(object)compartilhadoAntes != (Object)null) ? ((Object)compartilhadoAntes).name : "(nulo)");
				bool flag = text2.Contains("(Instance)");
				Plugin.Log.LogInfo((object)("[" + superficie + "] alvo: objeto='" + Nome(tmp) + "', componente=" + ((object)tmp).GetType().Name + ", fonte TMP='" + text + "', material compartilhado antes de clonar='" + text2 + "'" + (flag ? " (ja era instancia de outro mod — clonamos por cima)" : " (compartilhado do prefab)") + ", " + $"shader='{nomeShader}', tem _OutlineWidth (distance field/SDF)={df}"));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Better Combat Text: log de detalhe falhou: " + ex.GetType().Name + ": " + ex.Message));
			}
			InventarioDeCena();
		}
	}

	private static void InventarioDeCena()
	{
		if (_inventarioFeito)
		{
			return;
		}
		_inventarioFeito = true;
		try
		{
			TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>();
			TextMesh[] array2 = Resources.FindObjectsOfTypeAll<TextMesh>();
			Plugin.Log.LogInfo((object)($"Better Combat Text: inventario de cena — {array.Length} TMP_Text (TextMeshPro/UGUI, " + $"elegiveis ao halo suave) e {array2.Length} TextMesh legado (3D, usado por " + "DieSideAwareTextDie — NAO e tocado pelo mod)."));
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			foreach (TMP_Text val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Material val2 = null;
					try
					{
						val2 = val.fontSharedMaterial;
					}
					catch
					{
					}
					string key = (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "(sem material)");
					dictionary.TryGetValue(key, out var value);
					dictionary[key] = value + 1;
				}
			}
			int num = 0;
			foreach (KeyValuePair<string, int> item in dictionary)
			{
				if (num++ >= 10)
				{
					Plugin.Log.LogInfo((object)$"Better Combat Text: ... e mais {dictionary.Count - 10} materiais distintos.");
					break;
				}
				Plugin.Log.LogInfo((object)$"Better Combat Text: material de fonte em uso: '{item.Key}' x{item.Value}");
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Better Combat Text: inventario de cena falhou: " + ex.GetType().Name + ": " + ex.Message));
		}
	}

	private static string Nome(TMP_Text t)
	{
		try
		{
			return ((Object)(object)t != (Object)null && (Object)(object)((Component)t).gameObject != (Object)null) ? ((Object)((Component)t).gameObject).name : "(?)";
		}
		catch
		{
			return "(?)";
		}
	}

	private static string Part(float valor)
	{
		return valor.ToString("0.###");
	}

	private static string Part(ConfigEntry<float> e)
	{
		return e.Value.ToString("0.###");
	}

	private static void AvisoUma(string chave, string mensagem)
	{
		if (!AvisosDados.ContainsKey(chave))
		{
			AvisosDados[chave] = mensagem;
			Plugin.Log.LogWarning((object)("Better Combat Text: " + mensagem));
		}
	}
}