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 GlitnirRacesKingdom v0.0.6
GlitnirRaces.dll
Decompiled 2 weeks 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.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("GlitnirRaces")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GlitnirRaces")] [assembly: AssemblyTitle("GlitnirRaces")] [assembly: AssemblyVersion("1.0.0.0")] [BepInPlugin("glitnir.races", "Glitnir Races", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class GlitnirRacesPlugin : BaseUnityPlugin { public class RaceConfig { public string RaceId; public string DisplayName; public ConfigEntry<bool> Enabled; public ConfigEntry<string> Scale; public ConfigEntry<string> SkinColor; public ConfigEntry<string> HairColor; public ConfigEntry<string> EarColor; public ConfigEntry<string> EyeColor; public ConfigEntry<string> SecretCode; public ConfigEntry<float> HealthBonus; public ConfigEntry<float> StaminaBonus; public ConfigEntry<float> EitrBonus; public ConfigEntry<float> CarryWeightBonus; public ConfigEntry<float> HealthRegenMultiplier; public ConfigEntry<float> StaminaRegenMultiplier; public ConfigEntry<float> EitrRegenMultiplier; public ConfigEntry<float> DamageDoneMultiplier; public ConfigEntry<float> BackstabMultiplier; public ConfigEntry<float> DamageTakenMultiplier; public ConfigEntry<float> LifestealPercent; public ConfigEntry<float> StealthMultiplier; public ConfigEntry<float> SpeedMultiplier; public ConfigEntry<string> Resistances; public ConfigEntry<float> HeatResistanceBonus; public ConfigEntry<float> LowHealthThreshold; public ConfigEntry<float> LowHealthDamageBonus; public ConfigEntry<bool> StillHealAura; public ConfigEntry<float> StillHealAmount; public ConfigEntry<float> StillHealInterval; public ConfigEntry<float> StillHealRequiredStillTime; public ConfigEntry<bool> StillHealDayOnly; public ConfigEntry<bool> IronStanceEnabled; public ConfigEntry<float> IronStanceExtraDamageReduction; public ConfigEntry<bool> SecondWindEnabled; public ConfigEntry<float> SecondWindThreshold; public ConfigEntry<float> SecondWindHealAmount; public ConfigEntry<float> SecondWindStaminaAmount; public ConfigEntry<float> SecondWindCooldown; public ConfigEntry<string> SkillDamageMultipliers; public ConfigEntry<string> AttackDamageTypeMultipliers; public ConfigEntry<bool> NoResourceCost; public ConfigEntry<float> XpGainMultiplier; public ConfigEntry<float> KnockbackMultiplier; public ConfigEntry<float> EitrCostMultiplier; public ConfigEntry<string> StaminaCostModifiers; public ConfigEntry<bool> NightOnlyBonuses; public ConfigEntry<float> DayNightHealthShift; public ConfigEntry<string> BiomeHealthShifts; } private enum RaceAbility { None, Orc, Elf, Dwarf, Human } [HarmonyPatch(typeof(FejdStartup), "SetupCharacterPreview")] private static class FejdCharacterPreviewPatch { private static void Postfix(FejdStartup __instance, PlayerProfile profile) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)("[GlitnirRaces/Preview] SetupCharacterPreview disparou pro perfil '" + ((profile != null) ? profile.GetName() : null) + "'.")); } try { ApplyPreviewRace(__instance, profile); } catch (Exception arg) { GlitnirRacesPlugin instance2 = Instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Logger.LogWarning((object)$"Falha ao aplicar raça no preview do menu: {arg}"); } } } } [HarmonyPatch(typeof(Player), "OnSpawned")] private static class PlayerSpawnedPatch { private static void Postfix(Player __instance) { if ((Object)(object)__instance == (Object)null || (Object)(object)Instance == (Object)null) { return; } if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { Instance.RestoreLocalSavedRaceIfNeeded(); SendVersionCheckToServer(); } if (IsPlayerLocked(__instance)) { SetZdoLocked(__instance, locked: true); } Instance.ApplyRaceWithDelays(__instance); if (!IsHeadless()) { string race = GetRace(__instance); if (!string.IsNullOrWhiteSpace(race)) { UpdateRaceStatusEffect(__instance, race); } } } } [HarmonyPatch(typeof(Player), "OnDeath")] private static class PlayerDeathPatch { private static void Postfix(Player __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)Instance == (Object)null) && !IsHeadless()) { Instance.ApplyRaceWithDelays(__instance); string race = GetRace(__instance); if (!string.IsNullOrWhiteSpace(race)) { UpdateRaceStatusEffect(__instance, race); } } } } [HarmonyPatch(typeof(Player), "CreateDeathEffects")] private static class PlayerRagdollRacePatch { private static void Postfix(Player __instance) { if ((Object)(object)Instance == (Object)null || IsHeadless() || (Object)(object)__instance == (Object)null) { return; } Ragdoll ragdoll = __instance.GetRagdoll(); if ((Object)(object)ragdoll == (Object)null) { return; } string race = GetRace(__instance); if (string.IsNullOrWhiteSpace(race) || !IsRaceEnabled(race)) { return; } try { ZNetView component = ((Component)ragdoll).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.GetZDO() != null) { component.GetZDO().Set("GlitnirRagdollRace", race); } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("[GlitnirRaces] Falha ao gravar raça no ZDO do ragdoll: " + ex.Message)); } ApplyRaceVisualToRagdoll(ragdoll, race); } } [HarmonyPatch(typeof(Ragdoll), "Awake")] private static class RagdollAwakePatch { private static void Postfix(Ragdoll __instance) { if ((Object)(object)Instance == (Object)null || IsHeadless() || (Object)(object)__instance == (Object)null) { return; } try { ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.GetZDO() != null) { string text = component.GetZDO().GetString("GlitnirRagdollRace", ""); if (!string.IsNullOrWhiteSpace(text) && IsRaceEnabled(text)) { ApplyRaceVisualToRagdoll(__instance, text); } } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("[GlitnirRaces] Falha ao ler raça do ZDO do ragdoll: " + ex.Message)); } } } [HarmonyPatch(typeof(ZNet), "Disconnect")] private static class ZNetDisconnectPatch { private static void Prefix(ZNetPeer peer) { if (peer == null) { return; } try { OnPeerDisconnected(peer.m_uid); } catch { } } } [HarmonyPatch(typeof(ZNet), "Shutdown")] private static class ZNetShutdownPatch { private static void Prefix() { NetworkRaces.Clear(); LastAppliedRace.Clear(); OriginalSkinColors.Clear(); LastSkinRefreshRequest.Clear(); KnownAdmins.Clear(); HeadCache.Clear(); HeadCacheRace.Clear(); ApplyRaceCoroutineGeneration.Clear(); ZNetViewCache.Clear(); PendingAltarSwitch.Clear(); _cachedSavePrefix = null; _cachedZNetInstance = null; _cachedCharacterId = 0L; _cachedServerKey = null; RpcRegistered = false; RegisteredRpcInstance = null; if ((Object)(object)Instance != (Object)null) { Instance.lastBroadcastRace = null; Instance.isRestoringLocalRace = false; } } } [HarmonyPatch(typeof(VisEquipment), "SetHelmetItem")] private static class HelmetScaleOnEquipPatch { private static void Postfix(VisEquipment __instance) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && !IsHeadless()) { Player component = ((Component)__instance).GetComponent<Player>(); if (!((Object)(object)component == (Object)null)) { string race = GetRace(component); Vector3 targetScale = ((!string.IsNullOrWhiteSpace(race) && IsRaceEnabled(race)) ? GetRaceScale(race) : HumanScale); ScaleCurrentHelmetForRace(component, targetScale); } } } } [HarmonyPatch(typeof(VisEquipment), "SetHairColor")] private static class ForceRaceHairColorPatch { private static void Prefix(VisEquipment __instance, ref Vector3 __0) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || IsApplyingRace) { return; } Player component = ((Component)__instance).GetComponent<Player>(); if (!((Object)(object)component == (Object)null)) { string race = GetRace(component); if (RaceUsesForcedHair(race)) { __0 = GetRaceHairColor(race); } } } } [HarmonyPatch(typeof(VisEquipment), "SetSkinColor")] private static class PreventForcedRaceSkinOverridePatch { private static bool Prefix(VisEquipment __instance, Vector3 __0) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || IsApplyingRace) { return true; } Player component = ((Component)__instance).GetComponent<Player>(); if ((Object)(object)component == (Object)null) { return true; } string race = GetRace(component); if (!RaceUsesForcedSkin(race)) { return true; } CacheOriginalSkinValue(component, __0); if ((Object)(object)Instance != (Object)null) { Instance.ForceSkinAfterVanilla(component, race); } return false; } } [HarmonyPatch] private static class VisEquipmentOnlineRefreshPatch { private static IEnumerable<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[3] { "UpdateEquipment", "OnInventoryChanged", "UpdateVisual" }; string[] array = names; foreach (string name in array) { MethodInfo method = AccessTools.Method(typeof(Player), name, (Type[])null, (Type[])null); if (method != null) { yield return method; } } } private static void Postfix(Player __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)Instance == (Object)null) && !IsApplyingRace && !IsHeadless()) { Instance.RequestOnlineVisualRefresh(__instance); } } } [HarmonyPatch(typeof(Character), "SetVisible")] private static class CharacterSetVisiblePatch { private static void Postfix(Character __instance, bool visible) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (!visible || (Object)(object)__instance == (Object)null || (Object)(object)Instance == (Object)null || IsHeadless()) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null)) { string race = GetRace(val); if (!string.IsNullOrWhiteSpace(race) && IsRaceEnabled(race)) { ApplyScale(val, GetRaceScale(race)); } } } } [HarmonyPatch(typeof(Chat), "InputText")] private static class ChatPatch { private static bool Prefix(Chat __instance) { if ((Object)(object)__instance == (Object)null) { return true; } string text = ""; try { FieldInfo field = typeof(Chat).GetField("m_input", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { return true; } object value = field.GetValue(__instance); if (value == null) { return true; } text = (value.GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public)?.GetValue(value) as string)?.Trim() ?? ""; } catch { return true; } string raceFromSecretCode = GetRaceFromSecretCode(text); if (raceFromSecretCode == null) { return true; } TransformLocalPlayerFromMarketplace(raceFromSecretCode); try { object obj2 = typeof(Chat).GetField("m_input", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(__instance); PropertyInfo propertyInfo = obj2?.GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public); if (propertyInfo != null && propertyInfo.CanWrite) { propertyInfo.SetValue(obj2, ""); } } catch { } return false; } } [HarmonyPatch(typeof(Player), "SetMaxHealth")] private static class RaceMaxHealthPatch { private static Dictionary<Biome, float> ParseBiomeShifts(string value) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) Dictionary<Biome, float> dictionary = new Dictionary<Biome, float>(); if (string.IsNullOrWhiteSpace(value)) { return dictionary; } string[] array = value.Split(new char[1] { ',' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ':' }); if (array2.Length == 2 && Enum.TryParse<Biome>(array2[0].Trim(), ignoreCase: true, out Biome result) && float.TryParse(array2[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { dictionary[result] = result2; } } return dictionary; } private static void Prefix(Player __instance, ref float health) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (!TryGetRaceConfig(__instance, out var cfg)) { return; } health += cfg.HealthBonus.Value; if (cfg.DayNightHealthShift.Value != 0f) { health += (IsNightSafe() ? cfg.DayNightHealthShift.Value : (0f - cfg.DayNightHealthShift.Value)); } if (!string.IsNullOrWhiteSpace(cfg.BiomeHealthShifts.Value)) { try { Biome currentBiome = __instance.GetCurrentBiome(); Dictionary<Biome, float> dictionary = ParseBiomeShifts(cfg.BiomeHealthShifts.Value); if (dictionary.TryGetValue(currentBiome, out var value)) { health += value; } } catch (Exception ex) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("[GlitnirRaces] Falha ao ler bioma atual pra oscilação de vida: " + ex.Message)); } } } if (health < 10f) { health = 10f; } } } [HarmonyPatch(typeof(Player), "SetMaxStamina")] private static class RaceMaxStaminaPatch { private static void Prefix(Player __instance, ref float stamina) { if (TryGetRaceConfig(__instance, out var cfg)) { stamina += cfg.StaminaBonus.Value; } } } [HarmonyPatch(typeof(Player), "SetMaxEitr")] private static class RaceMaxEitrPatch { private static void Prefix(Player __instance, ref float eitr) { if (TryGetRaceConfig(__instance, out var cfg)) { eitr += cfg.EitrBonus.Value; } } } [HarmonyPatch(typeof(Player), "GetMaxCarryWeight")] private static class RaceMaxCarryWeightPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += cfg.CarryWeightBonus.Value; } } } [HarmonyPatch(typeof(Character), "Heal")] private static class RaceHealthRegenPatch { private static void Prefix(Character __instance, ref float hp) { if (!(hp <= 0f)) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg) && (!cfg.NightOnlyBonuses.Value || IsNightSafe())) { hp *= cfg.HealthRegenMultiplier.Value; } } } } [HarmonyPatch(typeof(Character), "AddStamina")] private static class RaceStaminaRegenPatch { private static void Prefix(Character __instance, ref float v) { if (!(v <= 0f)) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg) && (!cfg.NightOnlyBonuses.Value || IsNightSafe())) { v *= cfg.StaminaRegenMultiplier.Value; } } } } [HarmonyPatch(typeof(Character), "AddEitr")] private static class RaceEitrRegenPatch { private static void Prefix(Character __instance, ref float v) { if (!(v <= 0f)) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg) && (!cfg.NightOnlyBonuses.Value || IsNightSafe())) { v *= cfg.EitrRegenMultiplier.Value; } } } } [HarmonyPatch(typeof(Player), "UseStamina")] private static class RaceNoStaminaCostPatch { private static void Prefix(Player __instance, ref float v) { if (TryGetRaceConfig(__instance, out var cfg) && cfg.NoResourceCost.Value) { v = 0f; } } } [HarmonyPatch(typeof(Player), "UseEitr")] private static class RaceNoEitrCostPatch { private static void Prefix(Player __instance, ref float v) { if (TryGetRaceConfig(__instance, out var cfg) && cfg.NoResourceCost.Value) { v = 0f; } } } [HarmonyPatch(typeof(Character), "TryUseEitr")] private static class RaceNoEitrCostTryPatch { private static bool Prefix(Character __instance, ref bool __result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val == (Object)null || !TryGetRaceConfig(val, out var cfg) || !cfg.NoResourceCost.Value) { return true; } __result = true; return false; } } [HarmonyPatch(typeof(Character), "GetDamageModifier")] private static class RaceResistancePatch { private static void Postfix(Character __instance, DamageType damageType, ref DamageModifier __result) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected I4, but got Unknown if (__result) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg)) { Dictionary<DamageType, DamageModifier> dictionary = ParseResistances(cfg.Resistances.Value); if (dictionary.TryGetValue(damageType, out var value)) { __result = (DamageModifier)(int)value; } } } } [HarmonyPatch(typeof(Character), "Damage")] private static class RaceDamagePatch { private static void Prefix(Character __instance, HitData hit) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) if (hit == null) { return; } _ = hit.m_damage; if (false) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val != (Object)null && TryGetRaceConfig(val, out var cfg)) { if (cfg.DamageTakenMultiplier.Value != 1f) { ScaleDamage(ref hit.m_damage, cfg.DamageTakenMultiplier.Value); } if (RacialAbilitiesEnabled.Value && cfg.IronStanceEnabled != null && cfg.IronStanceEnabled.Value && cfg.IronStanceExtraDamageReduction.Value > 0f && ((Character)val).IsBlocking()) { ScaleDamage(ref hit.m_damage, 1f - cfg.IronStanceExtraDamageReduction.Value); hit.m_pushForce = 0f; } } Character attacker = hit.GetAttacker(); Player val2 = (Player)(object)((attacker is Player) ? attacker : null); if (!((Object)(object)val2 != (Object)null) || !TryGetRaceConfig(val2, out var cfg2)) { return; } float num = cfg2.DamageDoneMultiplier.Value; Dictionary<SkillType, float> dictionary = ParseSkillMultipliers(cfg2.SkillDamageMultipliers.Value); if (dictionary.TryGetValue(hit.m_skill, out var value)) { num *= value; } if (RacialAbilitiesEnabled.Value && cfg2.LowHealthThreshold != null && cfg2.LowHealthThreshold.Value > 0f && ((Character)val2).GetMaxHealth() > 0f && ((Character)val2).GetHealth() / ((Character)val2).GetMaxHealth() <= cfg2.LowHealthThreshold.Value) { num *= cfg2.LowHealthDamageBonus.Value; } if (num != 1f) { ScaleDamage(ref hit.m_damage, num); } Dictionary<DamageType, float> dictionary2 = ParseTypeMultipliers(cfg2.AttackDamageTypeMultipliers.Value); if (dictionary2.Count > 0) { ScaleDamageByType(ref hit.m_damage, dictionary2); } if (cfg2.BackstabMultiplier.Value != 1f) { hit.m_backstabBonus *= cfg2.BackstabMultiplier.Value; } if (cfg2.KnockbackMultiplier.Value != 1f) { hit.m_pushForce *= cfg2.KnockbackMultiplier.Value; } if (cfg2.XpGainMultiplier.Value != 1f) { hit.m_skillRaiseAmount *= cfg2.XpGainMultiplier.Value; } if (cfg2.LifestealPercent.Value > 0f) { float totalDamage = hit.GetTotalDamage(); if (totalDamage > 0f) { ((Character)val2).Heal(totalDamage * cfg2.LifestealPercent.Value, false); } } } private static void ScaleDamageByType(ref DamageTypes dmg, Dictionary<DamageType, float> mults) { if (mults.TryGetValue((DamageType)1, out var value)) { dmg.m_blunt *= value; } if (mults.TryGetValue((DamageType)2, out var value2)) { dmg.m_slash *= value2; } if (mults.TryGetValue((DamageType)4, out var value3)) { dmg.m_pierce *= value3; } if (mults.TryGetValue((DamageType)8, out var value4)) { dmg.m_chop *= value4; } if (mults.TryGetValue((DamageType)16, out var value5)) { dmg.m_pickaxe *= value5; } if (mults.TryGetValue((DamageType)32, out var value6)) { dmg.m_fire *= value6; } if (mults.TryGetValue((DamageType)64, out var value7)) { dmg.m_frost *= value7; } if (mults.TryGetValue((DamageType)128, out var value8)) { dmg.m_lightning *= value8; } if (mults.TryGetValue((DamageType)256, out var value9)) { dmg.m_poison *= value9; } if (mults.TryGetValue((DamageType)512, out var value10)) { dmg.m_spirit *= value10; } } private static void ScaleDamage(ref DamageTypes dmg, float mult) { dmg.m_blunt *= mult; dmg.m_slash *= mult; dmg.m_pierce *= mult; dmg.m_chop *= mult; dmg.m_pickaxe *= mult; dmg.m_fire *= mult; dmg.m_frost *= mult; dmg.m_lightning *= mult; dmg.m_poison *= mult; dmg.m_spirit *= mult; } } [HarmonyPatch(typeof(Character), "GetStealthFactor")] private static class RaceStealthPatch { private static void Postfix(Character __instance, ref float __result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg)) { __result *= cfg.StealthMultiplier.Value; } } } [HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[] { typeof(int), typeof(bool), typeof(int), typeof(int) })] private static class RaceBlockFreezingStatusPatch { private static bool Prefix(SEMan __instance, int nameHash, ref StatusEffect __result) { if (nameHash != SEMan.s_statusEffectFreezing && nameHash != SEMan.s_statusEffectCold) { return true; } Character sEManOwner = GetSEManOwner(__instance); Player val = (Player)(object)((sEManOwner is Player) ? sEManOwner : null); if ((Object)(object)val == (Object)null || !TryGetRaceConfig(val, out var cfg) || cfg.HeatResistanceBonus.Value == 0f) { return true; } __result = null; return false; } } [HarmonyPatch(typeof(Character), "GetJogSpeedFactor")] private static class RaceJogSpeedPatch { private static void Postfix(Character __instance, ref float __result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg) && (!cfg.NightOnlyBonuses.Value || IsNightSafe())) { __result *= cfg.SpeedMultiplier.Value; } } } [HarmonyPatch(typeof(Character), "GetRunSpeedFactor")] private static class RaceRunSpeedPatch { private static void Postfix(Character __instance, ref float __result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg) && (!cfg.NightOnlyBonuses.Value || IsNightSafe())) { __result *= cfg.SpeedMultiplier.Value; } } } [HarmonyPatch(typeof(Player), "GetEquipmentAttackStaminaModifier")] private static class RaceStaminaCostAttackPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += GetStaminaCostModifier(cfg, "Attack"); } } } [HarmonyPatch(typeof(Player), "GetEquipmentBlockStaminaModifier")] private static class RaceStaminaCostBlockPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += GetStaminaCostModifier(cfg, "Block"); } } } [HarmonyPatch(typeof(Player), "GetEquipmentDodgeStaminaModifier")] private static class RaceStaminaCostDodgePatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += GetStaminaCostModifier(cfg, "Dodge"); } } } [HarmonyPatch(typeof(Player), "GetEquipmentJumpStaminaModifier")] private static class RaceStaminaCostJumpPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += GetStaminaCostModifier(cfg, "Jump"); } } } [HarmonyPatch(typeof(Player), "GetEquipmentRunStaminaModifier")] private static class RaceStaminaCostRunPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += GetStaminaCostModifier(cfg, "Run"); } } } [HarmonyPatch(typeof(Player), "GetEquipmentSneakStaminaModifier")] private static class RaceStaminaCostSneakPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += GetStaminaCostModifier(cfg, "Sneak"); } } } [HarmonyPatch(typeof(Player), "GetEquipmentSwimStaminaModifier")] private static class RaceStaminaCostSwimPatch { private static void Postfix(Player __instance, ref float __result) { if (TryGetRaceConfig(__instance, out var cfg)) { __result += GetStaminaCostModifier(cfg, "Swim"); } } } [HarmonyPatch(typeof(Player), "UseEitr")] private static class RaceEitrCostPatch { private static void Prefix(Player __instance, ref float v) { if (TryGetRaceConfig(__instance, out var cfg) && !cfg.NoResourceCost.Value && cfg.EitrCostMultiplier.Value != 1f) { v *= cfg.EitrCostMultiplier.Value; } } } [HarmonyPatch(typeof(Character), "TryUseEitr")] private static class RaceEitrCostTryPatch { private static void Prefix(Character __instance, ref float eitrUse) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && TryGetRaceConfig(val, out var cfg) && !cfg.NoResourceCost.Value && cfg.EitrCostMultiplier.Value != 1f) { eitrUse *= cfg.EitrCostMultiplier.Value; } } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEventFailable <>9__35_0; internal object <RegisterOfflineResetCommand>b__35_0(ConsoleEventArgs args) { if (!HasDevCommands()) { args.Context.AddString(Text_SemPermissao.Value); return false; } if (args.Args.Length < 2) { args.Context.AddString(Text_UsoOfflineReset.Value); return false; } if (!long.TryParse(args.Args[1], out var result)) { args.Context.AddString(Text_IdInvalido.Value); return false; } bool flag = ResetOfflinePlayer(result); args.Context.AddString(flag ? Text_OfflineResetado.Value : Text_OfflineNaoEncontrado.Value); return flag; } } private static readonly HashSet<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); public static readonly Dictionary<string, RaceConfig> Races = new Dictionary<string, RaceConfig>(); public static ConfigEntry<float> EyeGlowPeak; public static ConfigEntry<bool> EmoteOnTransform; public static ConfigEntry<bool> FillVitalsOnTransform; public static ConfigEntry<bool> RacialAbilitiesEnabled; public static ConfigEntry<string> AltarSwitchCostItem; public static ConfigEntry<int> AltarSwitchCostAmount; public static ConfigEntry<string> AltarRecipe; private const string ZdoRagdollRaceKey = "GlitnirRagdollRace"; private const string ModGUID = "glitnir.races"; private const string ModName = "Glitnir Races"; private const string ModVersion = "1.0.0"; private const string RaceOrc = "orc"; private const string RaceElf = "elfo"; private const string RaceDwarf = "anao"; private const string RaceHuman = "humano"; private const string ZdoRaceKey = "GlitnirRace"; private const string ZdoRaceVersionKey = "GlitnirRaceVer"; private const int CurrentRaceDataVersion = 1; private const string ZdoLockedKey = "GlitnirRaceLocked"; private const string ZdoEarColorKey = "GlitnirRaceEarColor"; private const string ZdoSkinColorKey = "GlitnirRaceSkinColor"; private const string RpcSetRace = "GlitnirRaces_SetRace"; private const string RpcVersionCheck = "GlitnirRaces_VersionCheck"; private const string RpcAdminSetRaceRequest = "GlitnirRaces_AdminSetRaceRequest"; private const int FindHeadMaxDepth = 12; private const float RaceApplyMaxDistance = 60f; private static readonly WaitForSeconds Wait01 = new WaitForSeconds(0.1f); private static readonly WaitForSeconds Wait05 = new WaitForSeconds(0.5f); private static readonly WaitForSeconds Wait1 = new WaitForSeconds(1f); private static readonly WaitForSeconds Wait2 = new WaitForSeconds(2f); private static readonly WaitForSeconds WaitSkin005 = new WaitForSeconds(0.05f); private static readonly WaitForSeconds WaitSkin020 = new WaitForSeconds(0.2f); private static readonly WaitForSeconds WaitSkin050 = new WaitForSeconds(0.5f); private static readonly WaitForSeconds WaitSkin100 = new WaitForSeconds(1f); private readonly Harmony harmony = new Harmony("glitnir.races"); public static GlitnirRacesPlugin Instance; public ConfigFile MainConfigFile; public ConfigFile TextConfigFile; private static GameObject ElfEarsMalePrefab; private static GameObject ElfEarsFemalePrefab; private static GameObject OrcEarsMalePrefab; private static GameObject OrcEarsFemalePrefab; private static GameObject OrcTuskPrefab; private static GameObject HighElfEyesPrefab; private static GameObject AltarPrefab; private static bool IsApplyingRace = false; private static bool RpcRegistered = false; private static ZRoutedRpc RegisteredRpcInstance = null; private static readonly Dictionary<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 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 configWatchTimer = 0f; private DateTime _lastConfigWrite = DateTime.MinValue; private bool isRestoringLocalRace = false; private string lastBroadcastRace = null; private static string _cachedSavePrefix = null; private static long _cachedCharacterId = 0L; private static string _cachedServerKey = null; private static ZNet _cachedZNetInstance = null; private static readonly Vector3 HumanScale = Vector3.one; private static readonly Vector3 InvalidColor = new Vector3(-1f, -1f, -1f); private static readonly Vector3 ElfEarPosition = Vector3.zero; private static readonly Vector3 ElfEarRotation = Vector3.zero; private static readonly Vector3 ElfEarScale = Vector3.one; private static readonly Vector3 OrcEarPosition = new Vector3(0.00024f, 0.001475f, 0.001121f); private static readonly Vector3 OrcEarRotation = new Vector3(24.5f, 81.89f, -2.969f); private static readonly Vector3 OrcEarScale = new Vector3(1.137024f, 1.637663f, 1.083586f); private static readonly Vector3 HighElfEyesPosition = new Vector3(-0.0063f, -0.0194f, -0.00017f); private static readonly Vector3 HighElfEyesRotation = new Vector3(-18.776f, -89.449f, -0.691f); private static readonly Vector3 HighElfEyesScale = new Vector3(0.00993f, 0.011539f, 0.01272f); private static readonly Vector3 OrcTuskPosition = new Vector3(-0.00137f, 0.00114f, -0.00014f); private static readonly Vector3 OrcTuskRotation = new Vector3(-16.932f, -110.817f, 8.571f); private static readonly Vector3 OrcTuskScale = new Vector3(0.00494f, 0.005076f, 0.00559f); private bool _isReloadingConfig; private DateTime _lastTextConfigWrite = DateTime.MinValue; private static readonly Dictionary<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, float> SecondWindCooldownTimer = new Dictionary<string, float>(); private static bool _envNightWarningLogged; private const float BonusRegenSeconds = 30f; private static readonly Dictionary<string, DamageType> DamageTypeNames = new Dictionary<string, DamageType>(StringComparer.OrdinalIgnoreCase) { { "Blunt", (DamageType)1 }, { "Slash", (DamageType)2 }, { "Pierce", (DamageType)4 }, { "Chop", (DamageType)8 }, { "Pickaxe", (DamageType)16 }, { "Fire", (DamageType)32 }, { "Frost", (DamageType)64 }, { "Lightning", (DamageType)128 }, { "Poison", (DamageType)256 }, { "Spirit", (DamageType)512 } }; private static readonly Dictionary<string, DamageModifier> ModifierNames = new Dictionary<string, DamageModifier>(StringComparer.OrdinalIgnoreCase) { { "Normal", (DamageModifier)0 }, { "Resistant", (DamageModifier)1 }, { "Weak", (DamageModifier)2 }, { "Immune", (DamageModifier)3 }, { "Ignore", (DamageModifier)4 }, { "VeryResistant", (DamageModifier)5 }, { "VeryWeak", (DamageModifier)6 }, { "SlightlyResistant", (DamageModifier)7 }, { "SlightlyWeak", (DamageModifier)8 } }; private static FieldInfo _semanCharacterField; private static readonly Dictionary<string, StatusEffect> RaceStatusEffects = new Dictionary<string, StatusEffect>(); private static Sprite _placeholderIcon; private static bool _placeholderIconResolved; private const string RaceIconResourceName = "race_icon.rgba"; private const int RaceIconSize = 128; private const string ColorAccent = "#E8A33D"; private const string ColorAbilityBuff = "#8CFF8C"; private const string ColorAbilityDebuff = "#FF8C8C"; public static ConfigEntry<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_AltarJaEscolheu; 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_RaceName_Orc; public static ConfigEntry<string> Text_RaceName_Elf; public static ConfigEntry<string> Text_RaceName_Dwarf; public static ConfigEntry<string> Text_RaceName_Human; 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_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_HabSegundoFolego; public static ConfigEntry<string> Text_HabSegundoFolegoDesc; private static bool _modelIndexFieldWarningLogged; private static readonly FieldInfo ModelIndexField = AccessTools.Field(typeof(VisEquipment), "m_modelIndex"); private void RegisterAltarPiece() { //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Expected O, but got Unknown //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Expected O, but got Unknown if ((Object)(object)AltarPrefab == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[GlitnirRaces] Prefab 'altar_racas' não encontrado — peça do Altar das Raças não registrada."); return; } if ((Object)(object)AltarPrefab.GetComponent<Piece>() == (Object)null) { AltarPrefab.AddComponent<Piece>(); } 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)"[GlitnirRaces] 'altar_racas' não tinha Collider — criei um BoxCollider automático baseado na malha. Se ficar com hitbox estranha, adiciona um Collider certinho no Unity e ele passa a usar esse em vez do automático."); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[GlitnirRaces] 'altar_racas' não tem Collider nem Renderer — o altar provavelmente não vai responder a interação."); } } PieceConfig val2 = new PieceConfig { Name = Text_AltarNome.Value, Description = Text_AltarDescricao.Value, PieceTable = "Hammer", CraftingStation = "piece_workbench", Category = "Misc", Icon = (LoadIconFromEmbedded("altar_icon.rgba") ?? GetPlaceholderIcon()), Requirements = ParseAltarRecipe(AltarRecipe?.Value ?? "Wood:10,Stone:5") }; CustomPiece val3 = new CustomPiece(AltarPrefab, true, val2); PieceManager.Instance.AddPiece(val3); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[GlitnirRaces] Peça 'Altar das Raças' registrada."); } private static RequirementConfig[] ParseAltarRecipe(string recipe) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown List<RequirementConfig> list = new List<RequirementConfig>(); if (string.IsNullOrWhiteSpace(recipe)) { return (RequirementConfig[])(object)new RequirementConfig[1] { new RequirementConfig { Item = "Wood", Amount = 10, Recover = true } }; } string[] array = recipe.Split(new char[1] { ',' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ':' }); if (array2.Length == 2) { string text2 = array2[0].Trim(); if (!string.IsNullOrWhiteSpace(text2) && int.TryParse(array2[1].Trim(), out var result) && result > 0) { list.Add(new RequirementConfig { Item = text2, Amount = result, Recover = true }); } } } if (list.Count == 0) { list.Add(new RequirementConfig { Item = "Wood", Amount = 10, Recover = true }); } return list.ToArray(); } public static bool HasChosenRaceViaAltar(Player p) { return IsPlayerLocked(p); } public static bool HasPendingAltarSwitch(Player p) { if ((Object)(object)p == (Object)null) { return false; } long playerIdLong = GetPlayerIdLong(p); return playerIdLong != 0L && PendingAltarSwitch.Contains(playerIdLong); } public static void ChooseRaceFromAltar(string race) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)Instance == (Object)null) { return; } long playerIdLong = GetPlayerIdLong(localPlayer); bool flag = playerIdLong != 0L && PendingAltarSwitch.Contains(playerIdLong); if (!HasChosenRaceViaAltar(localPlayer) || flag) { if (flag) { PendingAltarSwitch.Remove(playerIdLong); } TransformLocalPlayerFromMarketplace(race); } } public static void SwitchRaceFromAltar(Player p) { if (!((Object)(object)Instance == (Object)null) && !((Object)(object)p == (Object)null)) { long playerIdLong = GetPlayerIdLong(p); if (playerIdLong != 0) { PendingAltarSwitch.Add(playerIdLong); } } } private void ApplyRaceWithDelays(Player p) { if (!((Object)(object)p == (Object)null)) { ApplyRace(p); if (!IsHeadless()) { int instanceID = ((Object)p).GetInstanceID(); int value; int num = ((!ApplyRaceCoroutineGeneration.TryGetValue(instanceID, out value)) ? 1 : (value + 1)); ApplyRaceCoroutineGeneration[instanceID] = num; ((MonoBehaviour)this).StartCoroutine(ApplyRaceDelayed(p, Wait01, num)); ((MonoBehaviour)this).StartCoroutine(ApplyRaceDelayed(p, Wait05, num)); ((MonoBehaviour)this).StartCoroutine(ApplyRaceDelayed(p, Wait1, num)); ((MonoBehaviour)this).StartCoroutine(ApplyRaceDelayed(p, Wait2, num)); } } } private IEnumerator ApplyRaceDelayed(Player p, WaitForSeconds wait, int generation) { yield return wait; if (!((Object)(object)p == (Object)null)) { int instanceId = ((Object)p).GetInstanceID(); if (ApplyRaceCoroutineGeneration.TryGetValue(instanceId, out var current) && current == generation) { ApplyRace(p); } } } private void QueueSkinRefresh(Player p, string race) { if (!IsHeadless() && !((Object)(object)p == (Object)null) && !string.IsNullOrWhiteSpace(race)) { string text = GetVisualKey(p); if (string.IsNullOrWhiteSpace(text)) { text = ((Object)p).GetInstanceID().ToString(); } float time = Time.time; if (!LastSkinRefreshRequest.TryGetValue(text, out var value) || !(time - value < 1.25f)) { LastSkinRefreshRequest[text] = time; ((MonoBehaviour)this).StartCoroutine(ForceSkinRefresh(p, race)); } } } private IEnumerator ForceSkinRefresh(Player p, string race) { yield return null; ForceSkinNow(p, race); yield return WaitSkin005; ForceSkinNow(p, race); yield return WaitSkin020; ForceSkinNow(p, race); yield return WaitSkin050; ForceSkinNow(p, race); yield return WaitSkin100; ForceSkinNow(p, race); } private void ForceSkinNow(Player p, string race) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null || string.IsNullOrWhiteSpace(race) || GetRace(p) != race) { return; } bool isApplyingRace = IsApplyingRace; IsApplyingRace = true; try { if (RaceUsesForcedSkin(race)) { ApplySkin(p, GetNetworkSkinColor(p, race)); } Color color = ToColor(GetRaceEarColor(p, race)); if (race == "orc") { ApplyOrcEars(p, color); } else if (race == "elfo") { ApplyEars(p, color); } Transform cachedHead = GetCachedHead(p, race); Transform val = ((cachedHead != null) ? cachedHead.Find("HighElfEyes") : null); if ((Object)(object)val != (Object)null) { ApplyEyeColor(val, GetRaceEyeColor(race)); } } finally { IsApplyingRace = isApplyingRace; } } public void RequestOnlineVisualRefresh(Player p) { if (IsHeadless() || (Object)(object)p == (Object)null) { return; } string race = GetRace(p); if (!string.IsNullOrWhiteSpace(race)) { ApplyRaceWithDelays(p); if (RaceUsesForcedSkin(race) || race == "elfo") { QueueSkinRefresh(p, race); } } } public void RequestOnlineVisualRefresh(VisEquipment vis) { if (!IsHeadless() && !((Object)(object)vis == (Object)null)) { Player val = ((Component)vis).GetComponent<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 == "elfo") { QueueSkinRefresh(val, race); } } } private Transform GetCachedHead(Player p, string race) { if ((Object)(object)p == (Object)null) { return null; } int instanceID = ((Object)p).GetInstanceID(); if (HeadCache.TryGetValue(instanceID, out var value) && HeadCacheRace.TryGetValue(instanceID, out var value2) && value2 == race && (Object)(object)value != (Object)null) { return value; } Transform val = FindHead(((Component)p).transform, 0); HeadCache[instanceID] = val; HeadCacheRace[instanceID] = race; return val; } private static void InvalidateHeadCache(Player p) { if (!((Object)(object)p == (Object)null)) { int instanceID = ((Object)p).GetInstanceID(); HeadCache.Remove(instanceID); HeadCacheRace.Remove(instanceID); } } private static ZNetView GetCachedZNetView(Player player) { if ((Object)(object)player == (Object)null) { return null; } int instanceID = ((Object)player).GetInstanceID(); if (ZNetViewCache.TryGetValue(instanceID, out var value) && (Object)(object)value != (Object)null) { return value; } ZNetView component = ((Component)player).GetComponent<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_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null || IsApplyingRace || GetPlayerIdLong(p) == 0) { return; } bool flag = IsHeadless(); string race = GetRace(p); string visualKey = GetVisualKey(p); string value = ""; if (!string.IsNullOrWhiteSpace(visualKey)) { LastAppliedRace.TryGetValue(visualKey, out value); } bool flag2 = value != race; IsApplyingRace = true; try { if (flag2) { InvalidateHeadCache(p); if (!flag) { ResetScaledHelmet(p); } ApplyScale(p, HumanScale); if (!flag) { if (RaceUsesForcedSkin(value)) { ResetSkin(p); } Transform cachedHead = GetCachedHead(p, race); RemoveElfEarsAnywhere(cachedHead); RemoveOrcEarsAnywhere(cachedHead); RemoveHeadAttachmentDirect(cachedHead, "HighElfEyes"); RemoveHeadAttachmentDirect(cachedHead, "OrcTusk"); } if (!string.IsNullOrWhiteSpace(visualKey)) { LastAppliedRace[visualKey] = race; } UpdateRaceStatusEffect(p, race); } if (string.IsNullOrWhiteSpace(race) || !IsRaceEnabled(race)) { ApplyScale(p, HumanScale); if (!flag && flag2) { string visualKey2 = GetVisualKey(p); if (!string.IsNullOrWhiteSpace(visualKey2) && OriginalSkinColors.TryGetValue(visualKey2, out var value2)) { ApplySkin(p, value2); } else { ApplySkin(p, Vector3.one); } ResetHelmet(p); Transform head = FindHead(((Component)p).transform, 0); RemoveElfEarsAnywhere(head); RemoveOrcEarsAnywhere(head); RemoveHeadAttachmentDirect(head, "HighElfEyes"); RemoveHeadAttachmentDirect(head, "OrcTusk"); } return; } ApplyScale(p, GetRaceScale(race)); ScaleCurrentHelmetForRace(p, GetRaceScale(race)); if (!flag) { if (RaceUsesForcedSkin(race)) { CacheOriginalSkinIfNeeded(p); ApplySkin(p, GetNetworkSkinColor(p, race)); QueueSkinRefresh(p, race); } if (RaceUsesForcedHair(race)) { ApplyHair(p, GetRaceHairColor(race)); } Transform cachedHead2 = GetCachedHead(p, race); switch (race) { case "orc": ApplyOrcEarsDirect(cachedHead2, ToColor(GetRaceEarColor(p, race)), IsPlayerFemale(p)); ApplyHighElfEyesDirect(p, cachedHead2); ApplyOrcTuskDirect(cachedHead2); break; case "elfo": ApplyEarsDirect(cachedHead2, ToColor(GetRaceEarColor(p, race)), IsPlayerFemale(p)); QueueSkinRefresh(p, race); ApplyHighElfEyesDirect(p, cachedHead2); break; case "anao": ApplyHighElfEyesDirect(p, cachedHead2); break; case "humano": ApplyHighElfEyesDirect(p, cachedHead2); break; } } } finally { IsApplyingRace = false; } } public void SpawnEffect(Player p) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) if (!IsHeadless() && !((Object)(object)p == (Object)null) && !((Object)(object)ZNetScene.instance == (Object)null)) { Vector3 val = ((Component)p).transform.position + Vector3.up; Quaternion rotation = ((Component)p).transform.rotation; GameObject prefab = ZNetScene.instance.GetPrefab("vfx_spawn_large"); GameObject prefab2 = ZNetScene.instance.GetPrefab("fx_Fader_Roar_Projectile_Hit"); if ((Object)(object)prefab != (Object)null) { Object.Instantiate<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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null || IsHeadless()) { return; } try { VisEquipment component = ((Component)p).GetComponent<VisEquipment>(); object? obj = HelmetInstanceField?.GetValue(component); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if (!((Object)(object)val == (Object)null)) { HelmetScaleMarker helmetScaleMarker = val.GetComponent<HelmetScaleMarker>(); if ((Object)(object)helmetScaleMarker == (Object)null) { helmetScaleMarker = val.AddComponent<HelmetScaleMarker>(); helmetScaleMarker.OriginalScale = val.transform.localScale; helmetScaleMarker.OriginalPosition = val.transform.localPosition; helmetScaleMarker.AppliedScale = Vector3.one; } if (!(helmetScaleMarker.AppliedScale == targetScale)) { val.transform.localScale = Vector3.Scale(helmetScaleMarker.OriginalScale, targetScale); val.transform.localPosition = helmetScaleMarker.OriginalPosition; helmetScaleMarker.AppliedScale = targetScale; } } } catch (Exception ex) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("[GlitnirRaces] Falha ao escalar capacete: " + ex.Message)); } } } private void ResetHelmet(Player p) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) ScaleCurrentHelmetForRace(p, Vector3.one); } private void ResetScaledHelmet(Player p) { ResetHelmet(p); } private static void ApplyScale(Player p, Vector3 scale) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)p == (Object)null)) { ((Component)p).transform.localScale = scale; } } private static void RemovePlayerAttachment(Player p, string objectName) { if (!((Object)(object)p == (Object)null)) { Transform val = ((Component)p).transform.Find(objectName); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } private void RegisterCommands() { RegisterRaceCommand("orc"); RegisterRaceCommand("elfo"); RegisterRaceCommand("anao"); RegisterRaceCommand("humano"); RegisterResetRaceCommand(); RegisterOfflineResetCommand(); ReRegisterSecretCodeCommands(); RegisterReloadCommand(); } private void RegisterReloadCommand() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) new ConsoleCommand("reloadracas", "Recarrega os codigos secretos do config", (ConsoleEventFailable)delegate(ConsoleEventArgs args) { if (!HasDevCommands()) { args.Context.AddString(Text_SemPermissao.Value); return false; } Instance.MainConfigFile.Reload(); Instance.TextConfigFile.Reload(); NetworkRaces.Clear(); ZNetViewCache.Clear(); foreach (Player allPlayer in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null)) { string visualKey = GetVisualKey(allPlayer); if (!string.IsNullOrWhiteSpace(visualKey)) { LastAppliedRace[visualKey] = ""; } InvalidateHeadCache(allPlayer); Instance.ApplyRaceWithDelays(allPlayer); } } ReRegisterSecretCodeCommands(); args.Context.AddString(Text_ConfigRecarregado.Value); args.Context.AddString(Text_CodigosSecretosAtivos.Value); foreach (KeyValuePair<string, RaceConfig> race in Races) { string value = race.Value.SecretCode.Value; if (!string.IsNullOrWhiteSpace(value)) { args.Context.AddString(" " + race.Value.DisplayName + " → " + value); } } return true; }, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private void ReRegisterSecretCodeCommands() { foreach (KeyValuePair<string, RaceConfig> race in Races) { string value = race.Value.SecretCode.Value; string key = race.Key; if (!string.IsNullOrWhiteSpace(value) && !RegisteredSecretCodes.Contains(value)) { RegisterSecretCodeCommand(value, key); RegisteredSecretCodes.Add(value); } } } private void RegisterSecretCodeCommand(string code, string race) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) new ConsoleCommand(code, "", (ConsoleEventFailable)delegate { TransformLocalPlayerFromMarketplace(race); return true; }, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private void RegisterRaceCommand(string race) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) new ConsoleCommand(race, race + " me ou " + race + " NomeDoPlayer", (ConsoleEventFailable)delegate(ConsoleEventArgs args) { if (!HasDevCommands()) { args.Context.AddString(Text_SemPermissao.Value); return false; } if (!IsRaceEnabled(race)) { args.Context.AddString(Fmt(Text_RacaDesativadaAdmin.Value, GetRaceName(race))); return false; } if (args.Args.Length < 2) { args.Context.AddString(Fmt(Text_UsoRaca.Value, race)); return false; } Player targetPlayer = GetTargetPlayer(args); if ((Object)(object)targetPlayer == (Object)null) { args.Context.AddString(Text_PlayerNaoEncontrado.Value); return false; } AdminSetRace(targetPlayer, race); args.Context.AddString(Fmt(Text_AgoraERaca.Value, targetPlayer.GetPlayerName(), GetRaceName(race))); return true; }, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private void RegisterResetRaceCommand() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) ConsoleEventFailable val = (ConsoleEventFailable)delegate(ConsoleEventArgs args) { if (!HasDevCommands()) { args.Context.AddString(Text_SemPermissao.Value); return false; } if (args.Args.Length < 2) { args.Context.AddString(Fmt(Text_UsoRaca.Value, args.Args[0])); return false; } Player targetPlayer = GetTargetPlayer(args); if ((Object)(object)targetPlayer == (Object)null) { args.Context.AddString(Text_PlayerNaoEncontrado.Value); return false; } long playerIdLong = GetPlayerIdLong(targetPlayer); if (playerIdLong == 0) { args.Context.AddString(Fmt(Text_PlayerNaoCarregado.Value, targetPlayer.GetPlayerName())); return false; } ResetRace(targetPlayer, broadcast: true); args.Context.AddString(Fmt(Text_RacaRemovida.Value, targetPlayer.GetPlayerName())); return true; }; new ConsoleCommand("racareset", "racareset me ou racareset NomeDoPlayer", val, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private Player GetTargetPlayer(ConsoleEventArgs args) { string typedName = string.Join(" ", args.Args.Skip(1)).Trim(); if (typedName.Equals("me", StringComparison.OrdinalIgnoreCase)) { return Player.m_localPlayer; } return ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => (Object)(object)p != (Object)null && p.GetPlayerName().Equals(typedName, StringComparison.OrdinalIgnoreCase))); } private void RegisterOfflineResetCommand() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown object obj = <>c.<>9__35_0; if (obj == null) { ConsoleEventFailable val = delegate(ConsoleEventArgs args) { if (!HasDevCommands()) { args.Context.AddString(Text_SemPermissao.Value); return false; } if (args.Args.Length < 2) { args.Context.AddString(Text_UsoOfflineReset.Value); return false; } if (!long.TryParse(args.Args[1], out var result)) { args.Context.AddString(Text_IdInvalido.Value); return false; } bool flag = ResetOfflinePlayer(result); args.Context.AddString(flag ? Text_OfflineResetado.Value : Text_OfflineNaoEncontrado.Value); return flag; }; <>c.<>9__35_0 = val; obj = (object)val; } new ConsoleCommand("glitnir_reset_offline", "glitnir_reset_offline <playerID/steamID>", (ConsoleEventFailable)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static bool ResetOfflinePlayer(long playerID) { if (ZDOMan.instance == null) { return false; } List<ZDO> list = new List<ZDO>(); int num = 0; while (ZDOMan.instance.GetAllZDOsWithPrefabIterative("Player", list, ref num)) { } foreach (ZDO item in list) { if (item != null) { long num2 = item.GetLong(ZDOVars.s_playerID, 0L); if (num2 == playerID) { item.Set("GlitnirRace", ""); item.Set("GlitnirRaceLocked", false); item.Set("GlitnirRaceEarColor_x", -1f); item.Set("GlitnirRaceEarColor_y", -1f); item.Set("GlitnirRaceEarColor_z", -1f); item.Set("GlitnirRaceSkinColor_x", -1f); item.Set("GlitnirRaceSkinColor_y", -1f); item.Set("GlitnirRaceSkinColor_z", -1f); NetworkRaces.Remove(playerID); return true; } } } return false; } private static void TransformLocalPlayerFromMarketplace(string race) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)Instance == (Object)null) { return; } if (!IsRaceEnabled(race)) { ((Character)localPlayer).Message((MessageType)2, Text_EssaRacaDesativada.Value, 0, (Sprite)null); return; } if (RaceUsesForcedSkin(race)) { Instance.CacheOriginalSkinIfNeeded(localPlayer); } Instance.SetRace(localPlayer, race, lockPlayer: true, broadcast: true); Instance.ApplyRaceWithDelays(localPlayer); TopOffVitals(localPlayer); if (!IsHeadless()) { Instance.SpawnEffect(localPlayer); } PlayTransformEmote(); ((Character)localPlayer).Message((MessageType)2, Fmt(Text_AgoraEuSou.Value, Instance.GetRaceName(race)), 0, (Sprite)null); } private static void PlayTransformEmote() { if (!EmoteOnTransform.Value) { return; } try { Emote.DoEmote((Emotes)11); } catch (Exception ex) { GlitnirRacesPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("Falha ao tocar emote de transformação: " + ex.Message)); } } } private void CreateRaceConfigs() { Races.Clear(); CreateRaceConfig("orc", Text_RaceName_Orc.Value, enabled: true, "1,1,1", "#3FA86B", "#3FA86B", "#FFFF00", "X9K7Q2M4Z8P1", RaceAbility.Orc, "-1", 0f, 0f, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f, 0f, 1f, 0.9f, "Blunt:Resistant,Frost:Weak", 0f, 0.3f, 1.3f); CreateRaceConfig("elfo", Text_RaceName_Elf.Value, enabled: true, "1,1,1", "-1", "-1", "#00FF00", "R3T8Y1U6I4O9", RaceAbility.Elf, "-1", 0f, 0f, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f, 0f, 1f, 1.15f, "Spirit:Resistant,Poison:Weak", 0f, 0f, 1f, stillHealAura: true, 5f, 2f, 2f, stillHealDayOnly: true); CreateRaceConfig("anao", Text_RaceName_Dwarf.Value, enabled: true, "0.8,0.8,0.8", "-1", "-1", "#9B30FF", "Z4P9X2C7B8N1", RaceAbility.Dwarf, "-1", 0f, 0f, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f, 0f, 1f, 0.9f, "Blunt:VeryResistant,Slash:Resistant,Pierce:Resistant,Fire:Weak", 0f, 0f, 1f, stillHealAura: false, 5f, 2f, 2f, stillHealDayOnly: false, ironStanceEnabled: true, 0.3f); CreateRaceConfig("humano", Text_RaceName_Human.Value, enabled: true, "1,1,1", "-1", "-1", "#00F0FF", "T2Y7U4I8O1P6", RaceAbility.Human, "-1", 0f, 0f, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f, 0f, 1f, 1f, "", 0f, 0f, 1f, stillHealAura: false, 5f, 2f, 2f, stillHealDayOnly: false, ironStanceEnabled: false, 0f, secondWindEnabled: true, 0.2f, 30f, 30f); } private void CreateRaceConfig(string raceId, string displayName, bool enabled, string scale, string skinColor, string earColor, string eyeColor, string secretCode, RaceAbility ability = RaceAbility.None, string hairColor = "-1", float healthBonus = 0f, float staminaBonus = 0f, float eitrBonus = 0f, float carryWeightBonus = 0f, float healthRegenMult = 1f, float staminaRegenMult = 1f, float eitrRegenMult = 1f, float damageDoneMult = 1f, float backstabMult = 1f, float damageTakenMult = 1f, float lifestealPercent = 0f, float stealthMult = 1f, float speedMult = 1f, string resistances = "", float heatResistanceBonus = 0f, float lowHealthThreshold = 0f, float lowHealthDamageBonus = 1f, bool stillHealAura = false, float stillHealAmount = 5f, float stillHealInterval = 2f, float stillHealRequiredStillTime = 2f, bool stillHealDayOnly = false, bool ironStanceEnabled = false, float ironStanceExtraDamageReduction = 0f, bool secondWindEnabled = false, float secondWindThreshold = 0.2f, float secondWindHealAmount = 0f, float secondWindStaminaAmount = 0f, float secondWindCooldown = 300f, string skillDamageMultipliers = "", string attackDamageTypeMultipliers = "", bool noResourceCost = false, float xpGainMult = 1f, float knockbackMult = 1f, float eitrCostMult = 1f, string staminaCostModifiers = "", bool nightOnlyBonuses = false, float dayNightHealthShift = 0f, string biomeHealthShifts = "") { string text = "Aparencia - " + displayName; string text2 = "Habilidades - " + displayName; RaceConfig raceConfig = new RaceConfig { RaceId = raceId, DisplayName = displayName, Enabled = SyncedConfig(text, "Usar", enabled, "Ativa ou desativa a raça " + displayName + "."), Scale = SyncedConfig(text, "Tamanho", scale, "Tamanho da raça no formato X,Y,Z."), SkinColor = SyncedConfig(text, "Cor", skinColor, "Cor da pele em HEX. Use -1 para não alterar."), HairColor = SyncedConfig(text, "CorCabeloBarba", hairColor, "Cor do cabelo e barba em HEX (os dois juntos, o jogo usa a mesma cor pros dois). Use -1 para não alterar."), EarColor = SyncedConfig(text, "CorOrelha", earColor, "Cor da orelha em HEX. Use -1 para usar a cor da pele."), EyeColor = SyncedConfig(text, "CorOlho", eyeColor, "Cor dos olhos em HEX."), SecretCode = SyncedConfig(text, "CodigoSecreto", secretCode, "Código secreto digitado no chat para escolher a raça."), HealthBonus = SyncedConfig(text2, "BonusVida", healthBonus, "Vida máxima extra, somada em cima do vanilla (nunca abaixo)."), StaminaBonus = SyncedConfig(text2, "BonusStamina", staminaBonus, "Stamina máxima extra, somada em cima do vanilla."), EitrBonus = SyncedConfig(text2, "BonusEitr", eitrBonus, "Eitr máximo extra, somado em cima do vanilla."), CarryWeightBonus = SyncedConfig(text2, "BonusPeso", carryWeightBonus, "Peso máximo extra que pode carregar, somado em cima do vanilla."), HealthRegenMultiplier = SyncedConfig(text2, "MultiplicadorRegenVida", healthRegenMult, "Velocidade de regeneração de vida (e cura em geral). 1.0 = vanilla, 1.4 = 40% mais rápido."), StaminaRegenMultiplier = SyncedConfig(text2, "MultiplicadorRegenStamina", staminaRegenMult, "Velocidade de regeneração de stamina. 1.0 = vanilla."), EitrRegenMultiplier = SyncedConfig(text2, "MultiplicadorRegenEitr", eitrRegenMult, "Velocidade de regeneração de eitr. 1.0 = vanilla."), DamageDoneMultiplier = SyncedConfig(text2, "MultiplicadorDanoCausado", damageDoneMult, "Multiplicador de dano causado em geral. 1.0 = vanilla, 1.15 = +15%."), BackstabMultiplier = SyncedConfig(text2, "MultiplicadorAtaqueFurtivo", backstabMult, "Multiplicador extra no bônus de dano de ataque furtivo (backstab). 1.0 = vanilla."), DamageTakenMultiplier = SyncedConfig(text2, "MultiplicadorDanoRecebido", damageTakenMult, "Multiplicador de dano recebido em geral. 1.0 = vanilla, 0.85 = -15%."), LifestealPercent = SyncedConfig(text2, "RouboDeVida", lifestealPercent, "Fração do dano causado que vira cura pro atacante. 0 = desativado, 0.12 = 12%."), StealthMultiplier = SyncedConfig(text2, "MultiplicadorFurtividade", stealthMult, "Multiplicador do fator de furtividade. Menor que 1.0 = mais furtivo."), SpeedMultiplier = SyncedConfig(text2, "MultiplicadorVelocidade", speedMult, "Multiplicador de velocidade de movimento (andar/correr). 1.0 = vanilla."), Resistances = SyncedConfig(text2, "Resistencias", resistances, "Resistências a dano por tipo, formato 'Tipo:Nivel,Tipo:Nivel'. Tipos: Blunt, Slash, Pierce, Chop, Pickaxe, Fire, Frost, Lightning, Poison, Spirit. Niveis: Normal, Resistant, VeryResistant, SlightlyResistant, Weak, VeryWeak, SlightlyWeak, Immune, Ignore. Ex: 'Frost:Immune,Fire:Weak'."), HeatResistanceBonus = SyncedConfig(text2, "BonusResistenciaFrio", heatResistanceBonus, "Se diferente de 0, essa raça é IMUNE ao frio/calor ambiente (status 'Congelando' e dano de exposição a lava). O valor em si não importa (só precisa ser != 0) — é liga/desliga, não intensidade."), SkillDamageMultipliers = SyncedConfig(text2, "MultiplicadorDanoPorSkill", skillDamageMultipliers, "[Uso raro] Bônus de dano extra quando o golpe usa um skill específico, formato 'Skill:Mult,Skill:Mult'. Skills comuns: Swords, Knives, Clubs, Polearms, Spears, Axes, Bows, Crossbows, Unarmed, ElementalMagic, BloodMagic. Ex: 'BloodMagic:1.3,Bows:1.15'."), AttackDamageTypeMultipliers = SyncedConfig(text2, "MultiplicadorDanoPorTipo", attackDamageTypeMultipliers, "[Uso raro] Bônus de dano causado, só na fatia daquele TIPO de dano específico. Formato 'Tipo:Mult,Tipo:Mult'."), NoResourceCost = SyncedConfig(text2, "SemGastoStaminaEitr", noResourceCost, "[Uso raro] Se true, não gasta stamina nem eitr ao usar ataques/habilidades (a barra só existe pra visual)."), XpGainMultiplier = SyncedConfig(text2, "MultiplicadorGanhoXP", xpGainMult, "[Uso raro] Multiplicador de XP ganho em skills ao acertar golpes. 1.0 = vanilla."), KnockbackMultiplier = SyncedConfig(text2, "MultiplicadorEmpurrao", knockbackMult, "[Uso raro] Multiplicador da força de empurrão (knockback) que os golpes causam. 1.0 = vanilla."), EitrCostMultiplier = SyncedConfig(text2, "MultiplicadorCustoEitr", eitrCostMult, "[Uso raro] Multiplicador do custo de Eitr ao usar magia. Ignorado se SemGastoStaminaEitr estiver ligado."), StaminaCostModifiers = SyncedConfig(text2, "ModificadoresCustoStamina", staminaCostModifiers, "[Uso raro] Reduz (ou aumenta) o custo de stamina por ação específica, formato 'Acao:Valor,Acao:Valor'. Ações: Attack, Block, Dodge, Jump, Run, Sneak, Swim. Valor positivo reduz custo, negativo aumenta."), NightOnlyBonuses = SyncedConfig(text2, "BonusSoDeNoite", nightOnlyBonuses, "[Uso raro] Se true, os multiplicadores de regen e de velocidade dessa raça só valem durante a noite."), DayNightHealthShift = SyncedConfig(text2, "OscilacaoVidaDiaNoite", dayNightHealthShift, "[Uso raro] Faz a vida máxima subir de noite e cair de dia, em cima do BonusVida normal."), BiomeHealthShifts = SyncedConfig(text2, "OscilacaoVidaPorBioma", biomeHealthShifts, "[Uso raro] Soma/subtrai vida máxima dependendo do bioma atual, formato 'Bioma:Valor,Bioma:Valor'.") }; switch (ability) { case RaceAbility.Orc: raceConfig.LowHealthThreshold = SyncedConfig(text2, "Habilidade_LimiarVida", lowHealthThreshold, "Fúria de Sangue: abaixo de que % de vida (0 a 1) o bônus de dano extra ativa. 0 = desativado."); raceConfig.LowHealthDamageBonus = SyncedConfig(text2, "Habilidade_BonusDano", lowHealthDamageBonus, "Fúria de Sangue: multiplicador de dano causado quando a vida está abaixo do limiar acima."); break; case RaceAbility.Elf: raceConfig.StillHealAura = SyncedConfig(text2, "Habilidade_Ativo", stillHealAura, "Aura de Cura: se true, ficar parado por um tempo regenera vida extra periodicamente."); raceConfig.StillHealAmount = SyncedConfig(text2, "Habilidade_QuantidadeCura", stillHealAmount, "Quantidade de vida curada por tick enquanto parado."); raceConfig.StillHealInterval = SyncedConfig(text2, "Habilidade_Intervalo", stillHealInterval, "Intervalo em segundos entre cada tick de cura enquanto parado."); raceConfig.StillHealRequiredStillTime = SyncedConfig(text2, "Habilidade_TempoParado", stillHealRequiredStillTime, "Quantos segundos parado até a cura começar a ativar."); raceConfig.StillHealDayOnly = SyncedConfig(text2, "Habilidade_SoDeDia", stillHealDayOnly, "Se true, a Aura de Cura só funciona durante o DIA."); break; case RaceAbility.Dwarf: raceConfig.IronStanceEnabled = SyncedConfig(text2, "Habilidade_Ativo", ironStanceEnabled, "Postura de Ferro: reduz dano extra e zera empurrão enquanto estiver bloqueando."); raceConfig.IronStanceExtraDamageReduction = SyncedConfig(text2, "Habilidade_ReducaoExtra", ironStanceExtraDamageReduction, "Redução de dano EXTRA (fração 0-1) enquanto bloqueando, somada ao bloqueio normal do jogo."); break; case RaceAbility.Human: raceConfig.SecondWindEnabled = SyncedConfig(text2, "Habilidade_Ativo", secondWindEnabled, "Segundo Fôlego: quando a vida cai abaixo do limiar, recupera vida/stamina uma vez, com cooldown."); raceConfig.SecondWindThreshold = SyncedConfig(text2, "Habilidade_LimiarVida", secondWindThreshold, "Abaixo de que % de vida (0 a 1) o Segundo Fôlego ativa."); raceConfig.SecondWindHealAmount = SyncedConfig(text2, "Habilidade_QuantidadeVida", secondWindHealAmount, "Quantidade de vida recuperada quando o Segundo Fôlego ativa."); raceConfig.SecondWindStaminaAmount = SyncedConfig(text2, "Habilidade_QuantidadeStamina", secondWindStaminaAmount, "Quantidade de stamina recuperada quando o Segundo Fôlego ativa."); raceConfig.SecondWindCooldown = SyncedConfig(text2, "Habilidade_Cooldown", secondWindCooldown, "Cooldown em segundos antes do Segundo Fôlego poder ativar de novo."); break; } Races[raceId] = raceConfig; } private ConfigEntry<T> SyncedConfig<T>(string group, string name, T value, string description) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { IsAdminOnly = true }; return MainConfigFile.Bind<T>(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { val })); } private void OnConfigurationSynchronized(object sender, EventArgs args) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Configuração sincronizada pelo Jotunn."); if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } NetworkRaces.Clear(); ZNetViewCache.Clear(); foreach (Player allPlayer in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null)) { string visualKey = GetVisualKey(allPlayer); if (!string.IsNullOrWhiteSpace(visualKey)) { LastAppliedRace[visualKey] = ""; } InvalidateHeadCache(allPlayer); } } ReRegisterSecretCodeCommands(); foreach (Player allPlayer2 in Player.GetAllPlayers()) { ApplyRaceWithDelays(allPlayer2); } } private void LoadAssets() { ElfEarsMalePrefab = LoadPrefabFromEmbedded("elf_ears_m"); ElfEarsFemalePrefab = LoadPrefabFromEmbedded("elf_ears_f"); OrcEarsMalePrefab = LoadPrefabFromEmbedded("orc_ears_m"); OrcEarsFemalePrefab = LoadPrefabFromEmbedded("orc_ears_f"); OrcTuskPrefab = LoadPrefabFromEmbedded("orc_tusk"); HighElfEyesPrefab = LoadPrefabFromEmbedded("high_elf_eyes"); } private GameObject LoadPrefabFromEmbedded(string assetName) { try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string x) => x.EndsWith(assetName)); if (text == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Asset embutido '" + assetName + "' não encontrado na DLL.")); string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); foreach (string text2 in manifestResourceNames) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("RESOURCE: " + text2)); } return null; } using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Stream '" + assetName + "' nulo.")); return null; } byte[] array; using (MemoryStream memoryStream = new MemoryStream()) { stream.CopyTo(memoryStream); array = memoryStream.ToArray(); } AssetBundle val = AssetBundle.LoadFromMemory(array); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Falha ao carregar AssetBundle '" + assetName + "'.")); return null; } GameObject val2 = val.LoadAsset<GameObject>(assetName) ?? val.LoadAllAssets<GameObject>().FirstOrDefault(); if ((Object)(object)val2 == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Nenhum prefab em '" + assetName + "'.")); } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Prefab '" + assetName + "' carregado.")); } return val2; } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Erro ao carregar asset '{assetName}': {arg}"); return null; } } private static bool IsRaceEnabled(string race) { RaceConfig value; return !string.IsNullOrWhiteSpace(race) && Races.TryGetValue(race, out value) && value.Enabled.Value; } private static bool RaceUsesForcedSkin(string race) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(race) || !Races.TryGetValue(race, out var value)) { return false; } Vector3 val = ParseColorConfig(value.SkinColor.Value, InvalidColor); return val.x >= 0f && val.y >= 0f && val.z >= 0f; } private static bool RaceUsesForcedHair(string race) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(race) || !Races.TryGetValue(race, out var value)) { return false; } Vector3 val = ParseColorConfig(value.HairColor.Value, InvalidColor); return val.x >= 0f && val.y >= 0f && val.z >= 0f; } private static Vector3 GetRaceHairColor(string race) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) RaceConfig value; return Races.TryGetValue(race, out value) ? ParseColorConfig(value.HairColor.Value, InvalidColor) : InvalidColor; } private static Vector3 GetRaceScale(string race) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) RaceConfig value; return Races.TryGetValue(race, out value) ? ParseVector(value.Scale.Value, HumanScale) : HumanScale; } private static Vector3 GetRaceSkinColor(string race) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) RaceConfig value; return Races.TryGetValue(race, out value) ? ParseColorConfig(value.SkinColor.Value, Vector3.one) : Vector3.one; } private static Vector3 ParseVector(string value, Vector3 fallback) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) try { if (string.IsNullOrWhiteSpace(value)) { return fallback; } string[] array = value.Split(new char[1] { ',' }); if (array.Length != 3) { return fallback; } return new Vector3(float.Parse(array[0].Trim(), CultureInfo.InvariantCulture), float.Parse(array[1].Trim(), CultureInfo.InvariantCulture), float.Parse(array[2].Trim(), CultureInfo.InvariantCulture)); } catch { return fallback; } } private static Vector3 ParseColorConfig(string value, Vector3 fallback) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) try { if (string.IsNullOrWhiteSpace(value)) { return fallback; } value = value.Trim(); if (value == "-1" || value.Equals("none", StringComparison.OrdinalIgnoreCase) || value.Equals("nao", StringComparison.OrdinalIgnoreCase) || value.Equals("não", StringComparison.OrdinalIgnoreCase) || value == "-1,-1,-1") { return InvalidColor; } if (value.StartsWith("#")) { Color val = default(Color); if (ColorUtility.TryParseHtmlString(value, ref val)) { return new Vector3(val.r, val.g, val.b); } return fallback; } return ParseVector(value, fallback); } catch { return fallback; } } private static string GetRaceFromSecretCode(string text) { if (string.IsNullOrWhiteSpace(text)) { return null; } foreach (KeyValuePair<string, RaceConfig> race in Races) { RaceConfig value = race.Value; if (value?.SecretCode == null || !value.Enabled.Value || !text.Equals(value.SecretCode.Value, StringComparison.Ordinal)) { continue; } return race.Key; } return null; } private string GetRaceName(string race) { RaceConfig value; return Races.TryGetValue(race, out value) ? value.DisplayName : race; } private static string GetPlayerId(Player player) { long playerIdLong = GetPlayerIdLong(player); return (playerIdLong != 0L) ? playerIdLong.ToString() : ""; } private static string GetVisualKey(Player player) { if ((Object)(object)player == (Object)null) { return ""; } long playerIdLong = GetPlayerIdLong(player); return (playerIdLong != 0L) ? playerIdLong.ToString() : ""; } private static long GetPlayerIdLong(Player player) { if ((Object)(object)player == (Object)null) { return 0L; } try { long playerID = player.GetPlayerID(); if (playerID != 0) { return playerID; } } catch { } return 0L; } private void RestoreLocalSavedRaceIfNeeded() { if (isRestoringLocalRace) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || GetPlayerIdLong(localPlayer) == 0) { return; } string savedLocalRace = GetSavedLocalRace(); if (string.IsNullOrWhiteSpace(savedLocalRace) || !IsRaceEnabled(savedLocalRace)) { return; } string race = GetRace(localPlayer); if (!string.IsNullOrWhiteSpace(race)) { return; } ZNetView cachedZNetView = GetCachedZNetView(localPlayer); if ((Object)(object)cachedZNetView == (Object)null || cachedZNetView.GetZDO() == null) { return; } isRestoringLocalRace = true; try { long playerIdLong = GetPlayerIdLong(localPlayer); if (playerIdLong != 0) { NetworkRaces[playerIdLong] = savedLocalRace; } ForceSetZdoRace(localPlayer, savedLocalRace); ForceSetRaceVisualZdo(localPlayer, savedLocalRace); SetZdoLocked(localPlayer, locked: true); BroadcastRace(localPlayer, savedLocalRace); lastBroadcastRace = savedLocalRace; ApplyRaceWithDelays(localPlayer); } finally { isRestoringLocalRace = false; } } private static string GetLocalSavePrefix() { long num = 0L; try { if ((Object)(object)Player.m_localPlayer != (Object)null) { num = Player.m_localPlayer.GetPlayerID(); } } catch { } if (_cachedSavePrefix != null && (Object)(object)_cachedZNetInstance == (Object)(object)ZNet.instance && _cachedCharacterId == num) { return _cachedSavePrefix; } string text = ((num != 0L) ? num.ToString() : "unknown"); string text2 = "local"; try { if ((Object)(object)ZNet.instance != (Object)null) { if (!ZNet.instance.IsServer()) { string text3 = ""; int result = 0; FieldInfo fieldInfo = AccessTools.Field(typeof(ZNet), "m_serverHost"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(ZNet), "m_serverPort"); if (fieldInfo != null) { text3 = fieldInfo.GetValue(ZNet.instance)?.ToString() ?? ""; } if (fieldInfo2 != null) { int.TryParse(fieldInfo2.GetValue(ZNet.instance)?.ToString() ?? "", out result); } if (!string.IsNullOrWhiteSpace(text3)) { text2 = text3 + ((result > 0) ? ("_" + result) : ""); } } else { MethodInfo methodInfo = AccessTools.Method(typeof(ZNet), "GetWorldName", (Type[])null, (Type[])null); if (methodInfo != null) { text2 = methodInfo.Invoke(ZNet.instance, null)?.ToString() ?? "local"; } } } } catch { } _cachedSavePrefix = "GlitnirRaces_c" + text + "_s" + SanitizeKey(text2) + "_"; _cachedZNetInstance = ZNet.instance; _cachedCharacterId = num; _cachedServerKey = text2; return _cachedSavePrefix; } private static string SanitizeKey(string value) { if (string.IsNullOrWhiteSpace(value)) { return "unknown"; } char[] array = value.ToCharArray(); for (int i = 0; i < array.Length; i++) { if (!char.IsLetterOrDigit(array[i]) && array[i] != '-') { array[i] = '_'; } } return new string(array); } private static string GetSavedLocalRace() { try { return PlayerPrefs.GetString(GetLocalSavePrefix() + "Race", ""); } catch { return ""; } } private static bool HasSavedLocalRaceLocked() { try { return PlayerPrefs.GetInt(GetLocalSavePrefix() + "Locked", 0) == 1; } catch { return false; } } private static void SaveLocalRace(string race, bool locked) { if (string.IsNullOrWhiteSpace(race)) { return; } try { PlayerPrefs.SetString(GetLocalSavePrefix() + "Race", race); PlayerPrefs.SetInt(GetLocalSavePrefix() + "Locked", locked ? 1 : 0); PlayerPrefs.Save(); } catch { } long localCharacterId = GetLocalCharacterId(); if (localCharacterId == 0) { return; } try { PlayerPrefs.SetString(GetGlobalRaceKey(localCharacterId), race); PlayerPrefs.Save(); } catch { } } private static long GetLocalCharacterId() { try { return ((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0; } catch { return 0L; } } private static string GetGlobalRaceKey(long characterId) { return $"GlitnirRaces_c{characterId}_LastRaceGlobal"; } private static string GetLastRaceGlobal(long characterId) { if (characterId == 0) { return ""; } try { return PlayerPrefs.GetString(GetGlobalRaceKey(characterId), ""); } catch { return ""; } } private static void ClearLocalSavedRace() { try { PlayerPrefs.DeleteKey(GetLocalSavePrefix() + "Race"); PlayerPrefs.DeleteKey(GetLocalSavePrefix() + "Locked"); PlayerPrefs.Save(); } catch { } } private static bool IsClientConnectedToRemoteServer() { try { return (Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer(); } catch { return false; } } private static bool IsSinglePlayer() { try { if ((Object)(object)ZNet.instance == (Object)null) { return false; } return ZNet.instance.IsServer() && ZNet.instance.GetNrOfPlayers() <= 1; } catch { return false; } } private static void ApplyPreviewRace(FejdStartup fejd, PlayerProfile profile) { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)fejd == (Object)null || profile == null || (Object)(object)Instance == (Object)null)