using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("GlitnirRaces")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GlitnirRaces")] [assembly: AssemblyTitle("GlitnirRaces")] [assembly: AssemblyVersion("1.0.0.0")] [BepInPlugin("glitnir.races", "Glitnir Races", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class GlitnirRacesPlugin : BaseUnityPlugin { public class RaceConfig { public string RaceId; public string DisplayName; public ConfigEntry Enabled; public ConfigEntry Scale; public ConfigEntry SkinColor; public ConfigEntry HairColor; public ConfigEntry EarColor; public ConfigEntry EyeColor; public ConfigEntry SecretCode; public ConfigEntry HealthBonus; public ConfigEntry StaminaBonus; public ConfigEntry EitrBonus; public ConfigEntry CarryWeightBonus; public ConfigEntry HealthRegenMultiplier; public ConfigEntry StaminaRegenMultiplier; public ConfigEntry EitrRegenMultiplier; public ConfigEntry DamageDoneMultiplier; public ConfigEntry BackstabMultiplier; public ConfigEntry DamageTakenMultiplier; public ConfigEntry LifestealPercent; public ConfigEntry StealthMultiplier; public ConfigEntry SpeedMultiplier; public ConfigEntry Resistances; public ConfigEntry HeatResistanceBonus; public ConfigEntry LowHealthThreshold; public ConfigEntry LowHealthDamageBonus; public ConfigEntry StillHealAura; public ConfigEntry StillHealAmount; public ConfigEntry StillHealInterval; public ConfigEntry StillHealRequiredStillTime; public ConfigEntry StillHealDayOnly; public ConfigEntry IronStanceEnabled; public ConfigEntry IronStanceExtraDamageReduction; public ConfigEntry SecondWindEnabled; public ConfigEntry SecondWindThreshold; public ConfigEntry SecondWindHealAmount; public ConfigEntry SecondWindStaminaAmount; public ConfigEntry SecondWindCooldown; public ConfigEntry SkillDamageMultipliers; public ConfigEntry AttackDamageTypeMultipliers; public ConfigEntry NoResourceCost; public ConfigEntry XpGainMultiplier; public ConfigEntry KnockbackMultiplier; public ConfigEntry EitrCostMultiplier; public ConfigEntry StaminaCostModifiers; public ConfigEntry NightOnlyBonuses; public ConfigEntry DayNightHealthShift; public ConfigEntry BiomeHealthShifts; } private enum RaceAbility { None, Orc, Elf, Dwarf, Human } [HarmonyPatch(typeof(FejdStartup), "SetupCharacterPreview")] private static class FejdCharacterPreviewPatch { private static void Postfix(FejdStartup __instance, PlayerProfile profile) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)("[GlitnirRaces/Preview] SetupCharacterPreview disparou pro perfil '" + ((profile != null) ? profile.GetName() : null) + "'.")); } try { ApplyPreviewRace(__instance, profile); } catch (Exception arg) { GlitnirRacesPlugin instance2 = Instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Logger.LogWarning((object)$"Falha ao aplicar raça no preview do menu: {arg}"); } } } } [HarmonyPatch(typeof(Player), "OnSpawned")] private static class PlayerSpawnedPatch { private static void Postfix(Player __instance) { if ((Object)(object)__instance == (Object)null || (Object)(object)Instance == (Object)null) { return; } if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { Instance.RestoreLocalSavedRaceIfNeeded(); SendVersionCheckToServer(); } if (IsPlayerLocked(__instance)) { SetZdoLocked(__instance, locked: true); } Instance.ApplyRaceWithDelays(__instance); if (!IsHeadless()) { string race = GetRace(__instance); if (!string.IsNullOrWhiteSpace(race)) { UpdateRaceStatusEffect(__instance, race); } } } } [HarmonyPatch(typeof(Player), "OnDeath")] private static class PlayerDeathPatch { private static void Postfix(Player __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)Instance == (Object)null) && !IsHeadless()) { Instance.ApplyRaceWithDelays(__instance); string race = GetRace(__instance); if (!string.IsNullOrWhiteSpace(race)) { UpdateRaceStatusEffect(__instance, race); } } } } [HarmonyPatch(typeof(Player), "CreateDeathEffects")] private static class PlayerRagdollRacePatch { private static void Postfix(Player __instance) { if ((Object)(object)Instance == (Object)null || IsHeadless() || (Object)(object)__instance == (Object)null) { return; } Ragdoll ragdoll = __instance.GetRagdoll(); if ((Object)(object)ragdoll == (Object)null) { return; } string race = GetRace(__instance); if (string.IsNullOrWhiteSpace(race) || !IsRaceEnabled(race)) { return; } try { ZNetView component = ((Component)ragdoll).GetComponent(); if ((Object)(object)component != (Object)null && component.GetZDO() != null) { component.GetZDO().Set("GlitnirRagdollRace", race); } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("[GlitnirRaces] Falha ao gravar raça no ZDO do ragdoll: " + ex.Message)); } ApplyRaceVisualToRagdoll(ragdoll, race); } } [HarmonyPatch(typeof(Ragdoll), "Awake")] private static class RagdollAwakePatch { private static void Postfix(Ragdoll __instance) { if ((Object)(object)Instance == (Object)null || IsHeadless() || (Object)(object)__instance == (Object)null) { return; } try { ZNetView component = ((Component)__instance).GetComponent(); if (!((Object)(object)component == (Object)null) && component.GetZDO() != null) { string text = component.GetZDO().GetString("GlitnirRagdollRace", ""); if (!string.IsNullOrWhiteSpace(text) && IsRaceEnabled(text)) { ApplyRaceVisualToRagdoll(__instance, text); } } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("[GlitnirRaces] Falha ao ler raça do ZDO do ragdoll: " + ex.Message)); } } } [HarmonyPatch(typeof(ZNet), "Disconnect")] private static class ZNetDisconnectPatch { private static void Prefix(ZNetPeer peer) { if (peer == null) { return; } try { OnPeerDisconnected(peer.m_uid); } catch { } } } [HarmonyPatch(typeof(ZNet), "Shutdown")] private static class ZNetShutdownPatch { private static void Prefix() { NetworkRaces.Clear(); LastAppliedRace.Clear(); OriginalSkinColors.Clear(); LastSkinRefreshRequest.Clear(); KnownAdmins.Clear(); HeadCache.Clear(); HeadCacheRace.Clear(); ApplyRaceCoroutineGeneration.Clear(); ZNetViewCache.Clear(); PendingAltarSwitch.Clear(); _cachedSavePrefix = null; _cachedZNetInstance = null; _cachedCharacterId = 0L; _cachedServerKey = null; RpcRegistered = false; RegisteredRpcInstance = null; if ((Object)(object)Instance != (Object)null) { Instance.lastBroadcastRace = null; Instance.isRestoringLocalRace = false; } } } [HarmonyPatch(typeof(VisEquipment), "SetHelmetItem")] private static class HelmetScaleOnEquipPatch { private static void Postfix(VisEquipment __instance) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && !IsHeadless()) { Player component = ((Component)__instance).GetComponent(); if (!((Object)(object)component == (Object)null)) { string race = GetRace(component); Vector3 targetScale = ((!string.IsNullOrWhiteSpace(race) && IsRaceEnabled(race)) ? GetRaceScale(race) : HumanScale); ScaleCurrentHelmetForRace(component, targetScale); } } } } [HarmonyPatch(typeof(VisEquipment), "SetHairColor")] private static class ForceRaceHairColorPatch { private static void Prefix(VisEquipment __instance, ref Vector3 __0) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || IsApplyingRace) { return; } Player component = ((Component)__instance).GetComponent(); if (!((Object)(object)component == (Object)null)) { string race = GetRace(component); if (RaceUsesForcedHair(race)) { __0 = GetRaceHairColor(race); } } } } [HarmonyPatch(typeof(VisEquipment), "SetSkinColor")] private static class PreventForcedRaceSkinOverridePatch { private static bool Prefix(VisEquipment __instance, Vector3 __0) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || IsApplyingRace) { return true; } Player component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } string race = GetRace(component); if (!RaceUsesForcedSkin(race)) { return true; } CacheOriginalSkinValue(component, __0); if ((Object)(object)Instance != (Object)null) { Instance.ForceSkinAfterVanilla(component, race); } return false; } } [HarmonyPatch] private static class VisEquipmentOnlineRefreshPatch { private static IEnumerable TargetMethods() { string[] names = new string[9] { "UpdateEquipmentVisuals", "UpdateVisuals", "SetChestItem", "SetLegItem", "SetHelmetItem", "SetShoulderItem", "SetUtilityItem", "SetLeftItem", "SetRightItem" }; string[] array = names; foreach (string name in array) { MethodInfo method = AccessTools.Method(typeof(VisEquipment), name, (Type[])null, (Type[])null); if (method != null) { yield return method; } } } private static void Postfix(VisEquipment __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)Instance == (Object)null) && !IsApplyingRace && !IsHeadless()) { Instance.ForceSkinAfterVanilla(__instance); } } } [HarmonyPatch] private static class PlayerOnlineRefreshPatch { private static IEnumerable TargetMethods() { string[] names = new string[3] { "UpdateEquipment", "OnInventoryChanged", "UpdateVisual" }; string[] array = names; foreach (string name in array) { MethodInfo method = AccessTools.Method(typeof(Player), name, (Type[])null, (Type[])null); if (method != null) { yield return method; } } } private static void Postfix(Player __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)Instance == (Object)null) && !IsApplyingRace && !IsHeadless()) { Instance.RequestOnlineVisualRefresh(__instance); } } } [HarmonyPatch(typeof(Character), "SetVisible")] private static class CharacterSetVisiblePatch { private static void Postfix(Character __instance, bool visible) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (!visible || (Object)(object)__instance == (Object)null || (Object)(object)Instance == (Object)null || IsHeadless()) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null)) { string race = GetRace(val); if (!string.IsNullOrWhiteSpace(race) && IsRaceEnabled(race)) { ApplyScale(val, GetRaceScale(race)); } } } } [HarmonyPatch(typeof(Chat), "InputText")] private static class ChatPatch { private static bool Prefix(Chat __instance) { if ((Object)(object)__instance == (Object)null) { return true; } string text = ""; try { FieldInfo field = typeof(Chat).GetField("m_input", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { return true; } object value = field.GetValue(__instance); if (value == null) { return true; } text = (value.GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public)?.GetValue(value) as string)?.Trim() ?? ""; } catch { return true; } string raceFromSecretCode = GetRaceFromSecretCode(text); if (raceFromSecretCode == null) { return true; } TransformLocalPlayerFromMarketplace(raceFromSecretCode); try { object obj2 = typeof(Chat).GetField("m_input", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(__instance); PropertyInfo propertyInfo = obj2?.GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public); if (propertyInfo != null && propertyInfo.CanWrite) { propertyInfo.SetValue(obj2, ""); } } catch { } return false; } } [HarmonyPatch(typeof(Player), "SetMaxHealth")] private static class RaceMaxHealthPatch { private static Dictionary ParseBiomeShifts(string value) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); if (string.IsNullOrWhiteSpace(value)) { return dictionary; } string[] array = value.Split(new char[1] { ',' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ':' }); if (array2.Length == 2 && Enum.TryParse(array2[0].Trim(), ignoreCase: true, out Biome result) && float.TryParse(array2[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { dictionary[result] = result2; } } return dictionary; } private static void Prefix(Player __instance, ref float health) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (!TryGetRaceConfig(__instance, out var cfg)) { return; } health += cfg.HealthBonus.Value; if (cfg.DayNightHealthShift.Value != 0f) { health += (IsNightSafe() ? cfg.DayNightHealthShift.Value : (0f - cfg.DayNightHealthShift.Value)); } if (!string.IsNullOrWhiteSpace(cfg.BiomeHealthShifts.Value)) { try { Biome currentBiome = __instance.GetCurrentBiome(); Dictionary dictionary = ParseBiomeShifts(cfg.BiomeHealthShifts.Value); if (dictionary.TryGetValue(currentBiome, out var value)) { health += value; } } catch (Exception ex) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("[GlitnirRaces] Falha ao ler bioma atual pra oscilação de vida: " + ex.Message)); } } } if (health < 10f) { health = 10f; } } } [HarmonyPatch(typeof(Player), "SetMaxStamina")] private static class RaceMaxStaminaPatch { private static void Prefix(Player __instance, ref float stamina) { if (TryGetRaceConfig(__instance, out var cfg)) { stamina += cfg.StaminaBonus.Value; } } } [HarmonyPatch(typeof(Player), "SetMaxEitr")] private static class RaceMaxEitrPatch { private static void Prefix(Player __instance, ref float eitr) { if (TryGetRaceConfig(__instance, out var cfg)) { eitr += cfg.EitrBonus.Value; } } } [HarmonyPatch(typeof(Player), "GetMaxCarryWeight")] private static class RaceMaxCarryWeightPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += cfg.CarryWeightBonus.Value; } } } [HarmonyPatch(typeof(Character), "Heal")] private static class RaceHealthRegenPatch { private static void Prefix(Character __instance, ref float hp) { if (!(hp <= 0f)) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg) && (!cfg.NightOnlyBonuses.Value || IsNightSafe())) { hp *= cfg.HealthRegenMultiplier.Value; } } } } [HarmonyPatch(typeof(Character), "AddStamina")] private static class RaceStaminaRegenPatch { private static void Prefix(Character __instance, ref float v) { if (!(v <= 0f)) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg) && (!cfg.NightOnlyBonuses.Value || IsNightSafe())) { v *= cfg.StaminaRegenMultiplier.Value; } } } } [HarmonyPatch(typeof(Character), "AddEitr")] private static class RaceEitrRegenPatch { private static void Prefix(Character __instance, ref float v) { if (!(v <= 0f)) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg) && (!cfg.NightOnlyBonuses.Value || IsNightSafe())) { v *= cfg.EitrRegenMultiplier.Value; } } } } [HarmonyPatch(typeof(Player), "UseStamina")] private static class RaceNoStaminaCostPatch { private static void Prefix(Player __instance, ref float v) { if (TryGetRaceConfig(__instance, out var cfg) && cfg.NoResourceCost.Value) { v = 0f; } } } [HarmonyPatch(typeof(Player), "UseEitr")] private static class RaceNoEitrCostPatch { private static void Prefix(Player __instance, ref float v) { if (TryGetRaceConfig(__instance, out var cfg) && cfg.NoResourceCost.Value) { v = 0f; } } } [HarmonyPatch(typeof(Character), "TryUseEitr")] private static class RaceNoEitrCostTryPatch { private static bool Prefix(Character __instance, ref bool __result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val == (Object)null || !TryGetRaceConfig(val, out var cfg) || !cfg.NoResourceCost.Value) { return true; } __result = true; return false; } } [HarmonyPatch(typeof(Character), "GetDamageModifier")] private static class RaceResistancePatch { private static void Postfix(Character __instance, DamageType damageType, ref DamageModifier __result) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected I4, but got Unknown if (__result) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg)) { Dictionary dictionary = ParseResistances(cfg.Resistances.Value); if (dictionary.TryGetValue(damageType, out var value)) { __result = (DamageModifier)(int)value; } } } } [HarmonyPatch(typeof(Character), "Damage")] private static class RaceDamagePatch { private static void Prefix(Character __instance, HitData hit) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) if (hit == null) { return; } _ = hit.m_damage; if (false) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val != (Object)null && TryGetRaceConfig(val, out var cfg)) { if (cfg.DamageTakenMultiplier.Value != 1f) { ScaleDamage(ref hit.m_damage, cfg.DamageTakenMultiplier.Value); } if (RacialAbilitiesEnabled.Value && cfg.IronStanceEnabled != null && cfg.IronStanceEnabled.Value && cfg.IronStanceExtraDamageReduction.Value > 0f && ((Character)val).IsBlocking()) { ScaleDamage(ref hit.m_damage, 1f - cfg.IronStanceExtraDamageReduction.Value); hit.m_pushForce = 0f; } } Character attacker = hit.GetAttacker(); Player val2 = (Player)(object)((attacker is Player) ? attacker : null); if (!((Object)(object)val2 != (Object)null) || !TryGetRaceConfig(val2, out var cfg2)) { return; } float num = cfg2.DamageDoneMultiplier.Value; Dictionary dictionary = ParseSkillMultipliers(cfg2.SkillDamageMultipliers.Value); if (dictionary.TryGetValue(hit.m_skill, out var value)) { num *= value; } if (RacialAbilitiesEnabled.Value && cfg2.LowHealthThreshold != null && cfg2.LowHealthThreshold.Value > 0f && ((Character)val2).GetMaxHealth() > 0f && ((Character)val2).GetHealth() / ((Character)val2).GetMaxHealth() <= cfg2.LowHealthThreshold.Value) { num *= cfg2.LowHealthDamageBonus.Value; } if (num != 1f) { ScaleDamage(ref hit.m_damage, num); } Dictionary dictionary2 = ParseTypeMultipliers(cfg2.AttackDamageTypeMultipliers.Value); if (dictionary2.Count > 0) { ScaleDamageByType(ref hit.m_damage, dictionary2); } if (cfg2.BackstabMultiplier.Value != 1f) { hit.m_backstabBonus *= cfg2.BackstabMultiplier.Value; } if (cfg2.KnockbackMultiplier.Value != 1f) { hit.m_pushForce *= cfg2.KnockbackMultiplier.Value; } if (cfg2.XpGainMultiplier.Value != 1f) { hit.m_skillRaiseAmount *= cfg2.XpGainMultiplier.Value; } if (cfg2.LifestealPercent.Value > 0f) { float totalDamage = hit.GetTotalDamage(); if (totalDamage > 0f) { ((Character)val2).Heal(totalDamage * cfg2.LifestealPercent.Value, false); } } } private static void ScaleDamageByType(ref DamageTypes dmg, Dictionary mults) { if (mults.TryGetValue((DamageType)1, out var value)) { dmg.m_blunt *= value; } if (mults.TryGetValue((DamageType)2, out var value2)) { dmg.m_slash *= value2; } if (mults.TryGetValue((DamageType)4, out var value3)) { dmg.m_pierce *= value3; } if (mults.TryGetValue((DamageType)8, out var value4)) { dmg.m_chop *= value4; } if (mults.TryGetValue((DamageType)16, out var value5)) { dmg.m_pickaxe *= value5; } if (mults.TryGetValue((DamageType)32, out var value6)) { dmg.m_fire *= value6; } if (mults.TryGetValue((DamageType)64, out var value7)) { dmg.m_frost *= value7; } if (mults.TryGetValue((DamageType)128, out var value8)) { dmg.m_lightning *= value8; } if (mults.TryGetValue((DamageType)256, out var value9)) { dmg.m_poison *= value9; } if (mults.TryGetValue((DamageType)512, out var value10)) { dmg.m_spirit *= value10; } } private static void ScaleDamage(ref DamageTypes dmg, float mult) { dmg.m_blunt *= mult; dmg.m_slash *= mult; dmg.m_pierce *= mult; dmg.m_chop *= mult; dmg.m_pickaxe *= mult; dmg.m_fire *= mult; dmg.m_frost *= mult; dmg.m_lightning *= mult; dmg.m_poison *= mult; dmg.m_spirit *= mult; } } [HarmonyPatch(typeof(Character), "GetStealthFactor")] private static class RaceStealthPatch { private static void Postfix(Character __instance, ref float __result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg)) { __result *= cfg.StealthMultiplier.Value; } } } [HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[] { typeof(int), typeof(bool), typeof(int), typeof(int) })] private static class RaceBlockFreezingStatusPatch { private static bool Prefix(SEMan __instance, int nameHash, ref StatusEffect __result) { if (nameHash != SEMan.s_statusEffectFreezing && nameHash != SEMan.s_statusEffectCold) { return true; } Character sEManOwner = GetSEManOwner(__instance); Player val = (Player)(object)((sEManOwner is Player) ? sEManOwner : null); if ((Object)(object)val == (Object)null || !TryGetRaceConfig(val, out var cfg) || cfg.HeatResistanceBonus.Value == 0f) { return true; } __result = null; return false; } } [HarmonyPatch(typeof(Character), "GetJogSpeedFactor")] private static class RaceJogSpeedPatch { private static void Postfix(Character __instance, ref float __result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg) && (!cfg.NightOnlyBonuses.Value || IsNightSafe())) { __result *= cfg.SpeedMultiplier.Value; } } } [HarmonyPatch(typeof(Character), "GetRunSpeedFactor")] private static class RaceRunSpeedPatch { private static void Postfix(Character __instance, ref float __result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg) && (!cfg.NightOnlyBonuses.Value || IsNightSafe())) { __result *= cfg.SpeedMultiplier.Value; } } } [HarmonyPatch(typeof(Player), "GetEquipmentAttackStaminaModifier")] private static class RaceStaminaCostAttackPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += GetStaminaCostModifier(cfg, "Attack"); } } } [HarmonyPatch(typeof(Player), "GetEquipmentBlockStaminaModifier")] private static class RaceStaminaCostBlockPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += GetStaminaCostModifier(cfg, "Block"); } } } [HarmonyPatch(typeof(Player), "GetEquipmentDodgeStaminaModifier")] private static class RaceStaminaCostDodgePatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += GetStaminaCostModifier(cfg, "Dodge"); } } } [HarmonyPatch(typeof(Player), "GetEquipmentJumpStaminaModifier")] private static class RaceStaminaCostJumpPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += GetStaminaCostModifier(cfg, "Jump"); } } } [HarmonyPatch(typeof(Player), "GetEquipmentRunStaminaModifier")] private static class RaceStaminaCostRunPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += GetStaminaCostModifier(cfg, "Run"); } } } [HarmonyPatch(typeof(Player), "GetEquipmentSneakStaminaModifier")] private static class RaceStaminaCostSneakPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += GetStaminaCostModifier(cfg, "Sneak"); } } } [HarmonyPatch(typeof(Player), "GetEquipmentSwimStaminaModifier")] private static class RaceStaminaCostSwimPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += GetStaminaCostModifier(cfg, "Swim"); } } } [HarmonyPatch(typeof(Player), "UseEitr")] private static class RaceEitrCostPatch { private static void Prefix(Player __instance, ref float v) { if (TryGetRaceConfig(__instance, out var cfg) && !cfg.NoResourceCost.Value && cfg.EitrCostMultiplier.Value != 1f) { v *= cfg.EitrCostMultiplier.Value; } } } [HarmonyPatch(typeof(Character), "TryUseEitr")] private static class RaceEitrCostTryPatch { private static void Prefix(Character __instance, ref float eitrUse) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg) && !cfg.NoResourceCost.Value && cfg.EitrCostMultiplier.Value != 1f) { eitrUse *= cfg.EitrCostMultiplier.Value; } } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEventFailable <>9__35_0; internal object b__35_0(ConsoleEventArgs args) { if (!HasDevCommands()) { args.Context.AddString(Text_SemPermissao.Value); return false; } if (args.Args.Length < 2) { args.Context.AddString(Text_UsoOfflineReset.Value); return false; } if (!long.TryParse(args.Args[1], out var result)) { args.Context.AddString(Text_IdInvalido.Value); return false; } bool flag = ResetOfflinePlayer(result); args.Context.AddString(flag ? Text_OfflineResetado.Value : Text_OfflineNaoEncontrado.Value); return flag; } } private static readonly HashSet PendingAltarSwitch = new HashSet(); private static readonly FieldInfo HelmetInstanceField = AccessTools.Field(typeof(VisEquipment), "m_helmetItemInstance"); private static readonly HashSet RegisteredSecretCodes = new HashSet(StringComparer.Ordinal); public static readonly Dictionary Races = new Dictionary(); public static ConfigEntry EyeGlowPeak; public static ConfigEntry EmoteOnTransform; public static ConfigEntry FillVitalsOnTransform; public static ConfigEntry RacialAbilitiesEnabled; public static ConfigEntry AltarSwitchCostItem; public static ConfigEntry AltarSwitchCostAmount; public static ConfigEntry AltarRecipe; private const string ZdoRagdollRaceKey = "GlitnirRagdollRace"; private const string ModGUID = "glitnir.races"; private const string ModName = "Glitnir Races"; private const string ModVersion = "1.0.0"; private const string RaceOrc = "orc"; private const string RaceElf = "elfo"; private const string RaceDwarf = "anao"; private const string RaceHuman = "humano"; private const string ZdoRaceKey = "GlitnirRace"; private const string ZdoRaceVersionKey = "GlitnirRaceVer"; private const int CurrentRaceDataVersion = 1; private const string ZdoLockedKey = "GlitnirRaceLocked"; private const string ZdoEarColorKey = "GlitnirRaceEarColor"; private const string ZdoSkinColorKey = "GlitnirRaceSkinColor"; private const string RpcSetRace = "GlitnirRaces_SetRace"; private const string RpcVersionCheck = "GlitnirRaces_VersionCheck"; private const string RpcAdminSetRaceRequest = "GlitnirRaces_AdminSetRaceRequest"; private const int FindHeadMaxDepth = 12; private const float RaceApplyMaxDistance = 60f; private static readonly WaitForSeconds Wait01 = new WaitForSeconds(0.1f); private static readonly WaitForSeconds Wait05 = new WaitForSeconds(0.5f); private static readonly WaitForSeconds Wait1 = new WaitForSeconds(1f); private static readonly WaitForSeconds Wait2 = new WaitForSeconds(2f); private static readonly WaitForSeconds WaitSkin005 = new WaitForSeconds(0.05f); private static readonly WaitForSeconds WaitSkin020 = new WaitForSeconds(0.2f); private static readonly WaitForSeconds WaitSkin050 = new WaitForSeconds(0.5f); private static readonly WaitForSeconds WaitSkin100 = new WaitForSeconds(1f); private readonly Harmony harmony = new Harmony("glitnir.races"); public static GlitnirRacesPlugin Instance; public ConfigFile MainConfigFile; public ConfigFile TextConfigFile; private static GameObject ElfEarsMalePrefab; private static GameObject ElfEarsFemalePrefab; private static GameObject OrcEarsMalePrefab; private static GameObject OrcEarsFemalePrefab; private static GameObject OrcTuskPrefab; private static GameObject HighElfEyesPrefab; private static GameObject AltarPrefab; private static bool IsApplyingRace = false; private static bool RpcRegistered = false; private static ZRoutedRpc RegisteredRpcInstance = null; private static readonly Dictionary NetworkRaces = new Dictionary(); private static readonly Dictionary LastAppliedRace = new Dictionary(); private static readonly Dictionary OriginalSkinColors = new Dictionary(); private static readonly Dictionary LastSkinRefreshRequest = new Dictionary(); private static readonly HashSet KnownAdmins = new HashSet(); private static readonly Dictionary HeadCache = new Dictionary(); private static readonly Dictionary HeadCacheRace = new Dictionary(); private static readonly Dictionary ApplyRaceCoroutineGeneration = new Dictionary(); private static readonly Dictionary ZNetViewCache = new Dictionary(); private float timer = 0f; private float syncTimer = 0f; private float localSaveTimer = 0f; private float adminCacheTimer = 0f; private float configWatchTimer = 0f; private DateTime _lastConfigWrite = DateTime.MinValue; private bool isRestoringLocalRace = false; private string lastBroadcastRace = null; private static string _cachedSavePrefix = null; private static long _cachedCharacterId = 0L; private static string _cachedServerKey = null; private static ZNet _cachedZNetInstance = null; private static readonly Vector3 HumanScale = Vector3.one; private static readonly Vector3 InvalidColor = new Vector3(-1f, -1f, -1f); private static readonly Vector3 ElfEarPosition = Vector3.zero; private static readonly Vector3 ElfEarRotation = Vector3.zero; private static readonly Vector3 ElfEarScale = Vector3.one; private static readonly Vector3 OrcEarPosition = new Vector3(0.00024f, 0.001475f, 0.001121f); private static readonly Vector3 OrcEarRotation = new Vector3(24.5f, 81.89f, -2.969f); private static readonly Vector3 OrcEarScale = new Vector3(1.137024f, 1.637663f, 1.083586f); private static readonly Vector3 HighElfEyesPosition = new Vector3(-0.0063f, -0.0194f, -0.00017f); private static readonly Vector3 HighElfEyesRotation = new Vector3(-18.776f, -89.449f, -0.691f); private static readonly Vector3 HighElfEyesScale = new Vector3(0.00993f, 0.011539f, 0.01272f); private static readonly Vector3 OrcTuskPosition = new Vector3(-0.00137f, 0.00114f, -0.00014f); private static readonly Vector3 OrcTuskRotation = new Vector3(-16.932f, -110.817f, 8.571f); private static readonly Vector3 OrcTuskScale = new Vector3(0.00494f, 0.005076f, 0.00559f); private bool _isReloadingConfig; private DateTime _lastTextConfigWrite = DateTime.MinValue; private static readonly Dictionary StillLastPos = new Dictionary(); private static readonly Dictionary StillTimer = new Dictionary(); private static readonly Dictionary StillHealTimer = new Dictionary(); private static readonly Dictionary SecondWindCooldownTimer = new Dictionary(); private static bool _envNightWarningLogged; private const float BonusRegenSeconds = 30f; private static readonly Dictionary DamageTypeNames = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "Blunt", (DamageType)1 }, { "Slash", (DamageType)2 }, { "Pierce", (DamageType)4 }, { "Chop", (DamageType)8 }, { "Pickaxe", (DamageType)16 }, { "Fire", (DamageType)32 }, { "Frost", (DamageType)64 }, { "Lightning", (DamageType)128 }, { "Poison", (DamageType)256 }, { "Spirit", (DamageType)512 } }; private static readonly Dictionary ModifierNames = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "Normal", (DamageModifier)0 }, { "Resistant", (DamageModifier)1 }, { "Weak", (DamageModifier)2 }, { "Immune", (DamageModifier)3 }, { "Ignore", (DamageModifier)4 }, { "VeryResistant", (DamageModifier)5 }, { "VeryWeak", (DamageModifier)6 }, { "SlightlyResistant", (DamageModifier)7 }, { "SlightlyWeak", (DamageModifier)8 } }; private static FieldInfo _semanCharacterField; private static readonly Dictionary RaceStatusEffects = new Dictionary(); private static Sprite _placeholderIcon; private static bool _placeholderIconResolved; private const string RaceIconResourceName = "race_icon.rgba"; private const int RaceIconSize = 128; private const string ColorAccent = "#E8A33D"; private const string ColorAbilityBuff = "#8CFF8C"; private const string ColorAbilityDebuff = "#FF8C8C"; public static ConfigEntry Text_AltarNome; public static ConfigEntry Text_AltarDescricao; public static ConfigEntry Text_AltarHoverEscolher; public static ConfigEntry Text_AltarHoverTrocar; public static ConfigEntry Text_AltarJaEscolheu; public static ConfigEntry Text_UiEscolhaTitulo; public static ConfigEntry Text_UiFechar; public static ConfigEntry Text_UiTrocarBotao; public static ConfigEntry Text_UiJaEscolheuTitulo; public static ConfigEntry Text_UiMoedaInsuficiente; public static ConfigEntry Text_RaceName_Orc; public static ConfigEntry Text_RaceName_Elf; public static ConfigEntry Text_RaceName_Dwarf; public static ConfigEntry Text_RaceName_Human; public static ConfigEntry Text_SemPermissao; public static ConfigEntry Text_UsoRaca; public static ConfigEntry Text_RacaDesativadaAdmin; public static ConfigEntry Text_PlayerNaoEncontrado; public static ConfigEntry Text_PlayerNaoCarregado; public static ConfigEntry Text_AgoraERaca; public static ConfigEntry Text_RacaRemovida; public static ConfigEntry Text_UsoOfflineReset; public static ConfigEntry Text_IdInvalido; public static ConfigEntry Text_OfflineResetado; public static ConfigEntry Text_OfflineNaoEncontrado; public static ConfigEntry Text_EssaRacaDesativada; public static ConfigEntry Text_AgoraEuSou; public static ConfigEntry Text_ConfigRecarregado; public static ConfigEntry Text_CodigosSecretosAtivos; public static ConfigEntry Text_VersaoDiferente; public static ConfigEntry Text_StatNomeRaca; public static ConfigEntry Text_StatVidaMaxima; public static ConfigEntry Text_StatStaminaMaxima; public static ConfigEntry Text_StatEitrMaximo; public static ConfigEntry Text_StatCapacidadeCarga; public static ConfigEntry Text_StatRegenVida; public static ConfigEntry Text_StatRegenStamina; public static ConfigEntry Text_StatRegenEitr; public static ConfigEntry Text_StatDanoCausado; public static ConfigEntry Text_StatDanoComSkill; public static ConfigEntry Text_StatDanoTipo; public static ConfigEntry Text_StatDanoAtaqueFurtivo; public static ConfigEntry Text_StatForcaEmpurrao; public static ConfigEntry Text_StatDanoRecebido; public static ConfigEntry Text_StatVelocidade; public static ConfigEntry Text_StatFurtividade; public static ConfigEntry Text_StatRouboVida; public static ConfigEntry Text_StatGanhoXP; public static ConfigEntry Text_StatRegenVelocidadeNoite; public static ConfigEntry Text_StatSoANoite; public static ConfigEntry Text_StatVidaNoiteDia; public static ConfigEntry Text_StatVidaBioma; public static ConfigEntry Text_StatFrioAmbiente; public static ConfigEntry Text_StatNaoCongela; public static ConfigEntry Text_StatModificadorDano; public static ConfigEntry Text_StatSemBonus; public static ConfigEntry Text_NivelImune; public static ConfigEntry Text_NivelMuitoResistente; public static ConfigEntry Text_NivelResistente; public static ConfigEntry Text_NivelLevementeResistente; public static ConfigEntry Text_NivelLevementeFraco; public static ConfigEntry Text_NivelFraco; public static ConfigEntry Text_NivelMuitoFraco; public static ConfigEntry Text_NivelIgnora; public static ConfigEntry Text_DanoBlunt; public static ConfigEntry Text_DanoSlash; public static ConfigEntry Text_DanoPierce; public static ConfigEntry Text_DanoChop; public static ConfigEntry Text_DanoPickaxe; public static ConfigEntry Text_DanoFire; public static ConfigEntry Text_DanoFrost; public static ConfigEntry Text_DanoLightning; public static ConfigEntry Text_DanoPoison; public static ConfigEntry Text_DanoSpirit; public static ConfigEntry Text_BiomaMeadows; public static ConfigEntry Text_BiomaBlackForest; public static ConfigEntry Text_BiomaSwamp; public static ConfigEntry Text_BiomaMountain; public static ConfigEntry Text_BiomaPlains; public static ConfigEntry Text_BiomaMistlands; public static ConfigEntry Text_BiomaAshLands; public static ConfigEntry Text_BiomaDeepNorth; public static ConfigEntry Text_BiomaOcean; public static ConfigEntry Text_HabFuriaSangue; public static ConfigEntry Text_HabFuriaSangueDesc; public static ConfigEntry Text_HabAuraCura; public static ConfigEntry Text_HabAuraCuraDesc; public static ConfigEntry Text_HabAuraCuraSoDeDia; public static ConfigEntry Text_HabPosturaFerro; public static ConfigEntry Text_HabPosturaFerroDesc; public static ConfigEntry Text_HabSegundoFolego; public static ConfigEntry Text_HabSegundoFolegoDesc; private static bool _modelIndexFieldWarningLogged; private static readonly FieldInfo ModelIndexField = AccessTools.Field(typeof(VisEquipment), "m_modelIndex"); private void RegisterAltarPiece() { //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Expected O, but got Unknown //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Expected O, but got Unknown if ((Object)(object)AltarPrefab == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[GlitnirRaces] Prefab 'altar_racas' não encontrado — peça do Altar das Raças não registrada."); return; } if ((Object)(object)AltarPrefab.GetComponent() == (Object)null) { AltarPrefab.AddComponent(); } if ((Object)(object)AltarPrefab.GetComponent() == (Object)null) { AltarPrefab.AddComponent(); } if ((Object)(object)AltarPrefab.GetComponent() == (Object)null) { AltarPrefab.AddComponent(); } if ((Object)(object)AltarPrefab.GetComponent() == (Object)null) { AltarPrefab.AddComponent(); } if ((Object)(object)AltarPrefab.GetComponentInChildren() == (Object)null) { Renderer componentInChildren = AltarPrefab.GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { BoxCollider val = AltarPrefab.AddComponent(); Bounds localBounds = componentInChildren.localBounds; val.center = ((Bounds)(ref localBounds)).center; val.size = ((Bounds)(ref localBounds)).size; ((BaseUnityPlugin)this).Logger.LogWarning((object)"[GlitnirRaces] 'altar_racas' não tinha Collider — criei um BoxCollider automático baseado na malha. Se ficar com hitbox estranha, adiciona um Collider certinho no Unity e ele passa a usar esse em vez do automático."); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[GlitnirRaces] 'altar_racas' não tem Collider nem Renderer — o altar provavelmente não vai responder a interação."); } } PieceConfig val2 = new PieceConfig { Name = Text_AltarNome.Value, Description = Text_AltarDescricao.Value, PieceTable = "Hammer", CraftingStation = "piece_workbench", Category = "Misc", Icon = (LoadIconFromEmbedded("altar_icon.rgba") ?? GetPlaceholderIcon()), Requirements = ParseAltarRecipe(AltarRecipe?.Value ?? "Wood:10,Stone:5") }; CustomPiece val3 = new CustomPiece(AltarPrefab, true, val2); PieceManager.Instance.AddPiece(val3); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[GlitnirRaces] Peça 'Altar das Raças' registrada."); } private static RequirementConfig[] ParseAltarRecipe(string recipe) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown List list = new List(); if (string.IsNullOrWhiteSpace(recipe)) { return (RequirementConfig[])(object)new RequirementConfig[1] { new RequirementConfig { Item = "Wood", Amount = 10, Recover = true } }; } string[] array = recipe.Split(new char[1] { ',' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ':' }); if (array2.Length == 2) { string text2 = array2[0].Trim(); if (!string.IsNullOrWhiteSpace(text2) && int.TryParse(array2[1].Trim(), out var result) && result > 0) { list.Add(new RequirementConfig { Item = text2, Amount = result, Recover = true }); } } } if (list.Count == 0) { list.Add(new RequirementConfig { Item = "Wood", Amount = 10, Recover = true }); } return list.ToArray(); } public static bool HasChosenRaceViaAltar(Player p) { return IsPlayerLocked(p); } public static bool HasPendingAltarSwitch(Player p) { if ((Object)(object)p == (Object)null) { return false; } long playerIdLong = GetPlayerIdLong(p); return playerIdLong != 0L && PendingAltarSwitch.Contains(playerIdLong); } public static void ChooseRaceFromAltar(string race) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)Instance == (Object)null) { return; } long playerIdLong = GetPlayerIdLong(localPlayer); bool flag = playerIdLong != 0L && PendingAltarSwitch.Contains(playerIdLong); if (!HasChosenRaceViaAltar(localPlayer) || flag) { if (flag) { PendingAltarSwitch.Remove(playerIdLong); } TransformLocalPlayerFromMarketplace(race); } } public static void SwitchRaceFromAltar(Player p) { if (!((Object)(object)Instance == (Object)null) && !((Object)(object)p == (Object)null)) { long playerIdLong = GetPlayerIdLong(p); if (playerIdLong != 0) { PendingAltarSwitch.Add(playerIdLong); } } } private void ApplyRaceWithDelays(Player p) { if (!((Object)(object)p == (Object)null)) { ApplyRace(p); if (!IsHeadless()) { int instanceID = ((Object)p).GetInstanceID(); int value; int num = ((!ApplyRaceCoroutineGeneration.TryGetValue(instanceID, out value)) ? 1 : (value + 1)); ApplyRaceCoroutineGeneration[instanceID] = num; ((MonoBehaviour)this).StartCoroutine(ApplyRaceDelayed(p, Wait01, num)); ((MonoBehaviour)this).StartCoroutine(ApplyRaceDelayed(p, Wait05, num)); ((MonoBehaviour)this).StartCoroutine(ApplyRaceDelayed(p, Wait1, num)); ((MonoBehaviour)this).StartCoroutine(ApplyRaceDelayed(p, Wait2, num)); } } } private IEnumerator ApplyRaceDelayed(Player p, WaitForSeconds wait, int generation) { yield return wait; if (!((Object)(object)p == (Object)null)) { int instanceId = ((Object)p).GetInstanceID(); if (ApplyRaceCoroutineGeneration.TryGetValue(instanceId, out var current) && current == generation) { ApplyRace(p); } } } private void QueueSkinRefresh(Player p, string race) { if (!IsHeadless() && !((Object)(object)p == (Object)null) && !string.IsNullOrWhiteSpace(race)) { string text = GetVisualKey(p); if (string.IsNullOrWhiteSpace(text)) { text = ((Object)p).GetInstanceID().ToString(); } float time = Time.time; if (!LastSkinRefreshRequest.TryGetValue(text, out var value) || !(time - value < 1.25f)) { LastSkinRefreshRequest[text] = time; ((MonoBehaviour)this).StartCoroutine(ForceSkinRefresh(p, race)); } } } private IEnumerator ForceSkinRefresh(Player p, string race) { yield return null; ForceSkinNow(p, race); yield return WaitSkin005; ForceSkinNow(p, race); yield return WaitSkin020; ForceSkinNow(p, race); yield return WaitSkin050; ForceSkinNow(p, race); yield return WaitSkin100; ForceSkinNow(p, race); } private void ForceSkinNow(Player p, string race) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null || string.IsNullOrWhiteSpace(race) || GetRace(p) != race) { return; } bool isApplyingRace = IsApplyingRace; IsApplyingRace = true; try { if (RaceUsesForcedSkin(race)) { ApplySkin(p, GetNetworkSkinColor(p, race)); } Color color = ToColor(GetRaceEarColor(p, race)); if (race == "orc") { ApplyOrcEars(p, color); } else if (race == "elfo") { ApplyEars(p, color); } Transform cachedHead = GetCachedHead(p, race); Transform val = ((cachedHead != null) ? cachedHead.Find("HighElfEyes") : null); if ((Object)(object)val != (Object)null) { ApplyEyeColor(val, GetRaceEyeColor(race)); } } finally { IsApplyingRace = isApplyingRace; } } public void RequestOnlineVisualRefresh(Player p) { if (IsHeadless() || (Object)(object)p == (Object)null) { return; } string race = GetRace(p); if (!string.IsNullOrWhiteSpace(race)) { ApplyRaceWithDelays(p); if (RaceUsesForcedSkin(race) || race == "elfo") { QueueSkinRefresh(p, race); } } } public void RequestOnlineVisualRefresh(VisEquipment vis) { if (!IsHeadless() && !((Object)(object)vis == (Object)null)) { Player val = ((Component)vis).GetComponent() ?? ((Component)vis).GetComponentInParent(); if ((Object)(object)val != (Object)null) { RequestOnlineVisualRefresh(val); } } } public void ForceSkinAfterVanilla(Player p, string race) { if (!IsHeadless() && !((Object)(object)p == (Object)null) && !string.IsNullOrWhiteSpace(race)) { QueueSkinRefresh(p, race); } } public void ForceSkinAfterVanilla(VisEquipment vis) { if (IsHeadless() || (Object)(object)vis == (Object)null) { return; } Player val = ((Component)vis).GetComponent() ?? ((Component)vis).GetComponentInParent(); if (!((Object)(object)val == (Object)null)) { string race = GetRace(val); if (RaceUsesForcedSkin(race) || race == "elfo") { QueueSkinRefresh(val, race); } } } private Transform GetCachedHead(Player p, string race) { if ((Object)(object)p == (Object)null) { return null; } int instanceID = ((Object)p).GetInstanceID(); if (HeadCache.TryGetValue(instanceID, out var value) && HeadCacheRace.TryGetValue(instanceID, out var value2) && value2 == race && (Object)(object)value != (Object)null) { return value; } Transform val = FindHead(((Component)p).transform, 0); HeadCache[instanceID] = val; HeadCacheRace[instanceID] = race; return val; } private static void InvalidateHeadCache(Player p) { if (!((Object)(object)p == (Object)null)) { int instanceID = ((Object)p).GetInstanceID(); HeadCache.Remove(instanceID); HeadCacheRace.Remove(instanceID); } } private static ZNetView GetCachedZNetView(Player player) { if ((Object)(object)player == (Object)null) { return null; } int instanceID = ((Object)player).GetInstanceID(); if (ZNetViewCache.TryGetValue(instanceID, out var value) && (Object)(object)value != (Object)null) { return value; } ZNetView component = ((Component)player).GetComponent(); if ((Object)(object)component != (Object)null) { ZNetViewCache[instanceID] = component; } return component; } public void ApplyRace(Player p) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null || IsApplyingRace || GetPlayerIdLong(p) == 0) { return; } bool flag = IsHeadless(); string race = GetRace(p); string visualKey = GetVisualKey(p); string value = ""; if (!string.IsNullOrWhiteSpace(visualKey)) { LastAppliedRace.TryGetValue(visualKey, out value); } bool flag2 = value != race; IsApplyingRace = true; try { if (flag2) { InvalidateHeadCache(p); if (!flag) { ResetScaledHelmet(p); } ApplyScale(p, HumanScale); if (!flag) { if (RaceUsesForcedSkin(value)) { ResetSkin(p); } Transform cachedHead = GetCachedHead(p, race); RemoveElfEarsAnywhere(cachedHead); RemoveOrcEarsAnywhere(cachedHead); RemoveHeadAttachmentDirect(cachedHead, "HighElfEyes"); RemoveHeadAttachmentDirect(cachedHead, "OrcTusk"); } if (!string.IsNullOrWhiteSpace(visualKey)) { LastAppliedRace[visualKey] = race; } UpdateRaceStatusEffect(p, race); } if (string.IsNullOrWhiteSpace(race) || !IsRaceEnabled(race)) { ApplyScale(p, HumanScale); if (!flag && flag2) { string visualKey2 = GetVisualKey(p); if (!string.IsNullOrWhiteSpace(visualKey2) && OriginalSkinColors.TryGetValue(visualKey2, out var value2)) { ApplySkin(p, value2); } else { ApplySkin(p, Vector3.one); } ResetHelmet(p); Transform head = FindHead(((Component)p).transform, 0); RemoveElfEarsAnywhere(head); RemoveOrcEarsAnywhere(head); RemoveHeadAttachmentDirect(head, "HighElfEyes"); RemoveHeadAttachmentDirect(head, "OrcTusk"); } return; } ApplyScale(p, GetRaceScale(race)); ScaleCurrentHelmetForRace(p, GetRaceScale(race)); if (!flag) { if (RaceUsesForcedSkin(race)) { CacheOriginalSkinIfNeeded(p); ApplySkin(p, GetNetworkSkinColor(p, race)); QueueSkinRefresh(p, race); } if (RaceUsesForcedHair(race)) { ApplyHair(p, GetRaceHairColor(race)); } Transform cachedHead2 = GetCachedHead(p, race); switch (race) { case "orc": ApplyOrcEarsDirect(cachedHead2, ToColor(GetRaceEarColor(p, race)), IsPlayerFemale(p)); ApplyHighElfEyesDirect(p, cachedHead2); ApplyOrcTuskDirect(cachedHead2); break; case "elfo": ApplyEarsDirect(cachedHead2, ToColor(GetRaceEarColor(p, race)), IsPlayerFemale(p)); QueueSkinRefresh(p, race); ApplyHighElfEyesDirect(p, cachedHead2); break; case "anao": ApplyHighElfEyesDirect(p, cachedHead2); break; case "humano": ApplyHighElfEyesDirect(p, cachedHead2); break; } } } finally { IsApplyingRace = false; } } public void SpawnEffect(Player p) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) if (!IsHeadless() && !((Object)(object)p == (Object)null) && !((Object)(object)ZNetScene.instance == (Object)null)) { Vector3 val = ((Component)p).transform.position + Vector3.up; Quaternion rotation = ((Component)p).transform.rotation; GameObject prefab = ZNetScene.instance.GetPrefab("vfx_spawn_large"); GameObject prefab2 = ZNetScene.instance.GetPrefab("fx_Fader_Roar_Projectile_Hit"); if ((Object)(object)prefab != (Object)null) { Object.Instantiate(prefab, val, rotation); } if ((Object)(object)prefab2 != (Object)null) { Object.Instantiate(prefab2, val, rotation); } } } private static void ScaleCurrentHelmetForRace(Player p, Vector3 targetScale) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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) //IL_0082: 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) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null || IsHeadless()) { return; } try { VisEquipment component = ((Component)p).GetComponent(); object? obj = HelmetInstanceField?.GetValue(component); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if (!((Object)(object)val == (Object)null)) { HelmetScaleMarker helmetScaleMarker = val.GetComponent(); if ((Object)(object)helmetScaleMarker == (Object)null) { helmetScaleMarker = val.AddComponent(); helmetScaleMarker.OriginalScale = val.transform.localScale; helmetScaleMarker.OriginalPosition = val.transform.localPosition; helmetScaleMarker.AppliedScale = Vector3.one; } if (!(helmetScaleMarker.AppliedScale == targetScale)) { val.transform.localScale = Vector3.Scale(helmetScaleMarker.OriginalScale, targetScale); val.transform.localPosition = helmetScaleMarker.OriginalPosition; helmetScaleMarker.AppliedScale = targetScale; } } } catch (Exception ex) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("[GlitnirRaces] Falha ao escalar capacete: " + ex.Message)); } } } private void ResetHelmet(Player p) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) ScaleCurrentHelmetForRace(p, Vector3.one); } private void ResetScaledHelmet(Player p) { ResetHelmet(p); } private static void ApplyScale(Player p, Vector3 scale) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)p == (Object)null)) { ((Component)p).transform.localScale = scale; } } private static void RemovePlayerAttachment(Player p, string objectName) { if (!((Object)(object)p == (Object)null)) { Transform val = ((Component)p).transform.Find(objectName); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } private void RegisterCommands() { RegisterRaceCommand("orc"); RegisterRaceCommand("elfo"); RegisterRaceCommand("anao"); RegisterRaceCommand("humano"); RegisterResetRaceCommand(); RegisterOfflineResetCommand(); ReRegisterSecretCodeCommands(); RegisterReloadCommand(); } private void RegisterReloadCommand() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) new ConsoleCommand("reloadracas", "Recarrega os codigos secretos do config", (ConsoleEventFailable)delegate(ConsoleEventArgs args) { if (!HasDevCommands()) { args.Context.AddString(Text_SemPermissao.Value); return false; } Instance.MainConfigFile.Reload(); Instance.TextConfigFile.Reload(); NetworkRaces.Clear(); ZNetViewCache.Clear(); foreach (Player allPlayer in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null)) { string visualKey = GetVisualKey(allPlayer); if (!string.IsNullOrWhiteSpace(visualKey)) { LastAppliedRace[visualKey] = ""; } InvalidateHeadCache(allPlayer); Instance.ApplyRaceWithDelays(allPlayer); } } ReRegisterSecretCodeCommands(); args.Context.AddString(Text_ConfigRecarregado.Value); args.Context.AddString(Text_CodigosSecretosAtivos.Value); foreach (KeyValuePair race in Races) { string value = race.Value.SecretCode.Value; if (!string.IsNullOrWhiteSpace(value)) { args.Context.AddString(" " + race.Value.DisplayName + " → " + value); } } return true; }, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private void ReRegisterSecretCodeCommands() { foreach (KeyValuePair race in Races) { string value = race.Value.SecretCode.Value; string key = race.Key; if (!string.IsNullOrWhiteSpace(value) && !RegisteredSecretCodes.Contains(value)) { RegisterSecretCodeCommand(value, key); RegisteredSecretCodes.Add(value); } } } private void RegisterSecretCodeCommand(string code, string race) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) new ConsoleCommand(code, "", (ConsoleEventFailable)delegate { TransformLocalPlayerFromMarketplace(race); return true; }, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private void RegisterRaceCommand(string race) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) new ConsoleCommand(race, race + " me ou " + race + " NomeDoPlayer", (ConsoleEventFailable)delegate(ConsoleEventArgs args) { if (!HasDevCommands()) { args.Context.AddString(Text_SemPermissao.Value); return false; } if (!IsRaceEnabled(race)) { args.Context.AddString(Fmt(Text_RacaDesativadaAdmin.Value, GetRaceName(race))); return false; } if (args.Args.Length < 2) { args.Context.AddString(Fmt(Text_UsoRaca.Value, race)); return false; } Player targetPlayer = GetTargetPlayer(args); if ((Object)(object)targetPlayer == (Object)null) { args.Context.AddString(Text_PlayerNaoEncontrado.Value); return false; } AdminSetRace(targetPlayer, race); args.Context.AddString(Fmt(Text_AgoraERaca.Value, targetPlayer.GetPlayerName(), GetRaceName(race))); return true; }, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private void RegisterResetRaceCommand() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) ConsoleEventFailable val = (ConsoleEventFailable)delegate(ConsoleEventArgs args) { if (!HasDevCommands()) { args.Context.AddString(Text_SemPermissao.Value); return false; } if (args.Args.Length < 2) { args.Context.AddString(Fmt(Text_UsoRaca.Value, args.Args[0])); return false; } Player targetPlayer = GetTargetPlayer(args); if ((Object)(object)targetPlayer == (Object)null) { args.Context.AddString(Text_PlayerNaoEncontrado.Value); return false; } long playerIdLong = GetPlayerIdLong(targetPlayer); if (playerIdLong == 0) { args.Context.AddString(Fmt(Text_PlayerNaoCarregado.Value, targetPlayer.GetPlayerName())); return false; } ResetRace(targetPlayer, broadcast: true); args.Context.AddString(Fmt(Text_RacaRemovida.Value, targetPlayer.GetPlayerName())); return true; }; new ConsoleCommand("racareset", "racareset me ou racareset NomeDoPlayer", val, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private Player GetTargetPlayer(ConsoleEventArgs args) { string typedName = string.Join(" ", args.Args.Skip(1)).Trim(); if (typedName.Equals("me", StringComparison.OrdinalIgnoreCase)) { return Player.m_localPlayer; } return ((IEnumerable)Player.GetAllPlayers()).FirstOrDefault((Func)((Player p) => (Object)(object)p != (Object)null && p.GetPlayerName().Equals(typedName, StringComparison.OrdinalIgnoreCase))); } private void RegisterOfflineResetCommand() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown object obj = <>c.<>9__35_0; if (obj == null) { ConsoleEventFailable val = delegate(ConsoleEventArgs args) { if (!HasDevCommands()) { args.Context.AddString(Text_SemPermissao.Value); return false; } if (args.Args.Length < 2) { args.Context.AddString(Text_UsoOfflineReset.Value); return false; } if (!long.TryParse(args.Args[1], out var result)) { args.Context.AddString(Text_IdInvalido.Value); return false; } bool flag = ResetOfflinePlayer(result); args.Context.AddString(flag ? Text_OfflineResetado.Value : Text_OfflineNaoEncontrado.Value); return flag; }; <>c.<>9__35_0 = val; obj = (object)val; } new ConsoleCommand("glitnir_reset_offline", "glitnir_reset_offline ", (ConsoleEventFailable)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static bool ResetOfflinePlayer(long playerID) { if (ZDOMan.instance == null) { return false; } List list = new List(); int num = 0; while (ZDOMan.instance.GetAllZDOsWithPrefabIterative("Player", list, ref num)) { } foreach (ZDO item in list) { if (item != null) { long num2 = item.GetLong(ZDOVars.s_playerID, 0L); if (num2 == playerID) { item.Set("GlitnirRace", ""); item.Set("GlitnirRaceLocked", false); item.Set("GlitnirRaceEarColor_x", -1f); item.Set("GlitnirRaceEarColor_y", -1f); item.Set("GlitnirRaceEarColor_z", -1f); item.Set("GlitnirRaceSkinColor_x", -1f); item.Set("GlitnirRaceSkinColor_y", -1f); item.Set("GlitnirRaceSkinColor_z", -1f); NetworkRaces.Remove(playerID); return true; } } } return false; } private static void TransformLocalPlayerFromMarketplace(string race) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)Instance == (Object)null) { return; } if (!IsRaceEnabled(race)) { ((Character)localPlayer).Message((MessageType)2, Text_EssaRacaDesativada.Value, 0, (Sprite)null); return; } if (RaceUsesForcedSkin(race)) { Instance.CacheOriginalSkinIfNeeded(localPlayer); } Instance.SetRace(localPlayer, race, lockPlayer: true, broadcast: true); Instance.ApplyRaceWithDelays(localPlayer); TopOffVitals(localPlayer); if (!IsHeadless()) { Instance.SpawnEffect(localPlayer); } PlayTransformEmote(); ((Character)localPlayer).Message((MessageType)2, Fmt(Text_AgoraEuSou.Value, Instance.GetRaceName(race)), 0, (Sprite)null); } private static void PlayTransformEmote() { if (!EmoteOnTransform.Value) { return; } try { Emote.DoEmote((Emotes)11); } catch (Exception ex) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("Falha ao tocar emote de transformação: " + ex.Message)); } } } private void CreateRaceConfigs() { Races.Clear(); CreateRaceConfig("orc", Text_RaceName_Orc.Value, enabled: true, "1,1,1", "#3FA86B", "#3FA86B", "#FFFF00", "X9K7Q2M4Z8P1", RaceAbility.Orc, "-1", 0f, 0f, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f, 0f, 1f, 0.9f, "Blunt:Resistant,Frost:Weak", 0f, 0.3f, 1.3f); CreateRaceConfig("elfo", Text_RaceName_Elf.Value, enabled: true, "1,1,1", "-1", "-1", "#00FF00", "R3T8Y1U6I4O9", RaceAbility.Elf, "-1", 0f, 0f, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f, 0f, 1f, 1.15f, "Spirit:Resistant,Poison:Weak", 0f, 0f, 1f, stillHealAura: true, 5f, 2f, 2f, stillHealDayOnly: true); CreateRaceConfig("anao", Text_RaceName_Dwarf.Value, enabled: true, "0.8,0.8,0.8", "-1", "-1", "#9B30FF", "Z4P9X2C7B8N1", RaceAbility.Dwarf, "-1", 0f, 0f, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f, 0f, 1f, 0.9f, "Blunt:VeryResistant,Slash:Resistant,Pierce:Resistant,Fire:Weak", 0f, 0f, 1f, stillHealAura: false, 5f, 2f, 2f, stillHealDayOnly: false, ironStanceEnabled: true, 0.3f); CreateRaceConfig("humano", Text_RaceName_Human.Value, enabled: true, "1,1,1", "-1", "-1", "#00F0FF", "T2Y7U4I8O1P6", RaceAbility.Human, "-1", 0f, 0f, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f, 0f, 1f, 1f, "", 0f, 0f, 1f, stillHealAura: false, 5f, 2f, 2f, stillHealDayOnly: false, ironStanceEnabled: false, 0f, secondWindEnabled: true, 0.2f, 30f, 30f); } private void CreateRaceConfig(string raceId, string displayName, bool enabled, string scale, string skinColor, string earColor, string eyeColor, string secretCode, RaceAbility ability = RaceAbility.None, string hairColor = "-1", float healthBonus = 0f, float staminaBonus = 0f, float eitrBonus = 0f, float carryWeightBonus = 0f, float healthRegenMult = 1f, float staminaRegenMult = 1f, float eitrRegenMult = 1f, float damageDoneMult = 1f, float backstabMult = 1f, float damageTakenMult = 1f, float lifestealPercent = 0f, float stealthMult = 1f, float speedMult = 1f, string resistances = "", float heatResistanceBonus = 0f, float lowHealthThreshold = 0f, float lowHealthDamageBonus = 1f, bool stillHealAura = false, float stillHealAmount = 5f, float stillHealInterval = 2f, float stillHealRequiredStillTime = 2f, bool stillHealDayOnly = false, bool ironStanceEnabled = false, float ironStanceExtraDamageReduction = 0f, bool secondWindEnabled = false, float secondWindThreshold = 0.2f, float secondWindHealAmount = 0f, float secondWindStaminaAmount = 0f, float secondWindCooldown = 300f, string skillDamageMultipliers = "", string attackDamageTypeMultipliers = "", bool noResourceCost = false, float xpGainMult = 1f, float knockbackMult = 1f, float eitrCostMult = 1f, string staminaCostModifiers = "", bool nightOnlyBonuses = false, float dayNightHealthShift = 0f, string biomeHealthShifts = "") { string text = "Aparencia - " + displayName; string text2 = "Habilidades - " + displayName; RaceConfig raceConfig = new RaceConfig { RaceId = raceId, DisplayName = displayName, Enabled = SyncedConfig(text, "Usar", enabled, "Ativa ou desativa a raça " + displayName + "."), Scale = SyncedConfig(text, "Tamanho", scale, "Tamanho da raça no formato X,Y,Z."), SkinColor = SyncedConfig(text, "Cor", skinColor, "Cor da pele em HEX. Use -1 para não alterar."), HairColor = SyncedConfig(text, "CorCabeloBarba", hairColor, "Cor do cabelo e barba em HEX (os dois juntos, o jogo usa a mesma cor pros dois). Use -1 para não alterar."), EarColor = SyncedConfig(text, "CorOrelha", earColor, "Cor da orelha em HEX. Use -1 para usar a cor da pele."), EyeColor = SyncedConfig(text, "CorOlho", eyeColor, "Cor dos olhos em HEX."), SecretCode = SyncedConfig(text, "CodigoSecreto", secretCode, "Código secreto digitado no chat para escolher a raça."), HealthBonus = SyncedConfig(text2, "BonusVida", healthBonus, "Vida máxima extra, somada em cima do vanilla (nunca abaixo)."), StaminaBonus = SyncedConfig(text2, "BonusStamina", staminaBonus, "Stamina máxima extra, somada em cima do vanilla."), EitrBonus = SyncedConfig(text2, "BonusEitr", eitrBonus, "Eitr máximo extra, somado em cima do vanilla."), CarryWeightBonus = SyncedConfig(text2, "BonusPeso", carryWeightBonus, "Peso máximo extra que pode carregar, somado em cima do vanilla."), HealthRegenMultiplier = SyncedConfig(text2, "MultiplicadorRegenVida", healthRegenMult, "Velocidade de regeneração de vida (e cura em geral). 1.0 = vanilla, 1.4 = 40% mais rápido."), StaminaRegenMultiplier = SyncedConfig(text2, "MultiplicadorRegenStamina", staminaRegenMult, "Velocidade de regeneração de stamina. 1.0 = vanilla."), EitrRegenMultiplier = SyncedConfig(text2, "MultiplicadorRegenEitr", eitrRegenMult, "Velocidade de regeneração de eitr. 1.0 = vanilla."), DamageDoneMultiplier = SyncedConfig(text2, "MultiplicadorDanoCausado", damageDoneMult, "Multiplicador de dano causado em geral. 1.0 = vanilla, 1.15 = +15%."), BackstabMultiplier = SyncedConfig(text2, "MultiplicadorAtaqueFurtivo", backstabMult, "Multiplicador extra no bônus de dano de ataque furtivo (backstab). 1.0 = vanilla."), DamageTakenMultiplier = SyncedConfig(text2, "MultiplicadorDanoRecebido", damageTakenMult, "Multiplicador de dano recebido em geral. 1.0 = vanilla, 0.85 = -15%."), LifestealPercent = SyncedConfig(text2, "RouboDeVida", lifestealPercent, "Fração do dano causado que vira cura pro atacante. 0 = desativado, 0.12 = 12%."), StealthMultiplier = SyncedConfig(text2, "MultiplicadorFurtividade", stealthMult, "Multiplicador do fator de furtividade. Menor que 1.0 = mais furtivo."), SpeedMultiplier = SyncedConfig(text2, "MultiplicadorVelocidade", speedMult, "Multiplicador de velocidade de movimento (andar/correr). 1.0 = vanilla."), Resistances = SyncedConfig(text2, "Resistencias", resistances, "Resistências a dano por tipo, formato 'Tipo:Nivel,Tipo:Nivel'. Tipos: Blunt, Slash, Pierce, Chop, Pickaxe, Fire, Frost, Lightning, Poison, Spirit. Niveis: Normal, Resistant, VeryResistant, SlightlyResistant, Weak, VeryWeak, SlightlyWeak, Immune, Ignore. Ex: 'Frost:Immune,Fire:Weak'."), HeatResistanceBonus = SyncedConfig(text2, "BonusResistenciaFrio", heatResistanceBonus, "Se diferente de 0, essa raça é IMUNE ao frio/calor ambiente (status 'Congelando' e dano de exposição a lava). O valor em si não importa (só precisa ser != 0) — é liga/desliga, não intensidade."), SkillDamageMultipliers = SyncedConfig(text2, "MultiplicadorDanoPorSkill", skillDamageMultipliers, "[Uso raro] Bônus de dano extra quando o golpe usa um skill específico, formato 'Skill:Mult,Skill:Mult'. Skills comuns: Swords, Knives, Clubs, Polearms, Spears, Axes, Bows, Crossbows, Unarmed, ElementalMagic, BloodMagic. Ex: 'BloodMagic:1.3,Bows:1.15'."), AttackDamageTypeMultipliers = SyncedConfig(text2, "MultiplicadorDanoPorTipo", attackDamageTypeMultipliers, "[Uso raro] Bônus de dano causado, só na fatia daquele TIPO de dano específico. Formato 'Tipo:Mult,Tipo:Mult'."), NoResourceCost = SyncedConfig(text2, "SemGastoStaminaEitr", noResourceCost, "[Uso raro] Se true, não gasta stamina nem eitr ao usar ataques/habilidades (a barra só existe pra visual)."), XpGainMultiplier = SyncedConfig(text2, "MultiplicadorGanhoXP", xpGainMult, "[Uso raro] Multiplicador de XP ganho em skills ao acertar golpes. 1.0 = vanilla."), KnockbackMultiplier = SyncedConfig(text2, "MultiplicadorEmpurrao", knockbackMult, "[Uso raro] Multiplicador da força de empurrão (knockback) que os golpes causam. 1.0 = vanilla."), EitrCostMultiplier = SyncedConfig(text2, "MultiplicadorCustoEitr", eitrCostMult, "[Uso raro] Multiplicador do custo de Eitr ao usar magia. Ignorado se SemGastoStaminaEitr estiver ligado."), StaminaCostModifiers = SyncedConfig(text2, "ModificadoresCustoStamina", staminaCostModifiers, "[Uso raro] Reduz (ou aumenta) o custo de stamina por ação específica, formato 'Acao:Valor,Acao:Valor'. Ações: Attack, Block, Dodge, Jump, Run, Sneak, Swim. Valor positivo reduz custo, negativo aumenta."), NightOnlyBonuses = SyncedConfig(text2, "BonusSoDeNoite", nightOnlyBonuses, "[Uso raro] Se true, os multiplicadores de regen e de velocidade dessa raça só valem durante a noite."), DayNightHealthShift = SyncedConfig(text2, "OscilacaoVidaDiaNoite", dayNightHealthShift, "[Uso raro] Faz a vida máxima subir de noite e cair de dia, em cima do BonusVida normal."), BiomeHealthShifts = SyncedConfig(text2, "OscilacaoVidaPorBioma", biomeHealthShifts, "[Uso raro] Soma/subtrai vida máxima dependendo do bioma atual, formato 'Bioma:Valor,Bioma:Valor'.") }; switch (ability) { case RaceAbility.Orc: raceConfig.LowHealthThreshold = SyncedConfig(text2, "Habilidade_LimiarVida", lowHealthThreshold, "Fúria de Sangue: abaixo de que % de vida (0 a 1) o bônus de dano extra ativa. 0 = desativado."); raceConfig.LowHealthDamageBonus = SyncedConfig(text2, "Habilidade_BonusDano", lowHealthDamageBonus, "Fúria de Sangue: multiplicador de dano causado quando a vida está abaixo do limiar acima."); break; case RaceAbility.Elf: raceConfig.StillHealAura = SyncedConfig(text2, "Habilidade_Ativo", stillHealAura, "Aura de Cura: se true, ficar parado por um tempo regenera vida extra periodicamente."); raceConfig.StillHealAmount = SyncedConfig(text2, "Habilidade_QuantidadeCura", stillHealAmount, "Quantidade de vida curada por tick enquanto parado."); raceConfig.StillHealInterval = SyncedConfig(text2, "Habilidade_Intervalo", stillHealInterval, "Intervalo em segundos entre cada tick de cura enquanto parado."); raceConfig.StillHealRequiredStillTime = SyncedConfig(text2, "Habilidade_TempoParado", stillHealRequiredStillTime, "Quantos segundos parado até a cura começar a ativar."); raceConfig.StillHealDayOnly = SyncedConfig(text2, "Habilidade_SoDeDia", stillHealDayOnly, "Se true, a Aura de Cura só funciona durante o DIA."); break; case RaceAbility.Dwarf: raceConfig.IronStanceEnabled = SyncedConfig(text2, "Habilidade_Ativo", ironStanceEnabled, "Postura de Ferro: reduz dano extra e zera empurrão enquanto estiver bloqueando."); raceConfig.IronStanceExtraDamageReduction = SyncedConfig(text2, "Habilidade_ReducaoExtra", ironStanceExtraDamageReduction, "Redução de dano EXTRA (fração 0-1) enquanto bloqueando, somada ao bloqueio normal do jogo."); break; case RaceAbility.Human: raceConfig.SecondWindEnabled = SyncedConfig(text2, "Habilidade_Ativo", secondWindEnabled, "Segundo Fôlego: quando a vida cai abaixo do limiar, recupera vida/stamina uma vez, com cooldown."); raceConfig.SecondWindThreshold = SyncedConfig(text2, "Habilidade_LimiarVida", secondWindThreshold, "Abaixo de que % de vida (0 a 1) o Segundo Fôlego ativa."); raceConfig.SecondWindHealAmount = SyncedConfig(text2, "Habilidade_QuantidadeVida", secondWindHealAmount, "Quantidade de vida recuperada quando o Segundo Fôlego ativa."); raceConfig.SecondWindStaminaAmount = SyncedConfig(text2, "Habilidade_QuantidadeStamina", secondWindStaminaAmount, "Quantidade de stamina recuperada quando o Segundo Fôlego ativa."); raceConfig.SecondWindCooldown = SyncedConfig(text2, "Habilidade_Cooldown", secondWindCooldown, "Cooldown em segundos antes do Segundo Fôlego poder ativar de novo."); break; } Races[raceId] = raceConfig; } private ConfigEntry SyncedConfig(string group, string name, T value, string description) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { IsAdminOnly = true }; return MainConfigFile.Bind(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { val })); } private void OnConfigurationSynchronized(object sender, EventArgs args) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Configuração sincronizada pelo Jotunn."); if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } NetworkRaces.Clear(); ZNetViewCache.Clear(); foreach (Player allPlayer in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null)) { string visualKey = GetVisualKey(allPlayer); if (!string.IsNullOrWhiteSpace(visualKey)) { LastAppliedRace[visualKey] = ""; } InvalidateHeadCache(allPlayer); } } ReRegisterSecretCodeCommands(); foreach (Player allPlayer2 in Player.GetAllPlayers()) { ApplyRaceWithDelays(allPlayer2); } } private void LoadAssets() { ElfEarsMalePrefab = LoadPrefabFromEmbedded("elf_ears_m"); ElfEarsFemalePrefab = LoadPrefabFromEmbedded("elf_ears_f"); OrcEarsMalePrefab = LoadPrefabFromEmbedded("orc_ears_m"); OrcEarsFemalePrefab = LoadPrefabFromEmbedded("orc_ears_f"); OrcTuskPrefab = LoadPrefabFromEmbedded("orc_tusk"); HighElfEyesPrefab = LoadPrefabFromEmbedded("high_elf_eyes"); } private GameObject LoadPrefabFromEmbedded(string assetName) { try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string x) => x.EndsWith(assetName)); if (text == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Asset embutido '" + assetName + "' não encontrado na DLL.")); string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); foreach (string text2 in manifestResourceNames) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("RESOURCE: " + text2)); } return null; } using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Stream '" + assetName + "' nulo.")); return null; } byte[] array; using (MemoryStream memoryStream = new MemoryStream()) { stream.CopyTo(memoryStream); array = memoryStream.ToArray(); } AssetBundle val = AssetBundle.LoadFromMemory(array); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Falha ao carregar AssetBundle '" + assetName + "'.")); return null; } GameObject val2 = val.LoadAsset(assetName) ?? val.LoadAllAssets().FirstOrDefault(); if ((Object)(object)val2 == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Nenhum prefab em '" + assetName + "'.")); } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Prefab '" + assetName + "' carregado.")); } return val2; } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Erro ao carregar asset '{assetName}': {arg}"); return null; } } private static bool IsRaceEnabled(string race) { RaceConfig value; return !string.IsNullOrWhiteSpace(race) && Races.TryGetValue(race, out value) && value.Enabled.Value; } private static bool RaceUsesForcedSkin(string race) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(race) || !Races.TryGetValue(race, out var value)) { return false; } Vector3 val = ParseColorConfig(value.SkinColor.Value, InvalidColor); return val.x >= 0f && val.y >= 0f && val.z >= 0f; } private static bool RaceUsesForcedHair(string race) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(race) || !Races.TryGetValue(race, out var value)) { return false; } Vector3 val = ParseColorConfig(value.HairColor.Value, InvalidColor); return val.x >= 0f && val.y >= 0f && val.z >= 0f; } private static Vector3 GetRaceHairColor(string race) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) RaceConfig value; return Races.TryGetValue(race, out value) ? ParseColorConfig(value.HairColor.Value, InvalidColor) : InvalidColor; } private static Vector3 GetRaceScale(string race) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) RaceConfig value; return Races.TryGetValue(race, out value) ? ParseVector(value.Scale.Value, HumanScale) : HumanScale; } private static Vector3 GetRaceSkinColor(string race) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) RaceConfig value; return Races.TryGetValue(race, out value) ? ParseColorConfig(value.SkinColor.Value, Vector3.one) : Vector3.one; } private static Vector3 ParseVector(string value, Vector3 fallback) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) try { if (string.IsNullOrWhiteSpace(value)) { return fallback; } string[] array = value.Split(new char[1] { ',' }); if (array.Length != 3) { return fallback; } return new Vector3(float.Parse(array[0].Trim(), CultureInfo.InvariantCulture), float.Parse(array[1].Trim(), CultureInfo.InvariantCulture), float.Parse(array[2].Trim(), CultureInfo.InvariantCulture)); } catch { return fallback; } } private static Vector3 ParseColorConfig(string value, Vector3 fallback) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) try { if (string.IsNullOrWhiteSpace(value)) { return fallback; } value = value.Trim(); if (value == "-1" || value.Equals("none", StringComparison.OrdinalIgnoreCase) || value.Equals("nao", StringComparison.OrdinalIgnoreCase) || value.Equals("não", StringComparison.OrdinalIgnoreCase) || value == "-1,-1,-1") { return InvalidColor; } if (value.StartsWith("#")) { Color val = default(Color); if (ColorUtility.TryParseHtmlString(value, ref val)) { return new Vector3(val.r, val.g, val.b); } return fallback; } return ParseVector(value, fallback); } catch { return fallback; } } private static string GetRaceFromSecretCode(string text) { if (string.IsNullOrWhiteSpace(text)) { return null; } foreach (KeyValuePair race in Races) { RaceConfig value = race.Value; if (value?.SecretCode == null || !value.Enabled.Value || !text.Equals(value.SecretCode.Value, StringComparison.Ordinal)) { continue; } return race.Key; } return null; } private string GetRaceName(string race) { RaceConfig value; return Races.TryGetValue(race, out value) ? value.DisplayName : race; } private static string GetPlayerId(Player player) { long playerIdLong = GetPlayerIdLong(player); return (playerIdLong != 0L) ? playerIdLong.ToString() : ""; } private static string GetVisualKey(Player player) { if ((Object)(object)player == (Object)null) { return ""; } long playerIdLong = GetPlayerIdLong(player); return (playerIdLong != 0L) ? playerIdLong.ToString() : ""; } private static long GetPlayerIdLong(Player player) { if ((Object)(object)player == (Object)null) { return 0L; } try { long playerID = player.GetPlayerID(); if (playerID != 0) { return playerID; } } catch { } return 0L; } private void RestoreLocalSavedRaceIfNeeded() { if (isRestoringLocalRace) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || GetPlayerIdLong(localPlayer) == 0) { return; } string savedLocalRace = GetSavedLocalRace(); if (string.IsNullOrWhiteSpace(savedLocalRace) || !IsRaceEnabled(savedLocalRace)) { return; } string race = GetRace(localPlayer); if (!string.IsNullOrWhiteSpace(race)) { return; } ZNetView cachedZNetView = GetCachedZNetView(localPlayer); if ((Object)(object)cachedZNetView == (Object)null || cachedZNetView.GetZDO() == null) { return; } isRestoringLocalRace = true; try { long playerIdLong = GetPlayerIdLong(localPlayer); if (playerIdLong != 0) { NetworkRaces[playerIdLong] = savedLocalRace; } ForceSetZdoRace(localPlayer, savedLocalRace); ForceSetRaceVisualZdo(localPlayer, savedLocalRace); SetZdoLocked(localPlayer, locked: true); BroadcastRace(localPlayer, savedLocalRace); lastBroadcastRace = savedLocalRace; ApplyRaceWithDelays(localPlayer); } finally { isRestoringLocalRace = false; } } private static string GetLocalSavePrefix() { long num = 0L; try { if ((Object)(object)Player.m_localPlayer != (Object)null) { num = Player.m_localPlayer.GetPlayerID(); } } catch { } if (_cachedSavePrefix != null && (Object)(object)_cachedZNetInstance == (Object)(object)ZNet.instance && _cachedCharacterId == num) { return _cachedSavePrefix; } string text = ((num != 0L) ? num.ToString() : "unknown"); string text2 = "local"; try { if ((Object)(object)ZNet.instance != (Object)null) { if (!ZNet.instance.IsServer()) { string text3 = ""; int result = 0; FieldInfo fieldInfo = AccessTools.Field(typeof(ZNet), "m_serverHost"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(ZNet), "m_serverPort"); if (fieldInfo != null) { text3 = fieldInfo.GetValue(ZNet.instance)?.ToString() ?? ""; } if (fieldInfo2 != null) { int.TryParse(fieldInfo2.GetValue(ZNet.instance)?.ToString() ?? "", out result); } if (!string.IsNullOrWhiteSpace(text3)) { text2 = text3 + ((result > 0) ? ("_" + result) : ""); } } else { MethodInfo methodInfo = AccessTools.Method(typeof(ZNet), "GetWorldName", (Type[])null, (Type[])null); if (methodInfo != null) { text2 = methodInfo.Invoke(ZNet.instance, null)?.ToString() ?? "local"; } } } } catch { } _cachedSavePrefix = "GlitnirRaces_c" + text + "_s" + SanitizeKey(text2) + "_"; _cachedZNetInstance = ZNet.instance; _cachedCharacterId = num; _cachedServerKey = text2; return _cachedSavePrefix; } private static string SanitizeKey(string value) { if (string.IsNullOrWhiteSpace(value)) { return "unknown"; } char[] array = value.ToCharArray(); for (int i = 0; i < array.Length; i++) { if (!char.IsLetterOrDigit(array[i]) && array[i] != '-') { array[i] = '_'; } } return new string(array); } private static string GetSavedLocalRace() { try { return PlayerPrefs.GetString(GetLocalSavePrefix() + "Race", ""); } catch { return ""; } } private static bool HasSavedLocalRaceLocked() { try { return PlayerPrefs.GetInt(GetLocalSavePrefix() + "Locked", 0) == 1; } catch { return false; } } private static void SaveLocalRace(string race, bool locked) { if (string.IsNullOrWhiteSpace(race)) { return; } try { PlayerPrefs.SetString(GetLocalSavePrefix() + "Race", race); PlayerPrefs.SetInt(GetLocalSavePrefix() + "Locked", locked ? 1 : 0); PlayerPrefs.Save(); } catch { } long localCharacterId = GetLocalCharacterId(); if (localCharacterId == 0) { return; } try { PlayerPrefs.SetString(GetGlobalRaceKey(localCharacterId), race); PlayerPrefs.Save(); } catch { } } private static long GetLocalCharacterId() { try { return ((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0; } catch { return 0L; } } private static string GetGlobalRaceKey(long characterId) { return $"GlitnirRaces_c{characterId}_LastRaceGlobal"; } private static string GetLastRaceGlobal(long characterId) { if (characterId == 0) { return ""; } try { return PlayerPrefs.GetString(GetGlobalRaceKey(characterId), ""); } catch { return ""; } } private static void ClearLocalSavedRace() { try { PlayerPrefs.DeleteKey(GetLocalSavePrefix() + "Race"); PlayerPrefs.DeleteKey(GetLocalSavePrefix() + "Locked"); PlayerPrefs.Save(); } catch { } } private static bool IsClientConnectedToRemoteServer() { try { return (Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer(); } catch { return false; } } private static bool IsSinglePlayer() { try { if ((Object)(object)ZNet.instance == (Object)null) { return false; } return ZNet.instance.IsServer() && ZNet.instance.GetNrOfPlayers() <= 1; } catch { return false; } } private static void ApplyPreviewRace(FejdStartup fejd, PlayerProfile profile) { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)fejd == (Object)null || profile == null || (Object)(object)Instance == (Object)null) { return; } long playerID = profile.GetPlayerID(); if (playerID == 0) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)"[GlitnirRaces/Preview] characterId = 0, ignorando."); } return; } string lastRaceGlobal = GetLastRaceGlobal(playerID); if (string.IsNullOrWhiteSpace(lastRaceGlobal) || !IsRaceEnabled(lastRaceGlobal)) { GlitnirRacesPlugin instance2 = Instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Logger.LogInfo((object)$"[GlitnirRaces/Preview] Nenhuma raça salva (global) pro personagem {playerID}. Valor lido: '{lastRaceGlobal}'."); } return; } Player previewPlayer = fejd.GetPreviewPlayer(); if ((Object)(object)previewPlayer == (Object)null) { GlitnirRacesPlugin instance3 = Instance; if (instance3 != null) { ((BaseUnityPlugin)instance3).Logger.LogInfo((object)"[GlitnirRaces/Preview] GetPreviewPlayer() retornou null."); } return; } GlitnirRacesPlugin instance4 = Instance; if (instance4 != null) { ((BaseUnityPlugin)instance4).Logger.LogInfo((object)$"[GlitnirRaces/Preview] Aplicando raça '{lastRaceGlobal}' no preview do personagem {playerID}."); } ApplyScale(previewPlayer, GetRaceScale(lastRaceGlobal)); Transform val = Instance.FindHead(((Component)previewPlayer).transform, 0); if ((Object)(object)val == (Object)null) { GlitnirRacesPlugin instance5 = Instance; if (instance5 != null) { ((BaseUnityPlugin)instance5).Logger.LogInfo((object)"[GlitnirRaces/Preview] FindHead não achou a cabeça do preview."); } return; } Color color = ToColor(GetRaceEarColorForPreview(previewPlayer, lastRaceGlobal)); string text = lastRaceGlobal; string text2 = text; if (!(text2 == "orc")) { if (text2 == "elfo") { Instance.ApplyEarsDirect(val, color, Instance.IsPlayerFemale(previewPlayer)); } } else { Instance.ApplyOrcEarsDirect(val, color, Instance.IsPlayerFemale(previewPlayer)); Instance.ApplyOrcTuskDirect(val); } Instance.ApplyHighElfEyesPreview(val, lastRaceGlobal); if (RaceUsesForcedSkin(lastRaceGlobal)) { Instance.ApplySkin(previewPlayer, GetRaceSkinColor(lastRaceGlobal)); } if (RaceUsesForcedHair(lastRaceGlobal)) { Instance.ApplyHair(previewPlayer, GetRaceHairColor(lastRaceGlobal)); } } private static Vector3 GetRaceEarColorForPreview(Player preview, string race) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (Races.TryGetValue(race, out var value)) { Vector3 val = ParseColorConfig(value.EarColor.Value, InvalidColor); if (val.x >= 0f) { return val; } } if (RaceUsesForcedSkin(race)) { return GetRaceSkinColor(race); } return ((Object)(object)Instance != (Object)null) ? Instance.GetCurrentSkinVector(preview) : Vector3.one; } private void ApplyHighElfEyesPreview(Transform head, string race) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)head == (Object)null) && !((Object)(object)HighElfEyesPrefab == (Object)null)) { Transform val = head.Find("HighElfEyes"); if ((Object)(object)val == (Object)null) { GameObject val2 = Object.Instantiate(HighElfEyesPrefab, head); ((Object)val2).name = "HighElfEyes"; StripItemComponents(val2); val = val2.transform; } val.localPosition = HighElfEyesPosition; val.localRotation = Quaternion.Euler(HighElfEyesRotation); val.localScale = HighElfEyesScale; ApplyEyeColor(val, GetRaceEyeColor(race)); } } private static void ApplyRaceVisualToRagdoll(Ragdoll ragdoll, string race) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ragdoll == (Object)null || string.IsNullOrWhiteSpace(race)) { return; } try { Transform transform = ((Component)ragdoll).transform; Vector3 localScale = (transform.localScale = GetRaceScale(race)); Transform val = transform.Find("Visual") ?? transform.Find("_Visual") ?? transform.Find("visual"); if ((Object)(object)val != (Object)null) { val.localScale = localScale; } Transform val2 = Instance.FindHead(transform, 0); if ((Object)(object)val2 == (Object)null) { return; } Color color = ToColor(GetRagdollEarColor(race)); if (!(race == "orc")) { if (race == "elfo") { Instance.ApplyEarsDirect(val2, color, IsRagdollFemale(ragdoll)); } } else { Instance.ApplyOrcEarsDirect(val2, color, IsRagdollFemale(ragdoll)); Instance.ApplyOrcTuskDirect(val2); } Instance.ApplyHighElfEyesPreview(val2, race); if (RaceUsesForcedSkin(race)) { VisEquipment componentInChildren = ((Component)ragdoll).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { typeof(VisEquipment).GetMethod("SetSkinColor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(componentInChildren, new object[1] { GetRaceSkinColor(race) }); } } } catch (Exception arg) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)$"[GlitnirRaces] Falha ao aplicar raça no ragdoll: {arg}"); } } } private static Vector3 GetRagdollEarColor(string race) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrWhiteSpace(race) && Races.TryGetValue(race, out var value)) { Vector3 val = ParseColorConfig(value.EarColor.Value, InvalidColor); if (val.x >= 0f) { return val; } } if (RaceUsesForcedSkin(race)) { return GetRaceSkinColor(race); } return Vector3.one; } private static bool IsRagdollFemale(Ragdoll ragdoll) { if ((Object)(object)ragdoll == (Object)null) { return false; } try { VisEquipment componentInChildren = ((Component)ragdoll).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null && ModelIndexField != null && ModelIndexField.GetValue(componentInChildren) is int num) { return num == 1; } } catch (Exception ex) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("[GlitnirRaces] Falha ao ler gênero do ragdoll: " + ex.Message)); } } return false; } private static bool IsHeadless() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 return (int)SystemInfo.graphicsDeviceType == 4; } private void Awake() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown Instance = this; string text = Path.Combine(Paths.ConfigPath, "GlitnirRaces"); Directory.CreateDirectory(text); MainConfigFile = new ConfigFile(Path.Combine(text, "GlitnirRaces.cfg"), true); TextConfigFile = new ConfigFile(Path.Combine(text, "GlitnirRaces.Translation.cfg"), true); SynchronizationManager.Instance.RegisterCustomConfig(MainConfigFile); SynchronizationManager.Instance.RegisterCustomConfig(TextConfigFile); try { CreateTextConfigs(); CreateRaceConfigs(); MainConfigFile.Save(); TextConfigFile.Save(); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"[GlitnirRaces] ERRO CRÍTICO ao criar as configs/traduções: {arg}"); } EyeGlowPeak = SyncedConfig("0 - Geral", "BrilhoOlho", 1f, "Intensidade do brilho do olho (emissão), igual pra todas as raças. IMPORTANTE: valores acima de 1.0 estouram em branco em cores com mais de um canal forte (ex: lilás, roxo-avermelhado) quando o Bloom está desligado — só cores 100% puras num canal só (vermelho/verde/azul puro) escapam disso. 1.0 é o teto seguro que nunca estoura, com ou sem Bloom."); EmoteOnTransform = SyncedConfig("0 - Geral", "EmoteAoTransformar", value: true, "Toca o emote 'Despair' automaticamente sempre que o player troca de raça."); FillVitalsOnTransform = SyncedConfig("0 - Geral", "EncherAoTransformar", value: true, "Enche vida/stamina/eitr até o novo limite (com bônus da raça) assim que o player troca de raça."); RacialAbilitiesEnabled = SyncedConfig("0 - Geral", "HabilidadesRaciaisAtivas", value: true, "Interruptor geral: desliga TODAS as habilidades raciais especiais de uma vez (Fúria de Sangue, Aura de Cura, Postura de Ferro, Segundo Fôlego), sem precisar mexer raça por raça. Os atributos normais (vida, dano, resistência, etc) continuam funcionando normal."); AltarSwitchCostItem = SyncedConfig("0 - Geral", "AltarCustoItem", "Coins", "Nome do item (prefab) cobrado no Altar das Raças pra trocar de raça depois da primeira escolha."); AltarSwitchCostAmount = SyncedConfig("0 - Geral", "AltarCustoQuantidade", 50, "Quantidade do item acima cobrada pra trocar de raça no Altar das Raças."); AltarRecipe = SyncedConfig("0 - Geral", "AltarReceita", "Wood:10,Stone:5", "Custo pra CONSTRUIR o Altar das Raças (no Martelo), formato 'Item:Quantidade,Item:Quantidade'. Ex: 'Wood:10,Stone:5'."); SynchronizationManager.OnConfigurationSynchronized += OnConfigurationSynchronized; if (!IsHeadless()) { LoadAssets(); PrefabManager.OnVanillaPrefabsAvailable += FixEarMockReferencesOnce; } AltarPrefab = LoadPrefabFromEmbedded("altar_racas"); RegisterAltarPiece(); RegisterCommands(); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Glitnir Races 1.0.0 carregado!"); try { string location = Assembly.GetExecutingAssembly().Location; ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[GlitnirRaces] DLL compilada em: {File.GetLastWriteTime(location):dd/MM/yyyy HH:mm:ss}"); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[GlitnirRaces] Não consegui checar data da DLL: " + ex.Message)); } try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; if (!string.IsNullOrWhiteSpace(configFilePath) && File.Exists(configFilePath)) { File.Delete(configFilePath); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[GlitnirRaces] .cfg padrão vazio (fora da pasta GlitnirRaces) removido."); } } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[GlitnirRaces] Não consegui remover o .cfg padrão vazio: " + ex2.Message)); } } private void OnDestroy() { SynchronizationManager.OnConfigurationSynchronized -= OnConfigurationSynchronized; PrefabManager.OnVanillaPrefabsAvailable -= FixEarMockReferencesOnce; harmony.UnpatchSelf(); } private void FixEarMockReferencesOnce() { PrefabManager.OnVanillaPrefabsAvailable -= FixEarMockReferencesOnce; int num = 0; GameObject[] array = (GameObject[])(object)new GameObject[6] { ElfEarsMalePrefab, ElfEarsFemalePrefab, OrcEarsMalePrefab, OrcEarsFemalePrefab, OrcTuskPrefab, HighElfEyesPrefab }; foreach (GameObject val in array) { if (!((Object)(object)val == (Object)null)) { try { PrefabExtension.FixReferences(val); num++; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[GlitnirRaces] Falha ao resolver mock references de '" + ((Object)val).name + "': " + ex.Message)); } } } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[GlitnirRaces] Mock references resolvidas em {num} prefab(s) de orelha/olho/presa."); } private void Update() { //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) RegisterRpcIfNeeded(); if ((Object)(object)ZNet.instance != (Object)null) { adminCacheTimer += Time.deltaTime; if (adminCacheTimer >= 10f) { adminCacheTimer = 0f; RefreshAdminCache(); } } if (!IsHeadless()) { syncTimer += Time.deltaTime; if (syncTimer >= 2f) { syncTimer = 0f; SyncLocalRace(); } localSaveTimer += Time.deltaTime; if (localSaveTimer >= 3f) { localSaveTimer = 0f; RestoreLocalSavedRaceIfNeeded(); } } if (IsSinglePlayer() && (Object)(object)Player.m_localPlayer != (Object)null) { configWatchTimer += Time.deltaTime; if (configWatchTimer >= 2f) { configWatchTimer = 0f; CheckConfigFileChanged(); } } timer += Time.deltaTime; if (timer < 0.6f) { return; } timer = 0f; if (IsHeadless()) { foreach (Player allPlayer in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null)) { ApplyRace(allPlayer); RegenerateBonusVitals(allPlayer, 0.6f); TickStillHealAura(allPlayer, 0.6f); TickSecondWind(allPlayer, 0.6f); } } return; } if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } Vector3 position = ((Component)Player.m_localPlayer).transform.position; float num = 3600f; foreach (Player allPlayer2 in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer2 == (Object)null) && (!((Object)(object)allPlayer2 != (Object)(object)Player.m_localPlayer) || !(Vector3.SqrMagnitude(((Component)allPlayer2).transform.position - position) > num))) { ApplyRace(allPlayer2); } } RegenerateBonusVitals(Player.m_localPlayer, 0.6f); TickStillHealAura(Player.m_localPlayer, 0.6f); TickSecondWind(Player.m_localPlayer, 0.6f); } private void CheckConfigFileChanged() { if (_isReloadingConfig) { return; } try { string configFilePath = MainConfigFile.ConfigFilePath; string configFilePath2 = TextConfigFile.ConfigFilePath; bool flag = !string.IsNullOrWhiteSpace(configFilePath) && File.Exists(configFilePath) && File.GetLastWriteTime(configFilePath) > _lastConfigWrite; bool flag2 = !string.IsNullOrWhiteSpace(configFilePath2) && File.Exists(configFilePath2) && File.GetLastWriteTime(configFilePath2) > _lastTextConfigWrite; if (!flag && !flag2) { return; } _isReloadingConfig = true; if (flag) { MainConfigFile.Reload(); } if (flag2) { TextConfigFile.Reload(); } NetworkRaces.Clear(); ZNetViewCache.Clear(); if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } foreach (Player allPlayer in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null)) { string visualKey = GetVisualKey(allPlayer); if (!string.IsNullOrWhiteSpace(visualKey)) { LastAppliedRace[visualKey] = ""; } InvalidateHeadCache(allPlayer); ApplyRaceWithDelays(allPlayer); } } ReRegisterSecretCodeCommands(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Config recarregado automaticamente."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Erro ao monitorar config: " + ex.Message)); } finally { try { string configFilePath3 = MainConfigFile.ConfigFilePath; if (!string.IsNullOrWhiteSpace(configFilePath3) && File.Exists(configFilePath3)) { _lastConfigWrite = File.GetLastWriteTime(configFilePath3); } string configFilePath4 = TextConfigFile.ConfigFilePath; if (!string.IsNullOrWhiteSpace(configFilePath4) && File.Exists(configFilePath4)) { _lastTextConfigWrite = File.GetLastWriteTime(configFilePath4); } } catch { } _isReloadingConfig = false; } } private static void RefreshAdminCache() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null) { return; } KnownAdmins.Clear(); try { foreach (PlayerInfo player in ZNet.instance.GetPlayerList()) { ZDOID characterID = player.m_characterID; if (IsAdminById(((ZDOID)(ref characterID)).UserID)) { HashSet knownAdmins = KnownAdmins; characterID = player.m_characterID; knownAdmins.Add(((ZDOID)(ref characterID)).UserID); } } } catch { } } private static bool IsAdminById(long userId) { if ((Object)(object)ZNet.instance == (Object)null) { return false; } try { if (ZNet.instance.IsAdmin(userId.ToString())) { return true; } ulong num = (ulong)userId; return ZNet.instance.IsAdmin(num.ToString()); } catch { return false; } } public static bool HasDevCommands() { if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)ZNet.instance != (Object)null) { try { long playerID = Player.m_localPlayer.GetPlayerID(); if (playerID != 0L && (KnownAdmins.Contains(playerID) || IsAdminById(playerID))) { return true; } } catch { } } return GetStaticBool("Terminal", "m_cheat") || GetStaticBool("Console", "m_cheat") || GetStaticBool("Terminal", "m_devcommands") || GetStaticBool("Console", "m_devcommands"); } private static bool GetStaticBool(string typeName, string fieldName) { try { Type type = AccessTools.TypeByName(typeName); if (type == null) { return false; } FieldInfo fieldInfo = AccessTools.Field(type, fieldName); if (fieldInfo == null) { return false; } object value = fieldInfo.GetValue(null); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } public static void TickStillHealAura(Player p, float dt) { //IL_0082: 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) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null || !RacialAbilitiesEnabled.Value || !TryGetRaceConfig(p, out var cfg) || cfg.StillHealAura == null || !cfg.StillHealAura.Value || (cfg.StillHealDayOnly.Value && IsNightSafe())) { return; } string visualKey = GetVisualKey(p); if (string.IsNullOrWhiteSpace(visualKey)) { return; } Vector3 position = ((Component)p).transform.position; if (!StillLastPos.TryGetValue(visualKey, out var value) || Vector3.Distance(position, value) > 0.2f) { StillLastPos[visualKey] = position; StillTimer[visualKey] = 0f; StillHealTimer[visualKey] = 0f; return; } StillTimer.TryGetValue(visualKey, out var value2); value2 += dt; StillTimer[visualKey] = value2; if (value2 < cfg.StillHealRequiredStillTime.Value) { return; } StillHealTimer.TryGetValue(visualKey, out var value3); value3 += dt; if (value3 < cfg.StillHealInterval.Value) { StillHealTimer[visualKey] = value3; return; } StillHealTimer[visualKey] = 0f; if (cfg.StillHealAmount.Value > 0f) { ((Character)p).Heal(cfg.StillHealAmount.Value, false); } } public static void TickSecondWind(Player p, float dt) { if ((Object)(object)p == (Object)null || !RacialAbilitiesEnabled.Value || !TryGetRaceConfig(p, out var cfg) || cfg.SecondWindEnabled == null || !cfg.SecondWindEnabled.Value) { return; } string visualKey = GetVisualKey(p); if (string.IsNullOrWhiteSpace(visualKey)) { return; } SecondWindCooldownTimer.TryGetValue(visualKey, out var value); if (value > 0f) { SecondWindCooldownTimer[visualKey] = Mathf.Max(0f, value - dt); } else if (!(((Character)p).GetMaxHealth() <= 0f) && !(((Character)p).GetHealth() / ((Character)p).GetMaxHealth() > cfg.SecondWindThreshold.Value)) { if (cfg.SecondWindHealAmount.Value > 0f) { ((Character)p).Heal(cfg.SecondWindHealAmount.Value, false); } if (cfg.SecondWindStaminaAmount.Value > 0f) { ((Character)p).AddStamina(cfg.SecondWindStaminaAmount.Value); } SecondWindCooldownTimer[visualKey] = cfg.SecondWindCooldown.Value; } } private static bool IsNightSafe() { try { return EnvMan.IsNight(); } catch (Exception ex) { if (!_envNightWarningLogged) { _envNightWarningLogged = true; GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("[GlitnirRaces] EnvMan.IsNight() falhou (só avisando uma vez): " + ex.Message)); } } return false; } } private static bool TryGetRaceConfig(Player p, out RaceConfig cfg) { cfg = null; if ((Object)(object)p == (Object)null) { return false; } string race = GetRace(p); if (string.IsNullOrWhiteSpace(race)) { return false; } return Races.TryGetValue(race, out cfg); } public static void RegenerateBonusVitals(Player p, float dt) { if (!((Object)(object)p == (Object)null) && TryGetRaceConfig(p, out var cfg)) { TickBonusRegen(((Character)p).GetHealth(), ((Character)p).GetMaxHealth(), cfg.HealthBonus.Value, dt, delegate(float amount) { ((Character)p).Heal(amount, false); }); TickBonusRegen(p.GetStamina(), ((Character)p).GetMaxStamina(), cfg.StaminaBonus.Value, dt, delegate(float amount) { ((Character)p).AddStamina(amount); }); TickBonusRegen(p.GetEitr(), ((Character)p).GetMaxEitr(), cfg.EitrBonus.Value, dt, delegate(float amount) { ((Character)p).AddEitr(amount); }); } } private static void TickBonusRegen(float current, float max, float bonus, float dt, Action apply) { if (bonus <= 0f) { return; } float num = max - current; if (!(num <= 0f) && !(num > bonus + 0.1f)) { float num2 = Mathf.Min(num, bonus / 30f * dt); if (num2 > 0f) { apply(num2); } } } public static void TopOffVitals(Player p) { if ((Object)(object)p == (Object)null || FillVitalsOnTransform == null || !FillVitalsOnTransform.Value) { return; } try { ((Character)p).SetHealth(((Character)p).GetMaxHealth()); float num = ((Character)p).GetMaxStamina() - p.GetStamina(); if (num > 0f) { ((Character)p).AddStamina(num); } float num2 = ((Character)p).GetMaxEitr() - p.GetEitr(); if (num2 > 0f) { ((Character)p).AddEitr(num2); } } catch (Exception ex) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("Falha ao encher vida/stamina/eitr após transformação: " + ex.Message)); } } } private static Dictionary ParseResistances(string value) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); if (string.IsNullOrWhiteSpace(value)) { return dictionary; } string[] array = value.Split(new char[1] { ',' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ':' }); if (array2.Length == 2 && DamageTypeNames.TryGetValue(array2[0].Trim(), out var value2) && ModifierNames.TryGetValue(array2[1].Trim(), out var value3)) { dictionary[value2] = value3; } } return dictionary; } private static Dictionary ParseTypeMultipliers(string value) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); if (string.IsNullOrWhiteSpace(value)) { return dictionary; } string[] array = value.Split(new char[1] { ',' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ':' }); if (array2.Length == 2 && DamageTypeNames.TryGetValue(array2[0].Trim(), out var value2) && float.TryParse(array2[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { dictionary[value2] = result; } } return dictionary; } private static Dictionary ParseSkillMultipliers(string value) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); if (string.IsNullOrWhiteSpace(value)) { return dictionary; } string[] array = value.Split(new char[1] { ',' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ':' }); if (array2.Length == 2 && Enum.TryParse(array2[0].Trim(), ignoreCase: true, out SkillType result) && float.TryParse(array2[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { dictionary[result] = result2; } } return dictionary; } private static Character GetSEManOwner(SEMan seman) { if (seman == null) { return null; } if (_semanCharacterField == null) { _semanCharacterField = AccessTools.Field(typeof(SEMan), "m_character"); } object? obj = _semanCharacterField?.GetValue(seman); return (Character)((obj is Character) ? obj : null); } private static float GetStaminaCostModifier(RaceConfig cfg, string actionKey) { if (cfg == null || string.IsNullOrWhiteSpace(cfg.StaminaCostModifiers.Value)) { return 0f; } string[] array = cfg.StaminaCostModifiers.Value.Split(new char[1] { ',' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ':' }); if (array2.Length == 2 && array2[0].Trim().Equals(actionKey, StringComparison.OrdinalIgnoreCase) && float.TryParse(array2[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return result; } } return 0f; } private static void ForceSetZdoRace(Player player, string race) { if ((Object)(object)player == (Object)null) { return; } try { ZNetView cachedZNetView = GetCachedZNetView(player); if (!((Object)(object)cachedZNetView == (Object)null) && cachedZNetView.GetZDO() != null) { cachedZNetView.GetZDO().Set("GlitnirRace", race ?? ""); cachedZNetView.GetZDO().Set("GlitnirRaceVer", 1); } } catch { } } private static void ForceSetRaceVisualZdo(Player player, string race) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null) && !string.IsNullOrWhiteSpace(race)) { ForceSetZdoVector(player, "GlitnirRaceEarColor", GetCalculatedRaceEarColor(player, race)); if (RaceUsesForcedSkin(race)) { ForceSetZdoVector(player, "GlitnirRaceSkinColor", GetRaceSkinColor(race)); } } } private static void ForceSetZdoVector(Player player, string key, Vector3 value) { //IL_0051: 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) //IL_008b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || string.IsNullOrWhiteSpace(key)) { return; } try { ZNetView cachedZNetView = GetCachedZNetView(player); if (!((Object)(object)cachedZNetView == (Object)null) && cachedZNetView.GetZDO() != null) { cachedZNetView.GetZDO().Set(key + "_x", value.x); cachedZNetView.GetZDO().Set(key + "_y", value.y); cachedZNetView.GetZDO().Set(key + "_z", value.z); } } catch { } } private static string GetZdoRace(Player player) { if ((Object)(object)player == (Object)null) { return ""; } try { ZNetView cachedZNetView = GetCachedZNetView(player); if ((Object)(object)cachedZNetView == (Object)null || cachedZNetView.GetZDO() == null) { return ""; } ZDO zDO = cachedZNetView.GetZDO(); string text = zDO.GetString("GlitnirRace", ""); if (string.IsNullOrWhiteSpace(text)) { return ""; } int num = zDO.GetInt("GlitnirRaceVer", 0); if (num != 1) { zDO.Set("GlitnirRaceVer", 1); } return text; } catch { return ""; } } private static void SetZdoLocked(Player player, bool locked) { if ((Object)(object)player == (Object)null) { return; } try { ZNetView cachedZNetView = GetCachedZNetView(player); if (!((Object)(object)cachedZNetView == (Object)null) && cachedZNetView.GetZDO() != null) { cachedZNetView.GetZDO().Set("GlitnirRaceLocked", locked); } } catch { } } private static bool GetZdoLocked(Player player) { if ((Object)(object)player == (Object)null) { return false; } try { ZNetView cachedZNetView = GetCachedZNetView(player); if ((Object)(object)cachedZNetView == (Object)null || cachedZNetView.GetZDO() == null) { return false; } return cachedZNetView.GetZDO().GetBool("GlitnirRaceLocked", false); } catch { return false; } } private static Vector3 GetZdoVector(Player player, string key, Vector3 fallback) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || string.IsNullOrWhiteSpace(key)) { return fallback; } try { ZNetView cachedZNetView = GetCachedZNetView(player); if ((Object)(object)cachedZNetView == (Object)null || cachedZNetView.GetZDO() == null) { return fallback; } float num = cachedZNetView.GetZDO().GetFloat(key + "_x", fallback.x); float num2 = cachedZNetView.GetZDO().GetFloat(key + "_y", fallback.y); float num3 = cachedZNetView.GetZDO().GetFloat(key + "_z", fallback.z); return new Vector3(num, num2, num3); } catch { return fallback; } } private static string GetRace(Player player) { if ((Object)(object)player == (Object)null) { return ""; } long playerIdLong = GetPlayerIdLong(player); if (playerIdLong == 0) { return ""; } if (playerIdLong != 0L && NetworkRaces.TryGetValue(playerIdLong, out var value) && !string.IsNullOrWhiteSpace(value)) { return value; } string zdoRace = GetZdoRace(player); if (!string.IsNullOrWhiteSpace(zdoRace)) { NetworkRaces[playerIdLong] = zdoRace; } return zdoRace; } private bool SetRace(Player player, string race, bool lockPlayer, bool broadcast) { if ((Object)(object)player == (Object)null || !IsRaceEnabled(race)) { return false; } InvalidateHeadCache(player); long playerIdLong = GetPlayerIdLong(player); string visualKey = GetVisualKey(player); if (!IsHeadless()) { bool isApplyingRace = IsApplyingRace; IsApplyingRace = true; try { ResetHelmet(player); ResetSkin(player); } finally { IsApplyingRace = isApplyingRace; } } CleanPlayerVisualCaches(playerIdLong, visualKey); if (playerIdLong != 0) { NetworkRaces[playerIdLong] = race; } if (RaceUsesForcedSkin(race)) { CacheOriginalSkinIfNeeded(player); } ForceSetZdoRace(player, race); ForceSetRaceVisualZdo(player, race); if ((Object)(object)player == (Object)(object)Player.m_localPlayer) { SaveLocalRace(race, lockPlayer || IsPlayerLocked(player)); } if (lockPlayer) { SetZdoLocked(player, locked: true); } if (broadcast) { BroadcastRace(player, race); if ((Object)(object)player == (Object)(object)Player.m_localPlayer) { lastBroadcastRace = race; } } return true; } private void AdminSetRace(Player target, string race) { if ((Object)(object)target == (Object)null || !IsRaceEnabled(race)) { return; } long playerIdLong = GetPlayerIdLong(target); string visualKey = GetVisualKey(target); InvalidateHeadCache(target); if (playerIdLong != 0) { NetworkRaces.Remove(playerIdLong); } if (!string.IsNullOrWhiteSpace(visualKey)) { LastAppliedRace[visualKey] = ""; } if (!IsHeadless()) { bool isApplyingRace = IsApplyingRace; IsApplyingRace = true; try { ResetHelmet(target); ResetSkin(target); } finally { IsApplyingRace = isApplyingRace; } } CleanPlayerVisualCaches(playerIdLong, visualKey); if (playerIdLong != 0) { NetworkRaces[playerIdLong] = race; } ForceSetZdoRace(target, race); ForceSetRaceVisualZdo(target, race); if ((Object)(object)target == (Object)(object)Player.m_localPlayer) { SaveLocalRace(race, IsPlayerLocked(target)); } BroadcastRace(target, race); if ((Object)(object)target == (Object)(object)Player.m_localPlayer) { lastBroadcastRace = race; } ApplyRaceWithDelays(target); TopOffVitals(target); if (!IsHeadless()) { SpawnEffect(target); } if ((Object)(object)target == (Object)(object)Player.m_localPlayer) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)("[GlitnirRaces/Diag] Emote disparado via AdminSetRace (self) pra '" + target.GetPlayerName() + "'.")); } PlayTransformEmote(); } } private void AdminResetRace(Player target) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target == (Object)null) { return; } long playerIdLong = GetPlayerIdLong(target); string visualKey = GetVisualKey(target); if (playerIdLong != 0) { NetworkRaces.Remove(playerIdLong); } if (!string.IsNullOrWhiteSpace(visualKey)) { LastAppliedRace[visualKey] = ""; } try { InvalidateHeadCache(target); } catch { } int instanceID = ((Object)target).GetInstanceID(); if (ApplyRaceCoroutineGeneration.ContainsKey(instanceID)) { ApplyRaceCoroutineGeneration[instanceID]++; } try { ForceSetZdoRace(target, ""); } catch { } try { ForceSetZdoVector(target, "GlitnirRaceEarColor", InvalidColor); } catch { } try { ForceSetZdoVector(target, "GlitnirRaceSkinColor", InvalidColor); } catch { } if ((Object)(object)target == (Object)(object)Player.m_localPlayer) { lastBroadcastRace = null; } if (!IsHeadless()) { try { ResetHelmet(target); } catch { } try { ResetSkin(target); } catch { } } try { CleanPlayerVisualCaches(playerIdLong, visualKey); } catch { } try { ApplyScale(target, HumanScale); } catch { } if (!IsHeadless()) { try { Transform head = FindHead(((Component)target).transform, 0); RemoveElfEarsAnywhere(head); RemoveOrcEarsAnywhere(head); RemoveHeadAttachmentDirect(head, "HighElfEyes"); RemoveHeadAttachmentDirect(head, "OrcTusk"); } catch { } try { RemovePlayerAttachment(target, "JotunFreeze"); } catch { } } try { ApplyRaceWithDelays(target); } catch { } if (IsHeadless()) { return; } try { UpdateRaceStatusEffect(target, ""); } catch { } } private void ResetRace(Player player, bool broadcast) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null)) { long playerIdLong = GetPlayerIdLong(player); string visualKey = GetVisualKey(player); if (playerIdLong != 0) { NetworkRaces.Remove(playerIdLong); } if (!string.IsNullOrWhiteSpace(visualKey)) { LastAppliedRace[visualKey] = ""; } InvalidateHeadCache(player); int instanceID = ((Object)player).GetInstanceID(); if (ApplyRaceCoroutineGeneration.ContainsKey(instanceID)) { ApplyRaceCoroutineGeneration[instanceID]++; } ForceSetZdoRace(player, ""); SetZdoLocked(player, locked: false); ForceSetZdoVector(player, "GlitnirRaceEarColor", InvalidColor); ForceSetZdoVector(player, "GlitnirRaceSkinColor", InvalidColor); if ((Object)(object)player == (Object)(object)Player.m_localPlayer) { ClearLocalSavedRace(); lastBroadcastRace = null; } if (!IsHeadless()) { ResetHelmet(player); ResetSkin(player); } CleanPlayerVisualCaches(playerIdLong, visualKey); ApplyScale(player, HumanScale); if (!IsHeadless()) { Transform head = FindHead(((Component)player).transform, 0); RemoveElfEarsAnywhere(head); RemoveOrcEarsAnywhere(head); RemoveHeadAttachmentDirect(head, "HighElfEyes"); RemoveHeadAttachmentDirect(head, "OrcTusk"); RemovePlayerAttachment(player, "JotunFreeze"); } ApplyRaceWithDelays(player); if (!IsHeadless()) { UpdateRaceStatusEffect(player, ""); } if (broadcast) { BroadcastRace(player, ""); } } } private static void CleanPlayerVisualCaches(long playerIdL, string visualKey) { if (!string.IsNullOrWhiteSpace(visualKey)) { OriginalSkinColors.Remove(visualKey); LastSkinRefreshRequest.Remove(visualKey); } if (playerIdL != 0) { string key = playerIdL.ToString(); OriginalSkinColors.Remove(key); LastSkinRefreshRequest.Remove(key); } } private static bool IsPlayerLocked(Player player) { if ((Object)(object)player == (Object)null) { return false; } if (GetZdoLocked(player)) { return true; } if ((Object)(object)player == (Object)(object)Player.m_localPlayer && !IsClientConnectedToRemoteServer() && HasSavedLocalRaceLocked()) { return true; } return false; } private static Vector3 GetRaceEarColor(Player p, string race) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrWhiteSpace(race) && Races.TryGetValue(race, out var value)) { Vector3 val = ParseColorConfig(value.EarColor.Value, InvalidColor); if (val.x >= 0f) { return val; } } if (RaceUsesForcedSkin(race)) { return GetNetworkSkinColor(p, race); } return ((Object)(object)Instance != (Object)null) ? Instance.GetCurrentSkinVector(p) : Vector3.one; } private static Vector3 GetCalculatedRaceEarColor(Player p, string race) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0071: 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) //IL_0083: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrWhiteSpace(race) && Races.TryGetValue(race, out var value)) { Vector3 val = ParseColorConfig(value.EarColor.Value, InvalidColor); if (val.x >= 0f) { return val; } } if (RaceUsesForcedSkin(race)) { return GetRaceSkinColor(race); } return ((Object)(object)Instance != (Object)null) ? Instance.GetCurrentSkinVector(p) : Vector3.one; } private static Vector3 GetNetworkSkinColor(Player p, string race) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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) if (RaceUsesForcedSkin(race)) { return GetRaceSkinColor(race); } Vector3 zdoVector = GetZdoVector(p, "GlitnirRaceSkinColor", InvalidColor); if (zdoVector.x >= 0f) { return zdoVector; } return GetRaceSkinColor(race); } private static Color GetRaceEyeColor(string race) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_0072: Unknown result type (might be due to invalid IL or missing references) if (!Races.TryGetValue(race, out var value)) { return Color.red; } Vector3 val = ParseColorConfig(value.EyeColor.Value, new Vector3(1f, 0f, 0f)); return (Color)((val.x < 0f) ? Color.red : new Color(val.x, val.y, val.z, 1f)); } private static Sprite GetPlaceholderIcon() { if (_placeholderIconResolved) { return _placeholderIcon; } _placeholderIconResolved = true; _placeholderIcon = LoadIconFromEmbedded("race_icon.rgba"); if ((Object)(object)_placeholderIcon != (Object)null) { return _placeholderIcon; } string[] array = new string[5] { "TrophyNeck", "TrophyDeer", "TrophyGreyling", "Amber", "Feathers" }; try { string[] array2 = array; foreach (string text in array2) { ObjectDB instance = ObjectDB.instance; GameObject val = ((instance != null) ? instance.GetItemPrefab(text) : null); Sprite val2 = ((val != null) ? val.GetComponent() : null)?.m_itemData?.m_shared?.m_icons?.FirstOrDefault(); if ((Object)(object)val2 != (Object)null) { _placeholderIcon = val2; break; } } } catch (Exception ex) { GlitnirRacesPlugin instance2 = Instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Logger.LogWarning((object)("Falha ao buscar ícone de fallback pro status de raça: " + ex.Message)); } } return _placeholderIcon; } private static Sprite LoadIconFromEmbedded(string fileName) { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string x) => x.EndsWith(fileName)); if (text == null) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("Ícone embutido '" + fileName + "' não encontrado na DLL (verifique se foi adicionado como Embedded Resource).")); } return null; } using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { return null; } byte[] array; using (MemoryStream memoryStream = new MemoryStream()) { stream.CopyTo(memoryStream); array = memoryStream.ToArray(); } int num = 65536; if (array.Length != num) { GlitnirRacesPlugin instance2 = Instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Logger.LogWarning((object)$"Ícone '{fileName}' tem {array.Length} bytes, esperado {num} (RaceIconSize errado?)."); } return null; } Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false); val.LoadRawTextureData(array); val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } catch (Exception arg) { GlitnirRacesPlugin instance3 = Instance; if (instance3 != null) { ((BaseUnityPlugin)instance3).Logger.LogError((object)$"Erro ao carregar ícone '{fileName}': {arg}"); } return null; } } private static StatusEffect GetOrCreateRaceStatusEffect(string race) { if (RaceStatusEffects.TryGetValue(race, out var value) && (Object)(object)value != (Object)null) { return value; } if (!Races.TryGetValue(race, out var value2)) { return null; } StatusEffect val = ScriptableObject.CreateInstance(); ((Object)val).name = "GlitnirRace_" + race; val.m_name = Fmt(Text_StatNomeRaca.Value, Instance.GetRaceName(race)); val.m_icon = GetPlaceholderIcon(); val.m_tooltip = BuildTooltip(value2); RaceStatusEffects[race] = val; return val; } private unsafe static string GetDamageTypeLabel(DamageType type) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: 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_0008: Invalid comparison between Unknown and I4 //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Invalid comparison between Unknown and I4 //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Invalid comparison between Unknown and I4 //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected I4, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Invalid comparison between Unknown and I4 //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Invalid comparison between Unknown and I4 //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 DamageType val = type; DamageType val2 = val; if ((int)val2 <= 32) { if ((int)val2 <= 8) { switch (val2 - 1) { default: if ((int)val2 != 8) { break; } return Text_DanoChop.Value; case 0: return Text_DanoBlunt.Value; case 1: return Text_DanoSlash.Value; case 3: return Text_DanoPierce.Value; case 2: break; } } else { if ((int)val2 == 16) { return Text_DanoPickaxe.Value; } if ((int)val2 == 32) { return Text_DanoFire.Value; } } } else if ((int)val2 <= 128) { if ((int)val2 == 64) { return Text_DanoFrost.Value; } if ((int)val2 == 128) { return Text_DanoLightning.Value; } } else { if ((int)val2 == 256) { return Text_DanoPoison.Value; } if ((int)val2 == 512) { return Text_DanoSpirit.Value; } } return ((object)(*(DamageType*)(&type))/*cast due to .constrained prefix*/).ToString(); } private unsafe static string GetBiomeLabel(Biome biome) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: 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_0008: Invalid comparison between Unknown and I4 //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected I4, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Invalid comparison between Unknown and I4 //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Invalid comparison between Unknown and I4 //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 Biome val = biome; Biome val2 = val; if ((int)val2 <= 16) { switch (val2 - 1) { default: if ((int)val2 != 8) { if ((int)val2 != 16) { break; } return Text_BiomaPlains.Value; } return Text_BiomaBlackForest.Value; case 0: return Text_BiomaMeadows.Value; case 1: return Text_BiomaSwamp.Value; case 3: return Text_BiomaMountain.Value; case 2: break; } } else if ((int)val2 <= 64) { if ((int)val2 == 32) { return Text_BiomaAshLands.Value; } if ((int)val2 == 64) { return Text_BiomaDeepNorth.Value; } } else { if ((int)val2 == 256) { return Text_BiomaOcean.Value; } if ((int)val2 == 512) { return Text_BiomaMistlands.Value; } } return ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString(); } private static Dictionary ParseBiomeShiftsForTooltip(string value) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); if (string.IsNullOrWhiteSpace(value)) { return dictionary; } string[] array = value.Split(new char[1] { ',' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ':' }); if (array2.Length == 2 && Enum.TryParse(array2[0].Trim(), ignoreCase: true, out Biome result) && float.TryParse(array2[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { dictionary[result] = result2; } } return dictionary; } private static string BuildTooltip(RaceConfig cfg) { //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_051f: Unknown result type (might be due to invalid IL or missing references) //IL_05ff: Unknown result type (might be due to invalid IL or missing references) //IL_060d: Unknown result type (might be due to invalid IL or missing references) //IL_0613: Invalid comparison between Unknown and I4 //IL_062e: Unknown result type (might be due to invalid IL or missing references) //IL_0634: Invalid comparison between Unknown and I4 //IL_064f: Unknown result type (might be due to invalid IL or missing references) //IL_0655: Invalid comparison between Unknown and I4 //IL_0670: Unknown result type (might be due to invalid IL or missing references) //IL_0676: Invalid comparison between Unknown and I4 //IL_068e: Unknown result type (might be due to invalid IL or missing references) //IL_0694: Invalid comparison between Unknown and I4 //IL_06ac: Unknown result type (might be due to invalid IL or missing references) //IL_06b2: Invalid comparison between Unknown and I4 //IL_06ca: Unknown result type (might be due to invalid IL or missing references) //IL_06d0: Invalid comparison between Unknown and I4 //IL_06e8: Unknown result type (might be due to invalid IL or missing references) //IL_06ee: Invalid comparison between Unknown and I4 List parts = new List(); FlatStat(cfg.HealthBonus.Value, Text_StatVidaMaxima.Value); FlatStat(cfg.StaminaBonus.Value, Text_StatStaminaMaxima.Value); FlatStat(cfg.EitrBonus.Value, Text_StatEitrMaximo.Value); FlatStat(cfg.CarryWeightBonus.Value, Text_StatCapacidadeCarga.Value); PctStat(cfg.HealthRegenMultiplier.Value, Text_StatRegenVida.Value); PctStat(cfg.StaminaRegenMultiplier.Value, Text_StatRegenStamina.Value); PctStat(cfg.EitrRegenMultiplier.Value, Text_StatRegenEitr.Value); PctStat(cfg.DamageDoneMultiplier.Value, Text_StatDanoCausado.Value); Dictionary dictionary = ParseSkillMultipliers(cfg.SkillDamageMultipliers.Value); foreach (KeyValuePair item in dictionary) { float num = (item.Value - 1f) * 100f; if (!(Mathf.Abs(num) < 0.1f)) { Stat(Fmt(Text_StatDanoComSkill.Value, item.Key), string.Format("{0}{1:0}%", (num > 0f) ? "+" : "", num)); } } Dictionary dictionary2 = ParseTypeMultipliers(cfg.AttackDamageTypeMultipliers.Value); foreach (KeyValuePair item2 in dictionary2) { float num2 = (item2.Value - 1f) * 100f; if (!(Mathf.Abs(num2) < 0.1f)) { string damageTypeLabel = GetDamageTypeLabel(item2.Key); Stat(Fmt(Text_StatDanoTipo.Value, damageTypeLabel), string.Format("{0}{1:0}%", (num2 > 0f) ? "+" : "", num2)); } } if (cfg.BackstabMultiplier.Value != 1f) { float num3 = (cfg.BackstabMultiplier.Value - 1f) * 100f; Stat(Text_StatDanoAtaqueFurtivo.Value, $"+{num3:0}%"); } PctStat(cfg.KnockbackMultiplier.Value, Text_StatForcaEmpurrao.Value); float num4 = (1f - cfg.DamageTakenMultiplier.Value) * 100f; if (Mathf.Abs(num4) >= 0.1f) { Stat(Text_StatDanoRecebido.Value, string.Format("{0}{1:0}%", (num4 > 0f) ? "-" : "+", Mathf.Abs(num4))); } PctStat(cfg.SpeedMultiplier.Value, Text_StatVelocidade.Value); float num5 = (1f - cfg.StealthMultiplier.Value) * 100f; if (Mathf.Abs(num5) >= 0.1f) { Stat(Text_StatFurtividade.Value, string.Format("{0}{1:0}%", (num5 > 0f) ? "+" : "-", Mathf.Abs(num5))); } if (cfg.LifestealPercent.Value != 0f) { Stat(Text_StatRouboVida.Value, $"{cfg.LifestealPercent.Value * 100f:0}%"); } PctStat(cfg.XpGainMultiplier.Value, Text_StatGanhoXP.Value); if (cfg.NightOnlyBonuses.Value) { Stat(Text_StatRegenVelocidadeNoite.Value, Text_StatSoANoite.Value); } if (cfg.DayNightHealthShift.Value != 0f) { Stat(Text_StatVidaNoiteDia.Value, $"+{cfg.DayNightHealthShift.Value:0} / -{cfg.DayNightHealthShift.Value:0}"); } Dictionary dictionary3 = ParseBiomeShiftsForTooltip(cfg.BiomeHealthShifts.Value); foreach (KeyValuePair item3 in dictionary3) { if (item3.Value != 0f) { string biomeLabel = GetBiomeLabel(item3.Key); Stat(Fmt(Text_StatVidaBioma.Value, biomeLabel), string.Format("{0}{1:0}", (item3.Value > 0f) ? "+" : "", item3.Value)); } } if (cfg.HeatResistanceBonus.Value != 0f) { Stat(Text_StatFrioAmbiente.Value, Text_StatNaoCongela.Value); } Dictionary dictionary4 = ParseResistances(cfg.Resistances.Value); foreach (KeyValuePair item4 in dictionary4) { string damageTypeLabel2 = GetDamageTypeLabel(item4.Key); string value; if ((int)item4.Value == 3) { value = Text_NivelImune.Value; } else if ((int)item4.Value == 5) { value = Text_NivelMuitoResistente.Value; } else if ((int)item4.Value == 1) { value = Text_NivelResistente.Value; } else if ((int)item4.Value == 7) { value = Text_NivelLevementeResistente.Value; } else if ((int)item4.Value == 8) { value = Text_NivelLevementeFraco.Value; } else if ((int)item4.Value == 2) { value = Text_NivelFraco.Value; } else if ((int)item4.Value == 6) { value = Text_NivelMuitoFraco.Value; } else { if ((int)item4.Value != 4) { continue; } value = Text_NivelIgnora.Value; } parts.Add(Text_StatModificadorDano.Value + ": " + value + " VS " + damageTypeLabel2 + ""); } if (cfg.LowHealthThreshold != null && cfg.LowHealthThreshold.Value > 0f) { AbilityStat(Text_HabFuriaSangue.Value, Fmt(Text_HabFuriaSangueDesc.Value, (cfg.LowHealthDamageBonus.Value - 1f) * 100f, cfg.LowHealthThreshold.Value * 100f)); } if (cfg.StillHealAura != null && cfg.StillHealAura.Value) { AbilityStat(Text_HabAuraCura.Value, Fmt(Text_HabAuraCuraDesc.Value, cfg.StillHealAmount.Value, cfg.StillHealInterval.Value) + (cfg.StillHealDayOnly.Value ? Text_HabAuraCuraSoDeDia.Value : "")); } if (cfg.IronStanceEnabled != null && cfg.IronStanceEnabled.Value) { AbilityStat(Text_HabPosturaFerro.Value, Fmt(Text_HabPosturaFerroDesc.Value, cfg.IronStanceExtraDamageReduction.Value * 100f)); } if (cfg.SecondWindEnabled != null && cfg.SecondWindEnabled.Value) { AbilityStat(Text_HabSegundoFolego.Value, Fmt(Text_HabSegundoFolegoDesc.Value, cfg.SecondWindCooldown.Value, cfg.SecondWindThreshold.Value * 100f)); } return (parts.Count > 0) ? string.Join("\n", parts) : Text_StatSemBonus.Value; void AbilityStat(string label, string text) { parts.Add("" + label + ": " + text + ""); } void FlatStat(float num6, string label) { if (num6 != 0f) { Stat(label, string.Format("{0}{1:0}", (num6 > 0f) ? "+" : "", num6)); } } void PctStat(float multiplier, string label) { float num6 = (multiplier - 1f) * 100f; if (!(Mathf.Abs(num6) < 0.1f)) { Stat(label, string.Format("{0}{1:0}%", (num6 > 0f) ? "+" : "", num6)); } } void Stat(string label, string text) { parts.Add(label + ": " + text + ""); } } private static void UpdateRaceStatusEffect(Player p, string newRace) { if ((Object)(object)p == (Object)null) { return; } SEMan sEMan = ((Character)p).GetSEMan(); if (sEMan == null) { return; } try { foreach (StatusEffect value in RaceStatusEffects.Values) { if ((Object)(object)value != (Object)null && sEMan.HaveStatusEffect(value.NameHash())) { sEMan.RemoveStatusEffect(value, true); } } if (!string.IsNullOrWhiteSpace(newRace) && IsRaceEnabled(newRace)) { StatusEffect orCreateRaceStatusEffect = GetOrCreateRaceStatusEffect(newRace); if ((Object)(object)orCreateRaceStatusEffect != (Object)null) { sEMan.AddStatusEffect(orCreateRaceStatusEffect, true, 0, 0f); } } } catch (Exception ex) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("Falha ao atualizar status effect de raça: " + ex.Message)); } } } private void RegisterRpcIfNeeded() { if (ZRoutedRpc.instance != null && (!RpcRegistered || RegisteredRpcInstance != ZRoutedRpc.instance)) { RpcRegistered = true; RegisteredRpcInstance = ZRoutedRpc.instance; try { ZRoutedRpc.instance.Register("GlitnirRaces_SetRace", (Action)RPC_SetRace); ((BaseUnityPlugin)this).Logger.LogInfo((object)"RPC SetRace registrado."); } catch (ArgumentException) { } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Erro RPC SetRace: {arg}"); } try { ZRoutedRpc.instance.Register("GlitnirRaces_VersionCheck", (Action)RPC_VersionCheck); ((BaseUnityPlugin)this).Logger.LogInfo((object)"RPC VersionCheck registrado."); } catch (ArgumentException) { } catch (Exception arg2) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Erro RPC VersionCheck: {arg2}"); } try { ZRoutedRpc.instance.Register("GlitnirRaces_AdminSetRaceRequest", (Action)RPC_AdminSetRaceRequest); ((BaseUnityPlugin)this).Logger.LogInfo((object)"RPC AdminSetRaceRequest registrado."); } catch (ArgumentException) { } catch (Exception arg3) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Erro RPC AdminSetRaceRequest: {arg3}"); } RefreshAdminCache(); } } private static void RPC_VersionCheck(long sender, string remoteVersion) { bool flag = (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer(); bool flag2 = remoteVersion != "1.0.0"; if (flag) { try { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { instance.InvokeRoutedRPC(sender, "GlitnirRaces_VersionCheck", new object[1] { "1.0.0" }); } } catch (Exception ex) { GlitnirRacesPlugin instance2 = Instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Logger.LogWarning((object)("[GlitnirRaces] Falha ao responder VersionCheck: " + ex.Message)); } } if (flag2) { GlitnirRacesPlugin instance3 = Instance; if (instance3 != null) { ((BaseUnityPlugin)instance3).Logger.LogWarning((object)string.Format("[GlitnirRaces] Peer {0} conectou com versão do mod diferente: {1} (servidor: {2}).", sender, remoteVersion, "1.0.0")); } } } else if (flag2) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, Fmt(Text_VersaoDiferente.Value, "1.0.0", remoteVersion), 0, (Sprite)null); } GlitnirRacesPlugin instance4 = Instance; if (instance4 != null) { ((BaseUnityPlugin)instance4).Logger.LogWarning((object)("[GlitnirRaces] Versão do mod diferente do servidor! Local=1.0.0, Servidor=" + remoteVersion + ".")); } } } private static void RPC_AdminSetRaceRequest(long sender, long playerId, string race) { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || playerId == 0) { return; } if (sender != playerId && !IsAdminById(sender)) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)$"[GlitnirRaces] AdminSetRaceRequest rejeitado: sender={sender} não é admin, tentando mudar playerId={playerId}."); } return; } try { ZRoutedRpc instance2 = ZRoutedRpc.instance; if (instance2 != null) { instance2.InvokeRoutedRPC(ZRoutedRpc.Everybody, "GlitnirRaces_SetRace", new object[2] { playerId, race ?? "" }); } } catch (Exception ex) { GlitnirRacesPlugin instance3 = Instance; if (instance3 != null) { ((BaseUnityPlugin)instance3).Logger.LogWarning((object)("[GlitnirRaces] Falha ao repassar AdminSetRaceRequest: " + ex.Message)); } } } private static void RPC_SetRace(long sender, long playerId, string race) { if (playerId == 0) { return; } if (!IsRpcSenderAuthorized(sender, playerId)) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)$"RPC_SetRace rejeitado: sender={sender} → playerId={playerId}"); } return; } Player val = FindPlayerById(playerId); if (string.IsNullOrWhiteSpace(race)) { NetworkRaces.Remove(playerId); if ((Object)(object)val != (Object)null && (Object)(object)Instance != (Object)null) { Instance.AdminResetRace(val); } return; } string value; string text = (NetworkRaces.TryGetValue(playerId, out value) ? value : (((Object)(object)val != (Object)null) ? GetZdoRace(val) : "")); bool flag = text != race; NetworkRaces[playerId] = race; if (!((Object)(object)val != (Object)null) || !((Object)(object)Instance != (Object)null)) { return; } ForceSetZdoRace(val, race); ForceSetRaceVisualZdo(val, race); if ((Object)(object)val == (Object)(object)Player.m_localPlayer) { SaveLocalRace(race, locked: true); if (flag) { PlayTransformEmote(); } } Instance.ApplyRaceWithDelays(val); } private static bool IsRpcSenderAuthorized(long sender, long playerId) { if (ZRoutedRpc.instance == null) { return true; } try { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { return true; } } catch { } if (sender == playerId) { return true; } if (sender == GetServerPeerId()) { return true; } return false; } private static void SendVersionCheckToServer() { try { if (ZRoutedRpc.instance != null && (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsServer())) { long serverPeerId = GetServerPeerId(); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerId, "GlitnirRaces_VersionCheck", new object[1] { "1.0.0" }); } } catch (Exception ex) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("[GlitnirRaces] Falha ao enviar VersionCheck: " + ex.Message)); } } } private static void BroadcastRace(Player player, string race) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || ZRoutedRpc.instance == null) { return; } long playerIdLong = GetPlayerIdLong(player); if (playerIdLong != 0) { if (string.IsNullOrWhiteSpace(race)) { NetworkRaces.Remove(playerIdLong); ForceSetZdoRace(player, ""); SetZdoLocked(player, locked: false); ForceSetZdoVector(player, "GlitnirRaceEarColor", InvalidColor); ForceSetZdoVector(player, "GlitnirRaceSkinColor", InvalidColor); } else { NetworkRaces[playerIdLong] = race; ForceSetZdoRace(player, race); ForceSetRaceVisualZdo(player, race); } bool flag = (Object)(object)player == (Object)(object)Player.m_localPlayer; bool flag2 = (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer(); if (flag || flag2) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "GlitnirRaces_SetRace", new object[2] { playerIdLong, race ?? "" }); } else { long serverPeerId = GetServerPeerId(); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerId, "GlitnirRaces_AdminSetRaceRequest", new object[2] { playerIdLong, race ?? "" }); } } } private void SyncLocalRace() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { string race = GetRace(localPlayer); if (!string.IsNullOrWhiteSpace(race) && !(race == lastBroadcastRace)) { lastBroadcastRace = race; BroadcastRace(localPlayer, race); } } } private static Player FindPlayerById(long playerId) { if (playerId == 0) { return null; } return ((IEnumerable)Player.GetAllPlayers()).FirstOrDefault((Func)((Player p) => (Object)(object)p != (Object)null && GetPlayerIdLong(p) == playerId)); } private static long GetServerPeerId() { if (ZRoutedRpc.instance == null) { return ZRoutedRpc.Everybody; } try { MethodInfo method = typeof(ZRoutedRpc).GetMethod("GetServerPeerID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { return (long)method.Invoke(ZRoutedRpc.instance, null); } } catch { } try { FieldInfo field = typeof(ZRoutedRpc).GetField("m_serverPeerID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { long num = (long)field.GetValue(ZRoutedRpc.instance); if (num != 0) { return num; } } } catch { } return ZRoutedRpc.Everybody; } private static void OnPeerDisconnected(long peerId) { if (peerId == 0) { return; } Player val = FindPlayerById(peerId); if ((Object)(object)val == (Object)null) { val = ((IEnumerable)Player.GetAllPlayers()).FirstOrDefault((Func)delegate(Player p) { if (!((Object)(object)p == (Object)null)) { try { ZNetView cachedZNetView = GetCachedZNetView(p); return (Object)(object)cachedZNetView != (Object)null && cachedZNetView.GetZDO() != null && ((ZDOID)(ref cachedZNetView.GetZDO().m_uid)).UserID == peerId; } catch { return false; } } return false; }); } long num = (((Object)(object)val != (Object)null) ? GetPlayerIdLong(val) : peerId); string text = (((Object)(object)val != (Object)null) ? GetVisualKey(val) : peerId.ToString()); NetworkRaces.Remove(num); if (num != peerId) { NetworkRaces.Remove(peerId); } if (!string.IsNullOrWhiteSpace(text)) { LastAppliedRace.Remove(text); OriginalSkinColors.Remove(text); LastSkinRefreshRequest.Remove(text); } KnownAdmins.Remove(peerId); PendingAltarSwitch.Remove(num); if (num != peerId) { PendingAltarSwitch.Remove(peerId); } if ((Object)(object)val != (Object)null) { int instanceID = ((Object)val).GetInstanceID(); InvalidateHeadCache(val); ApplyRaceCoroutineGeneration.Remove(instanceID); ZNetViewCache.Remove(instanceID); } GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)$"Caches limpos para peer {peerId} (playerID={num}) ao desconectar."); } } private void CreateTextConfigs() { Text_AltarNome = TextConfig("Translation - Altar", "AltarNome", "Altar das Raças"); Text_AltarDescricao = TextConfig("Translation - Altar", "AltarDescricao", "Escolha sua raça. Só pode ser usado uma vez por personagem."); Text_AltarHoverEscolher = TextConfig("Translation - Altar", "AltarHoverEscolher", "[E] Escolher raça"); Text_AltarHoverTrocar = TextConfig("Translation - Altar", "AltarHoverTrocar", "[E] Trocar de raça"); Text_AltarJaEscolheu = TextConfig("Translation - Altar", "AltarJaEscolheu", "Você já escolheu sua raça."); Text_UiEscolhaTitulo = TextConfig("Translation - Altar", "UiEscolhaTitulo", "Escolha sua raça"); Text_UiFechar = TextConfig("Translation - Altar", "UiFechar", "Fechar"); Text_UiTrocarBotao = TextConfig("Translation - Altar", "UiTrocarBotao", "Trocar ({0} {1})"); Text_UiJaEscolheuTitulo = TextConfig("Translation - Altar", "UiJaEscolheuTitulo", "Você já escolheu sua raça"); Text_UiMoedaInsuficiente = TextConfig("Translation - Altar", "UiMoedaInsuficiente", "Você precisa de {0}x {1} pra trocar de raça."); Text_RaceName_Orc = TextConfig("Translation - Nomes de Raca", "NomeOrc", "Orc"); Text_RaceName_Elf = TextConfig("Translation - Nomes de Raca", "NomeElfo", "Elfo"); Text_RaceName_Dwarf = TextConfig("Translation - Nomes de Raca", "NomeAnao", "Anão"); Text_RaceName_Human = TextConfig("Translation - Nomes de Raca", "NomeHumano", "Humano"); Text_SemPermissao = TextConfig("Translation - Comandos", "SemPermissao", "Ops! você não pode fazer isso!"); Text_UsoRaca = TextConfig("Translation - Comandos", "UsoRaca", "Uso: {0} me ou {0} NomeDoPlayer"); Text_RacaDesativadaAdmin = TextConfig("Translation - Comandos", "RacaDesativadaAdmin", "A raça {0} está desativada."); Text_PlayerNaoEncontrado = TextConfig("Translation - Comandos", "PlayerNaoEncontrado", "Player não encontrado."); Text_PlayerNaoCarregado = TextConfig("Translation - Comandos", "PlayerNaoCarregado", "Erro: {0} ainda não carregou no mundo. Aguarde e tente novamente."); Text_AgoraERaca = TextConfig("Translation - Comandos", "AgoraERaca", "{0} agora é {1}."); Text_RacaRemovida = TextConfig("Translation - Comandos", "RacaRemovida", "Raça de {0} removida!"); Text_UsoOfflineReset = TextConfig("Translation - Comandos", "UsoOfflineReset", "Uso: glitnir_reset_offline "); Text_IdInvalido = TextConfig("Translation - Comandos", "IdInvalido", "ID inválido."); Text_OfflineResetado = TextConfig("Translation - Comandos", "OfflineResetado", "Player offline resetado."); Text_OfflineNaoEncontrado = TextConfig("Translation - Comandos", "OfflineNaoEncontrado", "Player não encontrado no mundo."); Text_EssaRacaDesativada = TextConfig("Translation - Comandos", "EssaRacaDesativada", "Essa raça está desativada."); Text_AgoraEuSou = TextConfig("Translation - Comandos", "AgoraEuSou", "Agora eu sou: {0}!"); Text_ConfigRecarregado = TextConfig("Translation - Comandos", "ConfigRecarregado", "Config e codigos recarregados!"); Text_CodigosSecretosAtivos = TextConfig("Translation - Comandos", "CodigosSecretosAtivos", "Codigos secretos ativos:"); Text_VersaoDiferente = TextConfig("Translation - Comandos", "VersaoDiferente", "Aviso: sua versão do GlitnirRaces ({0}) é diferente da do servidor ({1}). Pode causar bugs — atualize o mod."); Text_StatNomeRaca = TextConfig("Translation - Tooltip Geral", "StatNomeRaca", "Raça: {0}"); Text_StatVidaMaxima = TextConfig("Translation - Tooltip Geral", "StatVidaMaxima", "Vida Máxima"); Text_StatStaminaMaxima = TextConfig("Translation - Tooltip Geral", "StatStaminaMaxima", "Stamina Máxima"); Text_StatEitrMaximo = TextConfig("Translation - Tooltip Geral", "StatEitrMaximo", "Eitr Máximo"); Text_StatCapacidadeCarga = TextConfig("Translation - Tooltip Geral", "StatCapacidadeCarga", "Capacidade de Carga"); Text_StatRegenVida = TextConfig("Translation - Tooltip Geral", "StatRegenVida", "Regeneração de Vida"); Text_StatRegenStamina = TextConfig("Translation - Tooltip Geral", "StatRegenStamina", "Regeneração de Stamina"); Text_StatRegenEitr = TextConfig("Translation - Tooltip Geral", "StatRegenEitr", "Regeneração de Eitr"); Text_StatDanoCausado = TextConfig("Translation - Tooltip Geral", "StatDanoCausado", "Dano Causado"); Text_StatDanoComSkill = TextConfig("Translation - Tooltip Geral", "StatDanoComSkill", "Dano com {0}"); Text_StatDanoTipo = TextConfig("Translation - Tooltip Geral", "StatDanoTipo", "Dano {0}"); Text_StatDanoAtaqueFurtivo = TextConfig("Translation - Tooltip Geral", "StatDanoAtaqueFurtivo", "Dano de Ataque Furtivo"); Text_StatForcaEmpurrao = TextConfig("Translation - Tooltip Geral", "StatForcaEmpurrao", "Força de Empurrão"); Text_StatDanoRecebido = TextConfig("Translation - Tooltip Geral", "StatDanoRecebido", "Dano Recebido"); Text_StatVelocidade = TextConfig("Translation - Tooltip Geral", "StatVelocidade", "Velocidade de Movimento"); Text_StatFurtividade = TextConfig("Translation - Tooltip Geral", "StatFurtividade", "Furtividade"); Text_StatRouboVida = TextConfig("Translation - Tooltip Geral", "StatRouboVida", "Roubo de Vida"); Text_StatGanhoXP = TextConfig("Translation - Tooltip Geral", "StatGanhoXP", "Ganho de XP em Skills"); Text_StatRegenVelocidadeNoite = TextConfig("Translation - Tooltip Geral", "StatRegenVelocidadeNoite", "Regen. e Velocidade"); Text_StatSoANoite = TextConfig("Translation - Tooltip Geral", "StatSoANoite", "só à noite"); Text_StatVidaNoiteDia = TextConfig("Translation - Tooltip Geral", "StatVidaNoiteDia", "Vida (noite / dia)"); Text_StatVidaBioma = TextConfig("Translation - Tooltip Geral", "StatVidaBioma", "Vida em {0}"); Text_StatFrioAmbiente = TextConfig("Translation - Tooltip Geral", "StatFrioAmbiente", "Frio Ambiente"); Text_StatNaoCongela = TextConfig("Translation - Tooltip Geral", "StatNaoCongela", "Não Congela"); Text_StatModificadorDano = TextConfig("Translation - Tooltip Geral", "StatModificadorDano", "Modificador de Dano"); Text_StatSemBonus = TextConfig("Translation - Tooltip Geral", "StatSemBonus", "Sem bônus de atributos."); Text_NivelImune = TextConfig("Translation - Tooltip Niveis", "NivelImune", "Imune"); Text_NivelMuitoResistente = TextConfig("Translation - Tooltip Niveis", "NivelMuitoResistente", "Muito Resistente"); Text_NivelResistente = TextConfig("Translation - Tooltip Niveis", "NivelResistente", "Resistente"); Text_NivelLevementeResistente = TextConfig("Translation - Tooltip Niveis", "NivelLevementeResistente", "Levemente Resistente"); Text_NivelLevementeFraco = TextConfig("Translation - Tooltip Niveis", "NivelLevementeFraco", "Levemente Fraco"); Text_NivelFraco = TextConfig("Translation - Tooltip Niveis", "NivelFraco", "Fraco"); Text_NivelMuitoFraco = TextConfig("Translation - Tooltip Niveis", "NivelMuitoFraco", "Muito Fraco"); Text_NivelIgnora = TextConfig("Translation - Tooltip Niveis", "NivelIgnora", "Ignora"); Text_DanoBlunt = TextConfig("Translation - Tooltip Tipos de Dano", "DanoBlunt", "Concussão"); Text_DanoSlash = TextConfig("Translation - Tooltip Tipos de Dano", "DanoSlash", "Corte"); Text_DanoPierce = TextConfig("Translation - Tooltip Tipos de Dano", "DanoPierce", "Perfuração"); Text_DanoChop = TextConfig("Translation - Tooltip Tipos de Dano", "DanoChop", "Corte de Machado"); Text_DanoPickaxe = TextConfig("Translation - Tooltip Tipos de Dano", "DanoPickaxe", "Picareta"); Text_DanoFire = TextConfig("Translation - Tooltip Tipos de Dano", "DanoFire", "Fogo"); Text_DanoFrost = TextConfig("Translation - Tooltip Tipos de Dano", "DanoFrost", "Gelo"); Text_DanoLightning = TextConfig("Translation - Tooltip Tipos de Dano", "DanoLightning", "Raio"); Text_DanoPoison = TextConfig("Translation - Tooltip Tipos de Dano", "DanoPoison", "Veneno"); Text_DanoSpirit = TextConfig("Translation - Tooltip Tipos de Dano", "DanoSpirit", "Espírito"); Text_BiomaMeadows = TextConfig("Translation - Tooltip Biomas", "BiomaMeadows", "Prado"); Text_BiomaBlackForest = TextConfig("Translation - Tooltip Biomas", "BiomaBlackForest", "Floresta Negra"); Text_BiomaSwamp = TextConfig("Translation - Tooltip Biomas", "BiomaSwamp", "Pântano"); Text_BiomaMountain = TextConfig("Translation - Tooltip Biomas", "BiomaMountain", "Montanha"); Text_BiomaPlains = TextConfig("Translation - Tooltip Biomas", "BiomaPlains", "Planície"); Text_BiomaMistlands = TextConfig("Translation - Tooltip Biomas", "BiomaMistlands", "Terras Nubladas"); Text_BiomaAshLands = TextConfig("Translation - Tooltip Biomas", "BiomaAshLands", "Terras Cinzentas"); Text_BiomaDeepNorth = TextConfig("Translation - Tooltip Biomas", "BiomaDeepNorth", "Norte Profundo"); Text_BiomaOcean = TextConfig("Translation - Tooltip Biomas", "BiomaOcean", "Oceano"); Text_HabFuriaSangue = TextConfig("Translation - Tooltip Habilidades", "HabFuriaSangue", "Fúria de Sangue"); Text_HabFuriaSangueDesc = TextConfig("Translation - Tooltip Habilidades", "HabFuriaSangueDesc", "+{0}% Dano abaixo de {1}% Vida"); Text_HabAuraCura = TextConfig("Translation - Tooltip Habilidades", "HabAuraCura", "Aura de Cura"); Text_HabAuraCuraDesc = TextConfig("Translation - Tooltip Habilidades", "HabAuraCuraDesc", "+{0} Vida a cada {1}s parado"); Text_HabAuraCuraSoDeDia = TextConfig("Translation - Tooltip Habilidades", "HabAuraCuraSoDeDia", " (só de dia)"); Text_HabPosturaFerro = TextConfig("Translation - Tooltip Habilidades", "HabPosturaFerro", "Postura de Ferro"); Text_HabPosturaFerroDesc = TextConfig("Translation - Tooltip Habilidades", "HabPosturaFerroDesc", "-{0}% Dano e Sem Empurrão ao Bloquear"); Text_HabSegundoFolego = TextConfig("Translation - Tooltip Habilidades", "HabSegundoFolego", "Segundo Fôlego"); Text_HabSegundoFolegoDesc = TextConfig("Translation - Tooltip Habilidades", "HabSegundoFolegoDesc", "Recupera Vida/Stamina 1x a cada {0}s abaixo de {1}% Vida"); } private ConfigEntry TextConfig(string group, string name, string defaultValue) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown return TextConfigFile.Bind(group, name, defaultValue, new ConfigDescription("Texto exibido pro jogador. Pode traduzir/editar livremente — vale pra todo mundo no servidor.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); } public static string Fmt(string template, params object[] args) { if (string.IsNullOrEmpty(template)) { return template ?? ""; } try { return string.Format(template, args); } catch { return template; } } private void ApplySkin(Player p, Vector3 color) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) VisEquipment component = ((Component)p).GetComponent(); if (!((Object)(object)component == (Object)null)) { typeof(VisEquipment).GetMethod("SetSkinColor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(component, new object[1] { color }); } } private void ApplyHair(Player p, Vector3 color) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) VisEquipment component = ((Component)p).GetComponent(); if (!((Object)(object)component == (Object)null)) { typeof(VisEquipment).GetMethod("SetHairColor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(component, new object[1] { color }); } } private void CacheOriginalSkinIfNeeded(Player p) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)p == (Object)null)) { string visualKey = GetVisualKey(p); if (!string.IsNullOrWhiteSpace(visualKey) && !OriginalSkinColors.ContainsKey(visualKey)) { OriginalSkinColors[visualKey] = GetCurrentSkinVector(p); } } } private static void CacheOriginalSkinValue(Player p, Vector3 skin) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)p == (Object)null)) { string visualKey = GetVisualKey(p); if (!string.IsNullOrWhiteSpace(visualKey) && !OriginalSkinColors.ContainsKey(visualKey)) { OriginalSkinColors[visualKey] = skin; } } } private void ResetSkin(Player p) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)p == (Object)null)) { string visualKey = GetVisualKey(p); if (!string.IsNullOrWhiteSpace(visualKey) && OriginalSkinColors.TryGetValue(visualKey, out var value)) { ApplySkin(p, value); } } } private Vector3 GetCurrentSkinVector(Player p) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null) { return Vector3.one; } VisEquipment component = ((Component)p).GetComponent(); if ((Object)(object)component == (Object)null) { return Vector3.one; } try { FieldInfo field = typeof(VisEquipment).GetField("m_skinColor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.GetValue(component) is Vector3 result) { return result; } } catch { } return Vector3.one; } private void ApplyEarsDirect(Transform head, Color color, bool isFemale) { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) GameObject val = (isFemale ? ElfEarsFemalePrefab : ElfEarsMalePrefab); if ((Object)(object)head == (Object)null || (Object)(object)val == (Object)null) { if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Prefab elf_ears_" + (isFemale ? "f" : "m") + " não encontrado.")); } return; } Transform root = head.root; Transform val2 = root.Find("Ears"); if (!((Object)(object)val2 == (Object)null)) { return; } GameObject val3 = SkinnedAccessoryAttacher.Attach(val, root); if (!((Object)(object)val3 == (Object)null)) { ((Object)val3).name = "Ears"; StripItemComponents(val3); val2 = val3.transform; if (!ShareBodySkinMaterial(root, val2)) { FixEarMaterials(val2, forceStandardShader: false); ApplyColor(val2, color); } } } private bool IsPlayerFemale(Player p) { if ((Object)(object)p == (Object)null) { return false; } try { VisEquipment component = ((Component)p).GetComponent(); if ((Object)(object)component != (Object)null && ModelIndexField != null && ModelIndexField.GetValue(component) is int num) { return num == 1; } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[GlitnirRaces] Falha ao ler m_modelIndex: " + ex.Message)); } if (!_modelIndexFieldWarningLogged) { _modelIndexFieldWarningLogged = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)"[GlitnirRaces] Não consegui detectar o gênero do personagem (m_modelIndex). Usando orelha masculina como padrão. Rode 'checkmodel' com devcommands pra investigar."); } return false; } private void ApplyOrcEarsDirect(Transform head, Color color, bool isFemale) { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) GameObject val = (isFemale ? OrcEarsFemalePrefab : OrcEarsMalePrefab); if ((Object)(object)head == (Object)null || (Object)(object)val == (Object)null) { if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Prefab orc_ears_" + (isFemale ? "f" : "m") + " não encontrado.")); } return; } Transform root = head.root; Transform val2 = root.Find("OrcEars"); if (!((Object)(object)val2 == (Object)null)) { return; } GameObject val3 = SkinnedAccessoryAttacher.Attach(val, root); if (!((Object)(object)val3 == (Object)null)) { ((Object)val3).name = "OrcEars"; StripItemComponents(val3); val2 = val3.transform; if (!ShareBodySkinMaterial(root, val2)) { FixEarMaterials(val2, forceStandardShader: false); ApplyColor(val2, color); } } } private static bool ShareBodySkinMaterial(Transform playerRoot, Transform earTransform) { if ((Object)(object)playerRoot == (Object)null || (Object)(object)earTransform == (Object)null) { return false; } Material val = null; SkinnedMeshRenderer[] componentsInChildren = ((Component)playerRoot).GetComponentsInChildren(true); foreach (SkinnedMeshRenderer val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null || !string.Equals(((Object)((Component)val2).gameObject).name, "body", StringComparison.OrdinalIgnoreCase)) { continue; } Material[] sharedMaterials = ((Renderer)val2).sharedMaterials; foreach (Material val3 in sharedMaterials) { if ((Object)(object)val3 != (Object)null && ((Object)val3).name.StartsWith("PlayerMaterial")) { val = val3; break; } } if ((Object)(object)val != (Object)null) { break; } } if ((Object)(object)val == (Object)null) { return false; } SkinnedMeshRenderer[] componentsInChildren2 = ((Component)earTransform).GetComponentsInChildren(true); foreach (SkinnedMeshRenderer val4 in componentsInChildren2) { Material[] sharedMaterials2 = ((Renderer)val4).sharedMaterials; for (int l = 0; l < sharedMaterials2.Length; l++) { sharedMaterials2[l] = val; } ((Renderer)val4).sharedMaterials = sharedMaterials2; } return true; } private void ApplyOrcTuskDirect(Transform head) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)head == (Object)null || (Object)(object)OrcTuskPrefab == (Object)null) { if ((Object)(object)OrcTuskPrefab == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Prefab orc_tusk não encontrado."); } return; } Transform val = head.Find("OrcTusk"); if ((Object)(object)val == (Object)null) { GameObject val2 = Object.Instantiate(OrcTuskPrefab, head); ((Object)val2).name = "OrcTusk"; StripItemComponents(val2); FixEarMaterials(val2.transform); val = val2.transform; } val.localPosition = OrcTuskPosition; val.localRotation = Quaternion.Euler(OrcTuskRotation); val.localScale = OrcTuskScale; FixEarMaterials(val); } private void ApplyHighElfEyesDirect(Player p, Transform head) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)head == (Object)null) && !((Object)(object)HighElfEyesPrefab == (Object)null)) { Transform val = head.Find("HighElfEyes"); if ((Object)(object)val == (Object)null) { GameObject val2 = Object.Instantiate(HighElfEyesPrefab, head); ((Object)val2).name = "HighElfEyes"; StripItemComponents(val2); val = val2.transform; } val.localPosition = HighElfEyesPosition; val.localRotation = Quaternion.Euler(HighElfEyesRotation); val.localScale = HighElfEyesScale; ApplyEyeColor(val, GetRaceEyeColor(GetRace(p))); } } private void ApplyEyeColor(Transform t, Color color) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)t == (Object)null) { return; } float num = ((EyeGlowPeak != null) ? EyeGlowPeak.Value : 1.5f); float num2 = Mathf.Max(new float[3] { color.r, color.g, color.b }); Color val = ((num2 > 0.001f) ? (color * (num / num2)) : color); Renderer[] componentsInChildren = ((Component)t).GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null) { continue; } Material[] materials = val2.materials; foreach (Material val3 in materials) { if (!((Object)(object)val3 == (Object)null)) { if (val3.HasProperty("_EmissionColor")) { val3.EnableKeyword("_EMISSION"); val3.SetColor("_EmissionColor", val); } if (val3.HasProperty("_Color")) { val3.SetColor("_Color", color); } if (val3.HasProperty("_BaseColor")) { val3.SetColor("_BaseColor", color); } if (val3.HasProperty("_TintColor")) { val3.SetColor("_TintColor", color); } } } } } private void ApplyEars(Player p, Color color) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)p == (Object)null)) { ApplyEarsDirect(GetCachedHead(p, GetRace(p)), color, IsPlayerFemale(p)); } } private void ApplyOrcEars(Player p, Color color) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)p == (Object)null)) { ApplyOrcEarsDirect(GetCachedHead(p, GetRace(p)), color, IsPlayerFemale(p)); } } private void RemoveHeadAttachmentDirect(Transform head, string objectName) { if (!((Object)(object)head == (Object)null)) { Transform val = head.Find(objectName); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } private void RemoveSkinnedAttachmentAnywhere(Transform head, string objectName) { if ((Object)(object)head == (Object)null) { return; } RemoveHeadAttachmentDirect(head, objectName); Transform root = head.root; if ((Object)(object)root != (Object)null && (Object)(object)root != (Object)(object)head) { Transform val = root.Find(objectName); if ((Object)(object)val != (Object)null) { SkinnedAccessoryAttacher.ClearCache(root); Object.Destroy((Object)(object)((Component)val).gameObject); } } } private void RemoveOrcEarsAnywhere(Transform head) { RemoveSkinnedAttachmentAnywhere(head, "OrcEars"); } private void RemoveElfEarsAnywhere(Transform head) { RemoveSkinnedAttachmentAnywhere(head, "Ears"); } private void RemoveHeadAttachment(Player p, string objectName) { if (!((Object)(object)p == (Object)null)) { RemoveHeadAttachmentDirect(GetCachedHead(p, GetRace(p)), objectName); } } private void FixEarMaterials(Transform t, bool forceStandardShader = true) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)t == (Object)null) { return; } Shader val = (forceStandardShader ? Shader.Find("Standard") : null); Renderer[] componentsInChildren = ((Component)t).GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null) { continue; } Material[] materials = val2.materials; foreach (Material val3 in materials) { if (!((Object)(object)val3 == (Object)null)) { if (val3.IsKeywordEnabled("_EMISSION")) { val3.DisableKeyword("_EMISSION"); } if (val3.HasProperty("_EmissionColor")) { val3.SetColor("_EmissionColor", Color.black); } if (forceStandardShader && (Object)(object)val != (Object)null) { val3.shader = val; } } } } } private void ApplyColor(Transform t, Color c) { //IL_0063: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)t == (Object)null) { return; } Renderer[] componentsInChildren = ((Component)t).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } Material[] materials = val.materials; foreach (Material val2 in materials) { if (!((Object)(object)val2 == (Object)null)) { val2.color = c; if (val2.HasProperty("_Color")) { val2.SetColor("_Color", c); } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", c); } if (val2.HasProperty("_TintColor")) { val2.SetColor("_TintColor", c); } } } } } private Transform FindHead(Transform t, int depth) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown if ((Object)(object)t == (Object)null || depth > 12) { return null; } string text = ((Object)t).name.ToLowerInvariant(); if (text == "head" || text.Contains("head") || text.Contains("bip001 head") || text.Contains("helmet_attach") || text.Contains("head_attach")) { return t; } foreach (Transform item in t) { Transform t2 = item; Transform val = FindHead(t2, depth + 1); if ((Object)(object)val != (Object)null) { return val; } } return null; } private void StripItemComponents(GameObject obj) { if (!((Object)(object)obj == (Object)null)) { Collider[] componentsInChildren = obj.GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { Object.Destroy((Object)(object)val); } Rigidbody[] componentsInChildren2 = obj.GetComponentsInChildren(true); foreach (Rigidbody val2 in componentsInChildren2) { Object.Destroy((Object)(object)val2); } ItemDrop[] componentsInChildren3 = obj.GetComponentsInChildren(true); foreach (ItemDrop val3 in componentsInChildren3) { Object.Destroy((Object)(object)val3); } ZNetView[] componentsInChildren4 = obj.GetComponentsInChildren(true); foreach (ZNetView val4 in componentsInChildren4) { Object.Destroy((Object)(object)val4); } } } private static Color ToColor(Vector3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) return new Color(v.x, v.y, v.z, 1f); } private string GetTransformPath(Transform t) { if ((Object)(object)t == (Object)null) { return ""; } List list = new List(); Transform val = t; while ((Object)(object)val != (Object)null) { list.Add(((Object)val).name); val = val.parent; } list.Reverse(); return string.Join("/", list); } } public class HelmetScaleMarker : MonoBehaviour { public Vector3 AppliedScale = Vector3.one; public Vector3 OriginalScale = Vector3.one; public Vector3 OriginalPosition = Vector3.zero; } public class RaceAltar : MonoBehaviour, Interactable, Hoverable { public string GetHoverName() { return GlitnirRacesPlugin.Text_AltarNome.Value; } public string GetHoverText() { Player localPlayer = Player.m_localPlayer; string value = GlitnirRacesPlugin.Text_AltarNome.Value; if ((Object)(object)localPlayer != (Object)null && !GlitnirRacesPlugin.HasPendingAltarSwitch(localPlayer) && GlitnirRacesPlugin.HasChosenRaceViaAltar(localPlayer)) { return value + "\n" + GlitnirRacesPlugin.Text_AltarHoverTrocar.Value; } return value + "\n" + GlitnirRacesPlugin.Text_AltarHoverEscolher.Value; } public bool Interact(Humanoid user, bool hold, bool alt) { if (hold) { return false; } Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer) { return false; } if (GlitnirRacesPlugin.HasPendingAltarSwitch(val)) { RaceAltarUI.Open(val); } else if (GlitnirRacesPlugin.HasChosenRaceViaAltar(val)) { RaceAltarUI.OpenSwitchPanel(val); } else { RaceAltarUI.Open(val); } return true; } public bool UseItem(Humanoid user, ItemData item) { return false; } } public static class RaceAltarUI { private static GameObject _canvasRoot; private static GameObject _panel; public static bool IsOpen => (Object)(object)_panel != (Object)null; private static (string race, string label)[] BuildOptions() { return new(string, string)[4] { ("orc", GlitnirRacesPlugin.Text_RaceName_Orc.Value), ("elfo", GlitnirRacesPlugin.Text_RaceName_Elf.Value), ("anao", GlitnirRacesPlugin.Text_RaceName_Dwarf.Value), ("humano", GlitnirRacesPlugin.Text_RaceName_Human.Value) }; } public static void Open(Player player) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Expected O, but got Unknown //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Expected O, but got Unknown if ((Object)(object)_panel != (Object)null) { return; } EnsureEventSystem(); EnsureCanvas(); _panel = new GameObject("GlitnirRaceAltarPanel", new Type[1] { typeof(RectTransform) }); _panel.transform.SetParent(_canvasRoot.transform, false); RectTransform component = _panel.GetComponent(); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.sizeDelta = new Vector2(420f, 400f); component.anchoredPosition = Vector2.zero; Image val = _panel.AddComponent(); ((Graphic)val).color = new Color(0f, 0f, 0f, 0.85f); CreateText(_panel.transform, GlitnirRacesPlugin.Text_UiEscolhaTitulo.Value, new Vector2(0f, 160f), 26); (string, string)[] array = BuildOptions(); float num = 80f; float num2 = 65f; for (int i = 0; i < array.Length; i++) { var (race, label) = array[i]; CreateButton(_panel.transform, label, new Vector2(0f, num - (float)i * num2), 260f, 50f, (UnityAction)delegate { GlitnirRacesPlugin.ChooseRaceFromAltar(race); Close(); }); } CreateButton(_panel.transform, GlitnirRacesPlugin.Text_UiFechar.Value, new Vector2(0f, -180f), 150f, 40f, new UnityAction(Close)); GUIManager.BlockInput(true); } public static void OpenSwitchPanel(Player player) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Expected O, but got Unknown //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Expected O, but got Unknown if (!((Object)(object)_panel != (Object)null)) { EnsureEventSystem(); EnsureCanvas(); _panel = new GameObject("GlitnirRaceAltarSwitchPanel", new Type[1] { typeof(RectTransform) }); _panel.transform.SetParent(_canvasRoot.transform, false); RectTransform component = _panel.GetComponent(); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.sizeDelta = new Vector2(420f, 240f); component.anchoredPosition = Vector2.zero; Image val = _panel.AddComponent(); ((Graphic)val).color = new Color(0f, 0f, 0f, 0.85f); CreateText(_panel.transform, GlitnirRacesPlugin.Text_UiJaEscolheuTitulo.Value, new Vector2(0f, 80f), 22); string costItem = GlitnirRacesPlugin.AltarSwitchCostItem?.Value ?? "Coins"; int costAmount = GlitnirRacesPlugin.AltarSwitchCostAmount?.Value ?? 50; CreateButton(_panel.transform, GlitnirRacesPlugin.Fmt(GlitnirRacesPlugin.Text_UiTrocarBotao.Value, costAmount, costItem), new Vector2(0f, 10f), 260f, 50f, (UnityAction)delegate { TrySwitchRace(player, costItem, costAmount); }); CreateButton(_panel.transform, GlitnirRacesPlugin.Text_UiFechar.Value, new Vector2(0f, -60f), 150f, 40f, new UnityAction(Close)); GUIManager.BlockInput(true); } } private static void TrySwitchRace(Player player, string costItem, int costAmount) { if ((Object)(object)player == (Object)null) { return; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory != null) { int num = CountItemByPrefabName(inventory, costItem); if (num < costAmount) { ((Character)player).Message((MessageType)2, GlitnirRacesPlugin.Fmt(GlitnirRacesPlugin.Text_UiMoedaInsuficiente.Value, costAmount, costItem), 0, (Sprite)null); } else { RemoveItemByPrefabName(inventory, costItem, costAmount); GlitnirRacesPlugin.SwitchRaceFromAltar(player); Close(); Open(player); } } } private static int CountItemByPrefabName(Inventory inv, string prefabName) { int num = 0; foreach (ItemData allItem in inv.GetAllItems()) { if (allItem != null && (Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == prefabName) { num += allItem.m_stack; } } return num; } private static void RemoveItemByPrefabName(Inventory inv, string prefabName, int amount) { int num = amount; foreach (ItemData item in new List(inv.GetAllItems())) { if (num <= 0) { break; } if (item != null && !((Object)(object)item.m_dropPrefab == (Object)null) && !(((Object)item.m_dropPrefab).name != prefabName)) { int num2 = Mathf.Min(num, item.m_stack); inv.RemoveItem(item, num2); num -= num2; } } } public static void Close() { if ((Object)(object)_panel != (Object)null) { Object.Destroy((Object)(object)_panel); _panel = null; } GUIManager.BlockInput(false); } private static void EnsureCanvas() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_canvasRoot != (Object)null)) { _canvasRoot = new GameObject("GlitnirRaceAltarCanvas"); Object.DontDestroyOnLoad((Object)(object)_canvasRoot); Canvas val = _canvasRoot.AddComponent(); val.renderMode = (RenderMode)0; val.sortingOrder = 5000; CanvasScaler val2 = _canvasRoot.AddComponent(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); _canvasRoot.AddComponent(); _canvasRoot.AddComponent(); } } private static void EnsureEventSystem() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!((Object)(object)Object.FindFirstObjectByType() != (Object)null)) { GameObject val = new GameObject("GlitnirRaceAltarEventSystem"); Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent(); val.AddComponent(); } } private static void CreateText(Transform parent, string text, Vector2 pos, int fontSize) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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) GameObject val = new GameObject("Label", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent(); component.anchoredPosition = pos; component.sizeDelta = new Vector2(380f, 40f); Text val2 = val.AddComponent(); val2.text = text; val2.font = Resources.GetBuiltinResource("Arial.ttf"); val2.fontSize = fontSize; val2.alignment = (TextAnchor)4; ((Graphic)val2).color = Color.white; } private static void CreateButton(Transform parent, string label, Vector2 pos, float width, float height, UnityAction onClick) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_003b: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Button_" + label, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent(); component.anchoredPosition = pos; component.sizeDelta = new Vector2(width, height); Image val2 = val.AddComponent(); ((Graphic)val2).color = new Color(0.35f, 0.28f, 0.18f, 1f); Button val3 = val.AddComponent