using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using Burst2Flame;
using Burst2Flame.Observable;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("RoguelikeDebugger")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Logs de investigação de mecânicas do Stolen Realm (loot, Gold, Experience, eventos).")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1")]
[assembly: AssemblyProduct("RoguelikeDebugger")]
[assembly: AssemblyTitle("RoguelikeDebugger")]
[assembly: AssemblyVersion("0.1.1.0")]
namespace RoguelikeDebugger
{
internal static class EfeitosInfo
{
private static readonly Dictionary<string, int> Contagem = new Dictionary<string, int>();
private static int _total;
private static int _naoGeneralEffect;
public static void Zerar()
{
Contagem.Clear();
_total = 0;
_naoGeneralEffect = 0;
}
public static string Resumo()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("total=").Append(_total);
stringBuilder.Append(" | porTipo={");
bool flag = true;
List<string> list = new List<string>(Contagem.Keys);
list.Sort(StringComparer.Ordinal);
foreach (string item in list)
{
if (!flag)
{
stringBuilder.Append("; ");
}
flag = false;
stringBuilder.Append(item).Append('=').Append(Contagem[item]);
}
stringBuilder.Append("}");
stringBuilder.Append(" | naoGeneralEffect=").Append(_naoGeneralEffect);
return stringBuilder.ToString();
}
public static int Conta(Array arr)
{
return arr?.Length ?? 0;
}
public static string Descreve(Array arr)
{
return DescreveCore(arr, origemIEffectInfo: false);
}
public static string Descreve(IEffectInfo[] arr)
{
return DescreveCore(arr, origemIEffectInfo: true);
}
private static string DescreveCore(Array arr, bool origemIEffectInfo)
{
if (arr == null || arr.Length == 0)
{
return "";
}
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < arr.Length; i++)
{
object value;
try
{
value = arr.GetValue(i);
}
catch (Exception ex)
{
value = null;
stringBuilder.Append(i).Append(":<erro:").Append(ex.GetType().Name)
.Append(">; ");
continue;
}
stringBuilder.Append(i).Append(':').Append(Um(value, origemIEffectInfo))
.Append("; ");
}
return stringBuilder.ToString().TrimEnd(' ', ';');
}
private static string Um(object o, bool origemIEffectInfo)
{
if (o == null)
{
Contagem["null"] = ((!Contagem.TryGetValue("null", out var value)) ? 1 : (value + 1));
_total++;
return "null";
}
Type type = o.GetType();
string name = type.Name;
Contagem[name] = ((!Contagem.TryGetValue(name, out var value2)) ? 1 : (value2 + 1));
_total++;
if (origemIEffectInfo && !(o is GeneralEffect))
{
_naoGeneralEffect++;
}
FieldInfo[] array;
try
{
array = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
}
catch (Exception)
{
array = new FieldInfo[0];
}
Array.Sort(array, (FieldInfo a, FieldInfo b) => string.CompareOrdinal(a.Name, b.Name));
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(name).Append('{');
bool flag = true;
FieldInfo[] array2 = array;
foreach (FieldInfo fieldInfo in array2)
{
if (!fieldInfo.IsStatic)
{
object v;
try
{
v = fieldInfo.GetValue(o);
}
catch (Exception ex2)
{
v = "<erro:" + ex2.GetType().Name + ">";
}
if (!flag)
{
stringBuilder.Append(';');
}
flag = false;
stringBuilder.Append(fieldInfo.Name).Append('=').Append(Valor(v));
}
}
stringBuilder.Append('}');
return stringBuilder.ToString();
}
private static string Valor(object v)
{
if (v == null)
{
return "-";
}
Object val = (Object)((v is Object) ? v : null);
if (val != (Object)null)
{
return Limpa(val.name);
}
if (v is string text)
{
if (text.Length != 0)
{
return Limpa(text);
}
return "-";
}
if (v is Array array)
{
return "[" + array.Length + "]";
}
return Limpa(v.ToString());
}
public static string Limpa(string s)
{
return (s ?? "").Replace("\n", " ").Replace("\r", " ").Replace("|", "/")
.Replace("\"", "'")
.Trim();
}
}
[BepInPlugin("com.gumatos.roguelikedebugger", "Roguelike Debugger", "0.1.1")]
public class Plugin : BaseUnityPlugin
{
internal static ManualLogSource Log { get; private set; }
private void Awake()
{
Log = ((BaseUnityPlugin)this).Logger;
((BaseUnityPlugin)this).Logger.LogInfo((object)"Roguelike Debugger carregado.");
AplicarPatches();
}
private static void 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.roguelikedebugger");
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)("Roguelike Debugger: nao deu para listar os tipos do mod — nenhum gancho aplicado: " + ex));
return;
}
foreach (Type type in types)
{
if (EhClasseDeGancho(type))
{
num++;
try
{
int num4 = val.CreateClassProcessor(type).Patch()?.Count ?? 0;
num3 += num4;
num2++;
Log.LogInfo((object)("Roguelike Debugger: gancho aplicado — " + type.Name + " (" + num4 + " metodo(s) do jogo)."));
}
catch (Exception ex2)
{
list.Add(type.Name);
Log.LogError((object)("Roguelike Debugger: FALHA ao aplicar o gancho " + type.Name + " — " + ex2.Message));
}
}
}
string text = "Roguelike Debugger: patches Harmony aplicados (" + num2 + "/" + num + " ganchos, " + num3 + " metodos do jogo).";
if (list.Count == 0)
{
Log.LogInfo((object)text);
}
else
{
Log.LogError((object)(text + " GANCHOS QUE FALHARAM: " + string.Join(", ", list.ToArray()) + ". O mod continua de pe, mas o log do recurso que dependia deles nao sai nesta sessao."));
}
}
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;
}
}
}
}
namespace RoguelikeDebugger.Patches
{
[HarmonyPatch(typeof(Game), "get_ActionStatuses")]
public static class ActionStatusInventoryPatch
{
private static bool _dumped;
private static int _lastCount = -1;
private static int _stableHits;
private static string TriggersDe(ActionStatusInfo s)
{
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)s == (Object)null || s.SkillTriggers == null || s.SkillTriggers.Length == 0)
{
return "";
}
StringBuilder stringBuilder = new StringBuilder();
SkillTrigger[] skillTriggers = s.SkillTriggers;
foreach (SkillTrigger val in skillTriggers)
{
if (val == null)
{
continue;
}
StringBuilder stringBuilder2 = new StringBuilder();
if (val.ActionStatuses != null)
{
ActionStatusInfo[] actionStatuses = val.ActionStatuses;
foreach (ActionStatusInfo val2 in actionStatuses)
{
if ((Object)(object)val2 != (Object)null)
{
stringBuilder2.Append(EfeitosInfo.Limpa(val2.Name)).Append(',');
}
}
}
StringBuilder stringBuilder3 = stringBuilder.Append(val.TriggerType).Append("[ef=");
IEffectInfo[] generalEffects = (IEffectInfo[])(object)val.GeneralEffects;
stringBuilder3.Append(EfeitosInfo.Descreve(generalEffects)).Append("~cond=").Append(EfeitosInfo.Limpa(val.Condition))
.Append("~status=")
.Append(stringBuilder2)
.Append("]; ");
}
return stringBuilder.ToString().TrimEnd(' ', ';');
}
private static void Postfix(List<ActionStatusInfo> __result)
{
//IL_0309: Unknown result type (might be due to invalid IL or missing references)
//IL_0314: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
try
{
if (_dumped || __result == null || __result.Count <= 1)
{
return;
}
if (__result.Count == _lastCount)
{
_stableHits++;
}
else
{
_stableHits = 1;
_lastCount = __result.Count;
}
if (_stableHits < 5)
{
return;
}
_dumped = true;
Plugin.Log.LogInfo((object)$"[Status] Inventário: {__result.Count} status carregados.");
EfeitosInfo.Zerar();
foreach (ActionStatusInfo item in __result)
{
if ((Object)(object)item == (Object)null)
{
continue;
}
string text = item.Description ?? "";
StringBuilder stringBuilder = new StringBuilder();
if (item.AttributeEffects != null)
{
CharacterEffectInfo[] attributeEffects = item.AttributeEffects;
foreach (CharacterEffectInfo val in attributeEffects)
{
if (val != null && !((Object)(object)val.CharacterAttribute == (Object)null))
{
stringBuilder.Append(((Object)val.CharacterAttribute).name).Append(':').Append(val.CharacterEffectMethod)
.Append(':')
.Append(val.Amount)
.Append(", ");
}
}
}
StringBuilder stringBuilder2 = new StringBuilder();
int num = 0;
if (item.Effects != null)
{
IEffectInfo[] effects = item.Effects;
foreach (IEffectInfo obj in effects)
{
GeneralEffect val2 = (GeneralEffect)(object)((obj is GeneralEffect) ? obj : null);
if (val2 != null)
{
num++;
if (!string.IsNullOrEmpty(val2.Action))
{
stringBuilder2.Append(val2.Action.Replace("\n", " ").Replace("\r", " ").Replace("|", "/")
.Replace("\"", "'")
.Trim()).Append("; ");
}
}
}
}
string arg = EfeitosInfo.Descreve(item.Effects);
string arg2 = EfeitosInfo.Descreve(item.AttributeEffects);
string text3;
if ((Object)(object)item.ModelChangeCharacter != (Object)null)
{
List<SkillInfo> skills = item.ModelChangeCharacter.Skills;
string text2 = "";
if (skills != null)
{
int num2 = ((skills.Count > 14) ? 14 : skills.Count);
for (int j = 0; j < num2; j++)
{
if (!((Object)(object)skills[j] == (Object)null))
{
text2 = text2 + ((text2.Length > 0) ? "; " : "") + ((Object)skills[j]).name;
}
}
if (skills.Count > num2)
{
text2 = text2 + "; (+" + (skills.Count - num2) + ")";
}
}
text3 = ((Object)item.ModelChangeCharacter).name + " [" + text2 + "]";
}
else
{
text3 = "-";
}
Plugin.Log.LogInfo((object)($"[Status] '{item.Name}' | tipo={item.StatusType} | raridade={item.Rarity} | " + $"efeitos={stringBuilder} | efeitosDano={stringBuilder2} | nEfeitosDano={num} | " + string.Format("aura={0} | raio={1} | ", item.IsAura ? "sim" : "nao", item.AuraRadius) + "auraAli=" + (item.AuraEffectsAllies ? "sim" : "nao") + " | auraIni=" + (item.AuraEffectsEnemies ? "sim" : "nao") + " | modelo=" + text3 + " | beneficio=" + (item.IsBeneficial ? "Buff" : (item.IsHarmful ? "Debuff" : "Neutro")) + " | " + $"dur={item.Duration} | maxStk={item.MaxStacks} | " + $"nEfeitosTot={EfeitosInfo.Conta(item.Effects)} | efTipos={arg} | " + $"nAttrEf={EfeitosInfo.Conta(item.AttributeEffects)} | attrTipos={arg2} | " + $"nTrig={EfeitosInfo.Conta(item.SkillTriggers)} | trigEf={TriggersDe(item)} | " + "desc=\"" + text.Replace("\n", " ") + "\""));
}
Plugin.Log.LogInfo((object)("[Efeitos] resumo (status): " + EfeitosInfo.Resumo()));
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[Status] erro no inventário: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(WorldMapGenerator), "GetRandomEvent")]
public static class EventRollDebugPatch
{
private static void Postfix(NodeTypeEventSet nodeTypeEventSet, TerrainAndTime terrainAndTime, int level, PartyEvent __result)
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((Object)(object)__result == (Object)null)
{
Plugin.Log.LogWarning((object)"[Event] roll retornou null (ver fallbacks no Player.log).");
}
else
{
Plugin.Log.LogInfo((object)($"[Event] '{((Object)__result).name}' | nodo={nodeTypeEventSet.nodeType} " + $"minor={nodeTypeEventSet.isMinor} spawn={nodeTypeEventSet.eventSpawnType} | " + $"terreno={terrainAndTime.TerrainType}/{terrainAndTime.TimeOfDay} | nível={level} | " + $"chance={__result.ChanceRatio} | temBatalha={__result.HasBattle}"));
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[Event] erro no debug: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(GameLogic), "GetTotalExpValue")]
public static class ExpDebugPatch
{
private static void Postfix(float modifier, ref float __result)
{
try
{
float num = ((modifier != 0f) ? (__result / modifier) : 0f);
float experienceMod = GameLogic.instance.CurrentDifficulty.ExperienceMod;
Plugin.Log.LogInfo((object)($"[Exp] total={__result:F1} | base(por inimigos)={num:F1} | " + $"modificador da batalha={modifier:F2} | multiplicador de dificuldade={experienceMod:F2}"));
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[Exp] erro no debug: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(Character), "GetExpValue")]
public static class EnemyExpDebugPatch
{
private static void Postfix(Character __instance, ref float __result)
{
try
{
if (__instance != null)
{
Plugin.Log.LogInfo((object)($"[ExpInimigo] {((Object)__instance.CharacterInfo).name} (Lv {__instance.Level}, " + $"PointValue {__instance.PointValue}) = {__result:F1} exp"));
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[ExpInimigo] erro no debug: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(GameLogic), "ApplyGoldModifiers")]
public static class GoldModifierDebugPatch
{
private static void Postfix(float originalGold, ref float __result)
{
try
{
NetworkingManager instance = NetworkingManager.Instance;
List<Character> list = ((instance != null) ? instance.MyPartyCharacters : null);
List<string> list2 = new List<string>();
float num = 0f;
if (list != null)
{
foreach (Character item in list)
{
float num2 = item["GoldMod"];
num += num2;
list2.Add($"{item.CharacterName}={num2}");
}
}
Plugin.Log.LogInfo((object)(string.Format("[Gold] ouro base={0} party=[{1}] ", originalGold, (list2.Count > 0) ? string.Join(", ", list2) : "-") + $"GoldMod soma={num} ouro final={__result}"));
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[Gold] erro no debug: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(Game), "get_Items")]
public static class ItemInventoryPatch
{
private static bool _itemsDumped;
private static int _itemsLast = -1;
private static int _itemsStable;
private static bool _modsDumped;
private static void Postfix(List<ItemInfo> __result)
{
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_016d: Unknown result type (might be due to invalid IL or missing references)
try
{
if (_itemsDumped || __result == null || __result.Count <= 1)
{
return;
}
if (__result.Count == _itemsLast)
{
_itemsStable++;
}
else
{
_itemsStable = 1;
_itemsLast = __result.Count;
}
if (_itemsStable < 5)
{
return;
}
_itemsDumped = true;
EfeitosInfo.Zerar();
Plugin.Log.LogInfo((object)$"[Item] Inventário: {__result.Count} itens base carregados.");
foreach (ItemInfo item in __result)
{
if ((Object)(object)item == (Object)null)
{
continue;
}
string text = item.OptionalDescription ?? "";
StringBuilder stringBuilder = new StringBuilder();
if (item.IsConsumable && (Object)(object)item.ConsumableAction != (Object)null)
{
stringBuilder.Append(((Object)item.ConsumableAction).name).Append("::");
if (item.ConsumableAction.Effects != null)
{
IEffectInfo[] effects = item.ConsumableAction.Effects;
foreach (IEffectInfo obj in effects)
{
GeneralEffect val = (GeneralEffect)(object)((obj is GeneralEffect) ? obj : null);
if (val != null && !string.IsNullOrEmpty(val.Action))
{
stringBuilder.Append(val.Action).Append("; ");
}
}
}
}
Plugin.Log.LogInfo((object)($"[Item] '{((Object)item).name}' | tipo={item.ItemType} | raridade={item.Rarity} | " + string.Format("lvlMin={0} | consumivel={1} | ", item.MinLevel, stringBuilder.ToString().Replace("|", "/").Replace("\n", " ")) + "consEf=" + EfeitosInfo.Descreve((item.IsConsumable && (Object)(object)item.ConsumableAction != (Object)null) ? item.ConsumableAction.Effects : null) + " | desc=\"" + text.Replace("\n", " ") + "\""));
}
Plugin.Log.LogInfo((object)("[Efeitos] resumo (itens): " + EfeitosInfo.Resumo()));
DumpItemMods();
PowerupInventoryPatch.Trigger();
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[Item] erro no inventário: " + ex.Message));
}
}
private static void DumpItemMods()
{
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
try
{
if (_modsDumped)
{
return;
}
ItemMod[] itemMods = Game.Instance.ItemMods;
if (itemMods == null || itemMods.Length <= 1)
{
return;
}
_modsDumped = true;
Plugin.Log.LogInfo((object)$"[ItemMod] Inventário: {itemMods.Length} afixos carregados.");
ItemMod[] array = itemMods;
foreach (ItemMod val in array)
{
if (!((Object)(object)val == (Object)null))
{
string text = val.Description ?? "";
Plugin.Log.LogInfo((object)($"[ItemMod] '{((Object)val).name}' | tipo={val.ItemModType} | raridade={val.Rarity} | " + "desc=\"" + text.Replace("\n", " ") + "\""));
}
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[ItemMod] erro no inventário: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(MessageWindowManager), "CreateBattleLogMessage")]
public static class LifeStealDebugPatch
{
private static void Postfix(Character source, Character target, string message, float value)
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
try
{
if (message == null)
{
return;
}
if (message == "[source] healed [value] health from life steal" && source != null)
{
List<string> list = new List<string>();
foreach (SkillType value2 in Enum.GetValues(typeof(SkillType)))
{
float num = source["LifeSteal" + ((object)value2/*cast due to .constrained prefix*/).ToString()];
if (num > 0f)
{
list.Add($"{(object)value2}={num:F1}");
}
}
float num2 = source["LifeSteal"];
float maxHealth = source.MaxHealth;
_ = maxHealth * num2 / 100f;
Plugin.Log.LogInfo((object)($"[LifeSteal] {source.CharacterName} curou {value:F1} | " + $"vidaMáxima={maxHealth:F1} | LifeSteal%={num2:F1} | nível={source.Level} | " + "porTipo=[" + string.Join(", ", list) + "] | " + $"(15% da vidaMáx seria {maxHealth * 0.15f:F1})"));
}
else if (message == "[source] dealt [value] Damage to [target]" && source != null && !source.IsAI && value > 0f)
{
Plugin.Log.LogInfo((object)($"[Dmg] {source.CharacterName} causou {value:F1} dano em " + string.Format("{0} | LifeSteal%={1:F1}", (target != null) ? target.CharacterName : "?", source["LifeSteal"])));
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[LifeSteal] erro no debug: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(GameLogic), "GetCharacterLootDropModifier")]
public static class LootModifierDebugPatch
{
private static void Postfix(ref float __result)
{
try
{
NetworkingManager instance = NetworkingManager.Instance;
List<Character> list = ((instance != null) ? instance.MyPartyCharacters : null);
if (list == null)
{
Plugin.Log.LogInfo((object)"[Loot] Modificador de loot: party nula.");
return;
}
Root root = ((Observer<Root>)(object)NetworkingManager.Instance.NetworkManager).Root;
Plugin.Log.LogInfo((object)$"[Loot] PlayingRoguelike={((root != null) ? new bool?(root.PlayingRoguelike) : ((bool?)null))}");
ObservableRoguelikePowerupAndLevelSet val = default(ObservableRoguelikePowerupAndLevelSet);
foreach (Character item in list)
{
float num = item["DropQuantityMod"];
List<string> list2 = new List<string>();
if (root != null && root.RoguelikePowerupsByConnection != null && root.RoguelikePowerupsByConnection.TryGetValue(item.OwnerID, ref val) && val.PowerupAndLevels != null)
{
foreach (ObservableRoguelikePowerupAndLevel powerupAndLevel in val.PowerupAndLevels)
{
if (powerupAndLevel.Level > 0)
{
list2.Add(string.Format("{0} Lv{1}", Game.Instance.GetFromRoguelikePowerupDict(Game.Instance.GetGuidFromString(powerupAndLevel.Guid))?.Name ?? "?", powerupAndLevel.Level));
}
}
}
Plugin.Log.LogInfo((object)($"[Loot] {item.CharacterName}: DropQuantityMod={num}; " + string.Format("GoldMod={0}; DamageMod={1}; ", item["GoldMod"], item["DamageMod"]) + string.Format("DamageModHealing={0}; DamageReduction={1}; ", item["DamageModHealing"], item["DamageReduction"]) + string.Format("FreeMove={0}; RangeMelee={1}; ", item["FreeMovementPoints"], item["RangeTypeAdderMelee"]) + string.Format("RangeRanged={0}; SkillOpts={1}; ", item["RangeTypeAdderRanged"], item["AdditionalRoguelikeSkillOptions"]) + string.Format("AttrPtsPerLvl={0}; ", item["AdditionalRoguelikeAttributesPointsPerLevel"]) + string.Format("Resilience={0}; TakeCover={1}; ", item["Resilience"], item["TakeCover"]) + "powerups ativos: " + ((list2.Count > 0) ? string.Join(", ", list2) : "nenhum")));
}
Plugin.Log.LogInfo((object)$"[Loot] Multiplicador final={__result}");
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[Loot] erro no debug: " + ex.Message + "\n" + ex.StackTrace));
}
}
}
[HarmonyPatch(typeof(Game), "get_RoguelikePowerups")]
public static class PowerupInventoryPatch
{
private static bool _dumped;
internal static void Trigger()
{
try
{
Plugin.Log.LogInfo((object)"[Powerup] trigger chamado (forçando o load lazy).");
RoguelikePowerup[] roguelikePowerups = Game.Instance.RoguelikePowerups;
Plugin.Log.LogInfo((object)("[Powerup] getter retornou " + ((roguelikePowerups == null) ? "null" : (roguelikePowerups.Length + " itens")) + "."));
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[Powerup] trigger falhou: " + ex.Message));
}
}
private static void Postfix(RoguelikePowerup[] __result)
{
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
try
{
if (_dumped || __result == null || __result.Length <= 1)
{
return;
}
_dumped = true;
Plugin.Log.LogInfo((object)$"[Powerup] Inventário: {__result.Length} powerups carregados.");
foreach (RoguelikePowerup val in __result)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
if (val.PowerupLevels == null || val.PowerupLevels.Length == 0)
{
Plugin.Log.LogInfo((object)$"[Powerup] '{val.Name}' | guid={val.Guid} | (sem níveis)");
continue;
}
for (int j = 0; j < val.PowerupLevels.Length; j++)
{
RoguelikePowerupLevel val2 = val.PowerupLevels[j];
if (val2 == null)
{
continue;
}
StringBuilder stringBuilder = new StringBuilder();
if (val2.CharacterEffects != null)
{
CharacterEffectInfo[] characterEffects = val2.CharacterEffects;
foreach (CharacterEffectInfo val3 in characterEffects)
{
if (val3 != null && !((Object)(object)val3.CharacterAttribute == (Object)null))
{
stringBuilder.Append(((Object)val3.CharacterAttribute).name).Append(':').Append(val3.CharacterEffectMethod)
.Append(':')
.Append(val3.Amount)
.Append(", ");
}
}
}
string arg = (val2.Description ?? "").Replace("\n", " ");
Plugin.Log.LogInfo((object)($"[Powerup] '{val.Name}' | guid={val.Guid} | nivel={j + 1} | custo={val2.Cost} | " + $"efeitos={stringBuilder} | desc=\"{arg}\""));
}
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[Powerup] erro no inventário: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(Game), "get_Skills")]
public static class SkillInventoryPatch
{
private static bool _dumped;
private static int _lastCount = -1;
private static int _stableHits;
private static readonly Dictionary<string, ActionInfo> _acoes = new Dictionary<string, ActionInfo>();
private static string Limpa(string s)
{
return (s ?? "").Replace("\n", " ").Replace("\r", " ").Replace("|", "/")
.Replace("\"", "'")
.Trim();
}
private static string Junta(string[] itens)
{
if (itens == null)
{
return "";
}
StringBuilder stringBuilder = new StringBuilder();
foreach (string text in itens)
{
if (!string.IsNullOrEmpty(text))
{
stringBuilder.Append(Limpa(text)).Append("; ");
}
}
return stringBuilder.ToString().TrimEnd(' ', ';');
}
private static void DespejaAcoes()
{
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
//IL_0719: Unknown result type (might be due to invalid IL or missing references)
//IL_0724: Unknown result type (might be due to invalid IL or missing references)
//IL_073c: Unknown result type (might be due to invalid IL or missing references)
Plugin.Log.LogInfo((object)$"[Action] Inventário: {_acoes.Count} ações concedidas por skills.");
EfeitosInfo.Zerar();
Queue<string> queue = new Queue<string>(_acoes.Keys.OrderBy<string, string>((string x) => x, StringComparer.Ordinal));
HashSet<string> hashSet = new HashSet<string>();
while (queue.Count > 0)
{
string text = queue.Dequeue();
if (!hashSet.Add(text) || !_acoes.TryGetValue(text, out var value) || (Object)(object)value == (Object)null)
{
continue;
}
ActionInfo tooltipDamageInfoRefAction = value.TooltipDamageInfoRefAction;
ActionStatusInfo tooltipDamageInfoRefStatus = value.TooltipDamageInfoRefStatus;
if ((Object)(object)tooltipDamageInfoRefAction != (Object)null && !string.IsNullOrEmpty(((Object)tooltipDamageInfoRefAction).name))
{
_acoes[((Object)tooltipDamageInfoRefAction).name] = tooltipDamageInfoRefAction;
queue.Enqueue(((Object)tooltipDamageInfoRefAction).name);
}
string text2 = EfeitosDe(value);
string text3 = (((Object)(object)tooltipDamageInfoRefAction != (Object)null) ? EfeitosDe(tooltipDamageInfoRefAction) : "");
int num = ContaEfeitos(value);
int num2 = (((Object)(object)tooltipDamageInfoRefAction != (Object)null) ? ContaEfeitos(tooltipDamageInfoRefAction) : 0);
string arg = EfeitosInfo.Descreve(value.Effects);
Plugin.Log.LogInfo((object)($"[Action] '{text}' | dano={value.DamageType} | " + $"nEfeitosTot={EfeitosInfo.Conta(value.Effects)} | efTipos={arg} | " + "efeitos=" + text2 + " | refAcao=" + (((Object)(object)tooltipDamageInfoRefAction != (Object)null) ? Limpa(((Object)tooltipDamageInfoRefAction).name) : "") + " | efeitosRef=" + text3 + " | " + $"nEfeitos={num} | nEfeitosRef={num2} | " + $"nSummons={((value.Summons == null) ? (-1) : value.Summons.Count)} | " + "refStatus=" + (((Object)(object)tooltipDamageInfoRefStatus != (Object)null) ? Limpa(tooltipDamageInfoRefStatus.Name) : "") + " | danoExpr=" + Junta(value.DamageExpressionOverrides) + " | expr=" + Junta(value.DescriptionExpressions) + " | desc=\"" + Limpa(value.Description) + "\""));
StringBuilder stringBuilder = new StringBuilder();
int num3 = 0;
if (value.Targets != null)
{
ITargetInfo[] targets = value.Targets;
foreach (ITargetInfo obj in targets)
{
TargetInfo val = (TargetInfo)(object)((obj is TargetInfo) ? obj : null);
if (val != null)
{
num3++;
stringBuilder.Append('[').Append("sel=").Append(Limpa(val.Selection))
.Append(';')
.Append("rsel=")
.Append(Limpa(val.RangeSelection))
.Append(';')
.Append("blast=")
.Append(Limpa(val.BlastRange))
.Append(';')
.Append("range=")
.Append(val.SimpleRange)
.Append(';')
.Append("ali=")
.Append(val.TargetAllies ? 1 : 0)
.Append("ini=")
.Append(val.TargetEnemies ? 1 : 0)
.Append("self=")
.Append(val.TargetSelf ? 1 : 0)
.Append(']');
}
}
}
StringBuilder stringBuilder2 = new StringBuilder();
if (value.ActionChances != null)
{
foreach (ActionChance actionChance in value.ActionChances)
{
if (actionChance != null)
{
stringBuilder2.Append(((Object)(object)actionChance.ActionInfo != (Object)null) ? Limpa(((Object)actionChance.ActionInfo).name) : "?").Append(':').Append(actionChance.Chance)
.Append(',');
}
}
}
StringBuilder stringBuilder3 = new StringBuilder();
if (value.StatusEffects != null)
{
ActionStatusInfo[] statusEffects = value.StatusEffects;
foreach (ActionStatusInfo val2 in statusEffects)
{
if ((Object)(object)val2 != (Object)null)
{
stringBuilder3.Append(Limpa(val2.Name)).Append(',');
}
}
}
StringBuilder stringBuilder4 = new StringBuilder();
if (value.SourceStatusEffects != null)
{
ActionStatusInfo[] statusEffects = value.SourceStatusEffects;
foreach (ActionStatusInfo val3 in statusEffects)
{
if ((Object)(object)val3 != (Object)null)
{
stringBuilder4.Append(Limpa(val3.Name)).Append(',');
}
}
}
Dictionary<string, int> dictionary = new Dictionary<string, int>();
if (value.StatusEffects != null)
{
ActionStatusInfo[] statusEffects = value.StatusEffects;
foreach (ActionStatusInfo val4 in statusEffects)
{
if (!((Object)(object)val4 == (Object)null))
{
string key = Limpa(val4.Name);
dictionary[key] = ((!dictionary.TryGetValue(key, out var value2)) ? 1 : (value2 + 1));
}
}
}
if (value.SourceStatusEffects != null)
{
ActionStatusInfo[] statusEffects = value.SourceStatusEffects;
foreach (ActionStatusInfo val5 in statusEffects)
{
if (!((Object)(object)val5 == (Object)null))
{
string key2 = Limpa(val5.Name);
dictionary[key2] = ((!dictionary.TryGetValue(key2, out var value3)) ? 1 : (value3 + 1));
}
}
}
StringBuilder stringBuilder5 = new StringBuilder();
foreach (KeyValuePair<string, int> item in dictionary)
{
stringBuilder5.Append(item.Key).Append("x").Append(item.Value)
.Append(",");
}
string text4 = "-";
if (value.UseGroundEffect)
{
StringBuilder stringBuilder6 = new StringBuilder();
if (value.GroundActionStatuses != null)
{
ActionStatusInfo[] statusEffects = value.GroundActionStatuses;
foreach (ActionStatusInfo val6 in statusEffects)
{
if ((Object)(object)val6 != (Object)null)
{
stringBuilder6.Append(Limpa(val6.Name)).Append(",");
}
}
}
text4 = Limpa(value.GroundTargetConditions) + " dur=" + Limpa(value.GroundDuration) + (value.GroundIsInfinite ? " infinito" : "") + " maxTrg=" + value.GroundMaxNumTriggers + " status=" + stringBuilder6;
}
Plugin.Log.LogInfo((object)($"[ActionProps] '{text}' | tipo={value.ActionType} | beneficio={value.BenefitType} | " + $"skillType={value.SkillType} | nAlvos={num3} | alvos={stringBuilder} | " + "alcance=" + (value.UseMaxRangeOverride ? value.MaxRangeOverride.ToString() : "-") + " | alcanceBlast=" + (value.UseMaxRangeBlastOverride ? value.MaxRangeBlastOverride.ToString() : "-") + " | knockback=" + (value.UseKnockback ? value.KnockbackAmount.ToString() : "-") + " | hits=" + (value.UseMultipleHits ? value.NumHits.ToString() : "-") + " | " + $"maxChain={value.DashMaxChainCount} | " + "colisao=" + (((Object)(object)value.KnockbackCollideAction != (Object)null) ? ((Object)value.KnockbackCollideAction).name : "-") + " | hexesAtiv=" + (string.IsNullOrEmpty(value.ActivationIndicatorHexes) ? "-" : value.ActivationIndicatorHexes.Replace('\n', ',')) + " | numHitsEq=" + (value.UseNumHitsEquation ? "Sim" : "-") + " | chainProj=" + (value.ProjectileChain ? "Sim" : "Nao") + " | " + $"chainProjN={value.ProjectileChainCount} | " + "chainProjAlvo=" + Limpa(value.ProjectileChainTarget) + " | " + $"chainMesmo={value.ChainSameTarget} | " + "chainAlvo=" + Limpa(value.DashChainTarget) + " | chainMesmoAlvo=" + (value.DashChainSameTarget ? "Sim" : "Nao") + " | " + $"remocoes={((value.StatusRemovals != null) ? value.StatusRemovals.Length : 0)} | " + $"remocoesP={((value.PostActionStatusRemovals != null) ? value.PostActionStatusRemovals.Length : 0)} | " + "remocao=" + ((value.StatusRemovals != null && value.StatusRemovals.Length != 0 && (Object)(object)value.StatusRemovals[0].ActionOnRemoval != (Object)null) ? (Limpa(((Object)value.StatusRemovals[0].ActionOnRemoval).name) + "=>" + EfeitosDe(value.StatusRemovals[0].ActionOnRemoval)) : "-") + " | remocaoTipo=" + ((value.StatusRemovals != null && value.StatusRemovals.Length != 0) ? (((object)Unsafe.As<BeneficialOrHarmful, BeneficialOrHarmful>(ref value.StatusRemovals[0].BenefitType)/*cast due to .constrained prefix*/).ToString() + "/" + Limpa(value.StatusRemovals[0].NumStatusesToRemove)) : "-") + " | exprHits=" + Limpa(value.NumHitsEquation) + " | alcanceHits=" + Limpa(value.MultipleHitRange) + " | cooldown=" + Limpa(value.Cooldown) + " | cargas=" + Limpa(value.MaxCharges) + "/" + Limpa(value.InitialCharges) + " | precisa=" + Limpa(value.UseCondition) + " | condFalha=" + Limpa(value.UseConditionFailText) + " | " + $"statusAplicados={stringBuilder3} | stacks={stringBuilder5} | ground={text4} | statusFonte={stringBuilder4} | chances={stringBuilder2}"));
if (value.Summons == null || value.Summons.Count <= 0)
{
continue;
}
StringBuilder stringBuilder7 = new StringBuilder();
foreach (CharacterInfo summon in value.Summons)
{
if ((Object)(object)summon == (Object)null)
{
continue;
}
stringBuilder7.Append(Limpa(((Object)summon).name)).Append('[');
int num5 = 0;
if (summon.SkillsAndAI != null)
{
SkillAndAI[] skillsAndAI = summon.SkillsAndAI;
foreach (SkillAndAI val7 in skillsAndAI)
{
if (val7 != null && (Object)(object)val7.Skill != (Object)null && !string.IsNullOrEmpty(val7.Skill.SkillName))
{
stringBuilder7.Append(Limpa(val7.Skill.SkillName)).Append(',');
num5++;
}
}
}
if (num5 == 0 && summon.Skills != null)
{
foreach (SkillInfo skill in summon.Skills)
{
if ((Object)(object)skill != (Object)null && !string.IsNullOrEmpty(skill.SkillName))
{
stringBuilder7.Append(Limpa(skill.SkillName)).Append(',');
}
}
}
stringBuilder7.Append("]; ");
}
Plugin.Log.LogInfo((object)("[Summon] '" + text + "' | sorteio=" + (value.RandomSummonFromList ? "sim" : "nao") + " | herdaStats=" + (value.BenefitFromCasterStats ? "sim" : "nao") + " | morreComCaster=" + (value.DieWhenCasterDies ? "sim" : "nao") + " | persistente=" + (value.IsPersistantSummon ? "sim" : "nao") + " | doencaDeInvocacao=" + (value.HasSummoningSickness ? "sim" : "nao") + " | " + $"criaturas={stringBuilder7}"));
}
Plugin.Log.LogInfo((object)("[Efeitos] resumo (acoes): " + EfeitosInfo.Resumo()));
}
private static int ContaEfeitos(ActionInfo ac)
{
int num = 0;
if ((Object)(object)ac != (Object)null && ac.Effects != null)
{
IEffectInfo[] effects = ac.Effects;
for (int i = 0; i < effects.Length; i++)
{
if (effects[i] is GeneralEffect)
{
num++;
}
}
}
return num;
}
private static string EfeitosDe(ActionInfo ac)
{
StringBuilder stringBuilder = new StringBuilder();
if ((Object)(object)ac != (Object)null && ac.Effects != null)
{
IEffectInfo[] effects = ac.Effects;
foreach (IEffectInfo obj in effects)
{
GeneralEffect val = (GeneralEffect)(object)((obj is GeneralEffect) ? obj : null);
if (val != null && !string.IsNullOrEmpty(val.Action))
{
stringBuilder.Append(Limpa(val.Action)).Append("; ");
}
}
}
return stringBuilder.ToString().TrimEnd(' ', ';');
}
private static void Postfix(List<SkillInfo> __result)
{
//IL_025f: Unknown result type (might be due to invalid IL or missing references)
//IL_026a: Unknown result type (might be due to invalid IL or missing references)
//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
//IL_0482: Unknown result type (might be due to invalid IL or missing references)
try
{
if (_dumped || __result == null || __result.Count <= 1)
{
return;
}
if (__result.Count == _lastCount)
{
_stableHits++;
}
else
{
_stableHits = 1;
_lastCount = __result.Count;
}
if (_stableHits < 5)
{
return;
}
_dumped = true;
EfeitosInfo.Zerar();
Plugin.Log.LogInfo((object)$"[Skill] Inventário: {__result.Count} skills carregados.");
foreach (SkillInfo item in __result)
{
if ((Object)(object)item == (Object)null)
{
continue;
}
string text = item.Description ?? "";
StringBuilder stringBuilder = new StringBuilder();
if (item.ActionsGranted != null)
{
ActionInfo[] actionsGranted = item.ActionsGranted;
foreach (ActionInfo val in actionsGranted)
{
if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(((Object)val).name))
{
stringBuilder.Append(Limpa(((Object)val).name)).Append("; ");
_acoes[((Object)val).name] = val;
}
}
}
StringBuilder stringBuilder2 = new StringBuilder();
if (item.PassiveActionStatuses != null)
{
ActionStatusInfo[] passiveActionStatuses = item.PassiveActionStatuses;
foreach (ActionStatusInfo val2 in passiveActionStatuses)
{
if ((Object)(object)val2 != (Object)null && !string.IsNullOrEmpty(val2.Name))
{
stringBuilder2.Append(Limpa(val2.Name)).Append("; ");
}
}
}
StringBuilder stringBuilder3 = new StringBuilder();
if (item.AttributeEffects != null)
{
CharacterEffectInfo[] attributeEffects = item.AttributeEffects;
foreach (CharacterEffectInfo val3 in attributeEffects)
{
if (val3 != null && !((Object)(object)val3.CharacterAttribute == (Object)null))
{
stringBuilder3.Append(((Object)val3.CharacterAttribute).name).Append(':').Append(val3.CharacterEffectMethod)
.Append(':')
.Append(val3.Amount)
.Append(", ");
}
}
}
string arg = EfeitosInfo.Descreve(item.AttributeEffects);
string arg2 = ((item.SkillTags != null) ? string.Join(",", item.SkillTags) : "");
Plugin.Log.LogInfo((object)($"[Skill] '{item.SkillName}' | tipo={item.SkillType} | dano={item.DamageType} | " + $"tier={item.Tier} | tags={arg2} | skid={item.Guid} | " + "passivo=" + (item.IsPassive ? "sim" : "nao") + " | " + $"attr={stringBuilder3} | acts={stringBuilder} | pstat={stringBuilder2} | " + $"nAttrEf={EfeitosInfo.Conta(item.AttributeEffects)} | attrTipos={arg} | " + "expr=" + Junta(item.DescriptionExpressions) + " | danoExpr=" + Junta(item.DamageExpressionOverrides) + " | upg=" + Limpa(item.UpgradeText) + " | desc=\"" + text.Replace("\n", " ") + "\""));
if (item.SkillTriggers == null)
{
continue;
}
SkillTrigger[] skillTriggers = item.SkillTriggers;
foreach (SkillTrigger val4 in skillTriggers)
{
if (val4 == null)
{
continue;
}
StringBuilder stringBuilder4 = new StringBuilder();
if (val4.Actions != null)
{
ActionInfo[] actionsGranted = val4.Actions;
foreach (ActionInfo val5 in actionsGranted)
{
if ((Object)(object)val5 != (Object)null && !string.IsNullOrEmpty(((Object)val5).name))
{
stringBuilder4.Append(Limpa(((Object)val5).name)).Append(',');
_acoes[((Object)val5).name] = val5;
}
}
}
StringBuilder stringBuilder5 = new StringBuilder();
if (val4.ActionStatuses != null)
{
ActionStatusInfo[] passiveActionStatuses = val4.ActionStatuses;
foreach (ActionStatusInfo val6 in passiveActionStatuses)
{
if ((Object)(object)val6 != (Object)null)
{
stringBuilder5.Append(Limpa(val6.Name)).Append(',');
}
}
}
Plugin.Log.LogInfo((object)($"[Trigger] '{item.SkillName}' | tipo={val4.TriggerType} | " + "cond=" + Limpa(val4.Condition) + " | addBasicAttack=" + (val4.AddBasicAttackToActionList ? "sim" : "nao") + " | garanteUm=" + (val4.GauranteeOneAction ? "sim" : "nao") + " | chanceIgual=" + (val4.GiveAllActionsEqualChance ? "sim" : "nao") + " | " + $"chances={Junta(val4.ActionChanceEquations)} | acoes={stringBuilder4} | " + $"status={stringBuilder5} | chancesStatus={Junta(val4.ActionStatusChanceEquations)} | " + $"nEfeitos={((val4.GeneralEffects != null) ? val4.GeneralEffects.Length : 0)} | " + $"cooldownTrig={val4.Cooldown}"));
}
}
Plugin.Log.LogInfo((object)("[Efeitos] resumo (skills): " + EfeitosInfo.Resumo()));
DespejaAcoes();
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[Skill] erro no inventário: " + ex.Message));
}
}
}
}