using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;
using UnityEngine.SceneManagement;
using YAPYAP;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("SpellEditor")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SpellEditor")]
[assembly: AssemblyTitle("SpellEditor")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace SpellEditor
{
[StructLayout(LayoutKind.Sequential, Size = 1)]
public struct FlightRequestMessage : NetworkMessage
{
}
public static class FlightCommand
{
[HarmonyPatch(typeof(NetworkManager), "OnStartServer")]
public static class OnStartServerPatch
{
public static void Postfix()
{
RegisterHandlers();
}
}
[HarmonyPatch(typeof(NetworkManager), "OnStartClient")]
public static class OnStartClientPatch
{
public static void Postfix()
{
RegisterHandlers();
}
}
[HarmonyPatch(typeof(PawnVoiceCommands), "Start")]
public static class PawnVoiceCommandsStartPatch
{
public static void Postfix(PawnVoiceCommands __instance)
{
Pawn component = ((Component)__instance).GetComponent<Pawn>();
if (!((Object)(object)component == (Object)null) && ((NetworkBehaviour)component).isLocalPlayer && !((Object)(object)component.Voice == (Object)null))
{
PawnVoice voice = component.Voice;
voice.OnVoiceResult = (Action<string>)Delegate.Combine(voice.OnVoiceResult, new Action<string>(OnVoiceResult));
if ((Object)(object)UIManager.Instance?.uiChat != (Object)null)
{
UIManager.Instance.uiChat.OnMessageSendVoice += OnVoiceResult;
}
Plugin.Log.LogInfo((object)"[FlightCommand] Voice listener registered on local player.");
}
}
}
[HarmonyPatch(typeof(StatusFlying), "OnFixedUpdate")]
public static class StatusFlyingLandingPatch
{
public static void Postfix(StatusFlying __instance)
{
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
object? obj = _pawnField?.GetValue(__instance);
Pawn val = (Pawn)((obj is Pawn) ? obj : null);
if ((Object)(object)val == (Object)null || !((NetworkBehaviour)val).isServer)
{
return;
}
Rigidbody rigidbody = val.Rigidbody;
if (!((Object)(object)rigidbody == (Object)null) && !(Time.time - _activatedTime < 3f) && !(rigidbody.linearVelocity.y > 0.5f) && Physics.Raycast(((Component)val).transform.position, Vector3.down, 2f))
{
StatusFlying lastStatus = val.PawnStatus.GetLastStatus<StatusFlying>();
if (lastStatus != null)
{
val.PawnStatus.RemoveStatus((Status)(object)lastStatus);
}
}
}
}
private const string LocKey = "PLAYER_COMMAND_BECOME_WIND";
private const float Duration = 60f;
private static StatusFlyingSO? _statusSO;
private static float _activatedTime = -999f;
private const float GracePeriod = 3f;
private static readonly FieldInfo _pawnField = typeof(Status).GetField("_pawn", BindingFlags.Instance | BindingFlags.NonPublic);
private const float LandingRayDistance = 2f;
public static void RegisterHandlers()
{
try
{
NetworkServer.RegisterHandler<FlightRequestMessage>((Action<NetworkConnectionToClient, FlightRequestMessage>)OnServerReceive, false);
}
catch
{
}
try
{
NetworkClient.RegisterHandler<FlightRequestMessage>((Action<FlightRequestMessage>)OnClientReceive, false);
}
catch
{
}
}
private static void OnVoiceResult(string input)
{
if (string.IsNullOrEmpty(input) || !MatchesTrigger(input))
{
return;
}
if (NetworkServer.active)
{
Pawn val = ((IEnumerable<Pawn>)Object.FindObjectsByType<Pawn>((FindObjectsSortMode)0)).FirstOrDefault((Func<Pawn, bool>)((Pawn p) => ((NetworkBehaviour)p).isLocalPlayer));
if ((Object)(object)val != (Object)null)
{
Apply(val);
}
}
else if (NetworkClient.isConnected)
{
NetworkClient.Send<FlightRequestMessage>(default(FlightRequestMessage), 0);
}
}
private static bool MatchesTrigger(string input)
{
string[] currentWords = VoiceInjector.GetCurrentWords("PLAYER_COMMAND_BECOME_WIND", (SystemLanguage)10);
if (currentWords == null || currentWords.Length == 0)
{
return false;
}
int num = -1;
string[] array = currentWords;
foreach (string text in array)
{
int num2 = input.IndexOf(text, num + 1, StringComparison.OrdinalIgnoreCase);
if (num2 < 0)
{
return false;
}
num = num2 + text.Length - 1;
}
return true;
}
private static void OnServerReceive(NetworkConnectionToClient conn, FlightRequestMessage msg)
{
NetworkIdentity identity = ((NetworkConnection)conn).identity;
Pawn val = ((identity != null) ? ((Component)identity).GetComponent<Pawn>() : null);
if ((Object)(object)val != (Object)null)
{
Apply(val);
}
}
private static void OnClientReceive(FlightRequestMessage msg)
{
}
private static void Apply(Pawn pawn)
{
if (NetworkServer.active)
{
StatusFlyingSO statusFlyingSO = GetStatusFlyingSO();
if ((Object)(object)statusFlyingSO == (Object)null)
{
Plugin.Log.LogWarning((object)"[FlightCommand] StatusFlyingSO not found in resources.");
return;
}
_activatedTime = Time.time;
pawn.PawnStatus.AddStatus((StatusSO)(object)statusFlyingSO, 60f, 0f);
Plugin.Log.LogInfo((object)$"[FlightCommand] StatusFlying applied to {((Object)pawn).name} for {60f}s.");
}
}
private static StatusFlyingSO? GetStatusFlyingSO()
{
if ((Object)(object)_statusSO != (Object)null)
{
return _statusSO;
}
_statusSO = Resources.FindObjectsOfTypeAll<StatusFlyingSO>().FirstOrDefault();
return _statusSO;
}
}
public class NetworkSync : MonoBehaviour
{
[HarmonyPatch(typeof(NetworkManager), "OnStartServer")]
public static class ServerStartPatch
{
public static void Postfix()
{
TryRegisterHandlers();
}
}
[HarmonyPatch(typeof(NetworkManager), "OnStartClient")]
public static class ClientStartPatch
{
public static void Postfix()
{
TryRegisterHandlers();
}
}
public static NetworkSync? Instance { get; private set; }
private void Awake()
{
Instance = this;
}
private void Start()
{
TryRegisterHandlers();
}
public static void TryRegisterHandlers()
{
try
{
NetworkServer.RegisterHandler<WandSpellFieldMessage>((Action<NetworkConnectionToClient, WandSpellFieldMessage>)OnServerReceive, false);
}
catch
{
}
try
{
NetworkClient.RegisterHandler<WandSpellFieldMessage>((Action<WandSpellFieldMessage>)OnClientReceive, false);
}
catch
{
}
}
public void BroadcastFieldChange(NetworkPuppetWandProp wand, string fieldName, string value)
{
WandSpellFieldMessage wandSpellFieldMessage = default(WandSpellFieldMessage);
wandSpellFieldMessage.WandNetId = WandRegistry.GetWandId(wand);
wandSpellFieldMessage.FieldName = fieldName;
wandSpellFieldMessage.FieldValue = value;
WandSpellFieldMessage wandSpellFieldMessage2 = wandSpellFieldMessage;
if (NetworkServer.active)
{
NetworkServer.SendToAll<WandSpellFieldMessage>(wandSpellFieldMessage2, 0, false);
}
else if (NetworkClient.isConnected)
{
NetworkClient.Send<WandSpellFieldMessage>(wandSpellFieldMessage2, 0);
}
else
{
ApplyFieldChange(wandSpellFieldMessage2);
}
}
private static void ApplyFieldChange(WandSpellFieldMessage msg)
{
NetworkPuppetWandProp val = ((IEnumerable<NetworkPuppetWandProp>)WandRegistry.All).FirstOrDefault((Func<NetworkPuppetWandProp, bool>)((NetworkPuppetWandProp w) => WandRegistry.GetWandId(w) == msg.WandNetId));
if ((Object)(object)val == (Object)null)
{
WandRegistry.Refresh();
val = ((IEnumerable<NetworkPuppetWandProp>)WandRegistry.All).FirstOrDefault((Func<NetworkPuppetWandProp, bool>)((NetworkPuppetWandProp w) => WandRegistry.GetWandId(w) == msg.WandNetId));
}
if ((Object)(object)val == (Object)null)
{
Plugin.Log.LogWarning((object)("NetworkSync: wand '" + msg.WandNetId + "' not found."));
return;
}
Spell spell = val.Spell;
SpellData val2 = ((spell != null) ? spell.SpellData : null);
if ((Object)(object)val2 == (Object)null)
{
Plugin.Log.LogWarning((object)("NetworkSync: wand '" + msg.WandNetId + "' has no SpellData."));
return;
}
FieldInfo field = typeof(SpellData).GetField(msg.FieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field == null)
{
Plugin.Log.LogWarning((object)("NetworkSync: field '" + msg.FieldName + "' not found on SpellData."));
return;
}
try
{
object obj = SpellEditorWindow.ParseValue(field.FieldType, msg.FieldValue);
if (obj != null)
{
field.SetValue(val2, obj);
}
Plugin.Log.LogInfo((object)("NetworkSync: applied " + msg.FieldName + "=" + msg.FieldValue + " to wand " + msg.WandNetId + "."));
}
catch
{
Plugin.Log.LogWarning((object)("NetworkSync: could not parse '" + msg.FieldValue + "' for field '" + msg.FieldName + "'."));
}
}
private static void OnServerReceive(NetworkConnectionToClient conn, WandSpellFieldMessage msg)
{
ApplyFieldChange(msg);
NetworkServer.SendToAll<WandSpellFieldMessage>(msg, 0, false);
}
private static void OnClientReceive(WandSpellFieldMessage msg)
{
if (!NetworkServer.active)
{
ApplyFieldChange(msg);
}
}
}
public struct WandSpellFieldMessage : NetworkMessage
{
public string WandNetId;
public string FieldName;
public string FieldValue;
}
public static class OculusTempestVariant
{
[HarmonyPatch(typeof(ProjectileTornado), "Fire")]
public static class OculusTornadoSpawnPatch
{
public static void Postfix(ProjectileTornado __instance)
{
object? obj = _ownerSpellField?.GetValue(__instance);
object? obj2 = ((obj is Spell) ? obj : null);
if (((obj2 == null) ? null : ((Spell)obj2).SpellData?.voiceCommandKey) == "SPELL_BAS_OCULUS_TEMPEST")
{
_oculusTornadoes.Add(__instance);
}
}
}
[HarmonyPatch(typeof(ProjectileTornado), "FixedUpdate")]
public static class OculusTempestMovementPatch
{
public static void Postfix(ProjectileTornado __instance)
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
if (!((NetworkBehaviour)__instance).isServer || !_oculusTornadoes.Contains(__instance))
{
return;
}
object? obj = _casterField?.GetValue(__instance);
NetworkIdentity val = (NetworkIdentity)((obj is NetworkIdentity) ? obj : null);
if ((Object)(object)val == (Object)null)
{
return;
}
Pawn component = ((Component)val).GetComponent<Pawn>();
if (!((Object)(object)component == (Object)null))
{
Vector3 aimDirection = component.Blackboard.AimDirection;
aimDirection.y = 0f;
if (!(((Vector3)(ref aimDirection)).sqrMagnitude < 0.01f))
{
((Vector3)(ref aimDirection)).Normalize();
_baseDirectionField?.SetValue(__instance, aimDirection);
_targetDirectionField?.SetValue(__instance, aimDirection);
_isChangingDirectionField?.SetValue(__instance, false);
_nextDirectionChangeTimeField?.SetValue(__instance, Time.time + 9999f);
}
}
}
}
[HarmonyPatch(typeof(ProjectileTornado), "OnDestroy")]
public static class OculusTornadoDestroyPatch
{
public static void Postfix(ProjectileTornado __instance)
{
_oculusTornadoes.Remove(__instance);
}
}
private static readonly BindingFlags BF = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
private static readonly FieldInfo _baseDirectionField = typeof(ProjectileTornado).GetField("baseDirection", BF);
private static readonly FieldInfo _targetDirectionField = typeof(ProjectileTornado).GetField("targetDirection", BF);
private static readonly FieldInfo _nextDirectionChangeTimeField = typeof(ProjectileTornado).GetField("nextDirectionChangeTime", BF);
private static readonly FieldInfo _isChangingDirectionField = typeof(ProjectileTornado).GetField("isChangingDirection", BF);
private static readonly FieldInfo _casterField = typeof(BaseProjectile).GetField("Caster", BF);
private const string OculusKey = "SPELL_BAS_OCULUS_TEMPEST";
private static readonly FieldInfo _ownerSpellField = typeof(BaseProjectile).GetField("OwnerSpell", BF);
private static readonly HashSet<ProjectileTornado> _oculusTornadoes = new HashSet<ProjectileTornado>();
public static void RegisterProjectilePrefab(GameObject prefab)
{
}
}
[BepInPlugin("com.local.yapyap.SpellEditor", "SpellEditor", "1.0.1")]
public class Plugin : BaseUnityPlugin
{
public const string GUID = "com.local.yapyap.SpellEditor";
public const string Name = "SpellEditor";
public const string Version = "1.0.1";
private static readonly Dictionary<string, string> RequiredVoiceEntries = new Dictionary<string, string>
{
{ "SPELL_BAS_FEATHER_FALL", "FEATHER-FALL" },
{ "SPELL_BAS_AERO_MAXIMA", "FUS" },
{ "SPELL_BAS_OCULUS_TEMPEST", "OCULUS-TEMPEST" },
{ "PLAYER_COMMAND_BECOME_WIND", "LET-GO-YOUR-EARTHLY-TETHER-ENTER-THE-VOID-EMPTY-AND-BECOME-WIND" }
};
internal static ManualLogSource Log { get; private set; } = null;
private static void PatchEnglishTxt()
{
string text = Path.Combine(Application.dataPath, "StreamingAssets", "Vosk", "Localisation", "english.txt");
if (!File.Exists(text))
{
Log.LogWarning((object)("[SpellEditor] english.txt not found at " + text));
return;
}
List<string> list = new List<string>(File.ReadAllLines(text));
bool flag = false;
foreach (KeyValuePair<string, string> requiredVoiceEntry in RequiredVoiceEntries)
{
string key = requiredVoiceEntry.Key;
string value = requiredVoiceEntry.Value;
string text2 = key + " :: " + value;
bool flag2 = false;
foreach (string item in list)
{
if (item.StartsWith(key + " ::"))
{
flag2 = true;
break;
}
}
if (!flag2)
{
list.Add(text2);
flag = true;
Log.LogInfo((object)("[SpellEditor] Added voice entry: " + text2));
}
}
if (flag)
{
File.WriteAllLines(text, list);
}
else
{
Log.LogInfo((object)"[SpellEditor] english.txt already up to date.");
}
}
private void Awake()
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Expected O, but got Unknown
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
PatchEnglishTxt();
new Harmony("com.local.yapyap.SpellEditor").PatchAll(Assembly.GetExecutingAssembly());
FlightCommand.RegisterHandlers();
SpellVariants.RegisterTriggers();
VoiceInjector.SetOverride("PLAYER_COMMAND_BECOME_WIND", (SystemLanguage)10, VoiceInjector.ParseInput("LET-GO-YOUR-EARTHLY-TETHER-ENTER-THE-VOID-EMPTY-AND-BECOME-WIND"));
VoiceInjector.SetOverride("SPELL_BAS_OCULUS_TEMPEST", (SystemLanguage)10, VoiceInjector.ParseInput("OCULUS-TEMPEST"));
VoiceInjector.SetOverride("SPELL_BAS_FEATHER_FALL", (SystemLanguage)10, VoiceInjector.ParseInput("FEATHER-FALL"));
VoiceInjector.SetOverride("SPELL_BAS_AERO_MAXIMA", (SystemLanguage)10, VoiceInjector.ParseInput("FUS"));
GameObject val = new GameObject("SpellEditorRoot");
Object.DontDestroyOnLoad((Object)val);
val.AddComponent<SpellEditorWindow>();
val.AddComponent<NetworkSync>();
Log.LogInfo((object)"SpellEditor 1.0.1 loaded. Press F8 to open.");
}
}
public static class PrefabInjector
{
[HarmonyPatch(typeof(UpdraftSpell), "Update")]
public static class FeatherFallLandingPatch
{
public static void Postfix(UpdraftSpell __instance)
{
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
if (((Spell)__instance).SpellData?.voiceCommandKey != "SPELL_BAS_FEATHER_FALL")
{
return;
}
object obj = _isUpdraftActiveField?.GetValue(__instance);
if (!(obj is bool) || !(bool)obj)
{
return;
}
object? obj2 = _casterPawnField?.GetValue(__instance);
Pawn val = (Pawn)((obj2 is Pawn) ? obj2 : null);
if ((Object)(object)val == (Object)null || !((NetworkBehaviour)val).isLocalPlayer)
{
return;
}
float num2 = ((_updraftStartTimeField?.GetValue(__instance) is float num) ? num : 0f);
if (!(Time.time - num2 < 3f))
{
object? obj3 = _getActiveRigidbodyMethod?.Invoke(__instance, null);
Rigidbody val2 = (Rigidbody)((obj3 is Rigidbody) ? obj3 : null);
if (!((Object)(object)val2 == (Object)null) && !(val2.linearVelocity.y > 0.5f) && Physics.Raycast(((Component)__instance).transform.position, Vector3.down, 2f))
{
_stopUpdraftMethod?.Invoke(__instance, null);
}
}
}
}
[HarmonyPatch(typeof(VoiceSpell), "CollectHeldSpells")]
public static class CollectHeldSpellsPatch
{
public static void Postfix(VoiceSpell __instance)
{
if (_allSpellsField?.GetValue(__instance) is List<Spell> allSpells)
{
TryAdd(__instance, allSpells, (Spell?)(object)((IEnumerable<UpdraftSpell>)((Component)__instance).GetComponents<UpdraftSpell>()).FirstOrDefault((Func<UpdraftSpell, bool>)((UpdraftSpell u) => ((Spell)u).SpellData?.voiceCommandKey == "SPELL_BAS_FEATHER_FALL")));
TryAdd(__instance, allSpells, ((IEnumerable<Spell>)((Component)__instance).GetComponents<Spell>()).FirstOrDefault((Func<Spell, bool>)((Spell s) => ((s == null) ? null : s.SpellData?.voiceCommandKey) == "SPELL_BAS_AERO_MAXIMA")));
TryAdd(__instance, allSpells, ((IEnumerable<Spell>)((Component)__instance).GetComponents<Spell>()).FirstOrDefault((Func<Spell, bool>)((Spell s) => ((s == null) ? null : s.SpellData?.voiceCommandKey) == "SPELL_BAS_OCULUS_TEMPEST")));
}
}
private static void TryAdd(VoiceSpell vs, List<Spell> allSpells, Spell? spell)
{
if ((Object)(object)spell == (Object)null || allSpells.Contains(spell))
{
return;
}
if (!spell.IsInitialized)
{
spell.Initialize(((Spell)vs).CasterIdentity);
if (NetworkServer.active)
{
spell.SetWandHeld(true);
}
}
allSpells.Add(spell);
_sortSpells?.Invoke(vs, null);
}
}
[HarmonyPatch(typeof(Spell), "CanCast")]
public static class FeatherFallCanCastPatch
{
public static bool Prefix(Spell __instance, ref bool __result)
{
if (__instance.SpellData?.voiceCommandKey != "SPELL_BAS_FEATHER_FALL")
{
return true;
}
UpdraftSpell val = FindParentUpDog((Component)(object)__instance);
if ((Object)(object)val == (Object)null)
{
return true;
}
__result = ((Spell)val).CanCast();
return false;
}
}
[HarmonyPatch(typeof(UpdraftSpell), "OnSpellActivate")]
public static class FeatherFallActivatePatch
{
public static void Postfix(UpdraftSpell __instance)
{
if (!(((Spell)__instance).SpellData?.voiceCommandKey != "SPELL_BAS_FEATHER_FALL") && NetworkServer.active)
{
UpdraftSpell? obj = FindParentUpDog((Component)(object)__instance);
if (obj != null)
{
((Spell)obj).SetCastData();
}
}
}
}
[HarmonyPatch(typeof(Spell), "OnSpellDeactivate")]
public static class FeatherFallDeactivatePatch
{
public static void Postfix(Spell __instance)
{
if (!(__instance.SpellData?.voiceCommandKey != "SPELL_BAS_FEATHER_FALL") && NetworkServer.active)
{
UpdraftSpell? obj = FindParentUpDog((Component)(object)__instance);
if (obj != null)
{
((Spell)obj).OnSpellDeactivate();
}
}
}
}
[HarmonyPatch(typeof(Spell), "CanCast")]
public static class AeroMaximaCanCastPatch
{
public static bool Prefix(Spell __instance, ref bool __result)
{
if (__instance.SpellData?.voiceCommandKey != "SPELL_BAS_AERO_MAXIMA")
{
return true;
}
Spell val = FindParentAero((Component)(object)__instance);
if ((Object)(object)val == (Object)null)
{
return true;
}
__result = val.CanCast() && val.CurrentCharges >= 2;
return false;
}
}
[HarmonyPatch(typeof(Spell), "OnSpellActivate")]
public static class AeroMaximaActivatePatch
{
public static void Postfix(Spell __instance)
{
if (__instance.SpellData?.voiceCommandKey != "SPELL_BAS_AERO_MAXIMA" || !NetworkServer.active)
{
return;
}
Spell val = FindParentAero((Component)(object)__instance);
if ((Object)(object)val == (Object)null)
{
return;
}
val.SetCastData();
val.SetCastData();
if (Time.time - _lastYellTime < 1f)
{
return;
}
_lastYellTime = Time.time;
NetworkIdentity casterIdentity = __instance.CasterIdentity;
Pawn val2 = ((casterIdentity != null) ? ((Component)casterIdentity).GetComponent<Pawn>() : null);
if ((Object)(object)((val2 != null) ? val2.Emotes : null) != (Object)null)
{
object? obj = ((object)val2.Emotes).GetType().GetField("emoteState", BF)?.GetValue(val2.Emotes);
object? obj2 = ((obj is ControllerStateEmote) ? obj : null);
if (obj2 != null)
{
((ControllerStateEmote)obj2).PlayEmote(_yellEmoteHash, 1.5f);
}
}
}
}
[HarmonyPatch(typeof(Spell), "OnSpellDeactivate")]
public static class AeroMaximaDeactivatePatch
{
public static void Postfix(Spell __instance)
{
if (!(__instance.SpellData?.voiceCommandKey != "SPELL_BAS_AERO_MAXIMA") && NetworkServer.active)
{
Spell? obj = FindParentAero((Component)(object)__instance);
if (obj != null)
{
obj.OnSpellDeactivate();
}
}
}
}
[HarmonyPatch(typeof(Spell), "CanCast")]
public static class OculusTempestCanCastPatch
{
public static bool Prefix(Spell __instance, ref bool __result)
{
if (__instance.SpellData?.voiceCommandKey != "SPELL_BAS_OCULUS_TEMPEST")
{
return true;
}
Spell val = FindParentTempest((Component)(object)__instance);
if ((Object)(object)val == (Object)null)
{
return true;
}
__result = val.CanCast();
return false;
}
}
[HarmonyPatch(typeof(Spell), "OnSpellActivate")]
public static class OculusTempestActivatePatch
{
public static void Postfix(Spell __instance)
{
if (!(__instance.SpellData?.voiceCommandKey != "SPELL_BAS_OCULUS_TEMPEST") && NetworkServer.active)
{
Spell? obj = FindParentTempest((Component)(object)__instance);
if (obj != null)
{
obj.SetCastData();
}
}
}
}
[HarmonyPatch(typeof(Spell), "OnSpellDeactivate")]
public static class OculusTempestDeactivatePatch
{
public static void Postfix(Spell __instance)
{
if (!(__instance.SpellData?.voiceCommandKey != "SPELL_BAS_OCULUS_TEMPEST") && NetworkServer.active)
{
Spell? obj = FindParentTempest((Component)(object)__instance);
if (obj != null)
{
obj.OnSpellDeactivate();
}
}
}
}
[HarmonyPatch(typeof(NetworkManager), "OnStartServer")]
public static class OnStartServerPatch
{
public static void Postfix()
{
Inject();
}
}
[HarmonyPatch(typeof(NetworkManager), "OnStartClient")]
public static class OnStartClientPatch
{
public static void Postfix()
{
Inject();
}
}
private static bool _done;
private static readonly BindingFlags BF = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
private static readonly FieldInfo _spellDataField = typeof(Spell).GetField("spellData", BF);
private static readonly FieldInfo _isSecretField = typeof(Spell).GetField("isSecret", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo _allSpellsField = typeof(VoiceSpell).GetField("allSpells", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly MethodInfo _sortSpells = typeof(VoiceSpell).GetMethod("SortSpells", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo _isUpdraftActiveField = typeof(UpdraftSpell).GetField("isUpdraftActive", BF);
private static readonly FieldInfo _updraftStartTimeField = typeof(UpdraftSpell).GetField("updraftStartTime", BF);
private static readonly FieldInfo _casterPawnField = typeof(Spell).GetField("casterPawn", BF);
private static readonly MethodInfo _stopUpdraftMethod = typeof(UpdraftSpell).GetMethod("StopUpdraft", BF);
private static readonly MethodInfo _getActiveRigidbodyMethod = typeof(UpdraftSpell).GetMethod("GetActiveRigidbody", BF);
private const float FeatherFallGracePeriod = 3f;
private const float FeatherFallLandingRayDist = 2f;
private static readonly int _yellEmoteHash = Animator.StringToHash("Emote_Yell");
private static float _lastYellTime = -999f;
private static UpdraftSpell? FindParentUpDog(Component feather)
{
return Array.Find(feather.GetComponents<UpdraftSpell>(), (UpdraftSpell u) => ((Spell)u).SpellData?.voiceCommandKey == "SPELL_BAS_UPDOG");
}
private static Spell? FindParentAero(Component variant)
{
return Array.Find(variant.GetComponents<Spell>(), (Spell s) => ((s == null) ? null : s.SpellData?.voiceCommandKey) == "SPELL_BAS_VENTO");
}
private static Spell? FindParentTempest(Component variant)
{
return Array.Find(variant.GetComponents<Spell>(), (Spell s) => ((s == null) ? null : s.SpellData?.voiceCommandKey) == "SPELL_BAS_TEMPEST");
}
public static void Inject()
{
if (!_done)
{
NetworkPuppetWandProp val = FindWandPrefab();
if ((Object)(object)val == (Object)null)
{
Plugin.Log.LogWarning((object)"[PrefabInjector] PropWandOfBasics prefab not found.");
return;
}
InjectFeatherFall(val);
InjectAeroMaxima(val);
InjectOculusTempest(val);
_done = true;
}
}
private static void InjectFeatherFall(NetworkPuppetWandProp wand)
{
UpdraftSpell[] components = ((Component)wand).GetComponents<UpdraftSpell>();
if (components.Length < 2)
{
UpdraftSpell val = components.FirstOrDefault();
if ((Object)(object)((val != null) ? ((Spell)val).SpellData : null) == (Object)null)
{
Plugin.Log.LogWarning((object)"[PrefabInjector] Feather-Fall: source UpdraftSpell missing.");
return;
}
SpellData val2 = SpellRegistry.Clone(((Spell)val).SpellData, "FEATHER-FALL");
SetSdField(val2, "voiceCommandKey", "SPELL_BAS_FEATHER_FALL");
UpdraftSpell val3 = ((Component)wand).gameObject.AddComponent<UpdraftSpell>();
CopySerializedFields(typeof(UpdraftSpell), val, val3);
_spellDataField?.SetValue(val3, val2);
_isSecretField?.SetValue(val3, true);
SetCompField((Component)(object)val3, "initialUpwardForce", 0f);
SetCompField((Component)(object)val3, "continuousUpwardForce", 0f);
SetCompField((Component)(object)val3, "fallSlowMultiplier", 0.88f);
SetCompField((Component)(object)val3, "duration", 10f);
((Behaviour)val3).enabled = true;
Plugin.Log.LogInfo((object)"[PrefabInjector] Feather-Fall added.");
}
}
private static void InjectOculusTempest(NetworkPuppetWandProp wand)
{
Spell[] components = ((Component)wand).GetComponents<Spell>();
if (Array.Exists(components, (Spell s) => ((s == null) ? null : s.SpellData?.voiceCommandKey) == "SPELL_BAS_OCULUS_TEMPEST"))
{
return;
}
Spell val = Array.Find(components, (Spell s) => ((s == null) ? null : s.SpellData?.voiceCommandKey) == "SPELL_BAS_TEMPEST");
if ((Object)(object)((val != null) ? val.SpellData : null) == (Object)null)
{
Plugin.Log.LogWarning((object)"[PrefabInjector] Oculus-Tempest: source Tempest spell missing.");
return;
}
SpellData val2 = SpellRegistry.Clone(val.SpellData, "OCULUS-TEMPEST");
SetSdField(val2, "voiceCommandKey", "SPELL_BAS_OCULUS_TEMPEST");
GameObject val3 = CloneOculusProjectile(val.SpellData.objectToSpawnPrefab);
if ((Object)(object)val3 != (Object)null)
{
SetSdField(val2, "objectToSpawnPrefab", val3);
}
Component obj = ((Component)wand).gameObject.AddComponent(((object)val).GetType());
Spell val4 = (Spell)(object)((obj is Spell) ? obj : null);
if ((Object)(object)val4 == (Object)null)
{
Plugin.Log.LogWarning((object)"[PrefabInjector] Oculus-Tempest: AddComponent failed.");
return;
}
CopySerializedFields(((object)val).GetType(), val, val4);
_spellDataField?.SetValue(val4, val2);
_isSecretField?.SetValue(val4, true);
((Behaviour)val4).enabled = true;
Plugin.Log.LogInfo((object)"[PrefabInjector] Oculus-Tempest added.");
}
private static GameObject? CloneOculusProjectile(GameObject? original)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected O, but got Unknown
if ((Object)(object)original == (Object)null)
{
return null;
}
GameObject val = new GameObject("OculusTempestProjectileContainer");
val.SetActive(false);
Object.DontDestroyOnLoad((Object)(object)val);
GameObject obj = Object.Instantiate<GameObject>(original, val.transform);
OculusTempestVariant.RegisterProjectilePrefab(obj);
return obj;
}
private static void InjectAeroMaxima(NetworkPuppetWandProp wand)
{
Spell[] components = ((Component)wand).GetComponents<Spell>();
if (Array.Exists(components, (Spell s) => ((s == null) ? null : s.SpellData?.voiceCommandKey) == "SPELL_BAS_AERO_MAXIMA"))
{
return;
}
Spell val = Array.Find(components, (Spell s) => ((s == null) ? null : s.SpellData?.voiceCommandKey) == "SPELL_BAS_VENTO");
if ((Object)(object)((val != null) ? val.SpellData : null) == (Object)null)
{
Plugin.Log.LogWarning((object)"[PrefabInjector] Aero-Maxima: source Aero spell missing.");
return;
}
SpellData val2 = SpellRegistry.Clone(val.SpellData, "AERO-MAXIMA");
SetSdField(val2, "voiceCommandKey", "SPELL_BAS_AERO_MAXIMA");
GameObject val3 = CloneProjectilePrefab(val.SpellData.objectToSpawnPrefab);
if ((Object)(object)val3 != (Object)null)
{
SetSdField(val2, "objectToSpawnPrefab", val3);
}
Component obj = ((Component)wand).gameObject.AddComponent(((object)val).GetType());
Spell val4 = (Spell)(object)((obj is Spell) ? obj : null);
if ((Object)(object)val4 == (Object)null)
{
Plugin.Log.LogWarning((object)"[PrefabInjector] Aero-Maxima: AddComponent failed.");
return;
}
CopySerializedFields(((object)val).GetType(), val, val4);
_spellDataField?.SetValue(val4, val2);
_isSecretField?.SetValue(val4, true);
((Behaviour)val4).enabled = true;
Plugin.Log.LogInfo((object)"[PrefabInjector] Aero-Maxima added.");
}
private static GameObject? CloneProjectilePrefab(GameObject? original)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected O, but got Unknown
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)original == (Object)null)
{
return null;
}
GameObject val = new GameObject("AeroMaximaProjectileContainer");
val.SetActive(false);
Object.DontDestroyOnLoad((Object)(object)val);
GameObject obj = Object.Instantiate<GameObject>(original, val.transform);
obj.transform.localScale = original.transform.localScale * 1.5f;
ProjectilePush component = obj.GetComponent<ProjectilePush>();
if ((Object)(object)component != (Object)null)
{
SetCompField((Component)(object)component, "pushForce", 340f);
SetCompField((Component)(object)component, "playerPushForceMultiplier", 2.4f);
SetCompField((Component)(object)component, "playerPushLiftMultiplier", 2f);
SetCompField((Component)(object)component, "npcPushForceMultiplier", 4f);
SetCompField((Component)(object)component, "maxTravelDistanceOverride", 15f);
SetCompField((Component)(object)component, "decreaseForceByDistance", false);
return obj;
}
Plugin.Log.LogWarning((object)"[PrefabInjector] Aero-Maxima: ProjectilePush not found on clone.");
return obj;
}
private static void CopySerializedFields(Type type, object source, object dest)
{
FieldInfo[] fields = type.GetFields(BF);
foreach (FieldInfo fieldInfo in fields)
{
if (!fieldInfo.IsStatic && (fieldInfo.IsPublic || fieldInfo.GetCustomAttributes(typeof(SerializeField), inherit: true).Length != 0))
{
fieldInfo.SetValue(dest, fieldInfo.GetValue(source));
}
}
}
private static NetworkPuppetWandProp? FindWandPrefab()
{
return Array.Find(Resources.FindObjectsOfTypeAll<NetworkPuppetWandProp>(), delegate(NetworkPuppetWandProp w)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((Object)w).name == "PropWandOfBasics")
{
Scene scene = ((Component)w).gameObject.scene;
return !((Scene)(ref scene)).IsValid();
}
return false;
});
}
private static void SetSdField(SpellData sd, string name, object value)
{
typeof(SpellData).GetField(name, BF)?.SetValue(sd, value);
}
private static void SetCompField(Component comp, string name, object value)
{
((object)comp).GetType().GetField(name, BF)?.SetValue(comp, value);
}
}
public class SpellEditorWindow : MonoBehaviour
{
private bool _visible;
private Rect _windowRect = new Rect(20f, 20f, 1100f, 680f);
private int _mainTab;
private int _detailTab;
private string _search = "";
private string _schoolFilter = "ALL";
private Vector2 _listScroll;
private int _selectedIndex = -1;
private List<SpellData> _allSpells = new List<SpellData>();
private List<SpellData> _filtered = new List<SpellData>();
private Dictionary<string, string> _keyTriggers = new Dictionary<string, string>();
private List<(FieldInfo field, string draft, string live)> _fields = new List<(FieldInfo, string, string)>();
private Vector2 _detailScroll;
private string _editKey = "";
private string _editTrigger = "";
private static readonly Dictionary<string, Color32> Schools = new Dictionary<string, Color32>
{
["ARC"] = new Color32((byte)153, (byte)102, (byte)230, byte.MaxValue),
["BAS"] = new Color32((byte)102, (byte)204, (byte)102, byte.MaxValue),
["BLS"] = new Color32((byte)230, (byte)204, (byte)76, byte.MaxValue),
["FIR"] = new Color32((byte)230, (byte)102, (byte)51, byte.MaxValue),
["GRS"] = new Color32((byte)179, (byte)230, (byte)51, byte.MaxValue),
["ICE"] = new Color32((byte)102, (byte)204, (byte)230, byte.MaxValue),
["ILU"] = new Color32((byte)230, (byte)102, (byte)179, byte.MaxValue),
["TEL"] = new Color32((byte)230, (byte)153, (byte)51, byte.MaxValue),
["WIP"] = new Color32((byte)153, (byte)153, (byte)153, byte.MaxValue)
};
private static readonly string[] SchoolKeys = new string[10] { "ALL", "ARC", "BAS", "BLS", "FIR", "GRS", "ICE", "ILU", "TEL", "WIP" };
private bool _stylesReady;
private GUIStyle _winStyle;
private GUIStyle _header;
private GUIStyle _subLabel;
private GUIStyle _fieldVal;
private GUIStyle _tab;
private GUIStyle _tabActive;
private GUIStyle _row;
private GUIStyle _rowSel;
private Texture2D _txDark;
private Texture2D _txPanel;
private Texture2D _txSel;
private Texture2D _txBtn;
private Texture2D _txBtnHov;
private void Update()
{
if (Input.GetKeyDown((KeyCode)289))
{
_visible = !_visible;
if (_visible)
{
Refresh();
}
}
}
private void OnGUI()
{
//IL_0026: 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_004c: Expected O, but got Unknown
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
if (_visible)
{
EnsureStyles();
GUI.skin.label.richText = true;
_windowRect = GUILayout.Window(47001, _windowRect, new WindowFunction(DrawWindow), "", _winStyle, Array.Empty<GUILayoutOption>());
}
}
private void Refresh()
{
SpellRegistry.Refresh();
WandRegistry.Refresh();
_keyTriggers = VoiceInjector.GetAllKeysWithTriggers((SystemLanguage)10).ToDictionary<(string, string), string, string>(((string key, string trigger) e) => e.key, ((string key, string trigger) e) => e.trigger);
_allSpells = SpellRegistry.All.Where((SpellData s) => !string.IsNullOrEmpty(s.voiceCommandKey)).ToList();
ApplyFilter();
if (_selectedIndex >= _filtered.Count)
{
SelectSpell(-1);
}
}
private void ApplyFilter()
{
_filtered = _allSpells.Where(delegate(SpellData s)
{
bool num = _schoolFilter == "ALL" || (s.voiceCommandKey?.Contains("_" + _schoolFilter + "_") ?? false);
int num2;
if (!string.IsNullOrEmpty(_search))
{
string spellName = s.spellName;
if (spellName == null || spellName.IndexOf(_search, StringComparison.OrdinalIgnoreCase) < 0)
{
string voiceCommandKey = s.voiceCommandKey;
num2 = ((voiceCommandKey != null && voiceCommandKey.IndexOf(_search, StringComparison.OrdinalIgnoreCase) >= 0) ? 1 : 0);
goto IL_008c;
}
}
num2 = 1;
goto IL_008c;
IL_008c:
bool flag = (byte)num2 != 0;
return num && flag;
}).ToList();
if (_selectedIndex >= _filtered.Count)
{
SelectSpell(-1);
}
}
private void SelectSpell(int index)
{
//IL_0008: 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)
_selectedIndex = index;
_detailScroll = Vector2.zero;
if (index < 0 || index >= _filtered.Count)
{
_fields = new List<(FieldInfo, string, string)>();
_editKey = (_editTrigger = "");
return;
}
SpellData val = _filtered[index];
_editKey = val.voiceCommandKey ?? "";
_editTrigger = (_keyTriggers.TryGetValue(_editKey, out string value) ? value : "");
LoadFields(val);
}
private void LoadFields(SpellData sd)
{
SpellData sd2 = sd;
_fields = (from f in typeof(SpellData).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
where IsEditable(f.FieldType) && f.Name != "spellName" && f.Name != "voiceCommandKey" && f.Name != "remainingCooldownAlpha"
select f).Select(delegate(FieldInfo f)
{
string text = f.GetValue(sd2)?.ToString() ?? "";
return (f, text, text);
}).ToList();
}
private void DrawWindow(int id)
{
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.Label("<b>SpellEditor</b> <size=10><color=#777>v2.0 · F8 to toggle</color></size>", _header, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
GUILayout.Label($"<size=10><color=#555>{SpellRegistry.All.Count} spells · {WandRegistry.All.Count} wands</color></size>", _subLabel, Array.Empty<GUILayoutOption>());
GUILayout.Space(8f);
if (GUILayout.Button("Refresh", _tab, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }))
{
Refresh();
}
GUILayout.EndHorizontal();
GUILayout.Space(6f);
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
DrawMainTab(0, " Spells ");
DrawMainTab(1, " Variants ");
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
DrawSeparator();
GUILayout.Space(4f);
if (_mainTab == 0)
{
DrawSpellsTab();
}
else
{
DrawVariantsTab();
}
GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref _windowRect)).width, 30f));
}
private void DrawMainTab(int index, string label)
{
if (GUILayout.Button(label, (_mainTab == index) ? _tabActive : _tab, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f) }) && _mainTab != index)
{
_mainTab = index;
}
}
private void DrawSpellsTab()
{
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(290f) });
DrawBrowser();
GUILayout.EndVertical();
GUILayout.Space(10f);
GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
DrawDetail();
GUILayout.EndVertical();
GUILayout.EndHorizontal();
}
private void DrawBrowser()
{
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
//IL_0195: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_0205: Unknown result type (might be due to invalid IL or missing references)
//IL_0211: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
_ = GUI.skin.textField.normal.background;
string text = GUILayout.TextField(_search, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
if (text != _search)
{
_search = text;
ApplyFilter();
}
GUILayout.EndHorizontal();
GUILayout.Space(4f);
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.FlexibleSpace();
string[] schoolKeys = SchoolKeys;
Color32 val = default(Color32);
foreach (string text2 in schoolKeys)
{
if (_schoolFilter == text2)
{
val = (Color32)(Schools.TryGetValue(text2, out var value) ? value : new Color32((byte)80, (byte)120, (byte)220, byte.MaxValue));
}
else
{
((Color32)(ref val))..ctor((byte)50, (byte)50, (byte)58, byte.MaxValue);
}
Color backgroundColor = GUI.backgroundColor;
GUI.backgroundColor = Color32.op_Implicit(val);
if (GUILayout.Button(text2, _tab, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width((float)((text2 == "ALL") ? 34 : 30)) }))
{
_schoolFilter = text2;
ApplyFilter();
}
GUI.backgroundColor = backgroundColor;
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.Space(4f);
GUILayout.Label($"<size=10><color=#555>{_filtered.Count} spells</color></size>", _subLabel, Array.Empty<GUILayoutOption>());
GUILayout.Space(2f);
_listScroll = GUILayout.BeginScrollView(_listScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
for (int j = 0; j < _filtered.Count; j++)
{
SpellData val2 = _filtered[j];
string school = GetSchool(val2.voiceCommandKey);
string value2;
string text3 = (_keyTriggers.TryGetValue(val2.voiceCommandKey ?? "", out value2) ? value2 : "?");
Color32 value3;
string text4 = (Schools.TryGetValue(school, out value3) ? $"#{value3.r:X2}{value3.g:X2}{value3.b:X2}" : "#888");
if (GUILayout.Button("<color=" + text4 + ">◆</color> <b>" + val2.spellName + "</b>\n<size=10><color=#888>" + text3 + "</color></size>", (j == _selectedIndex) ? _rowSel : _row, Array.Empty<GUILayoutOption>()))
{
SelectSpell(j);
}
}
GUILayout.EndScrollView();
}
private void DrawDetail()
{
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
if (_selectedIndex < 0 || _selectedIndex >= _filtered.Count)
{
GUILayout.FlexibleSpace();
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.FlexibleSpace();
GUILayout.Label("<color=#444>← select a spell</color>", _subLabel, Array.Empty<GUILayoutOption>());
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.FlexibleSpace();
return;
}
SpellData val = _filtered[_selectedIndex];
string school = GetSchool(val.voiceCommandKey);
Color32 value;
string text = (Schools.TryGetValue(school, out value) ? $"#{value.r:X2}{value.g:X2}{value.b:X2}" : "#888");
GUILayout.Label("<b><size=15>" + val.spellName + "</size></b> <color=" + text + "><size=11>" + school + "</size></color> <size=10><color=#555>" + val.voiceCommandKey + "</color></size>", _header, Array.Empty<GUILayoutOption>());
GUILayout.Space(4f);
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
DrawDetailTab(0, " Fields ");
DrawDetailTab(1, " Voice ");
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
DrawSeparator();
GUILayout.Space(4f);
_detailScroll = GUILayout.BeginScrollView(_detailScroll, Array.Empty<GUILayoutOption>());
if (_detailTab == 0)
{
DrawFieldsDetail(val);
}
else
{
DrawVoiceDetail();
}
GUILayout.EndScrollView();
}
private void DrawDetailTab(int index, string label)
{
if (GUILayout.Button(label, (_detailTab == index) ? _tabActive : _tab, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(22f) }) && _detailTab != index)
{
_detailTab = index;
}
}
private void DrawFieldsDetail(SpellData sd)
{
//IL_00e4: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_01e0: 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_020e: Unknown result type (might be due to invalid IL or missing references)
//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
//IL_0250: Unknown result type (might be due to invalid IL or missing references)
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.Label("<color=#555>Field</color>", _subLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(180f) });
GUILayout.Label("<color=#555>Current</color>", _subLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
GUILayout.Label("<color=#555>New value</color>", _subLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
GUILayout.EndHorizontal();
DrawSeparator();
GUILayout.Space(2f);
for (int i = 0; i < _fields.Count; i++)
{
(FieldInfo field, string draft, string live) tuple = _fields[i];
FieldInfo item = tuple.field;
string item2 = tuple.draft;
string item3 = tuple.live;
bool flag = item2 != item3;
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.Label(item.Name, _subLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(180f) });
Color color = GUI.color;
GUI.color = new Color(1f, 1f, 1f, 0.35f);
GUILayout.Label(item3, _fieldVal, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
GUI.color = color;
Color backgroundColor = GUI.backgroundColor;
if (flag)
{
GUI.backgroundColor = new Color(0.25f, 0.45f, 0.25f);
}
string text = GUILayout.TextField(item2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
GUI.backgroundColor = backgroundColor;
if (text != item2)
{
_fields[i] = (item, text, item3);
}
GUILayout.EndHorizontal();
}
GUILayout.Space(10f);
bool num = _fields.Any<(FieldInfo, string, string)>(((FieldInfo field, string draft, string live) f) => f.draft != f.live);
Color backgroundColor2 = GUI.backgroundColor;
GUI.backgroundColor = (num ? new Color(0.25f, 0.6f, 0.25f) : new Color(0.3f, 0.3f, 0.3f));
GUI.enabled = num;
if (GUILayout.Button("Apply Changes", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
{
ApplyFields(sd);
LoadFields(sd);
}
GUI.enabled = true;
GUI.backgroundColor = backgroundColor2;
}
private void DrawVoiceDetail()
{
GUILayout.Label("Voice Key <size=10><color=#555>internal command identifier</color></size>", _subLabel, Array.Empty<GUILayoutOption>());
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
_editKey = GUILayout.TextField(_editKey, Array.Empty<GUILayoutOption>());
if (GUILayout.Button("Assign", _tab, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }))
{
SpellData sd = _filtered[_selectedIndex];
AssignKey(sd, _editKey);
}
GUILayout.EndHorizontal();
GUILayout.Space(12f);
GUILayout.Label("Trigger <size=10><color=#555>what you say — hyphens or spaces</color></size>", _subLabel, Array.Empty<GUILayoutOption>());
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
_editTrigger = GUILayout.TextField(_editTrigger, Array.Empty<GUILayoutOption>());
if (GUILayout.Button("Apply", _tab, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }))
{
ApplyTrigger(_editKey, _editTrigger);
}
GUILayout.EndHorizontal();
}
private void DrawVariantsTab()
{
GUILayout.Label("Runtime Spell Variants <size=10><color=#555>injected when wands spawn · removed when mod is unloaded</color></size>", _header, Array.Empty<GUILayoutOption>());
DrawSeparator();
GUILayout.Space(6f);
GUILayout.Label("<color=#444>No variants defined.</color>", _subLabel, Array.Empty<GUILayoutOption>());
}
private void AssignKey(SpellData sd, string newKey)
{
typeof(SpellData).GetField("voiceCommandKey", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(sd, newKey);
_editTrigger = (_keyTriggers.TryGetValue(newKey, out string value) ? value : "");
Plugin.Log.LogInfo((object)("[SpellEditor] Assigned key '" + newKey + "' to '" + sd.spellName + "'."));
}
private void ApplyTrigger(string key, string input)
{
if (!string.IsNullOrWhiteSpace(key))
{
string[] array = VoiceInjector.ParseInput(input);
VoiceInjector.SetOverride(key, (SystemLanguage)10, array);
_keyTriggers[key] = VoiceInjector.SyllablesToDisplay(array);
Plugin.Log.LogInfo((object)("[SpellEditor] Trigger '" + key + "' → '" + string.Join("-", array) + "'."));
}
}
private void ApplyFields(SpellData sd)
{
foreach (var (fieldInfo, text, _) in _fields)
{
try
{
object obj = ParseValue(fieldInfo.FieldType, text);
if (obj != null)
{
fieldInfo.SetValue(sd, obj);
}
}
catch
{
Plugin.Log.LogWarning((object)("[SpellEditor] Could not parse '" + text + "' for '" + fieldInfo.Name + "'."));
}
}
Plugin.Log.LogInfo((object)("[SpellEditor] Fields applied to '" + sd.spellName + "'."));
}
private static string GetSchool(string? key)
{
if (key == null)
{
return "???";
}
string[] array = key.Split(new char[1] { '_' });
if (array.Length < 2)
{
return "???";
}
return array[1];
}
private void DrawSeparator()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
Color color = GUI.color;
GUI.color = new Color(1f, 1f, 1f, 0.1f);
GUILayout.Box("", (GUILayoutOption[])(object)new GUILayoutOption[2]
{
GUILayout.ExpandWidth(true),
GUILayout.Height(1f)
});
GUI.color = color;
}
private static bool IsEditable(Type t)
{
if (!(t == typeof(string)) && !(t == typeof(int)) && !(t == typeof(float)) && !(t == typeof(bool)))
{
return t == typeof(double);
}
return true;
}
public static object? ParseValue(Type t, string s)
{
if (t == typeof(string))
{
return s;
}
if (t == typeof(int) && int.TryParse(s, out var result))
{
return result;
}
if (t == typeof(float) && float.TryParse(s, out var result2))
{
return result2;
}
if (t == typeof(double) && double.TryParse(s, out var result3))
{
return result3;
}
if (t == typeof(bool) && bool.TryParse(s, out var result4))
{
return result4;
}
return null;
}
private void EnsureStyles()
{
//IL_001c: 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_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: 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_00bd: Expected O, but got Unknown
//IL_00c2: Expected O, but got Unknown
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
//IL_0113: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_0131: Expected O, but got Unknown
//IL_0136: Expected O, but got Unknown
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
//IL_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0179: Expected O, but got Unknown
//IL_017e: Expected O, but got Unknown
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
//IL_01d0: Expected O, but got Unknown
//IL_01d5: Expected O, but got Unknown
//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
//IL_0204: Unknown result type (might be due to invalid IL or missing references)
//IL_0209: Unknown result type (might be due to invalid IL or missing references)
//IL_0211: Unknown result type (might be due to invalid IL or missing references)
//IL_0218: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_0227: Expected O, but got Unknown
//IL_022c: Expected O, but got Unknown
//IL_025c: Unknown result type (might be due to invalid IL or missing references)
//IL_0287: Unknown result type (might be due to invalid IL or missing references)
//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
//IL_02d4: Expected O, but got Unknown
//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0320: Unknown result type (might be due to invalid IL or missing references)
//IL_0335: Unknown result type (might be due to invalid IL or missing references)
//IL_033a: Unknown result type (might be due to invalid IL or missing references)
//IL_0341: Unknown result type (might be due to invalid IL or missing references)
//IL_0348: Unknown result type (might be due to invalid IL or missing references)
//IL_0350: Unknown result type (might be due to invalid IL or missing references)
//IL_0356: Unknown result type (might be due to invalid IL or missing references)
//IL_0360: Expected O, but got Unknown
//IL_0365: Expected O, but got Unknown
//IL_0386: Unknown result type (might be due to invalid IL or missing references)
//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
//IL_03cc: Expected O, but got Unknown
//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
//IL_0418: Unknown result type (might be due to invalid IL or missing references)
if (!_stylesReady)
{
_stylesReady = true;
_txDark = MakeTex(new Color32((byte)28, (byte)28, (byte)32, byte.MaxValue));
_txPanel = MakeTex(new Color32((byte)38, (byte)38, (byte)44, byte.MaxValue));
_txSel = MakeTex(new Color32((byte)48, (byte)96, (byte)200, (byte)220));
_txBtn = MakeTex(new Color32((byte)52, (byte)52, (byte)60, byte.MaxValue));
_txBtnHov = MakeTex(new Color32((byte)68, (byte)68, (byte)80, byte.MaxValue));
_winStyle = new GUIStyle(GUI.skin.window)
{
padding = new RectOffset(12, 12, 12, 12)
};
_winStyle.normal.background = _txDark;
_winStyle.normal.textColor = Color.white;
_winStyle.onNormal.background = _txDark;
_header = new GUIStyle(GUI.skin.label)
{
fontSize = 13,
richText = true,
padding = new RectOffset(4, 4, 2, 2)
};
_header.normal.textColor = Color.white;
_subLabel = new GUIStyle(GUI.skin.label)
{
fontSize = 11,
richText = true,
padding = new RectOffset(4, 4, 2, 2)
};
_subLabel.normal.textColor = new Color(0.8f, 0.8f, 0.8f);
_fieldVal = new GUIStyle(GUI.skin.label)
{
fontSize = 11,
richText = false,
padding = new RectOffset(4, 4, 2, 2)
};
_fieldVal.normal.textColor = new Color(0.55f, 0.55f, 0.55f);
_tab = new GUIStyle(GUI.skin.button)
{
fontSize = 11,
richText = false,
padding = new RectOffset(8, 8, 4, 4)
};
_tab.normal.background = _txBtn;
_tab.normal.textColor = new Color(0.72f, 0.72f, 0.72f);
_tab.hover.background = _txBtnHov;
_tab.hover.textColor = Color.white;
_tab.active.background = _txSel;
_tab.active.textColor = Color.white;
_tabActive = new GUIStyle(_tab)
{
fontStyle = (FontStyle)1
};
_tabActive.normal.background = _txSel;
_tabActive.normal.textColor = Color.white;
_tabActive.hover.background = _txSel;
_tabActive.hover.textColor = Color.white;
_row = new GUIStyle(GUI.skin.button)
{
alignment = (TextAnchor)3,
richText = true,
fontSize = 12,
padding = new RectOffset(10, 6, 6, 6)
};
_row.normal.background = _txPanel;
_row.normal.textColor = Color.white;
_row.hover.background = _txBtn;
_row.hover.textColor = Color.white;
_rowSel = new GUIStyle(_row);
_rowSel.normal.background = _txSel;
_rowSel.normal.textColor = Color.white;
_rowSel.hover.background = _txSel;
_rowSel.hover.textColor = Color.white;
}
}
private static Texture2D MakeTex(Color32 c)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
Texture2D val = new Texture2D(1, 1);
val.SetPixel(0, 0, Color32.op_Implicit(c));
val.Apply();
return val;
}
}
public static class SpellRegistry
{
public static List<SpellData> All { get; private set; } = new List<SpellData>();
public static void Refresh()
{
SpellData[] array = Resources.LoadAll<SpellData>("");
All = (from s in array.Concat(Resources.FindObjectsOfTypeAll<SpellData>()).Distinct()
orderby s.voiceCommandKey
select s).ToList();
Plugin.Log.LogInfo((object)$"SpellRegistry: found {All.Count} spells ({array.Length} from Resources).");
}
public static SpellData Clone(SpellData source, string newName)
{
string newName2 = newName;
SpellData val = ScriptableObject.CreateInstance<SpellData>();
FieldInfo[] fields = typeof(SpellData).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
fieldInfo.SetValue(val, fieldInfo.GetValue(source));
}
val.spellName = newName2;
if (!All.Any((SpellData s) => s.spellName == newName2))
{
All.Add(val);
}
Plugin.Log.LogInfo((object)("Cloned '" + source.spellName + "' → '" + newName2 + "'"));
return val;
}
public static SpellData? Find(string spellName)
{
string spellName2 = spellName;
return ((IEnumerable<SpellData>)All).FirstOrDefault((Func<SpellData, bool>)((SpellData s) => s.spellName == spellName2));
}
}
public static class SpellVariants
{
public static void RegisterTriggers()
{
}
}
public static class VoiceInjector
{
[HarmonyPatch(typeof(VoiceManager), "LoadLocalisationData")]
public static class InjectOnLoad
{
public static void Postfix(VoiceManager __instance)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
foreach (KeyValuePair<string, Dictionary<SystemLanguage, string[]>> @override in Overrides)
{
foreach (KeyValuePair<SystemLanguage, string[]> item in @override.Value)
{
if (TryGetTranslatorCommands(__instance, item.Key, out Dictionary<string, string[]> commands))
{
commands[@override.Key] = item.Value;
}
}
}
Plugin.Log.LogInfo((object)$"VoiceInjector: injected {Overrides.Count} overrides.");
}
}
private static readonly Dictionary<string, Dictionary<SystemLanguage, string[]>> Overrides = new Dictionary<string, Dictionary<SystemLanguage, string[]>>();
private static VoiceManager? _vm;
private static bool _rebuildLogged;
public static IReadOnlyDictionary<string, Dictionary<SystemLanguage, string[]>> All => Overrides;
private static VoiceManager? GetVM()
{
if ((Object)(object)_vm == (Object)null)
{
_vm = Object.FindAnyObjectByType<VoiceManager>();
}
return _vm;
}
public static void SetOverride(string locKey, SystemLanguage lang, string[] syllables)
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
if (!Overrides.TryGetValue(locKey, out Dictionary<SystemLanguage, string[]> value))
{
value = new Dictionary<SystemLanguage, string[]>();
Overrides[locKey] = value;
}
value[lang] = syllables.Select((string w) => w.ToUpperInvariant()).ToArray();
PushLiveUpdate(locKey, lang, value[lang]);
}
public static void RemoveOverride(string locKey)
{
Overrides.Remove(locKey);
}
public static bool TryGetOverride(string locKey, SystemLanguage lang, out string[] syllables)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
syllables = Array.Empty<string>();
if (Overrides.TryGetValue(locKey, out Dictionary<SystemLanguage, string[]> value))
{
return value.TryGetValue(lang, out syllables);
}
return false;
}
public static List<(string key, string trigger)> GetAllKeysWithTriggers(SystemLanguage lang = 10)
{
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
VoiceManager vM = GetVM();
if ((Object)(object)vM != (Object)null && TryGetTranslatorCommands(vM, lang, out Dictionary<string, string[]> commands))
{
return (from k in commands
orderby k.Key
select (k.Key, string.Join("-", k.Value))).ToList();
}
return LoadKeysFromFile(lang);
}
private static List<(string key, string trigger)> LoadKeysFromFile(SystemLanguage lang)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
try
{
string path = Path.Combine(Application.streamingAssetsPath, "Vosk", "Localisation");
string path2 = Path.Combine(path, LanguageFileName(lang));
if (!File.Exists(path2))
{
path2 = Path.Combine(path, "english.txt");
}
List<(string, string)> list = new List<(string, string)>();
string[] array = File.ReadAllLines(path2);
foreach (string text in array)
{
int num = text.IndexOf(" :: ", StringComparison.Ordinal);
if (num >= 0)
{
string text2 = text.Substring(0, num).Trim();
string item = text.Substring(num + 4).Trim();
if (!string.IsNullOrEmpty(text2))
{
list.Add((text2, item));
}
}
}
return list.OrderBy(((string, string) x) => x.Item1).ToList();
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("VoiceInjector: could not read localization file — " + ex.Message));
return new List<(string, string)>();
}
}
private static string LanguageFileName(SystemLanguage lang)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Invalid comparison between Unknown and I4
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Invalid comparison between Unknown and I4
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Invalid comparison between Unknown and I4
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Invalid comparison between Unknown and I4
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Invalid comparison between Unknown and I4
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Invalid comparison between Unknown and I4
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Invalid comparison between Unknown and I4
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Invalid comparison between Unknown and I4
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Invalid comparison between Unknown and I4
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Invalid comparison between Unknown and I4
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Invalid comparison between Unknown and I4
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Invalid comparison between Unknown and I4
if ((int)lang == 14)
{
return "french.txt";
}
if ((int)lang == 15)
{
return "german.txt";
}
if ((int)lang == 34)
{
return "spanish.txt";
}
if ((int)lang == 21)
{
return "italian.txt";
}
if ((int)lang == 28)
{
return "portuguese.txt";
}
if ((int)lang == 30)
{
return "russian.txt";
}
if ((int)lang == 22)
{
return "japanese.txt";
}
if ((int)lang == 23)
{
return "korean.txt";
}
if ((int)lang == 40)
{
return "schinese.txt";
}
if ((int)lang == 27)
{
return "polish.txt";
}
if ((int)lang == 37)
{
return "turkish.txt";
}
if ((int)lang == 38)
{
return "ukrainian.txt";
}
return "english.txt";
}
public static string[]? GetCurrentWords(string locKey, SystemLanguage lang)
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
string locKey2 = locKey;
VoiceManager vM = GetVM();
if ((Object)(object)vM != (Object)null && TryGetTranslatorCommands(vM, lang, out Dictionary<string, string[]> commands))
{
if (!commands.TryGetValue(locKey2, out var value))
{
return null;
}
return value;
}
(string, string) tuple = LoadKeysFromFile(lang).FirstOrDefault<(string, string)>(((string key, string trigger) e) => e.key == locKey2);
if (tuple.Item1 == null)
{
return null;
}
return ParseInput(tuple.Item2);
}
public static string[] ParseInput(string input)
{
return input.ToUpperInvariant().Split(new char[2] { ' ', '-' }, StringSplitOptions.RemoveEmptyEntries);
}
public static string SyllablesToDisplay(string[]? syllables)
{
if (syllables == null || syllables.Length == 0)
{
return "";
}
return string.Join("-", syllables);
}
private static void PushLiveUpdate(string locKey, SystemLanguage lang, string[] syllables)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
VoiceManager vM = GetVM();
if (!((Object)(object)vM == (Object)null) && TryGetTranslatorCommands(vM, lang, out Dictionary<string, string[]> commands))
{
commands[locKey] = syllables;
TryRebuildGrammar(vM);
}
}
private static bool TryGetTranslatorCommands(VoiceManager vm, SystemLanguage lang, out Dictionary<string, string[]> commands)
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
commands = null;
if (!(typeof(VoiceManager).GetField("_voskTranslatorLookup", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(vm) is IDictionary dictionary))
{
return false;
}
object obj = dictionary[lang];
if (obj == null)
{
return false;
}
commands = (obj.GetType().GetField("_commands", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj) as Dictionary<string, string[]>) ?? null;
return commands != null;
}
private static void TryRebuildGrammar(VoiceManager vm)
{
string[] array = new string[8] { "RebuildGrammar", "RecreateGrammar", "BuildGrammar", "ReloadGrammar", "Reinitialize", "InitGrammar", "SetupGrammar", "LoadGrammar" };
foreach (string name in array)
{
MethodInfo method = typeof(VoiceManager).GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
{
method.Invoke(vm, null);
_rebuildLogged = false;
return;
}
}
if (!_rebuildLogged)
{
_rebuildLogged = true;
Plugin.Log.LogWarning((object)"VoiceInjector: grammar rebuild method not found — override applies on next scene load.");
MethodInfo[] methods = typeof(VoiceManager).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Plugin.Log.LogInfo((object)("VoiceManager methods: " + string.Join(", ", Array.ConvertAll(methods, (MethodInfo m) => m.Name))));
}
}
}
public static class WandRegistry
{
private static readonly FieldInfo SpellsField = typeof(VoiceSpell).GetField("spells", BindingFlags.Instance | BindingFlags.NonPublic);
public static List<NetworkPuppetWandProp> All { get; private set; } = new List<NetworkPuppetWandProp>();
public static void Refresh()
{
All = (from w in Object.FindObjectsByType<NetworkPuppetWandProp>((FindObjectsSortMode)0)
where ((Component)w).gameObject.activeInHierarchy
group w by ((NetworkBehaviour)w).netId into g
select g.First() into w
where (Object)(object)GetVoiceSpell(w) != (Object)null
orderby ((Object)((Component)w).gameObject).name
select w).ToList();
Plugin.Log.LogInfo((object)$"WandRegistry: found {All.Count} VoiceSpell wands.");
}
public static VoiceSpell? GetVoiceSpell(NetworkPuppetWandProp wand)
{
Spell spell = wand.Spell;
return (VoiceSpell?)(((object)((spell is VoiceSpell) ? spell : null)) ?? ((object)((Component)wand).GetComponent<VoiceSpell>()));
}
public static List<Spell> GetSpellComponents(NetworkPuppetWandProp wand)
{
VoiceSpell voiceSpell = GetVoiceSpell(wand);
if ((Object)(object)voiceSpell == (Object)null)
{
return new List<Spell>();
}
if (!(SpellsField?.GetValue(voiceSpell) is Spell[] source))
{
return new List<Spell>();
}
return source.Where((Spell s) => (Object)(object)s != (Object)null).ToList();
}
public static List<SpellData> GetSpells(NetworkPuppetWandProp wand)
{
return (from s in GetSpellComponents(wand)
where (Object)(object)s.SpellData != (Object)null
select s.SpellData).ToList();
}
public static string GetWandId(NetworkPuppetWandProp wand)
{
return ((NetworkBehaviour)wand).netId.ToString();
}
}
}