Decompiled source of BankOfAurai v1.0.4

plugins/BankOfAurai/BankOfAurai.dll

Decompiled 11 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using NodeCanvas.DialogueTrees;
using NodeCanvas.Framework;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace BankOfAurai;

[BepInPlugin("com.spencer4792.bankofaurai", "BankOfAurai", "1.0.3")]
public class BankOfAuraiPlugin : BaseUnityPlugin
{
	public const string GUID = "com.spencer4792.bankofaurai";

	public const string NAME = "BankOfAurai";

	public const string VERSION = "1.0.3";

	internal static ManualLogSource Log;

	internal static BankOfAuraiPlugin Instance;

	internal static ConfigEntry<float> InterestPerDay;

	internal static ConfigEntry<float> DepositFeePercent;

	internal static ConfigEntry<KeyboardShortcut> PlacementKey;

	internal static ConfigEntry<KeyboardShortcut> AudioScanKey;

	internal static ConfigEntry<KeyboardShortcut> CopyLookKey;

	internal static ConfigEntry<string> BarkDialogueKey;

	internal static ConfigEntry<string> BarkLineText;

	internal static ConfigEntry<string> BarkNpcKey;

	internal static ConfigEntry<bool> WiretapEnabled;

	internal static ConfigEntry<float> InteractionRadius;

	internal void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		Instance = this;
		try
		{
			Init();
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Startup failed: " + ex));
		}
	}

	private void Init()
	{
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		InterestPerDay = ((BaseUnityPlugin)this).Config.Bind<float>("Bank", "InterestPercentPerDay", 0.5f, "Interest earned on the deposited balance per in-game day (24h). 0 disables interest.");
		DepositFeePercent = ((BaseUnityPlugin)this).Config.Bind<float>("Bank", "DepositFeePercent", 0f, "Percentage fee charged on deposits. 0 = free banking.");
		InteractionRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Bank", "InteractionRadius", 1.6f, "Radius (meters) of the bank interaction spot.");
		BarkDialogueKey = ((BaseUnityPlugin)this).Config.Bind<string>("Bank", "BarkLineKey", "auto", "Localization key of the banker's voiced bark line. 'auto' = find it by searching dialogue text for BarkLineText (result is logged). Empty = silent banker.");
		BarkLineText = ((BaseUnityPlugin)this).Config.Bind<string>("Bank", "BarkLineText", "better have the money", "Phrase used to locate the bark line when BarkLineKey is 'auto'.");
		BarkNpcKey = ((BaseUnityPlugin)this).Config.Bind<string>("Bank", "BarkSpeakerNameKey", "Banker", "Name shown on the bark's vicinity subtitle bubble (a localization key, or plain text).");
		WiretapEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "AudioWiretap", false, "Log every sound played through the game's audio manager (very chatty).");
		AudioScanKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Placement", "AudioScanKey", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Debug: scan all dialogue trees loaded in the current scene for statements mentioning money and log their audio clip names. Used to identify the vendor greeting bark for the banker.");
		CopyLookKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Placement", "CopyBankerLookKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Stand next to any NPC and press this: their appearance becomes the banker's body at this city's bank spot, remembered across visits.");
		PlacementKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Placement", "PlaceBankSpotKey", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Stand where the bank should be in a city and press this to save/move the bank spot for the current scene. It spawns immediately and on every future visit.");
		AudioWiretap.Install();
		BankLedger.Load();
		BankSpots.Load();
		BankBody.Load();
		SceneManager.sceneLoaded += OnSceneLoaded;
		Log.LogMessage((object)"BankOfAurai 1.0.3 ready.");
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		try
		{
			BankSpots.SpawnForScene(((Scene)(ref scene)).name);
		}
		catch (Exception ex)
		{
			Log.LogError((object)("SpawnForScene: " + ex));
		}
	}

	private void Update()
	{
		//IL_0005: 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_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_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			KeyboardShortcut value = AudioScanKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				AudioWiretap.SnapshotPlaying();
			}
			KeyboardShortcut value2 = CopyLookKey.Value;
			if (((KeyboardShortcut)(ref value2)).IsDown())
			{
				BankBody.CopyNearestLook();
			}
			KeyboardShortcut value3 = PlacementKey.Value;
			if (((KeyboardShortcut)(ref value3)).IsDown())
			{
				Character val = ((!((Object)(object)CharacterManager.Instance != (Object)null)) ? null : CharacterManager.Instance.GetFirstLocalCharacter());
				if (!((Object)(object)val == (Object)null))
				{
					Scene activeScene = SceneManager.GetActiveScene();
					string name = ((Scene)(ref activeScene)).name;
					BankSpots.SetSpot(name, ((Component)val).transform.position);
					BankSpots.SpawnForScene(name);
					Log.LogMessage((object)("Bank spot saved for scene '" + name + "' at " + ((Component)val).transform.position));
				}
			}
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Update: " + ex));
		}
	}
}
internal static class BankLedger
{
	internal class Account
	{
		public long Balance;

		public float LastInterestTime;
	}

	private static readonly Dictionary<string, Account> s_accounts = new Dictionary<string, Account>();

	private static string DirPath => Path.Combine(Paths.ConfigPath, "BankOfAurai");

	private static string FilePath => Path.Combine(DirPath, "ledger.txt");

	public static void Load()
	{
		s_accounts.Clear();
		try
		{
			if (!File.Exists(FilePath))
			{
				return;
			}
			string[] array = File.ReadAllLines(FilePath);
			foreach (string text in array)
			{
				string[] array2 = text.Split(new char[1] { '\t' });
				if (array2.Length >= 3 && long.TryParse(array2[1], out var result))
				{
					if (!float.TryParse(array2[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
					{
						result2 = 0f;
					}
					s_accounts[array2[0]] = new Account
					{
						Balance = result,
						LastInterestTime = result2
					};
				}
			}
			BankOfAuraiPlugin.Log.LogInfo((object)("Ledger loaded: " + s_accounts.Count + " account(s)."));
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("Ledger load: " + ex));
		}
	}

	public static void Save()
	{
		try
		{
			Directory.CreateDirectory(DirPath);
			string text = FilePath + ".tmp";
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, Account> s_account in s_accounts)
			{
				list.Add(s_account.Key + "\t" + s_account.Value.Balance + "\t" + s_account.Value.LastInterestTime.ToString(CultureInfo.InvariantCulture));
			}
			File.WriteAllLines(text, list.ToArray());
			if (File.Exists(FilePath))
			{
				File.Delete(FilePath);
			}
			File.Move(text, FilePath);
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("Ledger save: " + ex));
		}
	}

	public static Account GetAccount(string uid)
	{
		if (!s_accounts.TryGetValue(uid, out var value))
		{
			Account account = new Account();
			account.Balance = 0L;
			account.LastInterestTime = NowGameHours();
			value = account;
			s_accounts[uid] = value;
		}
		AccrueInterest(value);
		return value;
	}

	private static void AccrueInterest(Account acc)
	{
		float num = NowGameHours();
		float value = BankOfAuraiPlugin.InterestPerDay.Value;
		if (value <= 0f || acc.Balance <= 0)
		{
			acc.LastInterestTime = num;
			return;
		}
		float num2 = num - acc.LastInterestTime;
		if (num2 <= 0f)
		{
			acc.LastInterestTime = num;
			return;
		}
		long num3 = (long)Math.Floor((float)acc.Balance * (value / 100f) * (num2 / 24f));
		if (num3 > 0)
		{
			acc.Balance += num3;
			acc.LastInterestTime = num;
			BankOfAuraiPlugin.Log.LogInfo((object)("Interest accrued: +" + num3 + " silver."));
		}
	}

	private static float NowGameHours()
	{
		try
		{
			return EnvironmentConditions.GameTimeF;
		}
		catch
		{
		}
		return 0f;
	}
}
internal static class BankSpots
{
	private static readonly Dictionary<string, Vector3> s_spots = new Dictionary<string, Vector3>();

	private static GameObject s_current;

	public static GameObject CurrentSpot => s_current;

	private static string FilePath => Path.Combine(Path.Combine(Paths.ConfigPath, "BankOfAurai"), "spots.txt");

	private static void ApplyDefaults()
	{
		//IL_002d: 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_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		if (!s_spots.ContainsKey("CierzoNewTerrain"))
		{
			s_spots["CierzoNewTerrain"] = new Vector3(1426.2f, 5.8f, 1658.8f);
		}
		if (!s_spots.ContainsKey("Monsoon"))
		{
			s_spots["Monsoon"] = new Vector3(62.5f, -4.6f, 159.5f);
		}
		if (!s_spots.ContainsKey("Levant"))
		{
			s_spots["Levant"] = new Vector3(-60.8f, 0.1f, 76.8f);
		}
		if (!s_spots.ContainsKey("Harmattan"))
		{
			s_spots["Harmattan"] = new Vector3(89f, 64.8f, 786.9f);
		}
		if (!s_spots.ContainsKey("Berg"))
		{
			s_spots["Berg"] = new Vector3(1206.1f, -13.7f, 1383.2f);
		}
		if (!s_spots.ContainsKey("NewSirocco"))
		{
			s_spots["NewSirocco"] = new Vector3(55.8f, 55.9f, -61.7f);
		}
	}

	public static void Load()
	{
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		s_spots.Clear();
		try
		{
			if (!File.Exists(FilePath))
			{
				ApplyDefaults();
				return;
			}
			string[] array = File.ReadAllLines(FilePath);
			foreach (string text in array)
			{
				string[] array2 = text.Split(new char[1] { '\t' });
				if (array2.Length >= 4 && float.TryParse(array2[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array2[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && float.TryParse(array2[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
				{
					s_spots[array2[0]] = new Vector3(result, result2, result3);
				}
			}
			ApplyDefaults();
			BankOfAuraiPlugin.Log.LogInfo((object)("Bank spots loaded: " + s_spots.Count + " scene(s)."));
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("Spots load: " + ex));
		}
	}

	private static void Save()
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: 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)
		try
		{
			Directory.CreateDirectory(Path.GetDirectoryName(FilePath));
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, Vector3> s_spot in s_spots)
			{
				list.Add(s_spot.Key + "\t" + s_spot.Value.x.ToString(CultureInfo.InvariantCulture) + "\t" + s_spot.Value.y.ToString(CultureInfo.InvariantCulture) + "\t" + s_spot.Value.z.ToString(CultureInfo.InvariantCulture));
			}
			File.WriteAllLines(FilePath, list.ToArray());
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("Spots save: " + ex));
		}
	}

	public static void SetSpot(string sceneName, Vector3 pos)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		s_spots[sceneName] = pos;
		Save();
	}

	public static void SpawnForScene(string sceneName)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Expected O, but got Unknown
		//IL_0050: 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)
		BankAudio.InvalidateCache();
		if ((Object)(object)s_current != (Object)null)
		{
			Object.Destroy((Object)(object)s_current);
			s_current = null;
		}
		if (s_spots.TryGetValue(sceneName, out var value))
		{
			GameObject val = new GameObject("BankOfAurai_Spot");
			val.SetActive(false);
			val.transform.position = value;
			InteractionTriggerBase val2 = val.AddComponent<InteractionTriggerBase>();
			val2.DetectionColliderRadius = BankOfAuraiPlugin.InteractionRadius.Value;
			FieldInfo field = typeof(InteractionTriggerBase).GetField("m_generateColliderIfNone", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field != null)
			{
				field.SetValue(val2, true);
			}
			val.AddComponent<InteractionActivator>();
			BankDialogue.Attach(val);
			val.SetActive(true);
			s_current = val;
			BankOfAuraiPlugin.Log.LogInfo((object)("Bank spot spawned in '" + sceneName + "' at " + value));
			BankBody.SpawnForScene(sceneName, val);
		}
	}
}
internal static class BankDialogue
{
	public const string ACTOR = "Banker";

	public static void Attach(GameObject go)
	{
		DialogueActor val = go.AddComponent<DialogueActor>();
		val.SetName("Banker");
		DialogueTreeController val2 = go.AddComponent<DialogueTreeController>();
		DialogueTreeExt val3 = ScriptableObject.CreateInstance<DialogueTreeExt>();
		((Graph)val3).name = "BankOfAuraiDialogue";
		val3.CanBeQueued = false;
		BuildGraph(val3);
		((GraphOwner)val2).graph = (Graph)(object)val3;
		try
		{
			FieldInfo field = typeof(GraphOwner).GetField("instances", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				IDictionary dictionary = field.GetValue(val2) as IDictionary;
				if (dictionary == null)
				{
					dictionary = (IDictionary)Activator.CreateInstance(field.FieldType);
					field.SetValue(val2, dictionary);
				}
				dictionary[val3] = val3;
			}
			else
			{
				BankOfAuraiPlugin.Log.LogWarning((object)"GraphOwner.instances not found; dialogue may not start.");
			}
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("Instance seed: " + ex));
		}
		DialogueStarter val4 = go.AddComponent<DialogueStarter>();
		BankTalkInteraction bankTalkInteraction = go.AddComponent<BankTalkInteraction>();
		bankTalkInteraction.Starter = val4;
		bankTalkInteraction.Controller = val2;
		DialogueTreeController dialogueController = val4.DialogueController;
		InteractionActivator component = go.GetComponent<InteractionActivator>();
		if ((Object)(object)component != (Object)null)
		{
			component.BasicInteraction = (IInteraction)(object)bankTalkInteraction;
		}
	}

	private static void BuildGraph(DialogueTreeExt tree)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Expected O, but got Unknown
		((DialogueTree)tree).actorParameters.Add(new ActorParameter("Banker"));
		StatementNodeExt val = ((Graph)tree).AddNode<StatementNodeExt>();
		val.statement = new Statement("I'm a representative of the Bank of Aurai. I can help you deposit your silver, or return what's yours.");
		BankAudio.ApplyGreetingClip(val.statement);
		val.SetActorName("Banker");
		ActionNode val2 = ((Graph)tree).AddNode<ActionNode>();
		val2.action = (ActionTask)(object)new RefreshVarsTask();
		StatementNodeExt val3 = ((Graph)tree).AddNode<StatementNodeExt>();
		val3.statement = new Statement("Your account holds [BANK_BALANCE] silver. You carry [POUCH] silver.");
		val3.SetActorName("Banker");
		MultipleChoiceNodeExt val4 = ((Graph)tree).AddNode<MultipleChoiceNodeExt>();
		AddChoice(val4, "Deposit everything.");
		AddChoice(val4, "Deposit half of my silver.");
		AddChoice(val4, "Withdraw everything.");
		AddChoice(val4, "Withdraw half of my balance.");
		AddChoice(val4, "I'll be on my way.");
		ActionNode val5 = MakeOp(tree, BankOpTask.Op.DepositAll);
		ActionNode val6 = MakeOp(tree, BankOpTask.Op.DepositHalf);
		ActionNode val7 = MakeOp(tree, BankOpTask.Op.WithdrawAll);
		ActionNode val8 = MakeOp(tree, BankOpTask.Op.WithdrawHalf);
		FinishNode val9 = ((Graph)tree).AddNode<FinishNode>();
		((Graph)tree).ConnectNodes((Node)(object)val, (Node)(object)val2, -1, -1);
		((Graph)tree).ConnectNodes((Node)(object)val2, (Node)(object)val3, -1, -1);
		((Graph)tree).ConnectNodes((Node)(object)val3, (Node)(object)val4, -1, -1);
		((Graph)tree).ConnectNodes((Node)(object)val4, (Node)(object)val5, 0, -1);
		((Graph)tree).ConnectNodes((Node)(object)val4, (Node)(object)val6, 1, -1);
		((Graph)tree).ConnectNodes((Node)(object)val4, (Node)(object)val7, 2, -1);
		((Graph)tree).ConnectNodes((Node)(object)val4, (Node)(object)val8, 3, -1);
		((Graph)tree).ConnectNodes((Node)(object)val4, (Node)(object)val9, 4, -1);
		((Graph)tree).ConnectNodes((Node)(object)val5, (Node)(object)val2, -1, -1);
		((Graph)tree).ConnectNodes((Node)(object)val6, (Node)(object)val2, -1, -1);
		((Graph)tree).ConnectNodes((Node)(object)val7, (Node)(object)val2, -1, -1);
		((Graph)tree).ConnectNodes((Node)(object)val8, (Node)(object)val2, -1, -1);
	}

	private static void AddChoice(MultipleChoiceNodeExt hub, string text)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		hub.availableChoices.Add(new Choice(new Statement(text)));
	}

	private static ActionNode MakeOp(DialogueTreeExt tree, BankOpTask.Op op)
	{
		ActionNode val = ((Graph)tree).AddNode<ActionNode>();
		BankOpTask bankOpTask = new BankOpTask();
		bankOpTask.Operation = op;
		val.action = (ActionTask)(object)bankOpTask;
		return val;
	}

	internal static Character LocalCharacter()
	{
		return (!((Object)(object)CharacterManager.Instance != (Object)null)) ? null : CharacterManager.Instance.GetFirstLocalCharacter();
	}
}
public class BankTalkInteraction : InteractionBase
{
	public DialogueStarter Starter;

	public DialogueTreeController Controller;

	private bool m_warmed;

	private static readonly FieldInfo s_lastCharField = typeof(InteractionBase).GetField("m_lastCharacter", BindingFlags.Instance | BindingFlags.NonPublic);

	protected override string DefaultPressText => "Talk";

	protected override void OnActivate()
	{
		BankOfAuraiPlugin.Log.LogInfo((object)"Bank talk: OnActivate fired.");
		((InteractionBase)this).OnActivate();
		try
		{
			Character val = null;
			if (s_lastCharField != null)
			{
				object? value = s_lastCharField.GetValue(this);
				val = (Character)((value is Character) ? value : null);
			}
			if ((Object)(object)val == (Object)null)
			{
				val = BankDialogue.LocalCharacter();
			}
			if ((Object)(object)val == (Object)null)
			{
				BankOfAuraiPlugin.Log.LogWarning((object)"Bank talk: no character found.");
				return;
			}
			if ((Object)(object)Starter == (Object)null)
			{
				BankOfAuraiPlugin.Log.LogWarning((object)"Bank talk: no DialogueStarter.");
				return;
			}
			BankOfAuraiPlugin.Log.LogInfo((object)("Bank talk: starting dialogue for " + val.Name));
			Starter.StartDialogue(val);
			if (!m_warmed)
			{
				m_warmed = true;
				BankOfAuraiPlugin.Log.LogInfo((object)"Bank talk: first-use warm restart.");
				if ((Object)(object)Controller != (Object)null)
				{
					Controller.StopDialogue();
				}
				Starter.StartDialogue(val);
			}
			else if ((Object)(object)Controller != (Object)null && !((GraphOwner)Controller).isRunning)
			{
				BankOfAuraiPlugin.Log.LogInfo((object)"Bank talk: start no-op'd, retrying.");
				Starter.StartDialogue(val);
			}
			BankAudio.PlayGreetingBark(((Component)this).gameObject, val);
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("Bank talk failed: " + ex));
		}
	}
}
public class RefreshVarsTask : ActionTask
{
	protected override void OnExecute()
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		BankOfAuraiPlugin.Log.LogInfo((object)"Bank dialogue running (RefreshVars).");
		try
		{
			Character val = BankDialogue.LocalCharacter();
			if ((Object)(object)val != (Object)null && ((Task)this).blackboard != null)
			{
				BankLedger.Account account = BankLedger.GetAccount(UID.op_Implicit(val.UID));
				int num = (((Object)(object)val.Inventory != (Object)null) ? val.Inventory.AvailableMoney : 0);
				SetVar("BANK_BALANCE", account.Balance.ToString());
				SetVar("POUCH", num.ToString());
			}
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("RefreshVarsTask: " + ex));
		}
		((ActionTask)this).EndAction(true);
	}

	private void SetVar(string name, string value)
	{
		if (((Task)this).blackboard.GetVariable(name, (Type)null) == null)
		{
			((Task)this).blackboard.AddVariable(name, (object)value);
		}
		else
		{
			((Task)this).blackboard.SetValue(name, (object)value);
		}
	}
}
public class BankOpTask : ActionTask
{
	public enum Op
	{
		DepositAll,
		DepositHalf,
		WithdrawAll,
		WithdrawHalf
	}

	public Op Operation;

	protected override void OnExecute()
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Character val = BankDialogue.LocalCharacter();
			if ((Object)(object)val != (Object)null && (Object)(object)val.Inventory != (Object)null)
			{
				BankLedger.Account account = BankLedger.GetAccount(UID.op_Implicit(val.UID));
				int availableMoney = val.Inventory.AvailableMoney;
				switch (Operation)
				{
				case Op.DepositAll:
					Deposit(val, account, availableMoney);
					break;
				case Op.DepositHalf:
					Deposit(val, account, availableMoney / 2);
					break;
				case Op.WithdrawAll:
					Withdraw(val, account, account.Balance);
					break;
				case Op.WithdrawHalf:
					Withdraw(val, account, account.Balance / 2);
					break;
				}
			}
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("BankOpTask: " + ex));
		}
		((ActionTask)this).EndAction(true);
	}

	private static void Deposit(Character character, BankLedger.Account acc, int amount)
	{
		if (amount > 0 && character.Inventory.RemoveMoney(amount, false))
		{
			long num = (long)Math.Floor((float)amount * (BankOfAuraiPlugin.DepositFeePercent.Value / 100f));
			acc.Balance += amount - num;
			BankLedger.Save();
		}
	}

	private static void Withdraw(Character character, BankLedger.Account acc, long amount)
	{
		if (amount > 0)
		{
			if (amount > acc.Balance)
			{
				amount = acc.Balance;
			}
			int num = (int)((amount <= int.MaxValue) ? amount : int.MaxValue);
			character.Inventory.AddMoney(num);
			acc.Balance -= num;
			BankLedger.Save();
		}
	}
}
internal static class BankAudio
{
	private static readonly Type s_clipType = Type.GetType("UnityEngine.AudioClip, UnityEngine.AudioModule");

	private static readonly Type s_sourceType = Type.GetType("UnityEngine.AudioSource, UnityEngine.AudioModule");

	private static readonly List<Object> s_repertoire = new List<Object>();

	private static string s_cachedPrefix;

	private static Object s_bundle;

	private static bool s_warnedBundle;

	private static readonly List<string> s_clipNames = new List<string>();

	private static string s_resolvedKey;

	public static void InvalidateCache()
	{
		s_repertoire.Clear();
		s_cachedPrefix = null;
	}

	public static void ApplyGreetingClip(Statement statement)
	{
	}

	public static void PlayGreetingBark(GameObject at, Character speaker)
	{
		try
		{
			string text = BankOfAuraiPlugin.BarkDialogueKey.Value;
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			if (text == "auto")
			{
				text = "dlg_buy_hostileman_1-";
			}
			text = text.ToLowerInvariant();
			Type type = Type.GetType("UnityEngine.AssetBundle, UnityEngine.AssetBundleModule");
			if (type == null || s_clipType == null || s_sourceType == null)
			{
				return;
			}
			if (s_bundle == (Object)null)
			{
				SNPCManager instance = SNPCManager.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return;
				}
				instance.LoadDialogueSoundsBundle();
				FieldInfo[] fields = typeof(SNPCManager).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (type.IsAssignableFrom(fieldInfo.FieldType))
					{
						object? value = fieldInfo.GetValue(instance);
						Object val = (Object)((value is Object) ? value : null);
						if (val != (Object)null)
						{
							s_bundle = val;
							break;
						}
					}
				}
				if (s_bundle == (Object)null)
				{
					if (!s_warnedBundle)
					{
						s_warnedBundle = true;
						BankOfAuraiPlugin.Log.LogInfo((object)"Banker voice unavailable (dialogue sound bundle not exposed); see README.");
					}
					return;
				}
				MethodInfo method = type.GetMethod("GetAllAssetNames");
				string[] array = ((!(method != null)) ? null : (method.Invoke(s_bundle, null) as string[]));
				if (array != null)
				{
					s_clipNames.Clear();
					string[] array2 = array;
					foreach (string text2 in array2)
					{
						if (text2.ToLowerInvariant().Contains(text))
						{
							s_clipNames.Add(text2);
						}
					}
					BankOfAuraiPlugin.Log.LogInfo((object)("Bark bundle loaded: " + array.Length + " assets, " + s_clipNames.Count + " matching '" + text + "'."));
				}
			}
			if (s_clipNames.Count == 0)
			{
				return;
			}
			string text3 = s_clipNames[Random.Range(0, s_clipNames.Count)];
			MethodInfo method2 = type.GetMethod("LoadAsset", new Type[2]
			{
				typeof(string),
				typeof(Type)
			});
			Object val2 = (Object)((!(method2 != null)) ? null : /*isinst with value type is only supported in some contexts*/);
			if (val2 == (Object)null)
			{
				BankOfAuraiPlugin.Log.LogWarning((object)("Could not load bark clip: " + text3));
				return;
			}
			Component val3 = at.GetComponent(s_sourceType);
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = at.AddComponent(s_sourceType);
			}
			if (!((Object)(object)val3 == (Object)null))
			{
				PropertyInfo property = s_sourceType.GetProperty("spatialBlend");
				if (property != null)
				{
					property.SetValue(val3, 0f, null);
				}
				PropertyInfo property2 = s_sourceType.GetProperty("volume");
				if (property2 != null)
				{
					property2.SetValue(val3, 1f, null);
				}
				MethodInfo method3 = s_sourceType.GetMethod("PlayOneShot", new Type[1] { s_clipType.MakeByRefType().GetElementType() ?? s_clipType });
				if (method3 == null)
				{
					method3 = s_sourceType.GetMethod("PlayOneShot", new Type[1] { s_clipType });
				}
				if (method3 != null)
				{
					method3.Invoke(val3, new object[1] { val2 });
					BankOfAuraiPlugin.Log.LogInfo((object)("Banker bark: " + text3));
				}
			}
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("PlayGreetingBark: " + ex));
		}
	}

	private static string FindKeyByText(string phrase)
	{
		try
		{
			if (string.IsNullOrEmpty(phrase))
			{
				return null;
			}
			string p = phrase.ToLowerInvariant();
			FieldInfo field = typeof(LocalizationManager).GetField("m_dialogueLocalization", BindingFlags.Instance | BindingFlags.NonPublic);
			IDictionary dictionary = ((!(field != null)) ? null : (field.GetValue(LocalizationManager.Instance) as IDictionary));
			if (dictionary == null)
			{
				return null;
			}
			foreach (DictionaryEntry item in dictionary)
			{
				if (ContainsPhrase(item.Value, p, 0))
				{
					BankOfAuraiPlugin.Log.LogMessage((object)string.Concat("Bark line found: key='", item.Key, "'"));
					return item.Key.ToString();
				}
			}
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("FindKeyByText: " + ex));
		}
		return null;
	}

	private static bool ContainsPhrase(object obj, string p, int depth)
	{
		if (obj == null || depth > 2)
		{
			return false;
		}
		Type type = obj.GetType();
		FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (FieldInfo fieldInfo in fields)
		{
			object value;
			try
			{
				value = fieldInfo.GetValue(obj);
			}
			catch
			{
				continue;
			}
			if (value is string)
			{
				if (((string)value).ToLowerInvariant().Contains(p))
				{
					return true;
				}
			}
			else
			{
				if (!(value is IEnumerable) || value is string)
				{
					continue;
				}
				foreach (object item in (IEnumerable)value)
				{
					if (item is string)
					{
						if (((string)item).ToLowerInvariant().Contains(p))
						{
							return true;
						}
					}
					else if (ContainsPhrase(item, p, depth + 1))
					{
						return true;
					}
				}
			}
		}
		return false;
	}

	private static void DumpCandidateKeys(string hint)
	{
		try
		{
			FieldInfo field = typeof(LocalizationManager).GetField("m_dialogueLocalization", BindingFlags.Instance | BindingFlags.NonPublic);
			IDictionary dictionary = ((!(field != null)) ? null : (field.GetValue(LocalizationManager.Instance) as IDictionary));
			if (dictionary == null)
			{
				BankOfAuraiPlugin.Log.LogWarning((object)"  (dialogue localization not readable)");
				return;
			}
			string text = (hint ?? "").ToLowerInvariant();
			int num = 0;
			foreach (object key in dictionary.Keys)
			{
				string text2 = key.ToString();
				string text3 = text2.ToLowerInvariant();
				if (text3.Contains("buy") || text3.Contains("hostile") || (text.Length > 2 && text3.Contains(text.Substring(0, 3))))
				{
					BankOfAuraiPlugin.Log.LogMessage((object)("  candidate: " + text2));
					if (++num >= 40)
					{
						break;
					}
				}
			}
			BankOfAuraiPlugin.Log.LogMessage((object)("  (" + dictionary.Count + " dialogue keys total, " + num + " shown)"));
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("DumpCandidateKeys: " + ex));
		}
	}

	public static void ScanScene()
	{
		try
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			DialogueTree[] array = Resources.FindObjectsOfTypeAll<DialogueTree>();
			BankOfAuraiPlugin.Log.LogMessage((object)("Audio scan: " + array.Length + " dialogue trees loaded."));
			DialogueTree[] array2 = array;
			foreach (DialogueTree val in array2)
			{
				List<Node> allNodes = ((Graph)val).allNodes;
				if (allNodes == null)
				{
					continue;
				}
				foreach (Node item in allNodes)
				{
					StatementNodeExt val2 = (StatementNodeExt)(object)((item is StatementNodeExt) ? item : null);
					if (val2 == null || val2.statement == null)
					{
						continue;
					}
					num++;
					string text = val2.statement.text ?? "";
					string text2 = text;
					try
					{
						string loc = LocalizationManager.Instance.GetLoc(text);
						if (!string.IsNullOrEmpty(loc))
						{
							text2 = loc;
						}
					}
					catch
					{
					}
					Object val3 = null;
					string text3 = (text + " " + text2).ToLowerInvariant();
					if (text3.Contains("money") || text3.Contains("better") || text3.Contains("coin"))
					{
						num3++;
						BankOfAuraiPlugin.Log.LogMessage((object)("  [" + ((Graph)val).name + "] text='" + text2 + "' key='" + text + "' clip=" + ((!(val3 != (Object)null)) ? "none" : val3.name)));
					}
				}
			}
			BankOfAuraiPlugin.Log.LogMessage((object)("Audio scan done: " + num + " statements, " + num2 + " voiced, " + num3 + " matched."));
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("Audio scan: " + ex));
		}
	}
}
internal static class AudioWiretap
{
	public static void Install()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		try
		{
			Harmony val = new Harmony("com.spencer4792.bankofaurai.wiretap");
			HarmonyMethod val2 = new HarmonyMethod(typeof(AudioWiretap).GetMethod("SoundPostfix", BindingFlags.Static | BindingFlags.NonPublic));
			int num = 0;
			MethodInfo[] methods = typeof(GlobalAudioManager).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (!methodInfo.Name.StartsWith("Play"))
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length != 0 && !(parameters[0].Name != "_sound"))
				{
					try
					{
						val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null);
						num++;
					}
					catch (Exception ex)
					{
						BankOfAuraiPlugin.Log.LogWarning((object)("Wiretap skip " + methodInfo.Name + ": " + ex.Message));
					}
				}
			}
			BankOfAuraiPlugin.Log.LogInfo((object)("Audio wiretap installed on " + num + " methods."));
		}
		catch (Exception ex2)
		{
			BankOfAuraiPlugin.Log.LogError((object)("Wiretap install: " + ex2));
		}
	}

	private static void SoundPostfix(object _sound, MethodBase __originalMethod)
	{
		try
		{
			if (BankOfAuraiPlugin.WiretapEnabled.Value)
			{
				BankOfAuraiPlugin.Log.LogMessage((object)("[wiretap] " + __originalMethod.Name + ": " + _sound));
			}
		}
		catch
		{
		}
	}

	public static void SnapshotPlaying()
	{
		try
		{
			Type type = Type.GetType("UnityEngine.AudioSource, UnityEngine.AudioModule");
			if (type == null)
			{
				BankOfAuraiPlugin.Log.LogWarning((object)"Snapshot: AudioSource type not found.");
				return;
			}
			PropertyInfo property = type.GetProperty("isPlaying");
			PropertyInfo property2 = type.GetProperty("clip");
			Object[] array = Resources.FindObjectsOfTypeAll(type);
			int num = 0;
			Object[] array2 = array;
			foreach (Object val in array2)
			{
				bool flag = false;
				try
				{
					flag = (bool)property.GetValue(val, null);
				}
				catch
				{
					continue;
				}
				if (flag)
				{
					num++;
					object? value = property2.GetValue(val, null);
					Object val2 = (Object)((value is Object) ? value : null);
					Component val3 = (Component)(object)((val is Component) ? val : null);
					string text = ((!((Object)(object)val3 != (Object)null)) ? "?" : ((Object)val3.gameObject).name);
					BankOfAuraiPlugin.Log.LogMessage((object)("[snapshot] playing: clip=" + ((!(val2 != (Object)null)) ? "none" : val2.name) + " on '" + text + "'"));
				}
			}
			BankOfAuraiPlugin.Log.LogMessage((object)("[snapshot] " + num + " sources playing of " + array.Length + "."));
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("Snapshot: " + ex));
		}
	}
}
internal static class BankBody
{
	private static readonly Dictionary<string, string> s_sources = new Dictionary<string, string>();

	private static readonly Dictionary<string, float> s_yaws = new Dictionary<string, float>();

	private static GameObject s_currentBody;

	private static string FilePath => Path.Combine(Path.Combine(Paths.ConfigPath, "BankOfAurai"), "bodies.txt");

	public static void Load()
	{
		s_sources.Clear();
		s_yaws.Clear();
		s_sources["CierzoNewTerrain"] = "snpc:HumanSNPCMoving (6)";
		s_yaws["CierzoNewTerrain"] = 73.34101f;
		s_sources["Monsoon"] = "snpc:HumanSNPC_Priest";
		s_yaws["Monsoon"] = 125.9873f;
		s_sources["Levant"] = "snpc:HumanSNPC_FestiveNoble";
		s_yaws["Levant"] = 26.10077f;
		s_sources["Berg"] = "snpc:HumanSNPCMoving (1)";
		s_yaws["Berg"] = 251.4524f;
		s_sources["NewSirocco"] = "snpc:UNPC_DLC2_AlchemySkillGiver";
		s_yaws["NewSirocco"] = 35.72704f;
		s_sources["Harmattan"] = "snpc:UNPC_DLC_VictorBerthelot_MilitaryDean";
		s_yaws["Harmattan"] = 125.2129f;
		try
		{
			if (!File.Exists(FilePath))
			{
				return;
			}
			string[] array = File.ReadAllLines(FilePath);
			foreach (string text in array)
			{
				string[] array2 = text.Split(new char[1] { '\t' });
				if (array2.Length >= 2)
				{
					s_sources[array2[0]] = array2[1];
				}
				if (array2.Length >= 3 && float.TryParse(array2[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					s_yaws[array2[0]] = result;
				}
			}
			BankOfAuraiPlugin.Log.LogInfo((object)("Banker bodies loaded: " + s_sources.Count + " scene(s)."));
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("Bodies load: " + ex));
		}
	}

	private static void Save()
	{
		try
		{
			Directory.CreateDirectory(Path.GetDirectoryName(FilePath));
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, string> s_source in s_sources)
			{
				string text = s_source.Key + "\t" + s_source.Value;
				if (s_yaws.TryGetValue(s_source.Key, out var value))
				{
					text = text + "\t" + value.ToString(CultureInfo.InvariantCulture);
				}
				list.Add(text);
			}
			File.WriteAllLines(FilePath, list.ToArray());
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("Bodies save: " + ex));
		}
	}

	public static void CopyNearestLook()
	{
		//IL_0093: 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_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Unknown result type (might be due to invalid IL or missing references)
		//IL_026e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		//IL_0278: Unknown result type (might be due to invalid IL or missing references)
		//IL_029e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a9: 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_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Character val = ((!((Object)(object)CharacterManager.Instance != (Object)null)) ? null : CharacterManager.Instance.GetFirstLocalCharacter());
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			GameObject val2 = null;
			string text = null;
			float num = 6f;
			Character[] array = Object.FindObjectsOfType<Character>();
			foreach (Character val3 in array)
			{
				if ((Object)(object)val3 == (Object)null || (Object)(object)val3 == (Object)(object)val)
				{
					continue;
				}
				CharacterVisuals visuals = val3.Visuals;
				if (!((Object)(object)visuals == (Object)null))
				{
					float num2 = Vector3.Distance(((Component)val3).transform.position, ((Component)val).transform.position);
					if (num2 < num)
					{
						num = num2;
						val2 = ((Component)visuals).gameObject;
						text = "char:" + val3.Name;
					}
				}
			}
			SNPC[] array2 = Object.FindObjectsOfType<SNPC>();
			foreach (SNPC val4 in array2)
			{
				if (!((Object)(object)val4 == (Object)null))
				{
					float num3 = Vector3.Distance(((Component)val4).transform.position, ((Component)val).transform.position);
					if (num3 < num)
					{
						num = num3;
						val2 = ((Component)val4).gameObject;
						text = "snpc:" + ((Object)((Component)val4).gameObject).name;
					}
				}
			}
			GameObject currentSpot = BankSpots.CurrentSpot;
			if ((Object)(object)val2 == (Object)null)
			{
				if ((Object)(object)currentSpot != (Object)null && (Object)(object)s_currentBody != (Object)null && Vector3.Distance(((Component)val).transform.position, currentSpot.transform.position) < 10f)
				{
					Scene activeScene = SceneManager.GetActiveScene();
					string name = ((Scene)(ref activeScene)).name;
					float value = AimBodyAt(currentSpot, ((Component)val).transform.position);
					s_yaws[name] = value;
					Save();
					BankOfAuraiPlugin.Log.LogMessage((object)("Banker re-aimed (yaw " + value.ToString("F0") + ") and saved."));
				}
				else
				{
					BankOfAuraiPlugin.Log.LogMessage((object)"No NPC within 6m to copy.");
				}
				return;
			}
			Scene activeScene2 = SceneManager.GetActiveScene();
			string name2 = ((Scene)(ref activeScene2)).name;
			s_sources[name2] = text;
			if ((Object)(object)BankSpots.CurrentSpot != (Object)null)
			{
				Vector3 val5 = ((Component)val).transform.position - BankSpots.CurrentSpot.transform.position;
				val5.y = 0f;
				if (((Vector3)(ref val5)).sqrMagnitude > 0.01f)
				{
					Dictionary<string, float> dictionary = s_yaws;
					Quaternion val6 = Quaternion.LookRotation(val5);
					dictionary[name2] = ((Quaternion)(ref val6)).eulerAngles.y;
				}
			}
			Save();
			BankOfAuraiPlugin.Log.LogMessage((object)("Banker for '" + name2 + "' cast: " + text));
			GameObject currentSpot2 = BankSpots.CurrentSpot;
			if ((Object)(object)currentSpot2 != (Object)null)
			{
				AttachCloneGO(val2, currentSpot2);
			}
			else
			{
				BankOfAuraiPlugin.Log.LogMessage((object)"No bank spot in this scene yet (F6 to place one).");
			}
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("CopyNearestLook: " + ex));
		}
	}

	public static void SpawnForScene(string sceneName, GameObject spot)
	{
		if ((Object)(object)s_currentBody != (Object)null)
		{
			Object.Destroy((Object)(object)s_currentBody);
			s_currentBody = null;
		}
		if (s_sources.TryGetValue(sceneName, out var value))
		{
			((MonoBehaviour)BankOfAuraiPlugin.Instance).StartCoroutine(WaitAndClone(value, spot));
		}
	}

	private static IEnumerator WaitAndClone(string key, GameObject spot)
	{
		for (int attempt = 0; attempt < 15; attempt++)
		{
			yield return (object)new WaitForSeconds(2f);
			if ((Object)(object)spot == (Object)null)
			{
				yield break;
			}
			GameObject found = null;
			if (key.StartsWith("snpc:"))
			{
				string text = key.Substring(5);
				SNPC[] array = Object.FindObjectsOfType<SNPC>();
				foreach (SNPC val in array)
				{
					if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name == text)
					{
						found = ((Component)val).gameObject;
						break;
					}
				}
			}
			else
			{
				string text2 = ((!key.StartsWith("char:")) ? key : key.Substring(5));
				Character[] array2 = Object.FindObjectsOfType<Character>();
				foreach (Character val2 in array2)
				{
					if ((Object)(object)val2 != (Object)null && val2.Name == text2 && (Object)(object)val2.Visuals != (Object)null)
					{
						found = ((Component)val2.Visuals).gameObject;
						break;
					}
				}
			}
			if ((Object)(object)found != (Object)null)
			{
				AttachCloneGO(found, spot);
				yield break;
			}
		}
		BankOfAuraiPlugin.Log.LogWarning((object)("Banker body source '" + key + "' never appeared in this scene."));
	}

	private static float AimBodyAt(GameObject spot, Vector3 target)
	{
		//IL_0000: 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_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = target - spot.transform.position;
		val.y = 0f;
		float num;
		if (((Vector3)(ref val)).sqrMagnitude > 0.01f)
		{
			Quaternion val2 = Quaternion.LookRotation(val);
			num = ((Quaternion)(ref val2)).eulerAngles.y;
		}
		else
		{
			num = 0f;
		}
		float num2 = num;
		if ((Object)(object)s_currentBody != (Object)null)
		{
			s_currentBody.transform.rotation = Quaternion.Euler(0f, num2, 0f);
		}
		return num2;
	}

	private static void AttachCloneGO(GameObject sourceGO, GameObject spot)
	{
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: 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_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)s_currentBody != (Object)null)
			{
				Object.Destroy((Object)(object)s_currentBody);
				s_currentBody = null;
			}
			GameObject val = Object.Instantiate<GameObject>(sourceGO);
			((Object)val).name = "BankOfAurai_Body";
			MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val2 in componentsInChildren)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Object.Destroy((Object)(object)val2);
				}
			}
			Collider[] componentsInChildren2 = val.GetComponentsInChildren<Collider>(true);
			foreach (Collider val3 in componentsInChildren2)
			{
				if ((Object)(object)val3 != (Object)null)
				{
					Object.Destroy((Object)(object)val3);
				}
			}
			Rigidbody[] componentsInChildren3 = val.GetComponentsInChildren<Rigidbody>(true);
			foreach (Rigidbody val4 in componentsInChildren3)
			{
				if ((Object)(object)val4 != (Object)null)
				{
					Object.Destroy((Object)(object)val4);
				}
			}
			val.transform.SetParent(spot.transform, false);
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			Dictionary<string, float> dictionary = s_yaws;
			Scene activeScene = SceneManager.GetActiveScene();
			if (dictionary.TryGetValue(((Scene)(ref activeScene)).name, out var value))
			{
				val.transform.rotation = Quaternion.Euler(0f, value, 0f);
			}
			else
			{
				Character val5 = ((!((Object)(object)CharacterManager.Instance != (Object)null)) ? null : CharacterManager.Instance.GetFirstLocalCharacter());
				if ((Object)(object)val5 != (Object)null)
				{
					Vector3 val6 = ((Component)val5).transform.position - spot.transform.position;
					val6.y = 0f;
					if (((Vector3)(ref val6)).sqrMagnitude > 0.01f)
					{
						val.transform.rotation = Quaternion.LookRotation(val6);
					}
				}
			}
			try
			{
				Type type = Type.GetType("UnityEngine.Animation, UnityEngine.AnimationModule");
				if (type != null)
				{
					Component componentInChildren = val.GetComponentInChildren(type);
					if ((Object)(object)componentInChildren != (Object)null)
					{
						MethodInfo method = type.GetMethod("Play", new Type[0]);
						if (method != null)
						{
							method.Invoke(componentInChildren, null);
						}
					}
				}
			}
			catch
			{
			}
			val.SetActive(true);
			s_currentBody = val;
			BankOfAuraiPlugin.Log.LogMessage((object)("Banker body attached from: " + ((Object)sourceGO).name));
		}
		catch (Exception ex)
		{
			BankOfAuraiPlugin.Log.LogError((object)("AttachClone: " + ex));
		}
	}
}