Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ValheimRaces v2.9.4
ValheimRaces.dll
Decompiled 5 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; 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.8", FrameworkDisplayName = "")] [assembly: AssemblyCompany("ValheimRaces")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ValheimRaces")] [assembly: AssemblyTitle("ValheimRaces")] [assembly: AssemblyVersion("1.0.0.0")] [BepInPlugin("valheim.races", "Valheim Races", "2.9.1")] public class ValheimRacesPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class RegisterAltarPrefabInZNetScenePatch { private static void Postfix(ZNetScene __instance) { if (!((Object)(object)Instance == (Object)null) && !((Object)(object)AltarPrefab == (Object)null) && !((Object)(object)__instance == (Object)null) && !__instance.m_prefabs.Contains(AltarPrefab)) { __instance.m_prefabs.Add(AltarPrefab); if (ZNetSceneNamedPrefabsField?.GetValue(__instance) is Dictionary<int, GameObject> dictionary) { dictionary[StringExtensionMethods.GetStableHashCode(((Object)AltarPrefab).name)] = AltarPrefab; } ((BaseUnityPlugin)Instance).Logger.LogInfo((object)"[ValheimRaces] 'altar_racas' registrado no ZNetScene."); } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class RegisterAltarPieceInHammerPatch { private static void Postfix(ObjectDB __instance) { //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Expected O, but got Unknown if ((Object)(object)Instance == (Object)null || (Object)(object)AltarPrefab == (Object)null || (Object)(object)__instance == (Object)null) { return; } Piece component = AltarPrefab.GetComponent<Piece>(); if ((Object)(object)component == (Object)null || (Object)(object)__instance.GetItemPrefab("Hammer") == (Object)null) { return; } component.m_resources = ParseAltarRecipe(__instance, AltarRecipe?.Value ?? "Wood:10,Stone:5"); GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("piece_workbench") : null); component.m_craftingStation = (((Object)(object)val != (Object)null) ? val.GetComponent<CraftingStation>() : null); if ((Object)(object)component.m_craftingStation == (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)"[ValheimRaces] Não achei a Bancada de Trabalho ('piece_workbench') — Altar ficará sem estação exigida."); } Piece val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Piece>() : null); if ((Object)(object)val2 != (Object)null && val2.m_placeEffect.m_effectPrefabs != null) { component.m_placeEffect = val2.m_placeEffect; } else { component.m_placeEffect = new EffectList(); } GameObject itemPrefab = __instance.GetItemPrefab("Hammer"); ItemDrop val3 = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); PieceTable val4 = ((!((Object)(object)val3 != (Object)null)) ? null : val3.m_itemData?.m_shared?.m_buildPieces); if ((Object)(object)val4 == (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)"[ValheimRaces] Não achei a tabela de peças do Martelo — Altar não vai aparecer no menu de construção."); return; } if (!val4.m_pieces.Contains(AltarPrefab)) { val4.m_pieces.Add(AltarPrefab); } ((BaseUnityPlugin)Instance).Logger.LogInfo((object)"[ValheimRaces] Peça 'Altar das Raças' registrada na tabela do Martelo."); } } [HarmonyPatch(typeof(FejdStartup), "Awake")] private static class FejdStartupPrewarmPatch { private static void Postfix(FejdStartup __instance) { try { GetUiClickClip(); } catch { } try { FejdRaceSelectorUI.Prewarm(__instance); } catch (Exception arg) { ValheimRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)$"Falha ao pré-aquecer o seletor de raça do menu: {arg}"); } } } } [HarmonyPatch(typeof(FejdStartup), "SetupCharacterPreview")] private static class FejdCharacterPreviewPatch { private static void Postfix(FejdStartup __instance, PlayerProfile profile) { try { ApplyPreviewRace(__instance, profile); } catch (Exception arg) { ValheimRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)$"Falha ao aplicar raça no preview do menu: {arg}"); } } try { if (string.IsNullOrEmpty((profile != null) ? profile.GetName() : null)) { FejdRaceSelectorUI.EnsureVisible(__instance); } else { FejdRaceSelectorUI.Hide(); } } catch (Exception arg2) { ValheimRacesPlugin instance2 = Instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Logger.LogWarning((object)$"Falha ao mostrar/esconder o seletor de raça do menu: {arg2}"); } } } } [HarmonyPatch(typeof(FejdStartup), "OnNewCharacterCancel")] private static class FejdCharacterCancelPatch { private static void Postfix() { _sessionSelectedPreviewRace = null; UserJustClickedRacePending = false; _typedNamePreview = null; _lastFullyAppliedRace = null; _lastAppliedIsFemale = false; } } [HarmonyPatch(typeof(VisEquipment), "SetSkinColor")] private static class ForcePreviewSkinColorPatch { private static void Prefix(VisEquipment __instance, ref Vector3 __0) { //IL_004e: 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_006d: 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 (!((Object)(object)__instance == (Object)null) && _previewSkinForced && !string.IsNullOrWhiteSpace(_sessionSelectedPreviewRace)) { Player component = ((Component)__instance).GetComponent<Player>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component != (Object)(object)_cachedPreviewPlayerInstance)) { __0 = BlendRaceHueWithBrightness(GetRaceSkinColor(_sessionSelectedPreviewRace), __0, GetRaceMinSkinBrightness(_sessionSelectedPreviewRace), GetRaceMaxSkinBrightness(_sessionSelectedPreviewRace)); } } } private static void Postfix(VisEquipment __instance) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || string.IsNullOrWhiteSpace(_sessionSelectedPreviewRace)) { return; } Player component = ((Component)__instance).GetComponent<Player>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component != (Object)(object)_cachedPreviewPlayerInstance)) { Color c = ToColor(GetRaceEarColorForPreview(component, _sessionSelectedPreviewRace)); Transform val = ((Component)component).transform.Find("Ears"); if ((Object)(object)val != (Object)null) { Instance.FixEarMaterials(val, forceStandardShader: false); Instance.ApplyColor(val, c); } Transform val2 = ((Component)component).transform.Find("OrcEars"); if ((Object)(object)val2 != (Object)null) { Instance.FixEarMaterials(val2, forceStandardShader: false); Instance.ApplyColor(val2, c); } } } } [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 Prefix(Player __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)Instance == (Object)null) && !IsHeadless()) { RemovePlayerAttachment(__instance, "JotunFreeze"); } } 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<ZNetView>(); if ((Object)(object)component != (Object)null && component.GetZDO() != null) { component.GetZDO().Set("ValheimRagdollRace", race); } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("[ValheimRaces] 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<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.GetZDO() != null) { string text = component.GetZDO().GetString("ValheimRagdollRace", ""); if (!string.IsNullOrWhiteSpace(text) && IsRaceEnabled(text)) { ApplyRaceVisualToRagdoll(__instance, text); } } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("[ValheimRaces] 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(); _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_0053: 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_004e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && !IsHeadless()) { Player component = ((Component)__instance).GetComponent<Player>(); if (!((Object)(object)component == (Object)null)) { string race = GetRace(component); Vector3 targetScale = ((!string.IsNullOrWhiteSpace(race) && IsRaceEnabled(race)) ? GetFinalScale(component, race) : HumanScale); ScaleCurrentHelmetForRace(component, targetScale); } } } } [HarmonyPatch(typeof(VisEquipment), "SetHairColor")] private static class ForceRaceHairColorPatch { private static void Prefix(VisEquipment __instance, ref Vector3 __0) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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<Player>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)((Component)component).GetComponent<ZNetView>() == (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_0063: 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<Player>(); if ((Object)(object)component == (Object)null) { return true; } if ((Object)(object)((Component)component).GetComponent<ZNetView>() == (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<MethodBase> 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<MethodBase> TargetMethods() { string[] names = new string[2] { "UpdateEquipment", "OnInventoryChanged" }; 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_0062: 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, GetFinalScale(val, race)); Instance.RequestOnlineVisualRefresh(val); } } } } [HarmonyPatch(typeof(Chat), "InputText")] private static class ChatPatch { private static readonly FieldInfo InputField = AccessTools.Field(typeof(Chat), "m_input"); private static PropertyInfo _textProp; private static bool Prefix(Chat __instance) { if ((Object)(object)__instance == (Object)null || InputField == null) { return true; } object value = InputField.GetValue(__instance); if (value == null) { return true; } if (_textProp == null) { _textProp = value.GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public); } if (_textProp == null) { return true; } string text; try { text = (_textProp.GetValue(value) as string)?.Trim() ?? ""; } catch { return true; } string raceFromSecretCode = GetRaceFromSecretCode(text); if (raceFromSecretCode == null) { return true; } TransformLocalPlayerFromMarketplace(raceFromSecretCode); try { if (_textProp.CanWrite) { _textProp.SetValue(value, ""); } } catch { } return false; } } [HarmonyPatch(typeof(Character), "UpdateLayer")] private static class FixNullColliderInUpdateLayerPatch { private static readonly FieldInfo ColliderField = AccessTools.Field(typeof(Character), "m_collider"); private static bool Prefix(Character __instance) { if (ColliderField == null || (Object)(object)__instance == (Object)null) { return true; } object? value = ColliderField.GetValue(__instance); Object val = (Object)((value is Object) ? value : null); if (val != (Object)null) { return true; } Collider component = ((Component)__instance).GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { ColliderField.SetValue(__instance, component); return true; } return false; } } [HarmonyPatch(typeof(BaseAI), "CanSenseTarget", new Type[] { typeof(Character) })] private static class RaceCrouchStealthSensePatch { private static void Postfix(Character target, ref bool __result) { if (__result && IsCrouchStealthed(target)) { __result = false; } } } [HarmonyPatch(typeof(BaseAI), "CanSeeTarget", new Type[] { typeof(Character) })] private static class RaceCrouchStealthSeePatch { private static void Postfix(Character target, ref bool __result) { if (__result && IsCrouchStealthed(target)) { __result = false; } } } [HarmonyPatch(typeof(BaseAI), "CanHearTarget", new Type[] { typeof(Character) })] private static class RaceCrouchStealthHearPatch { private static void Postfix(Character target, ref bool __result) { if (__result && IsCrouchStealthed(target)) { __result = false; } } } [HarmonyPatch(typeof(Humanoid), "BlockAttack", new Type[] { typeof(HitData), typeof(Character) })] private static class RaceIronStanceOnBlockPatch { private static void Postfix(Humanoid __instance, HitData hit, bool __result) { if (!__result) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && RacialAbilitiesEnabled.Value && TryGetRaceConfig(val, out var cfg) && cfg.UseRacialAbility.Value && cfg.IronStanceEnabled) { float num = Mathf.Clamp01(cfg.IronStanceExtraDamageReduction); if (num > 0f) { ScaleAllDamageTypes(ref hit.m_damage, 1f - num); } hit.m_pushForce = 0f; } } } [HarmonyPatch(typeof(Character), "UpdateGroundContact")] private static class RaceTremorPatch { private static void Postfix(Character __instance, float dt) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val == (Object)null || !RacialAbilitiesEnabled.Value || !TryGetRaceConfig(val, out var cfg) || !cfg.UseRacialAbility.Value || !cfg.TremorEnabled) { return; } string visualKey = GetVisualKey(val); if (string.IsNullOrWhiteSpace(visualKey)) { return; } bool flag = ((Character)val).IsOnGround(); TremorWasOnGround.TryGetValue(visualKey, out var value); TremorAirTime.TryGetValue(visualKey, out var value2); if (!flag) { TremorAirTime[visualKey] = value2 + dt; TremorWasOnGround[visualKey] = false; return; } if (!value && value2 >= cfg.TremorMinAirTime) { DoTremor(val, cfg); } TremorAirTime[visualKey] = 0f; TremorWasOnGround[visualKey] = true; } } [HarmonyPatch(typeof(Player), "SetMaxHealth")] private static class RaceMaxHealthPatch { private static void Prefix(Player __instance, ref float health) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) if (TryGetDevotionConfig(__instance, out var cfg)) { health += cfg.HealthBonus; } if (!TryGetRaceConfig(__instance, out var cfg2) || !cfg2.UseModAttributes.Value) { return; } health += cfg2.HealthBonus; if (cfg2.DayNightHealthShift != 0f) { health += (IsNightSafe() ? cfg2.DayNightHealthShift : (0f - cfg2.DayNightHealthShift)); } if (!string.IsNullOrWhiteSpace(cfg2.BiomeHealthShifts)) { try { Biome currentBiome = __instance.GetCurrentBiome(); Dictionary<Biome, float> dictionary = ParseBiomeShifts(cfg2.BiomeHealthShifts); if (dictionary.TryGetValue(currentBiome, out var value)) { health += value; } } catch (Exception ex) { ValheimRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("[ValheimRaces] 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 (TryGetDevotionConfig(__instance, out var cfg)) { stamina += cfg.StaminaBonus; } if (TryGetRaceConfig(__instance, out var cfg2) && cfg2.UseModAttributes.Value) { stamina += cfg2.StaminaBonus; } } } [HarmonyPatch(typeof(Player), "SetMaxEitr")] private static class RaceMaxEitrPatch { private static void Prefix(Player __instance, ref float eitr) { if (TryGetDevotionConfig(__instance, out var cfg)) { eitr += cfg.EitrBonus; } if (TryGetRaceConfig(__instance, out var cfg2) && cfg2.UseModAttributes.Value) { eitr += cfg2.EitrBonus; } } } [HarmonyPatch(typeof(Player), "GetMaxCarryWeight")] private static class RaceMaxCarryWeightPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetDevotionConfig(__instance, out var cfg)) { __result += cfg.CarryWeightBonus; } if (TryGetRaceConfig(__instance, out var cfg2) && cfg2.UseModAttributes.Value) { __result += cfg2.CarryWeightBonus; } } } [HarmonyPatch(typeof(Character), "Heal")] private static class RaceHealthRegenPatch { private static void Prefix(Character __instance, ref float hp) { if (hp <= 0f) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null)) { if (TryGetDevotionConfig(val, out var cfg)) { hp *= cfg.HealthRegenMultiplier; } if (TryGetRaceConfig(val, out var cfg2) && cfg2.UseModAttributes.Value && (!cfg2.NightOnlyBonuses || IsNightSafe())) { hp *= cfg2.HealthRegenMultiplier; } } } } [HarmonyPatch(typeof(Character), "AddStamina")] private static class RaceStaminaRegenPatch { private static void Prefix(Character __instance, ref float v) { if (v <= 0f) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null)) { if (TryGetDevotionConfig(val, out var cfg)) { v *= cfg.StaminaRegenMultiplier; } if (TryGetRaceConfig(val, out var cfg2) && cfg2.UseModAttributes.Value && (!cfg2.NightOnlyBonuses || IsNightSafe())) { v *= cfg2.StaminaRegenMultiplier; } } } } [HarmonyPatch(typeof(Character), "AddEitr")] private static class RaceEitrRegenPatch { private static void Prefix(Character __instance, ref float v) { if (v <= 0f) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null)) { if (TryGetDevotionConfig(val, out var cfg)) { v *= cfg.EitrRegenMultiplier; } if (TryGetRaceConfig(val, out var cfg2) && cfg2.UseModAttributes.Value && (!cfg2.NightOnlyBonuses || IsNightSafe())) { v *= cfg2.EitrRegenMultiplier; } } } } [HarmonyPatch(typeof(Player), "UseStamina")] private static class RaceNoStaminaCostPatch { private static void Prefix(Player __instance, ref float v) { if (TryGetRaceConfig(__instance, out var cfg) && cfg.UseModAttributes.Value && cfg.NoResourceCost) { v = 0f; } } } [HarmonyPatch(typeof(Player), "UseEitr")] private static class RaceNoEitrCostPatch { private static void Prefix(Player __instance, ref float v) { if (TryGetDevotionConfig(__instance, out var cfg) && cfg.EitrCostMultiplier != 1f) { v *= cfg.EitrCostMultiplier; } if (TryGetRaceConfig(__instance, out var cfg2) && cfg2.UseModAttributes.Value) { if (cfg2.NoResourceCost) { v = 0f; } else if (cfg2.EitrCostMultiplier != 1f) { v *= cfg2.EitrCostMultiplier; } } } } [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.UseModAttributes.Value || !cfg.NoResourceCost) { return true; } __result = true; return false; } } [HarmonyPatch(typeof(Player), "GetEquipmentHeatResistanceModifier")] private static class RaceHeatImmunityPatch { private static void Postfix(Player __instance, ref float __result) { if (!((Object)(object)__instance == (Object)null) && TryGetRaceConfig(__instance, out var cfg) && cfg.UseModAttributes.Value && cfg.HeatResistanceBonus != 0f) { __result = Mathf.Max(__result, 1f); } } } private class RaceAuraTag : MonoBehaviour { public string SourcePrefabName; } [HarmonyPatch(typeof(Humanoid), "BlockAttack", new Type[] { typeof(HitData), typeof(Character) })] private static class RaceBlockAuraOnBlockPatch { private static void Postfix(Humanoid __instance, HitData hit, Character attacker, bool __result) { if (__result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && RacialAbilitiesEnabled.Value && TryGetRaceConfig(val, out var cfg) && cfg.UseRacialAbility.Value && cfg.BlockAuraEnabled) { DoBlockAuraHit(val, attacker, cfg); } } } } [HarmonyPatch(typeof(Character), "GetJogSpeedFactor")] private static class ChilledJogSpeedPatch { private static void Postfix(Character __instance, ref float __result) { if (!((Object)(object)__instance == (Object)null) && ChilledStatus.TryGetValue(((Object)__instance).GetInstanceID(), out (float, float) value) && Time.time < value.Item1) { __result *= value.Item2; } } } [HarmonyPatch(typeof(Character), "GetRunSpeedFactor")] private static class ChilledRunSpeedPatch { private static void Postfix(Character __instance, ref float __result) { if (!((Object)(object)__instance == (Object)null) && ChilledStatus.TryGetValue(((Object)__instance).GetInstanceID(), out (float, float) value) && Time.time < value.Item1) { __result *= value.Item2; } } } [HarmonyPatch(typeof(Character), "Damage")] private static class OnHitElementalDamagePatch { private static void Prefix(HitData hit) { if (hit == null || RacialAbilitiesEnabled == null || !RacialAbilitiesEnabled.Value) { return; } Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val == null) { return; } string race = GetRace(val); if (string.IsNullOrWhiteSpace(race) || !Races.TryGetValue(race, out var value) || !value.UseRacialAbility.Value) { return; } if (value.OnHitElementalEnabled && value.OnHitElementalDamage > 0f) { if (value.BlockAuraIsFrost) { hit.m_damage.m_frost += value.OnHitElementalDamage; } else { hit.m_damage.m_fire += value.OnHitElementalDamage; } } if (value.OnHitSpiritEnabled && value.OnHitSpiritDamage > 0f) { hit.m_damage.m_spirit += value.OnHitSpiritDamage; } } } [HarmonyPatch(typeof(Character), "Damage")] private static class RaceCombatDamagePatch { private static void Prefix(Character __instance, HitData hit, out float __state) { //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) __state = (((Object)(object)__instance != (Object)null) ? __instance.GetHealth() : 0f); if ((Object)(object)__instance == (Object)null || hit == null) { return; } try { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)__instance && TryGetDevotionConfig(val, out var cfg)) { if (cfg.DamageDoneMultiplier != 1f) { ScaleAllDamageTypes(ref hit.m_damage, cfg.DamageDoneMultiplier); } if (!string.IsNullOrWhiteSpace(cfg.AttackDamageTypeMultipliers)) { Dictionary<DamageType, float> dictionary = ParseTypeMultipliers(cfg.AttackDamageTypeMultipliers); foreach (KeyValuePair<DamageType, float> item in dictionary) { ScaleDamageType(ref hit.m_damage, item.Key, item.Value); } } if (cfg.BackstabMultiplier != 1f && hit.m_backstabBonus > 1f) { ScaleAllDamageTypes(ref hit.m_damage, cfg.BackstabMultiplier); } if (cfg.KnockbackMultiplier != 1f) { hit.m_pushForce *= cfg.KnockbackMultiplier; } } if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)__instance && TryGetRaceConfig(val, out var cfg2) && cfg2.UseModAttributes.Value) { if (cfg2.DamageDoneMultiplier != 1f) { ScaleAllDamageTypes(ref hit.m_damage, cfg2.DamageDoneMultiplier); } if (!string.IsNullOrWhiteSpace(cfg2.SkillDamageMultipliers)) { Dictionary<string, float> dictionary2 = ParseSkillMultipliers(cfg2.SkillDamageMultipliers); if (dictionary2.TryGetValue(((object)Unsafe.As<SkillType, SkillType>(ref hit.m_skill)/*cast due to .constrained prefix*/).ToString(), out var value)) { ScaleAllDamageTypes(ref hit.m_damage, value); } } if (!string.IsNullOrWhiteSpace(cfg2.AttackDamageTypeMultipliers)) { Dictionary<DamageType, float> dictionary3 = ParseTypeMultipliers(cfg2.AttackDamageTypeMultipliers); foreach (KeyValuePair<DamageType, float> item2 in dictionary3) { ScaleDamageType(ref hit.m_damage, item2.Key, item2.Value); } } if (cfg2.BackstabMultiplier != 1f && hit.m_backstabBonus > 1f) { ScaleAllDamageTypes(ref hit.m_damage, cfg2.BackstabMultiplier); } if (cfg2.KnockbackMultiplier != 1f) { hit.m_pushForce *= cfg2.KnockbackMultiplier; } } if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)__instance && TryGetRaceConfig(val, out var cfg3) && cfg3.UseRacialAbility.Value && cfg3.LowHealthThreshold > 0f && cfg3.LowHealthDamageBonus != 1f) { float maxHealth = ((Character)val).GetMaxHealth(); if (maxHealth > 0f && ((Character)val).GetHealth() / maxHealth <= cfg3.LowHealthThreshold) { ScaleAllDamageTypes(ref hit.m_damage, cfg3.LowHealthDamageBonus); } } Player val2 = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val2 != (Object)null && TryGetDevotionConfig(val2, out var cfg4) && cfg4.DamageTakenMultiplier != 1f) { ScaleAllDamageTypes(ref hit.m_damage, cfg4.DamageTakenMultiplier); } if ((Object)(object)val2 != (Object)null && TryGetRaceConfig(val2, out var cfg5) && cfg5.UseModAttributes.Value && cfg5.DamageTakenMultiplier != 1f) { ScaleAllDamageTypes(ref hit.m_damage, cfg5.DamageTakenMultiplier); } } catch (Exception arg) { ValheimRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)$"[ValheimRaces] RaceCombatDamagePatch.Prefix deu exception (ignorando, dano segue sem bônus racial): {arg}"); } } } private static void Postfix(Character __instance, HitData hit, float __state) { if ((Object)(object)__instance == (Object)null || hit == null) { return; } try { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)__instance) { return; } if (__state > 0f && __instance.GetHealth() <= 0f) { if (TryGetDevotionConfig(val, out var cfg) && cfg.OnKillHealAmount > 0f && (!cfg.OnKillHealNightOnly || IsNightSafe())) { ((Character)val).Heal(cfg.OnKillHealAmount, false); } if (TryGetRaceConfig(val, out var cfg2) && cfg2.UseRacialAbility.Value && cfg2.OnKillHealAmount > 0f && (!cfg2.OnKillHealNightOnly || IsNightSafe())) { ((Character)val).Heal(cfg2.OnKillHealAmount, false); } } if (TryGetRaceConfig(val, out var cfg3) && cfg3.UseRacialAbility.Value && !(cfg3.LifestealPercent <= 0f)) { float num = __state - __instance.GetHealth(); if (num > 0f) { ((Character)val).Heal(num * cfg3.LifestealPercent, false); } } } catch (Exception arg) { ValheimRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)$"[ValheimRaces] RaceCombatDamagePatch.Postfix deu exception (ignorando): {arg}"); } } } } [HarmonyPatch(typeof(Character), "GetDamageModifier")] private static class RaceResistancePatch { private static void Postfix(Character __instance, DamageType damageType, ref DamageModifier __result) { //IL_004c: 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) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected I4, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_00b9: Expected I4, but got Unknown try { Player val = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val == (Object)null) { return; } if (TryGetDevotionConfig(val, out var cfg) && !string.IsNullOrWhiteSpace(cfg.Resistances)) { Dictionary<DamageType, DamageModifier> dictionary = ParseResistances(cfg.Resistances); if (dictionary.TryGetValue(damageType, out var value)) { __result = (DamageModifier)(int)StrongerDamageModifier(__result, value); } } if (TryGetRaceConfig(val, out var cfg2) && cfg2.UseModAttributes.Value && !string.IsNullOrWhiteSpace(cfg2.Resistances)) { Dictionary<DamageType, DamageModifier> dictionary2 = ParseResistances(cfg2.Resistances); if (dictionary2.TryGetValue(damageType, out var value2)) { __result = (DamageModifier)(int)StrongerDamageModifier(__result, value2); } } } catch (Exception arg) { ValheimRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)$"[ValheimRaces] RaceResistancePatch.Postfix deu exception (ignorando): {arg}"); } } } } [HarmonyPatch(typeof(Skills), "RaiseSkill")] private static class RaceXpGainPatch { private static void Prefix(Skills __instance, ref float factor) { try { if (!(SkillsOwnerPlayerField == null) && !(factor <= 0f)) { object? value = SkillsOwnerPlayerField.GetValue(__instance); Player val = (Player)((value is Player) ? value : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg) && cfg.UseModAttributes.Value && cfg.XpGainMultiplier != 1f) { factor *= cfg.XpGainMultiplier; } } } catch (Exception arg) { ValheimRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)$"[ValheimRaces] RaceXpGainPatch.Prefix deu exception (ignorando): {arg}"); } } } } public class RaceConfig { public string RaceId; public string DisplayName; public ConfigEntry<bool> Enabled; public ConfigEntry<bool> UseModAttributes; public ConfigEntry<bool> UseRacialAbility; public ConfigEntry<bool> UseEpicMmoAbilities; public string Scale; public string SkinColor; public string HairColor; public string EarColor; public string EyeColor; public string SecretCode; public bool HiddenFromSelector; public float HealthBonus; public float StaminaBonus; public float EitrBonus; public float CarryWeightBonus; public float HealthRegenMultiplier; public float StaminaRegenMultiplier; public float EitrRegenMultiplier; public float DamageDoneMultiplier; public string SkillDamageMultipliers; public float BackstabMultiplier; public float DamageTakenMultiplier; public float LifestealPercent; public float StealthMultiplier; public float SpeedMultiplier; public string Resistances; public bool NoResourceCost; public float XpGainMultiplier; public float KnockbackMultiplier; public float EitrCostMultiplier; public string StaminaCostModifiers; public string AttackDamageTypeMultipliers; public bool NightOnlyBonuses; public float DayNightHealthShift; public string BiomeHealthShifts; public float HeatResistanceBonus; public bool CrouchInvisible; public bool CrouchInvisibleNightOnly; public float LowHealthThreshold; public float LowHealthDamageBonus; public bool StillHealAura; public float StillHealAmount; public float StillHealInterval; public float StillHealRequiredStillTime; public bool IronStanceEnabled; public float IronStanceExtraDamageReduction; public float BackstabStaminaRefundChance; public float BackstabStaminaRefundAmount; public bool TremorEnabled; public float TremorMinAirTime; public float TremorRadius; public float TremorKnockback; public float TremorFireDamage; public float TremorStaggerMultiplier; public bool SecondWindEnabled; public float SecondWindThreshold; public float SecondWindHealAmount; public float SecondWindStaminaAmount; public float SecondWindCooldown; public float OnKillHealAmount; public string EvolvesTo; public float EvolutionThreshold; public bool OnKillHealNightOnly; public bool StillHealDayOnly; public bool BlockAuraEnabled; public float BlockAuraDamage; public float BlockAuraRadius; public bool BlockAuraIsFrost; public bool BlockAuraSlowEnabled; public float BlockAuraSlowPercent; public float BlockAuraSlowDuration; public bool OnHitElementalEnabled; public float OnHitElementalDamage; public bool OnHitSpiritEnabled; public float OnHitSpiritDamage; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Converter<ParameterInfo, string> <>9__30_2; public static ConsoleEventFailable <>9__38_0; public static ConsoleEventFailable <>9__39_0; public static ConsoleEventFailable <>9__46_0; public static ConsoleEvent <>9__84_0; public static Func<AudioClip, bool> <>9__384_0; public static Func<AudioClip, string> <>9__384_1; public static Func<AudioClip, string> <>9__387_1; internal string <RegisterInspectHeatCommand>b__30_2(ParameterInfo pi) { return pi.ParameterType.Name; } internal object <RegisterListFireItemsCommand>b__38_0(ConsoleEventArgs args) { if (!HasDevCommands()) { args.Context.AddString(Text_SemPermissao.Value); return false; } if ((Object)(object)ObjectDB.instance == (Object)null) { args.Context.AddString(Text_DebugObjectDBNaoCarregou.Value); return false; } args.Context.AddString(Text_DebugItensComFireStaff.Value); int num = 0; int num2 = 0; try { if (typeof(ObjectDB).GetField("m_items", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(ObjectDB.instance) is List<GameObject> list) { num2 = list.Count; foreach (GameObject item in list) { if (!((Object)(object)item == (Object)null)) { string name = ((Object)item).name; if (name.ToLowerInvariant().Contains("fire") || name.ToLowerInvariant().Contains("staff")) { args.Context.AddString(" " + name); num++; } } } } } catch (Exception ex) { args.Context.AddString(Fmt(Text_DebugErro.Value, ex.Message)); } args.Context.AddString(Fmt(Text_DebugTotalItens.Value, num2)); if (num == 0) { args.Context.AddString(Text_DebugNenhumEncontrado.Value); } return true; } internal object <RegisterWhatPieceTableCommand>b__39_0(ConsoleEventArgs args) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { args.Context.AddString(Text_DebugPlayerNaoCarregadoSimples.Value); return false; } try { FieldInfo fieldInfo = AccessTools.Field(typeof(Humanoid), "m_rightItem"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(Humanoid), "m_leftItem"); object? obj = fieldInfo?.GetValue(localPlayer); ItemData val = (ItemData)((obj is ItemData) ? obj : null); object? obj2 = fieldInfo2?.GetValue(localPlayer); ItemData val2 = (ItemData)((obj2 is ItemData) ? obj2 : null); ItemData val3 = val ?? val2; if (val3?.m_shared == null) { args.Context.AddString(Text_DebugNenhumaFerramenta.Value); return false; } string text = (((Object)(object)val3.m_shared.m_buildPieces != (Object)null) ? ((Object)val3.m_shared.m_buildPieces).name : "(nulo)"); args.Context.AddString(Fmt(Text_DebugFerramenta.Value, val3.m_shared.m_name)); args.Context.AddString(Fmt(Text_DebugPieceTableReal.Value, text)); if ((Object)(object)val3.m_shared.m_buildPieces != (Object)null) { List<GameObject> pieces = val3.m_shared.m_buildPieces.m_pieces; args.Context.AddString(Fmt(Text_DebugTotalPecas.Value, pieces.Count)); } CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation(); args.Context.AddString(((Object)(object)currentCraftingStation != (Object)null) ? Fmt(Text_DebugEstacaoPerto.Value, ((Object)currentCraftingStation).name) : Text_DebugNenhumaEstacao.Value); } catch (Exception ex) { args.Context.AddString(Fmt(Text_DebugErro.Value, ex.Message)); } return true; } internal object <RegisterOfflineResetCommand>b__46_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; } internal void <RegisterListDollsCommand>b__84_0(ConsoleEventArgs args) { VisEquipment[] array = Object.FindObjectsByType<VisEquipment>((FindObjectsInactive)1, (FindObjectsSortMode)0); args.Context.AddString($"[ValheimRaces] {array.Length} VisEquipment encontrado(s):"); VisEquipment[] array2 = array; foreach (VisEquipment val in array2) { if (!((Object)(object)val == (Object)null)) { bool flag = (Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)((Component)val).gameObject == (Object)(object)((Component)Player.m_localPlayer).gameObject; bool flag2 = (Object)(object)((Component)val).GetComponent<ZNetView>() != (Object)null; bool activeInHierarchy = ((Component)val).gameObject.activeInHierarchy; string hierarchyPath = GetHierarchyPath(((Component)val).transform); string text = $" - '{((Object)((Component)val).gameObject).name}' | ativo={activeInHierarchy} | ZNetView={flag2} | local={flag} | caminho={hierarchyPath}"; args.Context.AddString(text); ValheimRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)("[ValheimRaces/Diag] listdolls: " + text)); } } } } internal bool <GetUiClickClip>b__384_0(AudioClip c) { return (Object)(object)c != (Object)null; } internal string <GetUiClickClip>b__384_1(AudioClip c) { return ((Object)c).name; } internal string <ListAudioClipsContaining>b__387_1(AudioClip c) { return ((Object)c).name; } } private static readonly FieldInfo ZNetSceneNamedPrefabsField = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs"); private static readonly HashSet<long> PendingAltarSwitch = new HashSet<long>(); private static readonly FieldInfo HelmetInstanceField = AccessTools.Field(typeof(VisEquipment), "m_helmetItemInstance"); private static readonly HashSet<string> RegisteredSecretCodes = new HashSet<string>(StringComparer.Ordinal); private const float HumanXpMultiplier = 1.1f; private static readonly string[] MmoParamNames = new string[6] { "Strength", "Agility", "Intellect", "Body", "Vigour", "Special" }; private static readonly Dictionary<string, int[]> RaceMmoAttributeBonus = new Dictionary<string, int[]> { { "humano", new int[6] { 2, 2, 2, 2, 2, 2 } }, { "elfodaluz", new int[6] { 0, 5, 5, 0, 1, 3 } }, { "elfodanoite", new int[6] { 0, 6, 2, 0, 1, 4 } }, { "anao", new int[6] { 5, 0, 0, 6, 3, 1 } }, { "jotun", new int[6] { 5, 0, 0, 7, 3, 1 } }, { "efrit", new int[6] { 3, 0, 7, 0, 1, 3 } }, { "orc", new int[6] { 6, 0, 0, 7, 2, 1 } }, { "aesir", new int[6] { 7, 3, 2, 7, 3, 3 } }, { "vanir", new int[6] { 2, 4, 4, 3, 7, 5 } }, { "cavaleirovalhalla", new int[6] { 6, 4, 3, 6, 2, 3 } } }; private static bool _mmoChecked; private static bool _mmoAvailable; private static Type _mmoLevelSystemType; private static Type _mmoParameterType; private static MethodInfo _mmoGetInstance; private static MethodInfo _mmoGetParameter; private static MethodInfo _mmoSetParameter; private static bool _mmoXpPatched; private const string MmoKeyPrefix = "EpicMMOSystem_LevelSystem_"; private static readonly FieldInfo KnownTextsField = AccessTools.Field(typeof(Player), "m_knownTexts"); private static bool _mmoAddHpChecked; private static float _mmoAddHpConfigValue = 1f; private static readonly string[] MmoParamNamesPt = new string[6] { "Força", "Destreza", "Inteligência", "Resistência", "Vigor", "Especialização" }; private const string MmoBrandColor = "#8fd3f4"; private const string MmoPositiveColor = "#7fe08a"; private const string MmoNegativeColor = "#e07a6a"; private const string MmoNeutralColor = "#d8d0c0"; private const string MmoDividerColor = "#6b5a3f"; private static readonly Dictionary<int, string> LastDollAppliedRace = new Dictionary<int, string>(); private static Player _cachedPreviewPlayerInstance; private static Vector3? _originalPreviewSkin; private static Vector3? _originalPreviewHair; private static string _sessionSelectedPreviewRace; private static bool _previewSkinForced; private static bool _previewHairForced; private static string _lastFullyAppliedRace; private static bool _lastAppliedIsFemale; private static string _typedNamePreview; private static readonly FieldInfo NewCharacterNameField = AccessTools.Field(typeof(FejdStartup), "m_csNewCharacterName"); public static bool UserJustClickedRacePending; private static bool _previewShareRetryQueued; private const string ZdoRagdollRaceKey = "ValheimRagdollRace"; private const string ModGUID = "valheim.races"; private const string ModName = "Valheim Races"; private const string ModVersion = "2.9.1"; private const string RaceElf = "elfodaluz"; private const string RaceDarkElf = "elfodanoite"; private const string RaceDwarf = "anao"; private const string RaceHuman = "humano"; private const string RaceJotun = "jotun"; private const string RaceEfrit = "efrit"; private const string RaceOrc = "orc"; private const string RaceValhallaKnight = "cavaleirovalhalla"; private const string RaceAesir = "aesir"; private const string RaceVanir = "vanir"; private const string ZdoRaceKey = "ValheimRace"; private const string ZdoEvoProgressKey = "ValheimEvoProgress"; private const string ZdoRaceVersionKey = "ValheimRaceVer"; private const int CurrentRaceDataVersion = 1; private const string ZdoLockedKey = "ValheimRaceLocked"; private const string ZdoEarColorKey = "ValheimRaceEarColor"; private const string ZdoSkinColorKey = "ValheimRaceSkinColor"; private const string ZdoDevotionKey = "ValheimRaceDevotion"; private const string RpcSetRace = "ValheimRaces_SetRace"; private const string RpcVersionCheck = "ValheimRaces_VersionCheck"; private const string RpcAdminSetRaceRequest = "ValheimRaces_AdminSetRaceRequest"; private static ConfigSync ModConfigSync; 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("valheim.races"); public static ValheimRacesPlugin Instance; 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 HornMalePrefab; private static GameObject HornFemalePrefab; private static bool IsApplyingRace = false; private static bool RpcRegistered = false; private static ZRoutedRpc RegisteredRpcInstance = null; private static readonly Dictionary<long, string> NetworkRaces = new Dictionary<long, string>(); private static readonly Dictionary<string, string> LastAppliedRace = new Dictionary<string, string>(); private static readonly Dictionary<string, Vector3> OriginalSkinColors = new Dictionary<string, Vector3>(); private static readonly Dictionary<string, float> LastSkinRefreshRequest = new Dictionary<string, float>(); private static readonly Dictionary<string, string> LastSkinRefreshRace = new Dictionary<string, string>(); private static readonly HashSet<long> KnownAdmins = new HashSet<long>(); private static readonly Dictionary<int, Transform> HeadCache = new Dictionary<int, Transform>(); private static readonly Dictionary<int, string> HeadCacheRace = new Dictionary<int, string>(); private static readonly Dictionary<int, int> ApplyRaceCoroutineGeneration = new Dictionary<int, int>(); private static readonly Dictionary<int, ZNetView> ZNetViewCache = new Dictionary<int, ZNetView>(); private float timer = 0f; private float syncTimer = 0f; private float localSaveTimer = 0f; private float adminCacheTimer = 0f; private float raceReconcileTimer = 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 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 OrcTuskUpperPosition = new Vector3(-0.00137f, 0.00114f, -0.00014f); private static readonly Vector3 OrcTuskUpperRotation = new Vector3(-16.932f, -110.817f, 8.571f); private static readonly Vector3 OrcTuskUpperScale = new Vector3(0.00494f, 0.005076f, 0.00559f); private static readonly Vector3 OrcTuskLowerPosition = new Vector3(-0.00137f, -0.006f, -0.00014f); private static readonly Vector3 OrcTuskLowerRotation = new Vector3(16.932f, -110.817f, 8.571f); private static readonly Vector3 OrcTuskLowerScale = new Vector3(0.00494f, 0.005076f, 0.00559f); private static readonly string[] SuppressedLogSubstrings = new string[5] { "Failed to find expected binary shader data in 'Custom/Player'", "Failed to find expected binary shader data in 'Custom/Creature'", "Failed to find expected binary shader data in 'Custom/Piece'", "Failed to find expected binary shader data in 'Lux Lit Particles/", "Failed to find expected binary shader data in 'Particles/Standard" }; private bool _isReloadingConfig; private static readonly Dictionary<string, Vector3> StillLastPos = new Dictionary<string, Vector3>(); private static readonly Dictionary<string, float> StillTimer = new Dictionary<string, float>(); private static readonly Dictionary<string, float> StillHealTimer = new Dictionary<string, float>(); private static readonly Dictionary<string, Vector3> DevotionStillLastPos = new Dictionary<string, Vector3>(); private static readonly Dictionary<string, float> DevotionStillTimer = new Dictionary<string, float>(); private static readonly Dictionary<string, float> DevotionStillHealTimer = new Dictionary<string, float>(); private static readonly Dictionary<string, float> SecondWindCooldownTimer = new Dictionary<string, float>(); private static readonly Dictionary<string, float> TremorAirTime = new Dictionary<string, float>(); private static readonly Dictionary<string, bool> TremorWasOnGround = new Dictionary<string, bool>(); private static bool _envNightWarningLogged; private const float BonusRegenSeconds = 30f; public static ConfigEntry<string> AesirAuraPrefab; public static ConfigEntry<string> VanirAuraPrefab; private static readonly HashSet<string> AuraPrefabWarned = new HashSet<string>(); private static readonly Dictionary<int, (float until, float speedFactor)> ChilledStatus = new Dictionary<int, (float, float)>(); private static float _lastChilledPurgeTime; private static readonly DamageModifier[] DamageModifierProtectionRank; private static readonly FieldInfo SkillsOwnerPlayerField; public static readonly Dictionary<string, RaceConfig> Races; private static ConfigFile MainConfigFile; public static ConfigEntry<float> EyeGlowPeak; public static ConfigEntry<bool> EmoteOnTransform; public static ConfigEntry<bool> VfxOnTransform; public static ConfigEntry<bool> FillVitalsOnTransform; public static ConfigEntry<bool> RacialAbilitiesEnabled; private static GameObject AltarPrefab; public static ConfigEntry<string> AltarRaces; public static ConfigEntry<string> AltarRecipe; public static ConfigEntry<string> AltarSwitchCostItem; public static ConfigEntry<int> AltarSwitchCostAmount; public static ConfigEntry<string> DevotionCostItem; public static ConfigEntry<int> DevotionCostAmount; public static ConfigEntry<float> DevotionScaleBonus; private static readonly Dictionary<string, Texture2D> EmbeddedTextureCache; private static readonly Dictionary<string, Font> ValheimFontCache; private static readonly string[] UiClickClipCandidates; private static readonly string[] ExcludedClipSubstrings; private static AudioClip _uiClickClip; private static bool _uiClickClipResolved; private static AudioSource _uiClickSource; private static readonly Dictionary<string, StatusEffect> RaceStatusEffects; private static Sprite _placeholderIcon; private static bool _placeholderIconResolved; private const string RaceIconResourceName = "race_icon.rgba"; private const int RaceIconSize = 128; private static readonly Dictionary<string, Sprite> RaceSpecificIcons; private const string ColorAccent = "#E8A33D"; private const string ColorAbilityBuff = "#8CFF8C"; private const string ColorAbilityDebuff = "#FF8C8C"; private static ConfigFile TextConfigFile; public static ConfigEntry<string> Text_AltarNome; public static ConfigEntry<string> Text_AltarDescricao; public static ConfigEntry<string> Text_AltarHoverEscolher; public static ConfigEntry<string> Text_AltarHoverTrocar; public static ConfigEntry<string> Text_UiEscolhaTitulo; public static ConfigEntry<string> Text_UiFechar; public static ConfigEntry<string> Text_UiTrocarBotao; public static ConfigEntry<string> Text_UiJaEscolheuTitulo; public static ConfigEntry<string> Text_UiMoedaInsuficiente; public static ConfigEntry<string> Text_UiNenhumaRacaDisponivel; public static ConfigEntry<string> Text_UiConfirmar; public static ConfigEntry<string> Text_UiCancelar; public static ConfigEntry<string> Text_UiConfirmarRaca; public static ConfigEntry<string> Text_UiConfirmarDeus; public static ConfigEntry<string> Text_ChampionBotao; public static ConfigEntry<string> Text_ChampionTitulo; public static ConfigEntry<string> Text_ChampionDescricao; public static ConfigEntry<string> Text_ChampionEscolherAesir; public static ConfigEntry<string> Text_ChampionEscolherVanir; public static ConfigEntry<string> Text_ChampionCustoInsuficiente; public static ConfigEntry<string> Text_ChampionSucesso; public static ConfigEntry<string> Text_ChampionNomeStatus; public static ConfigEntry<string> Text_ChampionSecaoStatus; public static readonly Dictionary<string, ConfigEntry<string>> RaceNameTexts; public static ConfigEntry<string> Text_SemPermissao; public static ConfigEntry<string> Text_UsoRaca; public static ConfigEntry<string> Text_RacaDesativadaAdmin; public static ConfigEntry<string> Text_PlayerNaoEncontrado; public static ConfigEntry<string> Text_PlayerNaoCarregado; public static ConfigEntry<string> Text_AgoraERaca; public static ConfigEntry<string> Text_RacaRemovida; public static ConfigEntry<string> Text_UsoOfflineReset; public static ConfigEntry<string> Text_IdInvalido; public static ConfigEntry<string> Text_OfflineResetado; public static ConfigEntry<string> Text_OfflineNaoEncontrado; public static ConfigEntry<string> Text_EssaRacaDesativada; public static ConfigEntry<string> Text_AgoraEuSou; public static ConfigEntry<string> Text_ConfigRecarregado; public static ConfigEntry<string> Text_CodigosSecretosAtivos; public static ConfigEntry<string> Text_VersaoDiferente; public static ConfigEntry<string> Text_DebugObjectDBNaoCarregou; public static ConfigEntry<string> Text_DebugItensComFireStaff; public static ConfigEntry<string> Text_DebugTotalItens; public static ConfigEntry<string> Text_DebugNenhumEncontrado; public static ConfigEntry<string> Text_DebugPlayerNaoCarregadoSimples; public static ConfigEntry<string> Text_DebugNenhumaFerramenta; public static ConfigEntry<string> Text_DebugFerramenta; public static ConfigEntry<string> Text_DebugPieceTableReal; public static ConfigEntry<string> Text_DebugTotalPecas; public static ConfigEntry<string> Text_DebugEstacaoPerto; public static ConfigEntry<string> Text_DebugNenhumaEstacao; public static ConfigEntry<string> Text_DebugErro; public static ConfigEntry<string> Text_VoceEvoluiu; public static ConfigEntry<string> Text_StatNomeRaca; public static ConfigEntry<string> Text_StatVidaMaxima; public static ConfigEntry<string> Text_StatStaminaMaxima; public static ConfigEntry<string> Text_StatEitrMaximo; public static ConfigEntry<string> Text_StatCapacidadeCarga; public static ConfigEntry<string> Text_StatRegenVida; public static ConfigEntry<string> Text_StatRegenStamina; public static ConfigEntry<string> Text_StatRegenEitr; public static ConfigEntry<string> Text_StatDanoCausado; public static ConfigEntry<string> Text_StatDanoComSkill; public static ConfigEntry<string> Text_StatDanoTipo; public static ConfigEntry<string> Text_StatDanoAtaqueFurtivo; public static ConfigEntry<string> Text_StatForcaEmpurrao; public static ConfigEntry<string> Text_StatDanoRecebido; public static ConfigEntry<string> Text_StatVelocidade; public static ConfigEntry<string> Text_StatFurtividade; public static ConfigEntry<string> Text_StatRouboVida; public static ConfigEntry<string> Text_StatGanhoXP; public static ConfigEntry<string> Text_StatRegenVelocidadeNoite; public static ConfigEntry<string> Text_StatSoANoite; public static ConfigEntry<string> Text_StatVidaNoiteDia; public static ConfigEntry<string> Text_StatVidaBioma; public static ConfigEntry<string> Text_StatFrioAmbiente; public static ConfigEntry<string> Text_StatNaoCongela; public static ConfigEntry<string> Text_StatModificadorDano; public static ConfigEntry<string> Text_StatSemBonus; public static ConfigEntry<string> Text_NivelImune; public static ConfigEntry<string> Text_NivelMuitoResistente; public static ConfigEntry<string> Text_NivelResistente; public static ConfigEntry<string> Text_NivelLevementeResistente; public static ConfigEntry<string> Text_NivelLevementeFraco; public static ConfigEntry<string> Text_NivelFraco; public static ConfigEntry<string> Text_NivelMuitoFraco; public static ConfigEntry<string> Text_NivelIgnora; public static ConfigEntry<string> Text_DanoBlunt; public static ConfigEntry<string> Text_DanoSlash; public static ConfigEntry<string> Text_DanoPierce; public static ConfigEntry<string> Text_DanoChop; public static ConfigEntry<string> Text_DanoPickaxe; public static ConfigEntry<string> Text_DanoFire; public static ConfigEntry<string> Text_DanoFrost; public static ConfigEntry<string> Text_DanoLightning; public static ConfigEntry<string> Text_DanoPoison; public static ConfigEntry<string> Text_DanoSpirit; public static ConfigEntry<string> Text_BiomaMeadows; public static ConfigEntry<string> Text_BiomaBlackForest; public static ConfigEntry<string> Text_BiomaSwamp; public static ConfigEntry<string> Text_BiomaMountain; public static ConfigEntry<string> Text_BiomaPlains; public static ConfigEntry<string> Text_BiomaMistlands; public static ConfigEntry<string> Text_BiomaAshLands; public static ConfigEntry<string> Text_BiomaDeepNorth; public static ConfigEntry<string> Text_BiomaOcean; public static ConfigEntry<string> Text_HabFuriaSangue; public static ConfigEntry<string> Text_HabFuriaSangueDesc; public static ConfigEntry<string> Text_HabAuraCura; public static ConfigEntry<string> Text_HabAuraCuraDesc; public static ConfigEntry<string> Text_HabAuraCuraSoDeDia; public static ConfigEntry<string> Text_HabPosturaFerro; public static ConfigEntry<string> Text_HabPosturaFerroDesc; public static ConfigEntry<string> Text_HabGolpeOportunidade; public static ConfigEntry<string> Text_HabGolpeOportunidadeDesc; public static ConfigEntry<string> Text_HabSegundoFolego; public static ConfigEntry<string> Text_HabSegundoFolegoDesc; public static ConfigEntry<string> Text_HabSedeSangue; public static ConfigEntry<string> Text_HabSedeSangueDesc; public static ConfigEntry<string> Text_HabSedeSangueSoDeNoite; public static ConfigEntry<string> Text_HabMantoSombras; public static ConfigEntry<string> Text_HabMantoSombrasDesc; public static ConfigEntry<string> Text_HabMantoSombrasSoDeNoite; public static ConfigEntry<string> Text_HabTremor; public static ConfigEntry<string> Text_HabTremorDesc; public static ConfigEntry<string> Text_HabAuraChamas; public static ConfigEntry<string> Text_HabAuraChamasDesc; public static ConfigEntry<string> Text_HabSoproGlacial; public static ConfigEntry<string> Text_HabSoproGlacialDesc; public static ConfigEntry<string> Text_HabToqueFlamejante; public static ConfigEntry<string> Text_HabToqueFlamejanteDesc; public static ConfigEntry<string> Text_HabToqueGelado; public static ConfigEntry<string> Text_HabToqueGeladoDesc; public static ConfigEntry<string> Text_HabToqueEspiritual; public static ConfigEntry<string> Text_HabToqueEspiritualDesc; private static readonly FieldInfo ModelIndexField; private static readonly MethodInfo SetSkinColorMethod; private static readonly MethodInfo SetHairColorMethod; private static readonly FieldInfo SkinColorField; private void RegisterAltarPiece() { //IL_00c6: 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_00d1: 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_0167: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)AltarPrefab == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[ValheimRaces] Prefab 'altar_racas' não encontrado — peça do Altar das Raças não registrada."); return; } if ((Object)(object)AltarPrefab.GetComponent<ZNetView>() == (Object)null) { AltarPrefab.AddComponent<ZNetView>(); } if ((Object)(object)AltarPrefab.GetComponent<WearNTear>() == (Object)null) { AltarPrefab.AddComponent<WearNTear>(); } if ((Object)(object)AltarPrefab.GetComponent<RaceAltar>() == (Object)null) { AltarPrefab.AddComponent<RaceAltar>(); } if ((Object)(object)AltarPrefab.GetComponentInChildren<Collider>() == (Object)null) { Renderer componentInChildren = AltarPrefab.GetComponentInChildren<Renderer>(); if ((Object)(object)componentInChildren != (Object)null) { BoxCollider val = AltarPrefab.AddComponent<BoxCollider>(); Bounds localBounds = componentInChildren.localBounds; val.center = ((Bounds)(ref localBounds)).center; val.size = ((Bounds)(ref localBounds)).size; ((BaseUnityPlugin)this).Logger.LogWarning((object)"[ValheimRaces] '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)"[ValheimRaces] 'altar_racas' não tem Collider nem Renderer — o altar provavelmente não vai responder a interação."); } } Piece val2 = AltarPrefab.GetComponent<Piece>() ?? AltarPrefab.AddComponent<Piece>(); val2.m_name = Text_AltarNome.Value; val2.m_description = Text_AltarDescricao.Value; val2.m_icon = LoadIconFromEmbedded("altar_icon.rgba") ?? GetPlaceholderIcon(); val2.m_category = (PieceCategory)0; val2.m_enabled = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[ValheimRaces] Peça 'Altar das Raças' preparada — entra na tabela do Martelo quando o mundo carregar."); } private static Requirement[] ParseAltarRecipe(ObjectDB objectDB, string recipe) { //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown List<Requirement> list = new List<Requirement>(); if (!string.IsNullOrWhiteSpace(recipe)) { string[] array = recipe.Split(new char[1] { ',' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ':' }); if (array2.Length != 2) { continue; } string text2 = array2[0].Trim(); if (string.IsNullOrWhiteSpace(text2) || !int.TryParse(array2[1].Trim(), out var result) || result <= 0) { continue; } GameObject itemPrefab = objectDB.GetItemPrefab(text2); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null) { ValheimRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("[ValheimRaces] Item '" + text2 + "' da receita do altar não encontrado — ignorado.")); } } else { list.Add(new Requirement { m_resItem = val, m_amount = result, m_recover = true }); } } } if (list.Count == 0) { GameObject itemPrefab2 = objectDB.GetItemPrefab("Wood"); ItemDrop val2 = (((Object)(object)itemPrefab2 != (Object)null) ? itemPrefab2.GetComponent<ItemDrop>() : null); if ((Object)(object)val2 != (Object)null) { list.Add(new Requirement { m_resItem = val2, m_amount = 10, m_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 (!LastSkinRefreshRace.TryGetValue(text, out var value) || !(value == race) || !LastSkinRefreshRequest.TryGetValue(text, out var value2) || !(time - value2 < 1.25f)) { LastSkinRefreshRequest[text] = time; LastSkinRefreshRace[text] = race; ((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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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 == "jotun" || race == "anao") { ApplyOrcEars(p, color); } else if (race == "elfodanoite" || race == "elfodaluz") { 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 == "elfodaluz" || race == "anao" || race == "cavaleirovalhalla") { QueueSkinRefresh(p, race); } } } public void RequestOnlineVisualRefresh(VisEquipment vis) { if (!IsHeadless() && !((Object)(object)vis == (Object)null)) { Player val = ((Component)vis).GetComponent<Player>() ?? ((Component)vis).GetComponentInParent<Player>(); 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<Player>() ?? ((Component)vis).GetComponentInParent<Player>(); if (!((Object)(object)val == (Object)null)) { string race = GetRace(val); if (RaceUsesForcedSkin(race) || race == "elfodaluz" || race == "anao" || race == "cavaleirovalhalla") { 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<ZNetView>(); 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_027e: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_04a0: Unknown result type (might be due to invalid IL or missing references) //IL_0549: Unknown result type (might be due to invalid IL or missing references) //IL_054e: Unknown result type (might be due to invalid IL or missing references) //IL_05e2: Unknown result type (might be due to invalid IL or missing references) //IL_05e7: Unknown result type (might be due to invalid IL or missing references) //IL_058b: Unknown result type (might be due to invalid IL or missing references) //IL_0590: Unknown result type (might be due to invalid IL or missing references) //IL_0510: Unknown result type (might be due to invalid IL or missing references) //IL_0515: Unknown result type (might be due to invalid IL or missing references) //IL_04ce: Unknown result type (might be due to invalid IL or missing references) //IL_04d3: 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) { ResetHelmet(p); } ApplyScale(p, HumanScale); if (!flag) { if (RaceUsesForcedSkin(value)) { ResetSkin(p); } Transform cachedHead = GetCachedHead(p, race); RemoveHeadAttachmentDirect(((Component)p).transform, "Ears"); RemoveHeadAttachmentDirect(((Component)p).transform, "OrcEars"); RemoveHeadAttachmentDirect(cachedHead, "HighElfEyes"); RemoveHeadAttachmentDirect(cachedHead, "OrcTuskUpper"); RemoveHeadAttachmentDirect(cachedHead, "OrcTuskLower"); RemoveHeadAttachmentDirect(((Component)p).transform, "Horn"); RemovePlayerAttachment(p, "JotunFreeze"); RemoveConstantAura(p); } 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); RemoveHeadAttachmentDirect(((Component)p).transform, "Ears"); RemoveHeadAttachmentDirect(((Component)p).transform, "OrcEars"); RemoveHeadAttachmentDirect(head, "HighElfEyes"); RemoveHeadAttachmentDirect(head, "OrcTuskUpper"); RemoveHeadAttachmentDirect(head, "OrcTuskLower"); RemoveHeadAttachmentDirect(((Component)p).transform, "Horn"); RemovePlayerAttachment(p, "JotunFreeze"); RemoveConstantAura(p); } return; } ApplyScale(p, GetFinalScale(p, race)); ScaleCurrentHelmetForRace(p, GetFinalScale(p, 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); bool isFemale = IsFemaleModel(p); switch (race) { case "elfodanoite": case "elfodaluz": ApplyEarsDirect(((Component)p).transform, ToColor(GetRaceEarColor(p, race)), isFemale); QueueSkinRefresh(p, race); ApplyHighElfEyesDirect(p, cachedHead2); break; case "anao": ApplyOrcEarsDirect(((Component)p).transform, ToColor(GetRaceEarColor(p, race)), isFemale); QueueSkinRefresh(p, race); ApplyHighElfEyesDirect(p, cachedHead2); break; case "humano": ApplyHighElfEyesDirect(p, cachedHead2); break; case "jotun": ApplyOrcEarsDirect(((Component)p).transform, ToColor(GetRaceEarColor(p, race)), isFemale); ApplyHornDirect(((Component)p).transform, isFemale); ApplyHighElfEyesDirect(p, cachedHead2); break; case "efrit": ApplyEarsDirect(((Component)p).transform, ToColor(GetRaceEarColor(p, race)), isFemale); ApplyHornDirect(((Component)p).transform, isFemale); ApplyHighElfEyesDirect(p, cachedHead2); QueueSkinRefresh(p, race); break; case "orc": ApplyOrcEarsDirect(((Component)p).transform, ToColor(GetRaceEarColor(p, race)), isFemale); ApplyOrcTuskDirect(cachedHead2); ApplyHighElfEyesDirect(p, cachedHead2); QueueSkinRefresh(p, race); break; case "aesir": ApplyHighElfEyesDirect(p, cachedHead2); ApplyConstantAura(p, race); QueueSkinRefresh(p, race); break; case "vanir": ApplyEarsDirect(((Component)p).transform, ToColor(GetRaceEarColor(p, race)), isFemale); ApplyHornDirect(((Component)p).transform, isFemale: true); ApplyHighElfEyesDirect(p, cachedHead2); ApplyConstantAura(p, race); QueueSkinRefresh(p, race); break; case "cavaleirovalhalla": ApplyHighElfEyesDirect(p, cachedHead2); QueueSkinRefresh(p, race); break; } } } finally { IsApplyingRace = false; } } public void SpawnEffect(Player p) { //IL_004f: 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_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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) if (VfxOnTransform != null && VfxOnTransform.Value && !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<GameObject>(prefab, val, rotation); } if ((Object)(object)prefab2 != (Object)null) { Object.Instantiate<GameObject>(prefab2, val, rotation); } } } private static void ScaleCurrentHelmetForRace(Player p, Vector3 targetScale) { //IL_006f: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: 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<VisEquipment>(); object? obj = HelmetInstanceField?.GetValue(component); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)val.transform.parent == (Object)null)) { Vector3 lossyScale = val.transform.parent.lossyScale; Vector3 localScale = default(Vector3); ((Vector3)(ref localScale))..ctor(Mathf.Approximately(lossyScale.x, 0f) ? targetScale.x : (targetScale.x / lossyScale.x), Mathf.Approximately(lossyScale.y, 0f) ? targetScale.y : (targetScale.y / lossyScale.y), Mathf.Approximately(lossyScale.z, 0f) ? targetScale.z : (targetScale.z / lossyScale.z)); val.transform.localScale = localScale; } } catch (Exception ex) { ValheimRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("[ValheimRaces] 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 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 void RegisterCommands() { RegisterRaceCommand("elfodaluz"); RegisterRaceCommand("elfodanoite"); RegisterRaceCommand("anao"); RegisterRaceCommand("humano"); RegisterRaceCommand("jotun"); RegisterRaceCommand("efrit"); RegisterRaceCommand("orc"); RegisterRaceCommand("cavaleirovalhalla"); RegisterRaceCommand("aesir"); RegisterRaceCommand("vanir"); RegisterResetRaceCommand(); RegisterOfflineResetCommand(); ReRegisterSecretCodeCommands(); RegisterReloadCommand(); RegisterListFireItemsCommand(); RegisterWhatPieceTableCommand(); RegisterInspectPrefabCommand(); RegisterCheckBodyCommand(); RegisterListPrefabsCommand(); RegisterListSoundsCommand(); RegisterTestSoundCommand(); RegisterInspectHeatCommand(); } private void RegisterInspectHeatCommand() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0023: 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; } Both("[vr_inspecionar_frio] Membros de Player/Character com 'Heat'/'Cold'/'Freez'/'Comfort'/'Wet' no nome:"); string[] array = new string[5] { "heat", "cold", "freez", "comfort", "wet" }; int num = 0; Type[] array2 = new Type[3] { typeof(Player), typeof(Character), typeof(Humanoid) }; foreach (Type type in array2) { MemberInfo[] members = type.GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); MemberInfo[] array3 = members; foreach (MemberInfo memberInfo in array3) { if (memberInfo is MethodInfo || memberInfo is FieldInfo || memberInfo is PropertyInfo) { string text = memberInfo.Name.ToLowerInvariant(); bool flag = false; string[] array4 = array; foreach (string value in array4) { if (text.Contains(value)) { flag = true; break; } } if (flag && !text.StartsWith("get_") && !text.StartsWith("set_")) { string text2 = ((!(memberInfo is MethodInfo methodInfo)) ? ((!(memberInfo is FieldInfo fieldInfo)) ? ("[prop] " + ((PropertyInfo)memberInfo).PropertyType.Name + " " + type.Name + "." + memberInfo.Name) : ("[campo] " + fieldInfo.FieldType.Name + " " + type.Name + "." + fieldInfo.Name)) : ("[método] " + methodInfo.ReturnType.Name + " " + type.Name + "." + methodInfo.Name + "(" + string.Join(", ", Array.ConvertAll(methodInfo.GetParameters(), (ParameterInfo pi) => pi.ParameterType.Name)) + ")")); Both("[vr_inspecionar_frio] " + text2); num++; } } } } Both($"[vr_inspecionar_frio] {num} membro(s) encontrado(s)."); return true; void Both(string line) { args.Context.AddString(line); ((BaseUnityPlugin)this).Logger.LogInfo((object)line); } }; new ConsoleCommand("vr_inspecionar_frio", "vr_inspecionar_frio — lista métodos/campos de Player/Character/Humanoid relacionados a frio/calor (debug)", val, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private void RegisterListSoundsCommand() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0023: 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("Uso: vr_listar_sons TrechoDoNome"); return false; } ListAudioClipsContaining(Both, args.Args[1]); return true; void Both(string line) { args.Context.AddString(line); ((BaseUnityPlugin)this).Logger.LogInfo((object)line); } }; new ConsoleCommand("vr_listar_sons", "vr_listar_sons TrechoDoNome — lista clipes de áudio carregados com esse nome (debug)", val, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private void RegisterTestSoundCommand() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0023: 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("Uso: vr_testarsom TrechoDoNome"); return false; } return PlayAudioClipContaining(Both, args.Args[1]); void Both(string line) { args.Context.AddString(line); ((BaseUnityPlugin)this).Logger.LogInfo((object)line); } }; new ConsoleCommand("vr_testarsom", "vr_testarsom TrechoDoNome — toca o primeiro clipe carregado com esse nome (debug)", val, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private void RegisterListPrefabsCommand() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0023: 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("Uso: vr_listar_prefabs TrechoDoNome"); return false; } if ((Object)(object)ZNetScene.instance == (Object)null) { args.Context.AddString("[vr_listar_prefabs] ZNetScene ainda não carregado (entre no mundo primeiro)."); return false; } string text = args.Args[1].ToLowerInvariant(); int num = 0; try { if (typeof(ZNetScene).GetField("m_namedPrefabs", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(ZNetScene.instance) is IDictionary dictionary) { foreach (object value in dictionary.Values) { GameObject val2 = (GameObject)((value is GameObject) ? value : null); if (!((Object)(object)val2 == (Object)null) && ((Object)val2).name.ToLowerInvariant().Contains(text)) { Both("[vr_listar_prefabs] " + ((Object)val2).name); num++; } } } else { Both("[vr_listar_prefabs] Não achei o campo 'm_namedPrefabs' no ZNetScene (versão do jogo mudou?)."); } } catch (Exception ex) { Both("[vr_listar_prefabs] Erro ao procurar: " + ex.Message); } Both($"[vr_listar_prefabs] {num} prefab(s) encontrados contendo '{text}'."); return true; void Both(string line) { args.Context.AddString(line); ((BaseUnityPlugin)this).Logger.LogInfo((object)line); } }; new ConsoleCommand("vr_listar_prefabs", "vr_listar_prefabs TrechoDoNome — lista prefabs do ZNetScene com esse nome (debug)", val, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static SkinnedMeshRenderer FindBodyRenderer(Transform root) { if ((Object)(object)root == (Object)null) { return null; } SkinnedMeshRenderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val in componentsInChildren) { if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name.ToLowerInvariant() == "body") { return val; } } return null; } private static void DumpMeshInfo(Action<string> log, string label, SkinnedMeshRenderer smr) { Mesh val = (((Object)(object)smr != (Object)null) ? smr.sharedMesh : null); if ((Object)(object)val == (Object)null) { log("[vr_verificar_corpo] " + label + ": mesh=null"); return; } log($"[vr_verificar_corpo] {label}: mesh='{((Object)val).name}' subMeshCount={val.subMeshCount}"); Material[] sharedMaterials = ((Renderer)smr).sharedMaterials; for (int i = 0; i < val.subMeshCount; i++) { int num = 0; try { num = val.GetTriangles(i).Length / 3; } catch { } string text = ((i < sharedMaterials.Length && (Object)(object)sharedMaterials[i] != (Object)null) ? ((Object)sharedMaterials[i]).name : "(sem material)"); log($"[vr_verificar_corpo] {label}: submesh[{i}] tris={num} material='{text}'"); } } private void RegisterCheckBodyCommand() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) ConsoleEventFailable val = (ConsoleEventFailable)delegate(ConsoleEventArgs args) { //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Expected O, but got Unknown //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: 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_019b: 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_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_043c: Unknown result type (might be due to invalid IL or missing references) //IL_044b: Unknown result type (might be due to invalid IL or missing references) //IL_045a: Unknown result type (might be due to invalid IL or missing references) //IL_0469: Unknown result type (might be due to invalid IL or missing references) //IL_0478: Unknown result type (might be due to invalid IL or missing references) if (!HasDevCommands()) { args.Context.AddString(Text_SemPermissao.Value); return false; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { Both("[vr_verificar_corpo] Sem player local (entre no mundo primeiro)."); return false; } SkinnedMeshRenderer val2 = FindBodyRenderer(((Component)localPlayer).transform); if ((Object)(object)val2 == (Object)null) { Both("[vr_verificar_corpo] Não achei o renderer 'body' do player."); return false; } Both("[vr_verificar_corpo] Raça atual: '" + GetRace(localPlayer) + "'"); DumpMeshInfo(Both, "body", val2); Both($"[vr_verificar_corpo] HasPropertyBlock = {((Renderer)val2)