Decompiled source of Long Read v1.0.0

plugins/LongRead.dll

Decompiled 13 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LongRead.Dialogue;
using LongRead.Patches;
using NodeCanvas.DialogueTrees;
using NodeCanvas.Framework;
using NodeCanvas.Tasks.Actions;
using SideLoader;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("SideLoader")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace LongRead
{
	public enum TrainerChoice
	{
		Lawrence,
		Odette
	}
	public enum BowCast
	{
		PowerShot,
		PierceShot,
		EvasionShoot,
		StrafingShot
	}
	internal static class Settings
	{
		public static ConfigEntry<int> Price;

		public static ConfigEntry<bool> RequirePrerequisites;

		public static ConfigEntry<float> BowDamageMultiplier;

		public static ConfigEntry<float> FlourishDamageMultiplier;

		public static ConfigEntry<bool> ConsumeArrows;

		public static ConfigEntry<bool> UseBowFormNames;

		public static ConfigEntry<BowCast> BowCastAnimation;

		public static ConfigEntry<TrainerChoice> Trainer;

		public static void Bind(ConfigFile cfg)
		{
			Price = cfg.Bind<int>("General", "Price", 50, "Silver cost of Long Read when Dakers teaches it.");
			RequirePrerequisites = cfg.Bind<bool>("General", "RequirePrerequisites", true, "Require Probe and Hunter's Eye to be known before Dakers will teach Long Read.");
			BowDamageMultiplier = cfg.Bind<float>("Bow", "BowDamageMultiplier", 0.5f, "Weapon damage multiplier of the probing arrow at Alert levels 0-3 (vanilla melee Probe uses 0.5).");
			FlourishDamageMultiplier = cfg.Bind<float>("Bow", "FlourishDamageMultiplier", 1.25f, "Weapon damage multiplier of the probing arrow at Alert level 4 / Flourish (vanilla melee Flourish uses 1.25).");
			ConsumeArrows = cfg.Bind<bool>("Bow", "ConsumeArrows", true, "Consume one equipped arrow per probing shot.");
			UseBowFormNames = cfg.Bind<bool>("Bow", "UseBowFormNames", false, "Show bow-form stage names (Ranging Shot, Feint, Goad, Mark, Trick Shot) instead of the melee names while a bow is equipped.");
			BowCastAnimation = cfg.Bind<BowCast>("Bow", "BowCastAnimation", BowCast.PowerShot, "Animation used for the probing shot. PowerShot = Sniper Shot's long aimed draw; PierceShot = Piercing Shot's draw; EvasionShoot = quick shot with a backwards hop; StrafingShot = Strafing Run's shot.");
			Trainer = cfg.Bind<TrainerChoice>("Trainer", "Trainer", TrainerChoice.Lawrence, "Who teaches Long Read in Harmattan: Lawrence (extends Lawrence Dakers' dialogue) or Odette (spawns Odette Dakers, Tracker, beside him).");
		}
	}
	internal static class Ids
	{
		public const int LongRead = 2317000;

		public const int Probe = 8205422;

		public const int HuntersEye = 8205160;

		public const int Silver = 9000010;

		public const string AlertStatus = "Alert";
	}
	internal static class Text
	{
		public const string LongReadName = "Long Read";

		public const string TrainChoice = "I want to train with you.";

		public const string ReadyChoice = "I know the Probe and I've got the hunter's eye. Teach me.";

		public const string NotNowChoice = "Not now.";

		public const string AcceptLine = "You actually went and did it! Alright, nock an arrow and watch close...";

		public const string ClosingLine = "Hah! See that? A probing shot's no different from a probing jab. You just need farther eyes!";

		public const string OdetteWhoChoice = "Who are you?";

		public const string OdetteWhoLine = "Lawrence's sister. I run the trap lines outside the walls and read the ground for the Academy's hunters.";

		public const string OdetteGoodbye = "Goodbye.";

		public static readonly string[] BowFormNames = new string[5] { "Ranging Shot", "Feint", "Goad", "Mark", "Trick Shot" };

		public static string ExplainLine(int price)
		{
			string text = ((price > 0) ? ("Bring " + price + " silver with you and I'll teach you the rest!") : "Come back when you have them and I'll teach you the rest!");
			return "Reading a mark from bow range? Ha! Now that's a hunter's trick! But you need the basics first: learn Probe from Battleborn, right here in the market, and Hunter's Eye from Ture up in Berg. " + text;
		}
	}
	[BepInPlugin("djk.longread", "Long Read", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "djk.longread";

		public const string NAME = "Long Read";

		public const string VERSION = "1.0.0";

		internal static ManualLogSource Log;

		private Harmony m_harmony;

		private void Awake()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Settings.Bind(((BaseUnityPlugin)this).Config);
			string text = Settings.BowCastAnimation.Value.ToString();
			if (Enum.IsDefined(typeof(SpellCastType), text))
			{
				CastPatch.BowCastType = (SpellCastType)Enum.Parse(typeof(SpellCastType), text);
			}
			else
			{
				Log.LogWarning((object)("Could not resolve the bow cast type '" + text + "'; the probing shot will use PowerShot."));
			}
			m_harmony = new Harmony("djk.longread");
			m_harmony.PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)"Harmony patches applied.");
			SL.OnPacksLoaded += OnPacksLoaded;
			SL.OnSceneLoaded += OnSceneLoaded;
		}

		private static void OnPacksLoaded()
		{
			try
			{
				Item val = ((ResourcesPrefabManager.Instance != null) ? ResourcesPrefabManager.Instance.GetItemPrefab(2317000) : null);
				if ((Object)(object)val == (Object)null)
				{
					Log.LogWarning((object)"Long Read skill (2317000) was not created; check the SideLoader pack (Items/LongRead/LongRead.xml).");
				}
				else
				{
					Log.LogInfo((object)("Long Read skill registered (item " + 2317000 + ")."));
				}
				ProbeSetup.Apply();
				TrainerSetup.Prepare();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Long Read setup failed: " + ex));
			}
		}

		private static void OnSceneLoaded()
		{
			try
			{
				TrainerSetup.OnSceneLoaded();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Long Read trainer hook failed: " + ex));
			}
		}
	}
	public class LongReadBowRelay : MonoBehaviour
	{
		public const string BowChildName = "ReferencedLongReadBow";

		private LevelAttackSkill m_skill;

		private void Awake()
		{
			m_skill = ((Component)this).GetComponent<LevelAttackSkill>();
		}

		private bool TryGetBowCast(out Character owner, out ProjectileWeapon bow)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Invalid comparison between Unknown and I4
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			owner = (((Object)(object)m_skill != (Object)null) ? ((EffectSynchronizer)m_skill).OwnerCharacter : null);
			bow = (ProjectileWeapon)(((Object)(object)owner != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			return (Object)(object)bow != (Object)null && (int)((Weapon)bow).Type == 200 && owner.CurrentSpellCast == CastPatch.BowCastType;
		}

		private void ShootProjectileCastInit()
		{
			if (TryGetBowCast(out var _, out var bow) && ((Weapon)bow).IsEmpty && bow.CanBeLoaded())
			{
				((Weapon)bow).InstantLoadWeapon();
			}
		}

		private void ShootProjectileCast()
		{
			if (TryGetBowCast(out var owner, out var bow) && !((Weapon)bow).IsEmpty)
			{
				((Item)m_skill).CharSpellCast();
				((EffectSynchronizer)m_skill).SynchronizeEffects((EffectCategories)5, owner);
				bow.UnloadWeapon();
			}
		}

		private void ShootProjectileCastDone()
		{
		}
	}
	internal static class LongReadState
	{
		public static bool IsLearned(Character c, int itemId)
		{
			object obj;
			if (c == null)
			{
				obj = null;
			}
			else
			{
				CharacterInventory inventory = c.Inventory;
				obj = ((inventory != null) ? inventory.SkillKnowledge : null);
			}
			CharacterSkillKnowledge val = (CharacterSkillKnowledge)obj;
			return (Object)(object)val != (Object)null && ((CharacterKnowledge)val).IsItemLearned(itemId);
		}

		public static bool KnowsLongRead(Character c)
		{
			return IsLearned(c, 2317000);
		}

		public static bool HasPrerequisites(Character c)
		{
			if (!Settings.RequirePrerequisites.Value)
			{
				return true;
			}
			return IsLearned(c, 8205422) && IsLearned(c, 8205160);
		}

		public static bool IsBowEquipped(Character c)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			int result;
			if ((Object)(object)c != (Object)null)
			{
				Weapon currentWeapon = c.CurrentWeapon;
				ProjectileWeapon val = (ProjectileWeapon)(object)((currentWeapon is ProjectileWeapon) ? currentWeapon : null);
				if (val != null)
				{
					result = (((int)((Weapon)val).Type == 200) ? 1 : 0);
					goto IL_0029;
				}
			}
			result = 0;
			goto IL_0029;
			IL_0029:
			return (byte)result != 0;
		}

		public static bool IsBowBranch(Character c)
		{
			return IsBowEquipped(c) && KnowsLongRead(c);
		}
	}
	internal static class ProbeSetup
	{
		public static void Apply()
		{
			ResourcesPrefabManager instance = ResourcesPrefabManager.Instance;
			if (instance == null)
			{
				Plugin.Log.LogWarning((object)"ResourcesPrefabManager is not available; Probe could not be wired for bows.");
				return;
			}
			Item itemPrefab = instance.GetItemPrefab(8205422);
			LevelAttackSkill val = (LevelAttackSkill)(object)((itemPrefab is LevelAttackSkill) ? itemPrefab : null);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Probe prefab (8205422) not found; the bow branch is disabled.");
				return;
			}
			if ((Object)(object)((Component)val).GetComponent<LongReadBowRelay>() == (Object)null)
			{
				((Component)val).gameObject.AddComponent<LongReadBowRelay>();
			}
			Transform val2 = ((Component)val).transform.Find("ReferencedLongReadBow");
			if ((Object)(object)val2 == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Probe is missing the 'ReferencedLongReadBow' effect child; the SideLoader template Items/Probe_LongRead.xml did not apply.");
				return;
			}
			ShootProjectileAmmoVisuals component = ((Component)val2).GetComponent<ShootProjectileAmmoVisuals>();
			Projectile val3 = (((Object)(object)component != (Object)null) ? ((ShootProjectile)component).BaseProjectile : null);
			if ((Object)(object)val3 == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Probe's bow effect set has no projectile; the SniperShot projectile could not be cloned.");
				return;
			}
			int num = 0;
			WeaponDamageProjectileWeapon[] componentsInChildren = ((Component)val3).GetComponentsInChildren<WeaponDamageProjectileWeapon>(true);
			foreach (WeaponDamageProjectileWeapon val4 in componentsInChildren)
			{
				bool flag = ((Object)((Component)val4).transform).name.StartsWith("Flourish");
				((WeaponDamage)val4).WeaponDamageMult = (flag ? Settings.FlourishDamageMultiplier.Value : Settings.BowDamageMultiplier.Value);
				((WeaponDamage)val4).WeaponDurabilityLoss = 1f;
				num++;
			}
			UseLoadoutAmunition component2 = ((Component)val2).GetComponent<UseLoadoutAmunition>();
			if (!Settings.ConsumeArrows.Value && (Object)(object)component2 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component2);
			}
			string[] array = new string[3] { "Alert", "Confusion", "Pain" };
			foreach (string text in array)
			{
				if ((Object)(object)instance.GetStatusEffectPrefab(text) == (Object)null)
				{
					Plugin.Log.LogWarning((object)("Status effect '" + text + "' not found; the probing arrow will not apply it."));
				}
			}
			Plugin.Log.LogInfo((object)("Probe wired for bows: " + num + " hit groups, arrows " + (Settings.ConsumeArrows.Value ? "consumed" : "not consumed") + "."));
		}
	}
	internal static class TrainerSetup
	{
		public const string OdetteUid = "djk.longread.odette";

		public const string HarmattanScene = "Harmattan";

		public static bool LawrenceTeaches => Settings.Trainer.Value == TrainerChoice.Lawrence || PhotonNetwork.isNonMasterClientInRoom;

		public static void Prepare()
		{
			PrepareOdette();
			Plugin.Log.LogInfo((object)((Settings.Trainer.Value == TrainerChoice.Odette) ? "Trainer: Odette Dakers, Tracker spawns beside Lawrence Dakers when Harmattan loads." : "Trainer: Lawrence Dakers, Hunter (Harmattan) teaches Long Read in his dialogue."));
		}

		public static void PrepareOdette()
		{
			//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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			if (CustomCharacters.Templates.TryGetValue("djk.longread.odette", out var value))
			{
				SL_CharacterTrainer val = (SL_CharacterTrainer)(object)((value is SL_CharacterTrainer) ? value : null);
				if (val != null)
				{
					val.SkillTree = new SL_SkillTree
					{
						UID = "djk.longread.odette.unused",
						Name = "Long Read"
					};
					((SL_Character)val).ShouldSpawn = () => Settings.Trainer.Value == TrainerChoice.Odette;
					((SL_Character)val).OnSpawn -= OnOdetteSpawned;
					((SL_Character)val).OnSpawn += OnOdetteSpawned;
					return;
				}
			}
			Plugin.Log.LogWarning((object)"Odette Dakers' character template (Characters/OdetteDakers.xml) was not loaded; the Odette trainer option is unavailable.");
		}

		private static void OnOdetteSpawned(Character character, string rpcData)
		{
			try
			{
				if (CustomCharacters.Templates.TryGetValue("djk.longread.odette", out var value))
				{
					SL_CharacterTrainer val = (SL_CharacterTrainer)(object)((value is SL_CharacterTrainer) ? value : null);
					if (val != null)
					{
						OdetteDialogue.Build(character, val);
						Plugin.Log.LogInfo((object)"Trainer hooked: Odette Dakers, Tracker spawned in Harmattan.");
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Odette Dakers' dialogue could not be built: " + ex));
			}
		}

		public static void OnSceneLoaded()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			if (!LawrenceTeaches || SceneManagerHelper.ActiveSceneName != "Harmattan")
			{
				return;
			}
			DialogueTreeController[] array = Resources.FindObjectsOfTypeAll<DialogueTreeController>();
			foreach (DialogueTreeController val in array)
			{
				Graph val2 = (((Object)(object)val != (Object)null) ? ((GraphOwner)val).graph : null);
				if (DakersDialogue.IsDakersGraph(val2) && DakersDialogue.Inject((DialogueTreeExt)val2))
				{
					Plugin.Log.LogInfo((object)"Trainer hooked: Lawrence Dakers, Hunter (Harmattan) now offers Long Read.");
				}
			}
		}
	}
}
namespace LongRead.Patches
{
	[HarmonyPatch(typeof(Item), "StartEffectsCast")]
	internal static class CastPatch
	{
		internal static SpellCastType BowCastType = (SpellCastType)53;

		[HarmonyPrefix]
		private static bool Prefix(Item __instance, Character _targetChar)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (__instance.ItemID != 8205422 || (Object)(object)_targetChar == (Object)null)
			{
				return true;
			}
			if (!LongReadState.IsBowBranch(_targetChar))
			{
				return true;
			}
			_targetChar.CastSpell(BowCastType, ((Component)__instance).gameObject, (SpellCastModifier)0, __instance.GetCastSheathRequired(), __instance.MobileCastMovementMult);
			return false;
		}
	}
	[HarmonyPatch(typeof(DialogueTreeController), "GetInstance")]
	internal static class DialogueGraphPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Graph __result)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if (TrainerSetup.LawrenceTeaches && DakersDialogue.IsDakersGraph(__result) && DakersDialogue.Inject((DialogueTreeExt)__result))
			{
				Plugin.Log.LogInfo((object)"Trainer hooked: Lawrence Dakers, Hunter (Harmattan) now offers Long Read.");
			}
		}
	}
	[HarmonyPatch(typeof(SL), "Setup")]
	internal static class HotReloadPatch
	{
		[HarmonyPostfix]
		private static void Postfix(bool isFirstSetup)
		{
			if (isFirstSetup)
			{
				return;
			}
			try
			{
				ProbeSetup.Apply();
				TrainerSetup.PrepareOdette();
				Plugin.Log.LogInfo((object)"SideLoader hot reload: Long Read wiring re-applied.");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Long Read re-wiring after hot reload failed: " + ex));
			}
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class NamePatch
	{
		[HarmonyPostfix]
		private static void Postfix(Item __instance, ref string __result)
		{
			if (__instance.ItemID != 8205422 || !Settings.UseBowFormNames.Value)
			{
				return;
			}
			LevelAttackSkill val = (LevelAttackSkill)(object)((__instance is LevelAttackSkill) ? __instance : null);
			if (val == null)
			{
				return;
			}
			Character ownerCharacter = ((EffectSynchronizer)val).OwnerCharacter;
			if (!((Object)(object)ownerCharacter == (Object)null) && LongReadState.IsBowBranch(ownerCharacter))
			{
				int num = val.m_currentStage;
				if (num < 0)
				{
					num = 0;
				}
				if (num >= Text.BowFormNames.Length)
				{
					num = Text.BowFormNames.Length - 1;
				}
				__result = Text.BowFormNames[num];
			}
		}
	}
	[HarmonyPatch(typeof(AttackSkill), "OwnerHasAllRequiredItems")]
	internal static class ProbeRequirementPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(AttackSkill __instance, bool _TryingToActivate, ref bool __result)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Invalid comparison between Unknown and I4
			if (((Item)__instance).ItemID != 8205422)
			{
				return true;
			}
			Character ownerCharacter = ((EffectSynchronizer)__instance).OwnerCharacter;
			if (!((Object)(object)ownerCharacter == (Object)null))
			{
				Weapon currentWeapon = ownerCharacter.CurrentWeapon;
				ProjectileWeapon val = (ProjectileWeapon)(object)((currentWeapon is ProjectileWeapon) ? currentWeapon : null);
				if (val != null && (int)((Weapon)val).Type == 200)
				{
					__instance.m_weaponReq = null;
					__instance.m_offhandReq = null;
					if (!LongReadState.KnowsLongRead(ownerCharacter))
					{
						if (_TryingToActivate && (Object)(object)ownerCharacter.CharacterUI != (Object)null)
						{
							ownerCharacter.CharacterUI.ShowInfoNotificationLoc("Notification_Quickslot_MissingWeapon");
						}
						__result = false;
						return false;
					}
					if (((Weapon)val).IsEmpty && !val.CanBeLoaded())
					{
						if (_TryingToActivate && (Object)(object)ownerCharacter.CharacterUI != (Object)null)
						{
							ownerCharacter.CharacterUI.ShowInfoNotificationLoc("Notification_ProjectileWeapon_NoAmmunition");
						}
						__result = false;
						return false;
					}
					__instance.m_weaponReq = (Weapon)(object)val;
					__result = SkillOwnerHasAllRequiredItems((Skill)(object)__instance, _TryingToActivate);
					return false;
				}
			}
			return true;
		}

		[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPatch(typeof(Skill), "OwnerHasAllRequiredItems")]
		private static bool SkillOwnerHasAllRequiredItems(Skill instance, bool tryingToActivate)
		{
			throw new NotImplementedException("Harmony reverse patch stub");
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class WeaponDamagePatch
	{
		[HarmonyPrefix]
		private static bool Prefix(WeaponDamage __instance, Character _targetCharacter, ref DamageList _list, ref float _knockback, ref Weapon __result)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Invalid comparison between Unknown and I4
			if (!(__instance is WeaponDamageProjectileWeapon))
			{
				return true;
			}
			AttackSkill attackSkill = __instance.m_attackSkill;
			if ((Object)(object)attackSkill == (Object)null || ((Item)attackSkill).ItemID != 8205422)
			{
				return true;
			}
			__result = PunctualDamageBuildDamage((PunctualDamage)(object)__instance, _targetCharacter, ref _list, ref _knockback);
			Character ownerCharacter = ((EffectSynchronizer)attackSkill).OwnerCharacter;
			if ((Object)(object)ownerCharacter != (Object)null)
			{
				Weapon currentWeapon = ownerCharacter.CurrentWeapon;
				ProjectileWeapon val = (ProjectileWeapon)(object)((currentWeapon is ProjectileWeapon) ? currentWeapon : null);
				if (val != null && (int)((Weapon)val).Type == 200)
				{
					__instance.BuildDamage((Weapon)(object)val, _targetCharacter, true, ref _list, ref _knockback);
					__result = (Weapon)(object)val;
				}
			}
			return false;
		}

		[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static Weapon PunctualDamageBuildDamage(PunctualDamage instance, Character targetCharacter, ref DamageList list, ref float knockback)
		{
			throw new NotImplementedException("Harmony reverse patch stub");
		}
	}
}
namespace LongRead.Dialogue
{
	internal static class DakersDialogue
	{
		public const string GraphName = "Dialogue_Merchant_HarmattanGeneral";

		public const string ActorKey = "name_merchant_sorobormarketgeneral_01";

		private const string MenuNodeUid = "6b2bc05e-46e0-425f-a08d-842b9669d401";

		private const string FinishNodeUid = "4a817acc-d33a-4d44-99ed-1ca2624d92e0";

		private const string TrainChoiceLocKey = "Merchant_Generic_Train_01";

		public static bool IsDakersGraph(Graph graph)
		{
			return graph is DialogueTreeExt && graph.name != null && graph.name.StartsWith("Dialogue_Merchant_HarmattanGeneral");
		}

		public static bool Inject(DialogueTreeExt graph)
		{
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Expected O, but got Unknown
			if ((Object)(object)graph == (Object)null)
			{
				return false;
			}
			if (((Graph)graph).allNodes.Any((Node n) => n != null && n.tag == "LongRead.Train"))
			{
				return false;
			}
			MultipleChoiceNode val = ((Graph)graph).allNodes.OfType<MultipleChoiceNode>().FirstOrDefault((Func<MultipleChoiceNode, bool>)((MultipleChoiceNode n) => ((Node)n).UID == "6b2bc05e-46e0-425f-a08d-842b9669d401")) ?? ((Graph)graph).allNodes.OfType<MultipleChoiceNode>().FirstOrDefault();
			if (val == null)
			{
				Plugin.Log.LogWarning((object)"Lawrence Dakers' dialogue has no choice menu; the train option was not added.");
				return false;
			}
			FinishNode finish = ((Graph)graph).allNodes.OfType<FinishNode>().FirstOrDefault((Func<FinishNode, bool>)((FinishNode n) => ((Node)n).UID == "4a817acc-d33a-4d44-99ed-1ca2624d92e0")) ?? ((Graph)graph).allNodes.OfType<FinishNode>().FirstOrDefault() ?? TrainingDialogue.Tagged<FinishNode>(((Graph)graph).AddNode<FinishNode>());
			DTNode val2 = TrainingDialogue.Build(graph, "name_merchant_sorobormarketgeneral_01", finish);
			List<Choice> availableChoices = val.availableChoices;
			int num = ((availableChoices.Count > 0) ? (availableChoices.Count - 1) : 0);
			Choice item = new Choice(new Statement("I want to train with you.")
			{
				meta = "Merchant_Generic_Train_01"
			})
			{
				condition = (ConditionTask)(object)TrainingDialogue.Condition(graph, LongReadCondition.Check.NotLearned)
			};
			availableChoices.Insert(num, item);
			((Graph)graph).ConnectNodes((Node)(object)val, (Node)(object)val2, num, -1);
			return true;
		}
	}
	public class LongReadCondition : ConditionTask
	{
		public enum Check
		{
			NotLearned,
			CanTrain
		}

		public Check Mode;

		public BBParameter<Character> character;

		public override string info => "Long Read: " + Mode;

		public override bool OnCheck()
		{
			Character val = ((character != null) ? character.value : null);
			if ((Object)(object)val == (Object)null && (Object)(object)((Task)this).agent != (Object)null)
			{
				val = ((Task)this).agent.GetComponent<Character>();
			}
			if ((Object)(object)val == (Object)null && (Object)(object)CharacterManager.Instance != (Object)null)
			{
				val = CharacterManager.Instance.GetFirstLocalCharacter();
			}
			if ((Object)(object)val == (Object)null || (Object)(object)val.Inventory == (Object)null)
			{
				return false;
			}
			switch (Mode)
			{
			case Check.NotLearned:
				return !LongReadState.KnowsLongRead(val);
			case Check.CanTrain:
			{
				if (!LongReadState.HasPrerequisites(val))
				{
					return false;
				}
				int value = Settings.Price.Value;
				return value <= 0 || val.Inventory.OwnsItem(9000010, value);
			}
			default:
				return false;
			}
		}

		public LongReadCondition()
		{
			BBParameter<Character> obj = new BBParameter<Character>();
			((BBParameter)obj).name = "gInstigator";
			character = obj;
			((ConditionTask)this)..ctor();
		}
	}
	internal static class OdetteDialogue
	{
		public static void Build(Character trainer, SL_CharacterTrainer template)
		{
			DialogueTreeController componentInChildren = ((Component)trainer).GetComponentInChildren<DialogueTreeController>(true);
			DialogueTreeExt val = (DialogueTreeExt)(((Object)(object)componentInChildren != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Odette Dakers has no dialogue graph; her dialogue was left as SideLoader built it.");
			}
			else
			{
				if (((Graph)val).allNodes.Any((Node n) => n != null && n.tag == "LongRead.Train"))
				{
					return;
				}
				StatementNodeExt val2 = ((Graph)val).allNodes.OfType<StatementNodeExt>().FirstOrDefault();
				if (val2 == null)
				{
					Plugin.Log.LogWarning((object)"Odette Dakers' dialogue template is not the expected trainer graph; left unchanged.");
					return;
				}
				Connection[] array = ((Node)val2).outConnections.ToArray();
				foreach (Connection val3 in array)
				{
					((Graph)val).RemoveConnection(val3, false);
				}
				ActionNode[] array2 = ((Graph)val).allNodes.OfType<ActionNode>().ToArray();
				foreach (ActionNode item in array2)
				{
					((Graph)val).allNodes.Remove((Node)(object)item);
				}
				string name = ((SL_Character)template).Name;
				MultipleChoiceNodeExt val4 = TrainingDialogue.Tagged<MultipleChoiceNodeExt>(((Graph)val).AddNode<MultipleChoiceNodeExt>());
				StatementNodeExt val5 = TrainingDialogue.Statement(val, "Lawrence's sister. I run the trap lines outside the walls and read the ground for the Academy's hunters.", name);
				FinishNode val6 = TrainingDialogue.Tagged<FinishNode>(((Graph)val).AddNode<FinishNode>());
				DTNode target = TrainingDialogue.Build(val, name, val6);
				((Graph)val).ConnectNodes((Node)(object)val2, (Node)(object)val4, -1, -1);
				TrainingDialogue.AddChoice(val, val4, "Who are you?", null, null, (Node)(object)val5);
				TrainingDialogue.AddChoice(val, val4, "I want to train with you.", "Merchant_Generic_Train_01", (ConditionTask)(object)TrainingDialogue.Condition(val, LongReadCondition.Check.NotLearned), (Node)(object)target);
				TrainingDialogue.AddChoice(val, val4, "Goodbye.", null, null, (Node)(object)val6);
				((Graph)val).ConnectNodes((Node)(object)val5, (Node)(object)val6, -1, -1);
				((Node)val2).tag = "LongRead.Train";
				((Graph)val).primeNode = (Node)(object)val2;
			}
		}
	}
	internal static class TrainingDialogue
	{
		public const string Tag = "LongRead.Train";

		private const string NotNowLocKey = "Merchant_Generic_NotNow_01";

		public static DTNode Build(DialogueTreeExt graph, string actorKey, FinishNode finish)
		{
			StatementNodeExt val = Statement(graph, Text.ExplainLine(Settings.Price.Value), actorKey);
			MultipleChoiceNodeExt val2 = TrainingDialogue.Tagged<MultipleChoiceNodeExt>(((Graph)graph).AddNode<MultipleChoiceNodeExt>());
			StatementNodeExt val3 = Statement(graph, "You actually went and did it! Alright, nock an arrow and watch close...", actorKey);
			StatementNodeExt val4 = Statement(graph, "Hah! See that? A probing shot's no different from a probing jab. You just need farther eyes!", actorKey);
			ActionNode val5 = TrainingDialogue.Tagged<ActionNode>(((Graph)graph).AddNode<ActionNode>());
			val5.action = (ActionTask)(object)Task.Create<FadeOut>((ITaskSystem)(object)graph);
			ActionNode val6 = TrainingDialogue.Tagged<ActionNode>(((Graph)graph).AddNode<ActionNode>());
			val6.action = CreateRewardActions(graph);
			ActionNode val7 = TrainingDialogue.Tagged<ActionNode>(((Graph)graph).AddNode<ActionNode>());
			val7.action = (ActionTask)(object)Task.Create<FadeIn>((ITaskSystem)(object)graph);
			((Graph)graph).ConnectNodes((Node)(object)val, (Node)(object)val2, -1, -1);
			AddChoice(graph, val2, "I know the Probe and I've got the hunter's eye. Teach me.", null, (ConditionTask)(object)Condition(graph, LongReadCondition.Check.CanTrain), (Node)(object)val3);
			AddChoice(graph, val2, "Not now.", "Merchant_Generic_NotNow_01", null, (Node)(object)finish);
			((Graph)graph).ConnectNodes((Node)(object)val3, (Node)(object)val5, -1, -1);
			((Graph)graph).ConnectNodes((Node)(object)val5, (Node)(object)val6, -1, -1);
			((Graph)graph).ConnectNodes((Node)(object)val6, (Node)(object)val7, -1, -1);
			((Graph)graph).ConnectNodes((Node)(object)val7, (Node)(object)val4, -1, -1);
			((Graph)graph).ConnectNodes((Node)(object)val4, (Node)(object)finish, -1, -1);
			return (DTNode)(object)val;
		}

		private static ActionTask CreateRewardActions(DialogueTreeExt graph)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			GiveReward val = Task.Create<GiveReward>((ITaskSystem)(object)graph);
			val.RewardReceiver = (Receiver)1;
			val.SilverAmount = new BBParameter<int>(0);
			val.XpAmount = new BBParameter<int>(0);
			val.ItemReward.Add(new ItemQuantity
			{
				Item = new BBParameter<ItemReference>(new ItemReference
				{
					ItemID = 2317000
				}),
				Quantity = new BBParameter<int>(1),
				TryToEquip = new BBParameter<bool>(false)
			});
			int value = Settings.Price.Value;
			if (value <= 0)
			{
				return (ActionTask)(object)val;
			}
			RemoveItem val2 = Task.Create<RemoveItem>((ITaskSystem)(object)graph);
			BBParameter<Character> obj = new BBParameter<Character>();
			((BBParameter)obj).name = "gInstigator";
			val2.fromCharacter = obj;
			val2.Items.Add(new BBParameter<ItemReference>(new ItemReference
			{
				ItemID = 9000010
			}));
			val2.Amount.Add(new BBParameter<int>(value));
			ActionList val3 = Task.Create<ActionList>((ITaskSystem)(object)graph);
			val3.executionMode = (ActionsExecutionMode)0;
			val3.actions.Add((ActionTask)(object)val);
			val3.actions.Add((ActionTask)(object)val2);
			return (ActionTask)(object)val3;
		}

		public static LongReadCondition Condition(DialogueTreeExt graph, LongReadCondition.Check mode)
		{
			LongReadCondition longReadCondition = Task.Create<LongReadCondition>((ITaskSystem)(object)graph);
			longReadCondition.Mode = mode;
			return longReadCondition;
		}

		public static void AddChoice(DialogueTreeExt graph, MultipleChoiceNodeExt menu, string text, string locKey, ConditionTask condition, Node target)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			Statement val = new Statement(text);
			if (!string.IsNullOrEmpty(locKey))
			{
				val.meta = locKey;
			}
			menu.availableChoices.Add(new Choice(val)
			{
				condition = condition
			});
			((Graph)graph).ConnectNodes((Node)(object)menu, target, menu.availableChoices.Count - 1, -1);
		}

		public static StatementNodeExt Statement(DialogueTreeExt graph, string line, string actorKey)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			StatementNodeExt val = TrainingDialogue.Tagged<StatementNodeExt>(((Graph)graph).AddNode<StatementNodeExt>());
			val.statement = new Statement(line);
			val.SetActorName(actorKey);
			return val;
		}

		public static T Tagged<T>(T node) where T : Node
		{
			((Node)node).tag = "LongRead.Train";
			return node;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}