Decompiled source of BingBong Trading Co v1.0.0

plugins\BingBongTradingCo\BingBongContracts.dll

Decompiled 2 weeks ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Peak;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.Core;
using Zorro.Core.Serizalization;
using Zorro.Settings;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BingBongContracts")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+26c31d671172ca5005a576761a86e5cb1e1412cb")]
[assembly: AssemblyProduct("BingBongContracts")]
[assembly: AssemblyTitle("BingBongContracts")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 BingBongContracts
{
	internal sealed class BingBongContractPageVisual : MonoBehaviour
	{
		private sealed class PagePanel
		{
			public TextMeshProUGUI TaskType;

			public TextMeshProUGUI Quantity;
		}

		private static readonly Color PaperColor = new Color(0.82f, 0.72f, 0.53f, 1f);

		private static readonly Color InkColor = new Color(0.16f, 0.105f, 0.065f, 1f);

		private readonly List<PagePanel> panels = new List<PagePanel>();

		private readonly List<Texture2D> inkTextures = new List<Texture2D>();

		private readonly List<Sprite> inkSprites = new List<Sprite>();

		private Guidebook page;

		private ContractOffer offer;

		private bool helicopterTicket;

		private int renderedTicketTeamCount = -1;

		private Sprite ticketPlaneSprite;

		private Coroutine initializeRoutine;

		private Texture renderedTexture;

		internal bool ReadyForBurn
		{
			get
			{
				if (panels.Count != 0 && (Object)(object)page != (Object)null && (Object)(object)page.currentRenderTexture != (Object)null)
				{
					return (Object)(object)renderedTexture == (Object)(object)page.currentRenderTexture;
				}
				return false;
			}
		}

		internal static void Attach(Guidebook guidebook, ContractOffer contract)
		{
			BingBongContractPageVisual component = ((Component)guidebook).GetComponent<BingBongContractPageVisual>();
			if ((Object)(object)component != (Object)null)
			{
				component.page = guidebook;
				component.offer = contract;
				component.helicopterTicket = false;
				if (component.panels.Count != 0)
				{
					component.RefreshPage();
				}
				else
				{
					component.EnsureInitialized();
				}
			}
			else
			{
				BingBongContractPageVisual bingBongContractPageVisual = ((Component)guidebook).gameObject.AddComponent<BingBongContractPageVisual>();
				bingBongContractPageVisual.page = guidebook;
				bingBongContractPageVisual.offer = contract;
				bingBongContractPageVisual.EnsureInitialized();
			}
		}

		internal static void AttachTicket(Guidebook guidebook)
		{
			BingBongContractPageVisual bingBongContractPageVisual = ((Component)guidebook).GetComponent<BingBongContractPageVisual>();
			if ((Object)(object)bingBongContractPageVisual == (Object)null)
			{
				bingBongContractPageVisual = ((Component)guidebook).gameObject.AddComponent<BingBongContractPageVisual>();
			}
			bingBongContractPageVisual.page = guidebook;
			bingBongContractPageVisual.helicopterTicket = true;
			if (bingBongContractPageVisual.panels.Count != 0)
			{
				bingBongContractPageVisual.RefreshPage();
			}
			else
			{
				bingBongContractPageVisual.EnsureInitialized();
			}
		}

		private void EnsureInitialized()
		{
			if (!((Object)(object)page == (Object)null) && panels.Count == 0 && initializeRoutine == null && ((Behaviour)this).isActiveAndEnabled)
			{
				initializeRoutine = ((MonoBehaviour)this).StartCoroutine(Initialize());
			}
		}

		private IEnumerator Initialize()
		{
			while (!PageRenderTargetReady())
			{
				if ((Object)(object)page == (Object)null)
				{
					initializeRoutine = null;
					yield break;
				}
				yield return null;
			}
			TextMeshProUGUI componentInChildren = ((Component)page.canvasScaler).GetComponentInChildren<TextMeshProUGUI>(true);
			if ((Object)(object)componentInChildren == (Object)null)
			{
				initializeRoutine = null;
				yield break;
			}
			if (helicopterTicket)
			{
				ticketPlaneSprite = FindGamePlaneSprite();
			}
			List<Sprite> itemSprites = CreateItemSprites();
			RectTransform component = ((Component)page.canvasScaler).GetComponent<RectTransform>();
			GameObject val = new GameObject("BingBong Contract Spread", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)component, false);
			RectTransform component2 = val.GetComponent<RectTransform>();
			SetAnchors(component2, Vector2.zero, Vector2.one);
			panels.Add(CreatePanel("Left Page", component2, componentInChildren, itemSprites, Vector2.zero, new Vector2(0.5f, 1f)));
			panels.Add(CreatePanel("Right Page", component2, componentInChildren, itemSprites, new Vector2(0.5f, 0f), Vector2.one));
			val.transform.SetAsLastSibling();
			RefreshPage();
			LocalizedText.OnLangugageChanged = (Action)Delegate.Combine(LocalizedText.OnLangugageChanged, new Action(RefreshPage));
			initializeRoutine = null;
		}

		private bool PageRenderTargetReady()
		{
			if ((Object)(object)page == (Object)null || (Object)(object)page.canvasScaler == (Object)null || (Object)(object)page.renderCamera == (Object)null || (Object)(object)page.currentRenderTexture == (Object)null || page.currentRenderTexture.width <= 0 || page.currentRenderTexture.height <= 0 || page.pageRenderers == null || page.pageRenderers.Length == 0)
			{
				return false;
			}
			if (page.isSinglePage)
			{
				Texture currentRenderTexture = page.currentRenderTexture;
				RenderTexture val = (RenderTexture)(object)((currentRenderTexture is RenderTexture) ? currentRenderTexture : null);
				if (val != null && (Object)(object)page.renderCamera.targetTexture != (Object)(object)val)
				{
					return false;
				}
			}
			return true;
		}

		private PagePanel CreatePanel(string name, RectTransform parent, TextMeshProUGUI sourceText, IReadOnlyList<Sprite> itemSprites, Vector2 anchorMin, Vector2 anchorMax)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: 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_013b: 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_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			val.transform.SetParent((Transform)(object)parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			SetAnchors(component, anchorMin, anchorMax);
			Image component2 = val.GetComponent<Image>();
			((Graphic)component2).color = PaperColor;
			((Graphic)component2).raycastTarget = false;
			PagePanel pagePanel = new PagePanel
			{
				TaskType = CreateText("Task Type", (Transform)(object)component, sourceText, (FontStyles)1),
				Quantity = CreateText("Quantity", (Transform)(object)component, sourceText, (FontStyles)0)
			};
			SetAnchors(((TMP_Text)pagePanel.TaskType).rectTransform, new Vector2(0.08f, 0.79f), new Vector2(0.92f, 0.94f));
			SetAnchors(((TMP_Text)pagePanel.Quantity).rectTransform, new Vector2(0.08f, 0.06f), new Vector2(0.92f, 0.2f));
			CreateItemImages(component, itemSprites);
			bool flag = !helicopterTicket && offer.Accepted && offer.Kind == ContractKind.Special;
			if (flag)
			{
				SetAnchors(((TMP_Text)pagePanel.TaskType).rectTransform, new Vector2(0.16f, 0.42f), new Vector2(0.78f, 0.86f));
				SetAnchors(((TMP_Text)pagePanel.Quantity).rectTransform, new Vector2(0.16f, 0.22f), new Vector2(0.78f, 0.33f));
				((TMP_Text)pagePanel.TaskType).alignment = (TextAlignmentOptions)258;
				((TMP_Text)pagePanel.TaskType).fontStyle = (FontStyles)0;
				((TMP_Text)pagePanel.TaskType).fontWeight = (FontWeight)500;
				((TMP_Text)pagePanel.TaskType).textWrappingMode = (TextWrappingModes)1;
				((TMP_Text)pagePanel.TaskType).overflowMode = (TextOverflowModes)0;
				((TMP_Text)pagePanel.TaskType).lineSpacing = 4f;
				((TMP_Text)pagePanel.Quantity).alignment = (TextAlignmentOptions)258;
				((TMP_Text)pagePanel.Quantity).textWrappingMode = (TextWrappingModes)1;
				((TMP_Text)pagePanel.Quantity).overflowMode = (TextOverflowModes)0;
			}
			Rect rect = component.rect;
			float num = Mathf.Max(1f, ((Rect)(ref rect)).height);
			((TMP_Text)pagePanel.TaskType).enableAutoSizing = true;
			((TMP_Text)pagePanel.TaskType).fontSizeMin = num * (flag ? 0.052f : 0.055f);
			((TMP_Text)pagePanel.TaskType).fontSizeMax = num * (flag ? 0.082f : 0.09f);
			((TMP_Text)pagePanel.Quantity).enableAutoSizing = true;
			((TMP_Text)pagePanel.Quantity).fontSizeMin = num * (flag ? 0.062f : 0.05f);
			((TMP_Text)pagePanel.Quantity).fontSizeMax = num * (flag ? 0.095f : 0.08f);
			val.transform.SetAsLastSibling();
			return pagePanel;
		}

		private static TextMeshProUGUI CreateText(string name, Transform parent, TextMeshProUGUI sourceText, FontStyles style)
		{
			//IL_002e: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(TextMeshProUGUI)
			});
			val.transform.SetParent(parent, false);
			TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).font = ((TMP_Text)sourceText).font;
			((TMP_Text)component).fontSharedMaterial = ((TMP_Text)sourceText).fontSharedMaterial;
			((Graphic)component).color = InkColor;
			((TMP_Text)component).fontStyle = style;
			((TMP_Text)component).fontWeight = (FontWeight)(((style & 1) != 0) ? 700 : 400);
			((TMP_Text)component).alignment = (TextAlignmentOptions)514;
			((TMP_Text)component).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)component).overflowMode = (TextOverflowModes)1;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private List<Sprite> CreateItemSprites()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			if (helicopterTicket)
			{
				if ((Object)(object)ticketPlaneSprite == (Object)null)
				{
					return new List<Sprite>();
				}
				Texture2D val = CreateInkTexture(ticketPlaneSprite.texture);
				Rect rect = ticketPlaneSprite.rect;
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor((((Rect)(ref rect)).width > 0f) ? (ticketPlaneSprite.pivot.x / ((Rect)(ref rect)).width) : 0.5f, (((Rect)(ref rect)).height > 0f) ? (ticketPlaneSprite.pivot.y / ((Rect)(ref rect)).height) : 0.5f);
				Sprite val3 = Sprite.Create(val, rect, val2, ticketPlaneSprite.pixelsPerUnit);
				((Object)val3).name = "BingBong Contract Ink Plane";
				((Object)val3).hideFlags = (HideFlags)61;
				inkTextures.Add(val);
				inkSprites.Add(val3);
				return new List<Sprite> { val3 };
			}
			if (offer.Kind == ContractKind.Special && (offer.Accepted || (Object)(object)offer.TargetItem == (Object)null))
			{
				return new List<Sprite>();
			}
			List<Item> list = ((offer.Kind == ContractKind.Collection && offer.CollectionTargets.Count > 0) ? offer.CollectionTargets : new List<Item> { offer.TargetItem });
			List<Sprite> list2 = new List<Sprite>(list.Count);
			for (int i = 0; i < list.Count; i++)
			{
				Texture2D val4 = CreateInkTexture(list[i].UIData.GetIcon());
				Sprite val5 = Sprite.Create(val4, new Rect(0f, 0f, (float)((Texture)val4).width, (float)((Texture)val4).height), new Vector2(0.5f, 0.5f), 100f);
				((Object)val5).name = "BingBong Contract Ink " + ((Object)list[i]).name;
				((Object)val5).hideFlags = (HideFlags)61;
				inkTextures.Add(val4);
				inkSprites.Add(val5);
				list2.Add(val5);
			}
			return list2;
		}

		private static Texture2D CreateInkTexture(Texture2D source)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: 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_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: 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)
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)source).width, ((Texture)source).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)0);
			RenderTexture active = RenderTexture.active;
			Graphics.Blit((Texture)(object)source, temporary);
			RenderTexture.active = temporary;
			Texture2D val = new Texture2D(((Texture)source).width, ((Texture)source).height, (TextureFormat)4, false)
			{
				name = "BingBong Contract Ink " + ((Object)source).name,
				hideFlags = (HideFlags)61,
				filterMode = ((Texture)source).filterMode,
				wrapMode = (TextureWrapMode)1
			};
			val.ReadPixels(new Rect(0f, 0f, (float)((Texture)source).width, (float)((Texture)source).height), 0, 0);
			val.Apply();
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
			Color[] pixels = val.GetPixels();
			for (int i = 0; i < pixels.Length; i++)
			{
				Color val2 = pixels[i];
				float num = val2.r * 0.2126f + val2.g * 0.7152f + val2.b * 0.0722f;
				float num2 = Mathf.Lerp(1f, 0.28f, num);
				Color val3 = Color.Lerp(PaperColor, InkColor, num2);
				val3.a = val2.a;
				pixels[i] = val3;
			}
			val.SetPixels(pixels);
			val.Apply();
			return val;
		}

		private static Sprite FindGamePlaneSprite()
		{
			LoadingScreenHandler instance = RetrievableResourceSingleton<LoadingScreenHandler>.Instance;
			LoadingScreen val = (((Object)(object)instance != (Object)null) ? instance.loadingScreenPrefabPlane : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			LoadingScreenAnimation componentInChildren = ((Component)val).GetComponentInChildren<LoadingScreenAnimation>(true);
			if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.planeRotation != (Object)null)
			{
				Image val2 = ((Component)componentInChildren.planeRotation).GetComponent<Image>() ?? ((Component)componentInChildren.planeRotation).GetComponentInChildren<Image>(true);
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.sprite != (Object)null)
				{
					return val2.sprite;
				}
				SpriteRenderer val3 = ((Component)componentInChildren.planeRotation).GetComponent<SpriteRenderer>() ?? ((Component)componentInChildren.planeRotation).GetComponentInChildren<SpriteRenderer>(true);
				if ((Object)(object)val3 != (Object)null && (Object)(object)val3.sprite != (Object)null)
				{
					return val3.sprite;
				}
			}
			Image[] componentsInChildren = ((Component)val).GetComponentsInChildren<Image>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i].sprite != (Object)null && ((Object)componentsInChildren[i]).name.IndexOf("plane", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return componentsInChildren[i].sprite;
				}
			}
			return null;
		}

		private static void CreateItemImages(RectTransform parent, IReadOnlyList<Sprite> sprites)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_0156: Unknown result type (might be due to invalid IL or missing references)
			if (sprites.Count != 0)
			{
				int num = ((sprites.Count == 4) ? 2 : Mathf.Min(3, sprites.Count));
				int num2 = Mathf.CeilToInt((float)sprites.Count / (float)num);
				float num3 = 0.84000003f / (float)num;
				float num4 = 0.54999995f / (float)num2;
				for (int i = 0; i < sprites.Count; i++)
				{
					GameObject val = new GameObject($"Item Ink {i + 1}", new Type[3]
					{
						typeof(RectTransform),
						typeof(CanvasRenderer),
						typeof(Image)
					});
					val.transform.SetParent((Transform)(object)parent, false);
					Image component = val.GetComponent<Image>();
					component.sprite = sprites[i];
					((Graphic)component).color = Color.white;
					component.preserveAspect = true;
					((Graphic)component).raycastTarget = false;
					int num5 = i / num;
					int num6 = i % num;
					int num7 = Mathf.Min(num, sprites.Count - num5 * num);
					float num8 = (float)(num - num7) * num3 * 0.5f;
					float num9 = num3 * 0.08f;
					float num10 = num4 * 0.06f;
					SetAnchors(((Graphic)component).rectTransform, new Vector2(0.08f + num8 + (float)num6 * num3 + num9, 0.77f - (float)(num5 + 1) * num4 + num10), new Vector2(0.08f + num8 + (float)(num6 + 1) * num3 - num9, 0.77f - (float)num5 * num4 - num10));
				}
			}
		}

		private void RefreshPage()
		{
			if (helicopterTicket)
			{
				renderedTicketTeamCount = GetTeamCount();
				for (int i = 0; i < panels.Count; i++)
				{
					((TMP_Text)panels[i].TaskType).text = LocalizedText.GetText("BINGBONG_HELICOPTER_TICKET", true);
					((TMP_Text)panels[i].Quantity).text = $"× {renderedTicketTeamCount}";
				}
				RenderPage();
				return;
			}
			string text = ((offer.Kind == ContractKind.Special) ? ContractShopManager.GetSpecialTaskActionText(offer) : LocalizedText.GetText((offer.Kind == ContractKind.Transport) ? "BINGBONG_CONTRACT_TRANSPORT" : "BINGBONG_CONTRACT_COLLECT", true).Replace("#", string.Empty).Trim(' ', ':', ':'));
			for (int j = 0; j < panels.Count; j++)
			{
				((TMP_Text)panels[j].TaskType).text = text;
				((TMP_Text)panels[j].Quantity).text = ((offer.Accepted && offer.Kind == ContractKind.Special) ? ContractShopManager.GetSpecialTaskRequirementText(offer) : $"× {offer.RequiredCount}");
			}
			RenderPage();
		}

		private void Update()
		{
			if (panels.Count == 0)
			{
				EnsureInitialized();
				return;
			}
			if ((Object)(object)page != (Object)null && (Object)(object)page.currentRenderTexture != (Object)null && (Object)(object)renderedTexture != (Object)(object)page.currentRenderTexture && PageRenderTargetReady())
			{
				RefreshPage();
			}
			if (helicopterTicket && GetTeamCount() != renderedTicketTeamCount)
			{
				RefreshPage();
			}
		}

		private static int GetTeamCount()
		{
			int num = 0;
			for (int i = 0; i < Character.AllCharacters.Count; i++)
			{
				if ((Object)(object)Character.AllCharacters[i] != (Object)null)
				{
					num++;
				}
			}
			return Mathf.Max(1, num);
		}

		private void RenderPage()
		{
			if (PageRenderTargetReady())
			{
				Canvas.ForceUpdateCanvases();
				page.renderCamera.Render();
				for (int i = 0; i < page.pageRenderers.Length; i++)
				{
					page.pageRenderers[i].material.SetTexture(Guidebook.BASETEX, page.currentRenderTexture);
				}
				renderedTexture = page.currentRenderTexture;
			}
		}

		private void OnDestroy()
		{
			LocalizedText.OnLangugageChanged = (Action)Delegate.Remove(LocalizedText.OnLangugageChanged, new Action(RefreshPage));
			for (int i = 0; i < inkSprites.Count; i++)
			{
				Object.Destroy((Object)(object)inkSprites[i]);
			}
			for (int j = 0; j < inkTextures.Count; j++)
			{
				Object.Destroy((Object)(object)inkTextures[j]);
			}
		}

		private static void SetAnchors(RectTransform rect, Vector2 min, Vector2 max)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = min;
			rect.anchorMax = max;
			rect.offsetMin = Vector2.zero;
			rect.offsetMax = Vector2.zero;
		}
	}
	internal static class BingBongContractVisuals
	{
		private const string ClosedScrollPrefabName = "GuidebookPageScroll Variant";

		private static Item closedScroll;

		private static Guidebook openPage;

		internal static Item ClosedScroll
		{
			get
			{
				if ((Object)(object)closedScroll == (Object)null)
				{
					ItemDatabase.TryGetItem("GuidebookPageScroll Variant", ref closedScroll);
				}
				return closedScroll;
			}
		}

		internal static Guidebook OpenPage
		{
			get
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Invalid comparison between Unknown and I4
				if ((Object)(object)openPage == (Object)null)
				{
					Guidebook[] pages = SingletonAsset<GuidebookPageCollection>.Instance.pages;
					for (int i = 0; i < pages.Length; i++)
					{
						if ((int)pages[i].pageFlag == 1)
						{
							openPage = pages[i];
							break;
						}
					}
				}
				return openPage;
			}
		}

		internal static Texture ClosedIcon => (Texture)(object)ClosedScroll.UIData.GetIcon();

		internal static Texture OpenIcon => (Texture)(object)((Item)OpenPage).UIData.GetIcon();
	}
	internal sealed class BingBongCurrencyHud : MonoBehaviour
	{
		private const float NumberScale = 2.35f;

		private const float IconScale = 2.1f;

		private const float GapScale = 0.32f;

		private const float VerticalOffsetScale = 0.75f;

		private const float DeltaRaiseScale = 1.15f;

		private const float DeltaFadeIn = 0.12f;

		private const float DeltaHold = 2.45f;

		private const float DeltaFadeOut = 0.8f;

		private static readonly Color PenaltyDeltaColor = new Color(0.65f, 0.12f, 0.1f, 1f);

		private TextMeshProUGUI sourceText;

		private RectTransform root;

		private Image coinImage;

		private TextMeshProUGUI balanceText;

		private TextMeshProUGUI deltaText;

		private int lastBalance = int.MinValue;

		private int lastChangeSerial;

		private float deltaStartedAt = float.NegativeInfinity;

		private Color deltaBaseColor = Color.white;

		public static void Attach(AscentUI ascentUi)
		{
			((Component)ascentUi).gameObject.AddComponent<BingBongCurrencyHud>().Initialize(ascentUi.text);
		}

		private void Initialize(TextMeshProUGUI source)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_011a: 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_015c: Expected O, but got Unknown
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Expected O, but got Unknown
			sourceText = source;
			GameObject val = new GameObject("BingBong Currency", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)((TMP_Text)sourceText).rectTransform, false);
			root = val.GetComponent<RectTransform>();
			root.anchorMin = new Vector2(1f, 0f);
			root.anchorMax = new Vector2(1f, 0f);
			root.pivot = new Vector2(1f, 1f);
			GameObject val2 = new GameObject("Coin", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			val2.transform.SetParent((Transform)(object)root, false);
			coinImage = val2.GetComponent<Image>();
			coinImage.sprite = BingBongUiResources.CoinSprite;
			coinImage.preserveAspect = true;
			((Graphic)coinImage).raycastTarget = false;
			((Graphic)coinImage).color = Color.white;
			GameObject val3 = new GameObject("Balance", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(TextMeshProUGUI)
			});
			val3.transform.SetParent((Transform)(object)root, false);
			balanceText = val3.GetComponent<TextMeshProUGUI>();
			((TMP_Text)balanceText).font = ((TMP_Text)sourceText).font;
			((TMP_Text)balanceText).fontSharedMaterial = ((TMP_Text)sourceText).fontSharedMaterial;
			((Graphic)balanceText).color = Color.white;
			((TMP_Text)balanceText).fontStyle = (FontStyles)0;
			((TMP_Text)balanceText).fontWeight = (FontWeight)400;
			((TMP_Text)balanceText).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)balanceText).enableAutoSizing = false;
			((TMP_Text)balanceText).textWrappingMode = (TextWrappingModes)0;
			((Graphic)balanceText).raycastTarget = false;
			GameObject val4 = new GameObject("Balance Change", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(TextMeshProUGUI)
			});
			val4.transform.SetParent((Transform)(object)root, false);
			deltaText = val4.GetComponent<TextMeshProUGUI>();
			((TMP_Text)deltaText).font = ((TMP_Text)sourceText).font;
			((TMP_Text)deltaText).fontSharedMaterial = ((TMP_Text)sourceText).fontSharedMaterial;
			((TMP_Text)deltaText).fontStyle = (FontStyles)0;
			((TMP_Text)deltaText).fontWeight = (FontWeight)400;
			((TMP_Text)deltaText).alignment = (TextAlignmentOptions)260;
			((TMP_Text)deltaText).enableAutoSizing = false;
			((TMP_Text)deltaText).textWrappingMode = (TextWrappingModes)0;
			((Graphic)deltaText).raycastTarget = false;
			((Component)deltaText).gameObject.SetActive(false);
			lastChangeSerial = ContractShopManager.Instance?.CoinChangeSerial ?? 0;
			((Transform)root).SetAsLastSibling();
			RefreshLayout();
		}

		private void LateUpdate()
		{
			ContractShopManager instance = ContractShopManager.Instance;
			bool shouldShowCurrencyHud = instance.ShouldShowCurrencyHud;
			if (((Component)root).gameObject.activeSelf != shouldShowCurrencyHud)
			{
				((Component)root).gameObject.SetActive(shouldShowCurrencyHud);
			}
			if (shouldShowCurrencyHud)
			{
				int coinBalance = instance.CoinBalance;
				if (coinBalance != lastBalance)
				{
					lastBalance = coinBalance;
					((TMP_Text)balanceText).text = coinBalance.ToString("D3");
					RefreshLayout();
				}
				if (instance.CoinChangeSerial != lastChangeSerial)
				{
					lastChangeSerial = instance.CoinChangeSerial;
					ShowDelta(instance.LastCoinChangeAmount, instance.LastCoinChangeWasPenalty);
				}
				UpdateDeltaFade();
			}
		}

		private void ShowDelta(int amount, bool penalty)
		{
			//IL_0037: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (amount != 0)
			{
				((TMP_Text)deltaText).text = ((amount > 0) ? $"+{amount}" : amount.ToString());
				deltaBaseColor = (penalty ? PenaltyDeltaColor : Color.white);
				deltaStartedAt = Time.unscaledTime;
				((Graphic)deltaText).color = new Color(deltaBaseColor.r, deltaBaseColor.g, deltaBaseColor.b, 0f);
				((Component)deltaText).gameObject.SetActive(true);
				RefreshLayout();
			}
		}

		private void UpdateDeltaFade()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (((Component)deltaText).gameObject.activeSelf)
			{
				float num = Time.unscaledTime - deltaStartedAt;
				float num2 = ((num < 0.12f) ? Mathf.Clamp01(num / 0.12f) : ((num < 2.57f) ? 1f : (1f - Mathf.Clamp01((num - 0.12f - 2.45f) / 0.8f))));
				((Graphic)deltaText).color = new Color(deltaBaseColor.r, deltaBaseColor.g, deltaBaseColor.b, num2);
				if (num >= 3.37f)
				{
					((Component)deltaText).gameObject.SetActive(false);
				}
			}
		}

		private void RefreshLayout()
		{
			//IL_0074: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(1f, ((TMP_Text)sourceText).fontSize);
			float num2 = num * 2.35f;
			float num3 = num * 2.1f;
			float num4 = num * 0.32f;
			float num5 = num2;
			((TMP_Text)balanceText).fontSize = num2;
			((TMP_Text)deltaText).fontSize = num5;
			float num6 = Mathf.Max(num2 * 0.65f, ((TMP_Text)balanceText).preferredWidth);
			float num7 = num3 + num4 + num6;
			root.sizeDelta = new Vector2(num7, num3);
			root.anchoredPosition = new Vector2(0f, num * 0.75f);
			RectTransform rectTransform = ((Graphic)coinImage).rectTransform;
			rectTransform.anchorMin = new Vector2(0f, 0.5f);
			rectTransform.anchorMax = new Vector2(0f, 0.5f);
			rectTransform.pivot = new Vector2(0f, 0.5f);
			rectTransform.anchoredPosition = Vector2.zero;
			rectTransform.sizeDelta = new Vector2(num3, num3);
			RectTransform rectTransform2 = ((TMP_Text)balanceText).rectTransform;
			rectTransform2.anchorMin = new Vector2(0f, 0f);
			rectTransform2.anchorMax = new Vector2(0f, 1f);
			rectTransform2.pivot = new Vector2(0f, 0.5f);
			rectTransform2.anchoredPosition = new Vector2(num3 + num4, 0f);
			rectTransform2.sizeDelta = new Vector2(num6, 0f);
			RectTransform rectTransform3 = ((TMP_Text)deltaText).rectTransform;
			rectTransform3.anchorMin = new Vector2(1f, 0f);
			rectTransform3.anchorMax = new Vector2(1f, 0f);
			rectTransform3.pivot = new Vector2(1f, 1f);
			rectTransform3.sizeDelta = new Vector2(num7, num5);
			rectTransform3.anchoredPosition = new Vector2(0f, num * 1.15f);
		}
	}
	internal sealed class BingBongTaskHud : MonoBehaviour
	{
		private sealed class TaskRow
		{
			public RectTransform Root;

			public CanvasGroup Group;

			public RawImage Icon;

			public TextMeshProUGUI Description;

			public TextMeshProUGUI Progress;

			public float LayoutDescriptionHeight;

			public float LayoutHeight;

			public List<Image> StrikeLines { get; } = new List<Image>();
		}

		private const float PanelWidthScale = 20.5f;

		private const float PanelOffsetXScale = 0.15f;

		private const float PanelOffsetYScale = -3.35f;

		private const float HeaderHeightScale = 1.55f;

		private const float HeaderGapScale = 0.68f;

		private const float RowHeightScale = 3.75f;

		private const float RowGapScale = 0.62f;

		private const float IconSizeScale = 2.65f;

		private const float TextIconGapScale = 0.62f;

		private const float CompletedAlpha = 0.42f;

		private static readonly Color PrimaryTextColor = new Color(0.97f, 0.95f, 0.89f, 1f);

		private static readonly Color HeaderTextColor = new Color(0.91f, 0.87f, 0.78f, 1f);

		private static readonly Color SecondaryTextColor = new Color(0.83f, 0.75f, 0.62f, 1f);

		private static readonly Color FailedTextColor = new Color(0.46f, 0.12f, 0.1f, 1f);

		private readonly List<ContractOffer> visibleOffers = new List<ContractOffer>();

		private readonly List<TaskRow> rows = new List<TaskRow>();

		private TextMeshProUGUI sourceText;

		private RectTransform root;

		private TextMeshProUGUI headerText;

		private Texture closedScrollIcon;

		private Texture openScrollIcon;

		private bool userVisible = true;

		internal static void Attach(AscentUI ascentUi)
		{
			((Component)ascentUi).gameObject.AddComponent<BingBongTaskHud>().Initialize(ascentUi.text);
		}

		private void Initialize(TextMeshProUGUI source)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			sourceText = source;
			GameObject val = new GameObject("BingBong Tasks", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)((TMP_Text)sourceText).rectTransform, false);
			root = val.GetComponent<RectTransform>();
			root.anchorMin = new Vector2(1f, 0f);
			root.anchorMax = new Vector2(1f, 0f);
			root.pivot = new Vector2(1f, 1f);
			headerText = CreateText("Header", (Transform)(object)root, (TextAlignmentOptions)4100, HeaderTextColor, (FontStyles)1, (TextWrappingModes)0);
			((Transform)root).SetAsLastSibling();
			((Component)root).gameObject.SetActive(false);
		}

		private void LateUpdate()
		{
			//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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			KeyCode value = Plugin.TaskHudToggleKey.Value;
			if ((int)value != 0 && Input.GetKeyDown(value))
			{
				userVisible = !userVisible;
			}
			CollectVisibleOffers();
			bool flag = ContractShopManager.Instance.ShouldShowCurrencyHud && userVisible && visibleOffers.Count > 0;
			if (((Component)root).gameObject.activeSelf != flag)
			{
				((Component)root).gameObject.SetActive(flag);
			}
			if (flag)
			{
				ResolveIcons();
				EnsureRows(visibleOffers.Count);
				float sourceSize = Mathf.Max(1f, ((TMP_Text)sourceText).fontSize);
				((TMP_Text)headerText).text = LocalizedText.GetText("BINGBONG_CONTRACTS_HUD", true);
				for (int i = 0; i < visibleOffers.Count; i++)
				{
					BindRow(rows[i], visibleOffers[i]);
				}
				RefreshLayout(sourceSize);
				for (int j = 0; j < visibleOffers.Count; j++)
				{
					ContractOffer contractOffer = visibleOffers[j];
					UpdateStrikeThrough(rows[j], contractOffer.Completed || (contractOffer.SpecialFailed && !contractOffer.Completed), contractOffer.SpecialFailed && !contractOffer.Completed);
				}
			}
		}

		private void CollectVisibleOffers()
		{
			visibleOffers.Clear();
			IReadOnlyList<ContractOffer> contractOffers = ContractShopManager.Instance.ContractOffers;
			for (int i = 0; i < contractOffers.Count; i++)
			{
				if (contractOffers[i].State == ContractState.Active)
				{
					visibleOffers.Add(contractOffers[i]);
				}
			}
			for (int j = 0; j < contractOffers.Count; j++)
			{
				if (contractOffers[j].State == ContractState.Completed)
				{
					visibleOffers.Add(contractOffers[j]);
				}
			}
		}

		private void ResolveIcons()
		{
			if ((Object)(object)closedScrollIcon == (Object)null)
			{
				closedScrollIcon = BingBongContractVisuals.ClosedIcon;
			}
			if ((Object)(object)openScrollIcon == (Object)null)
			{
				openScrollIcon = BingBongContractVisuals.OpenIcon;
			}
		}

		private void EnsureRows(int count)
		{
			while (rows.Count < count)
			{
				rows.Add(CreateRow(rows.Count));
			}
			for (int i = 0; i < rows.Count; i++)
			{
				((Component)rows[i].Root).gameObject.SetActive(i < count);
			}
		}

		private TaskRow CreateRow(int index)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00dc: 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)
			GameObject val = new GameObject($"Task {index + 1}", new Type[2]
			{
				typeof(RectTransform),
				typeof(CanvasGroup)
			});
			val.transform.SetParent((Transform)(object)root, false);
			TaskRow taskRow = new TaskRow
			{
				Root = val.GetComponent<RectTransform>(),
				Group = val.GetComponent<CanvasGroup>()
			};
			GameObject val2 = new GameObject("Scroll", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(RawImage)
			});
			val2.transform.SetParent((Transform)(object)taskRow.Root, false);
			taskRow.Icon = val2.GetComponent<RawImage>();
			((Graphic)taskRow.Icon).raycastTarget = false;
			taskRow.Description = CreateText("Description", (Transform)(object)taskRow.Root, (TextAlignmentOptions)260, PrimaryTextColor, (FontStyles)0, (TextWrappingModes)0);
			((TMP_Text)taskRow.Description).fontWeight = (FontWeight)500;
			((TMP_Text)taskRow.Description).overflowMode = (TextOverflowModes)0;
			taskRow.Progress = CreateText("Progress", (Transform)(object)taskRow.Root, (TextAlignmentOptions)4100, SecondaryTextColor, (FontStyles)0, (TextWrappingModes)0);
			return taskRow;
		}

		private TextMeshProUGUI CreateText(string name, Transform parent, TextAlignmentOptions alignment, Color color, FontStyles style, TextWrappingModes wrapping)
		{
			//IL_002e: 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_0068: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(TextMeshProUGUI)
			});
			val.transform.SetParent(parent, false);
			TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).font = ((TMP_Text)sourceText).font;
			((TMP_Text)component).fontSharedMaterial = ((TMP_Text)sourceText).fontSharedMaterial;
			((Graphic)component).color = color;
			((TMP_Text)component).fontStyle = style;
			((TMP_Text)component).fontWeight = (FontWeight)(((style & 1) != 0) ? 700 : 400);
			((TMP_Text)component).alignment = alignment;
			((TMP_Text)component).enableAutoSizing = false;
			((TMP_Text)component).textWrappingMode = wrapping;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private void RefreshLayout(float sourceSize)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: 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)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			float num = sourceSize * 1.55f;
			float num2 = sourceSize * 0.68f;
			float num3 = sourceSize * 0.62f;
			float num4 = sourceSize * 2.65f;
			float num5 = num4 + sourceSize * 0.62f;
			float num6 = sourceSize * 20.5f;
			for (int i = 0; i < visibleOffers.Count; i++)
			{
				TaskRow taskRow = rows[i];
				((TMP_Text)taskRow.Description).enableAutoSizing = false;
				((TMP_Text)taskRow.Description).fontSize = sourceSize * 1.05f;
				((TMP_Text)taskRow.Description).textWrappingMode = (TextWrappingModes)0;
				num6 = Mathf.Max(num6, num5 + ((TMP_Text)taskRow.Description).GetPreferredValues(((TMP_Text)taskRow.Description).text).x);
			}
			float width = num6 - num5;
			float num7 = num + num2 + (float)Mathf.Max(0, visibleOffers.Count - 1) * num3;
			for (int j = 0; j < visibleOffers.Count; j++)
			{
				TaskRow taskRow2 = rows[j];
				((TMP_Text)taskRow2.Progress).fontSize = sourceSize * 0.86f;
				float num8 = sourceSize * 1.2f;
				float num9 = sourceSize * 0.14f;
				float num10 = sourceSize * 0.18f;
				float num11 = sourceSize * 0.86f;
				float num12 = sourceSize * 0.18f;
				taskRow2.LayoutDescriptionHeight = num8;
				taskRow2.LayoutHeight = Mathf.Max(sourceSize * 3.75f, num9 + num8 + num10 + num11 + num12);
				num7 += taskRow2.LayoutHeight;
			}
			root.sizeDelta = new Vector2(num6, num7);
			root.anchoredPosition = new Vector2((0f - sourceSize) * 0.15f, sourceSize * -3.35f);
			SetTopRight(((TMP_Text)headerText).rectTransform, 0f, 0f, num6, num);
			((TMP_Text)headerText).fontSize = sourceSize * 1.16f;
			float num13 = num + num2;
			for (int k = 0; k < visibleOffers.Count; k++)
			{
				TaskRow taskRow3 = rows[k];
				SetTopRight(taskRow3.Root, 0f, num13, num6, taskRow3.LayoutHeight);
				RectTransform rectTransform = ((Graphic)taskRow3.Icon).rectTransform;
				rectTransform.anchorMin = Vector2.one;
				rectTransform.anchorMax = Vector2.one;
				rectTransform.pivot = Vector2.one;
				rectTransform.anchoredPosition = new Vector2(0f, (0f - sourceSize) * 0.14f);
				rectTransform.sizeDelta = new Vector2(num4, num4);
				SetTopRight(((TMP_Text)taskRow3.Description).rectTransform, num5, sourceSize * 0.14f, width, taskRow3.LayoutDescriptionHeight);
				SetTopRight(((TMP_Text)taskRow3.Progress).rectTransform, num5, sourceSize * 0.14f + taskRow3.LayoutDescriptionHeight + sourceSize * 0.18f, width, sourceSize * 0.86f);
				num13 += taskRow3.LayoutHeight + num3;
			}
		}

		private void BindRow(TaskRow row, ContractOffer offer)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			string contractDisplayText = ContractShopManager.GetContractDisplayText(offer);
			string text = $"{offer.Progress} / {offer.RequiredCount}";
			bool flag = offer.SpecialFailed && !offer.Completed;
			((TMP_Text)row.Description).text = contractDisplayText;
			((TMP_Text)row.Progress).text = text;
			((Graphic)row.Description).color = (flag ? FailedTextColor : PrimaryTextColor);
			((Graphic)row.Progress).color = (flag ? FailedTextColor : SecondaryTextColor);
			row.Icon.texture = (offer.Completed ? openScrollIcon : closedScrollIcon);
			row.Group.alpha = (offer.Completed ? 0.42f : 1f);
		}

		private static void UpdateStrikeThrough(TaskRow row, bool visible, bool failed)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			int usedCount = 0;
			if (visible)
			{
				AddStrikeLines(row, row.Description, failed ? FailedTextColor : PrimaryTextColor, ref usedCount);
				AddStrikeLines(row, row.Progress, failed ? FailedTextColor : SecondaryTextColor, ref usedCount);
			}
			for (int i = usedCount; i < row.StrikeLines.Count; i++)
			{
				((Component)row.StrikeLines[i]).gameObject.SetActive(false);
			}
		}

		private static void AddStrikeLines(TaskRow row, TextMeshProUGUI text, Color color, ref int usedCount)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_006e: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: 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_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			((TMP_Text)text).ForceMeshUpdate(false, false);
			for (int i = 0; i < ((TMP_Text)text).textInfo.lineCount; i++)
			{
				TMP_LineInfo val = ((TMP_Text)text).textInfo.lineInfo[i];
				if (val.visibleCharacterCount == 0)
				{
					continue;
				}
				float num = float.PositiveInfinity;
				float num2 = float.NegativeInfinity;
				float num3 = float.PositiveInfinity;
				float num4 = float.NegativeInfinity;
				for (int j = val.firstVisibleCharacterIndex; j <= val.lastVisibleCharacterIndex; j++)
				{
					TMP_CharacterInfo val2 = ((TMP_Text)text).textInfo.characterInfo[j];
					if (val2.isVisible)
					{
						num = Mathf.Min(num, val2.bottomLeft.x);
						num2 = Mathf.Max(num2, val2.topRight.x);
						num3 = Mathf.Min(num3, val2.bottomLeft.y);
						num4 = Mathf.Max(num4, val2.topRight.y);
					}
				}
				Image val3;
				if (usedCount < row.StrikeLines.Count)
				{
					val3 = row.StrikeLines[usedCount];
					((Component)val3).transform.SetParent((Transform)(object)((TMP_Text)text).rectTransform, false);
				}
				else
				{
					GameObject val4 = new GameObject("Strike", new Type[3]
					{
						typeof(RectTransform),
						typeof(CanvasRenderer),
						typeof(Image)
					});
					val4.transform.SetParent((Transform)(object)((TMP_Text)text).rectTransform, false);
					val3 = val4.GetComponent<Image>();
					((Graphic)val3).raycastTarget = false;
					row.StrikeLines.Add(val3);
				}
				((Graphic)val3).color = color;
				((Component)val3).gameObject.SetActive(true);
				((Component)val3).transform.SetAsLastSibling();
				RectTransform rectTransform = ((Graphic)val3).rectTransform;
				rectTransform.anchorMin = ((TMP_Text)text).rectTransform.pivot;
				rectTransform.anchorMax = ((TMP_Text)text).rectTransform.pivot;
				rectTransform.pivot = new Vector2(0.5f, 0.5f);
				rectTransform.anchoredPosition = new Vector2((num + num2) * 0.5f, (num3 + num4) * 0.5f);
				rectTransform.sizeDelta = new Vector2(num2 - num, Mathf.Max(1f, ((TMP_Text)text).fontSize * 0.07f));
				usedCount++;
			}
		}

		private static void SetTopRight(RectTransform rect, float right, float top, float width, float height)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = new Vector2(1f, 1f);
			rect.anchorMax = new Vector2(1f, 1f);
			rect.pivot = new Vector2(1f, 1f);
			rect.anchoredPosition = new Vector2(0f - right, 0f - top);
			rect.sizeDelta = new Vector2(width, height);
		}
	}
	internal static class BingBongUiResources
	{
		private const string CoinResourceName = "BingBongContracts.bingbong_coin.png";

		private static readonly Rect CoinContentRect = new Rect(47f, 48f, 161f, 163f);

		private static Sprite coinSprite;

		public static Sprite CoinSprite => coinSprite ?? (coinSprite = LoadCoinSprite());

		private static Sprite LoadCoinSprite()
		{
			//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_0031: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_0055: 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_0073: Expected O, but got Unknown
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BingBongContracts.bingbong_coin.png");
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false)
			{
				name = "BingBong Coin",
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1,
				hideFlags = (HideFlags)61
			};
			ImageConversion.LoadImage(val, memoryStream.ToArray(), true);
			Sprite obj = Sprite.Create(val, CoinContentRect, new Vector2(0.5f, 0.5f), 100f);
			((Object)obj).name = "BingBong Coin";
			((Object)obj).hideFlags = (HideFlags)61;
			return obj;
		}
	}
	internal enum ContractKind
	{
		Transport,
		Collection,
		Special
	}
	internal enum SpecialTaskId
	{
		None,
		LightGloomBells,
		BreakCalderaEggs,
		BreakGloomEggs,
		OpenLuggage,
		OpenChests,
		FeedTeammate,
		PullTeammate,
		EatFood,
		UseConsumableItem,
		WarmTogether,
		RainClimb,
		VineTravel,
		EatDifferentMushrooms,
		PlaceMushroomItems,
		MushroomBounce,
		KnockCoconuts,
		SoakHotSpring,
		WarmByGeyser,
		GeothermalCook,
		ThrowIntoLava,
		NoFoodUntilNextShop,
		NoItemUseUntilNextShop,
		SprintDistance,
		PickDifferentItems,
		UseStageAmulet,
		DescendWithoutGround,
		CookItems,
		CookDifferentDoneness,
		ThrowDifferentBananaPeels,
		ThrowDynamite
	}
	internal enum ContractState
	{
		Offered,
		Active,
		Completed,
		Defaulted
	}
	internal enum RouteRegion
	{
		Shore,
		Tropics,
		Roots,
		Alpine,
		Mesa,
		Caldera,
		Gloom,
		Kiln,
		Citadel,
		Peak
	}
	internal sealed class ShopProduct
	{
		public Item Item { get; }

		public int Price { get; }

		public bool Discounted { get; }

		public ShopProduct(Item item, int price, bool discounted = false)
		{
			Item = item;
			Price = price;
			Discounted = discounted;
		}
	}
	internal sealed class ContractOffer
	{
		public int Id;

		public ContractKind Kind;

		public Item TargetItem;

		public int RequiredCount;

		public int Reward;

		public int PenaltyRewardBase;

		public int Progress;

		public ContractState State;

		public Guid CargoGuid;

		public int DestinationBagViewId;

		public int DeadlineLightOrdinal;

		public int OriginShopId;

		public RouteRegion OriginRegion;

		public SpecialTaskId SpecialTask;

		public string SpecialTaskLocalizationKey;

		public int AcceptedByViewId;

		public bool SpecialFailed;

		public float SpecialProgressFloat;

		public bool HasSpecialTargetItemId;

		public ushort SpecialTargetItemId;

		public int DeliveredCollectionSellValue;

		public bool IsMesaSpecialCollection;

		public int RequiredCookingCount;

		public bool HasRequiredItemUses;

		public int RequiredItemUses;

		public bool HasRequiredUseRemainingPercentage;

		public float RequiredUseRemainingPercentage;

		public HashSet<ushort> SpecialUniqueItemIds { get; } = new HashSet<ushort>();

		public HashSet<Guid> SpecialUniqueGuids { get; } = new HashSet<Guid>();

		public HashSet<int> SpecialUniqueEventIds { get; } = new HashSet<int>();

		public Dictionary<Guid, int> SpecialCookedAmounts { get; } = new Dictionary<Guid, int>();

		public List<Item> CollectionTargets { get; } = new List<Item>();

		public HashSet<ushort> DeliveredCollectionItemIds { get; } = new HashSet<ushort>();

		public bool Accepted => State != ContractState.Offered;

		public bool Settled
		{
			get
			{
				ContractState state = State;
				if ((uint)(state - 2) <= 1u)
				{
					return true;
				}
				return false;
			}
		}

		public bool Completed => State == ContractState.Completed;

		public int Penalty => Math.Max(0, (int)Math.Ceiling((float)PenaltyRewardBase * 1.5f) - DeliveredCollectionSellValue);
	}
	[Flags]
	internal enum ModTag : ulong
	{
		None = 0uL,
		Stock = 1uL,
		RecycleRequest = 2uL,
		Transport = 4uL,
		PeakStore = 8uL,
		CollectShore = 0x10uL,
		CollectTropics = 0x20uL,
		CollectRoots = 0x40uL,
		CollectAlpine = 0x80uL,
		CollectMesa = 0x100uL,
		CollectCaldera = 0x200uL,
		CollectGloom = 0x400uL,
		RecommendTropics = 0x800uL,
		RecommendRoots = 0x1000uL,
		RecommendAlpine = 0x2000uL,
		RecommendMesa = 0x4000uL,
		RecommendCaldera = 0x8000uL,
		RecommendGloom = 0x10000uL,
		RecommendKiln = 0x20000uL,
		RecommendCitadel = 0x40000uL,
		SpecialCollection = 0x80000uL,
		ColorMushroom = 0x100000uL,
		ColorApple = 0x200000uL,
		ColorBerrynana = 0x400000uL,
		ColorClusterberry = 0x800000uL,
		ColorKingberry = 0x1000000uL,
		ColorPrickleberry = 0x2000000uL,
		ColorShroomberry = 0x4000000uL,
		ColorWinterberry = 0x8000000uL
	}
	internal static class ContractCatalog
	{
		internal sealed class CatalogItem
		{
			public Item Item;

			public int? BasePrice;

			public int ProgressPriceStep;

			public int? TransportWeightBonus;

			public int TransportValueReverseAdjustment;

			public ModTag Tags;

			public bool HasPrice => BasePrice.HasValue;
		}

		private const double AncientRecycleChance = 0.1;

		private const double NextRegionRecycleChance = 0.6;

		internal const double SpecialCollectionChance = 0.7;

		private const double RegionSpecialTaskChance = 0.7;

		private const string CatalogDirectoryName = "BingBongContracts";

		private const string CatalogFileName = "CatalogItems.csv";

		private const string SpecialTaskFileName = "SpecialTasks.csv";

		private const ModTag CollectionTags = ModTag.CollectShore | ModTag.CollectTropics | ModTag.CollectRoots | ModTag.CollectAlpine | ModTag.CollectMesa | ModTag.CollectCaldera | ModTag.CollectGloom;

		private const ModTag ColorTags = ModTag.ColorMushroom | ModTag.ColorApple | ModTag.ColorBerrynana | ModTag.ColorClusterberry | ModTag.ColorKingberry | ModTag.ColorPrickleberry | ModTag.ColorShroomberry | ModTag.ColorWinterberry;

		private static readonly HashSet<ushort> AncientItemIds = new HashSet<ushort>();

		internal static readonly List<CatalogItem> items = new List<CatalogItem>();

		private static readonly Dictionary<string, CatalogItem> itemsByPrefab = new Dictionary<string, CatalogItem>(StringComparer.Ordinal);

		private static readonly Dictionary<ushort, CatalogItem> itemsById = new Dictionary<ushort, CatalogItem>();

		private static readonly Dictionary<SpecialTaskId, int> specialTaskRewards = new Dictionary<SpecialTaskId, int>();

		private static bool itemsLoaded;

		private static bool ancientItemsInitialized;

		public static void InitializeTable()
		{
			EnsureItems();
			LoadSpecialTaskRewards();
		}

		public static RouteRegion ResolveRegion(int routeSegmentIndex, BiomeType biome)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Invalid comparison between Unknown and I4
			return routeSegmentIndex switch
			{
				0 => RouteRegion.Shore, 
				1 => ((int)biome != 7) ? RouteRegion.Tropics : RouteRegion.Roots, 
				2 => ((int)biome == 6) ? RouteRegion.Mesa : RouteRegion.Alpine, 
				3 => ((int)biome == 8) ? RouteRegion.Gloom : RouteRegion.Caldera, 
				4 => ((int)biome == 8) ? RouteRegion.Citadel : RouteRegion.Kiln, 
				_ => RouteRegion.Peak, 
			};
		}

		public static Item DrawProduct(Random random, SpawnPool pool, ModTag tags, Func<Item, bool> filter = null)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			HashSet<ushort> poolIds = (((int)pool == 0) ? null : new HashSet<ushort>(from item in LootData.GetAllItemsInPool(pool)
				select item.itemID));
			List<Item> list = (from entry in FindItems(tags)
				select entry.Item into item
				where ((tags & ModTag.Stock) == ModTag.None || !IsAncientItem(item)) && (poolIds == null || poolIds.Contains(item.itemID)) && (filter == null || filter(item))
				select item).ToList();
			return list[random.Next(list.Count)];
		}

		public static List<ContractOffer> BuildContracts(RouteRegion region, int rewardProgress, Random random, bool mesaSpecialCollectionEligible = false, bool multiplayer = false, int ascent = -1, bool hasStageAmulet = false, bool hasNapberry = true, ISet<SpecialTaskId> excludedSpecialTasks = null)
		{
			List<ContractOffer> list = new List<ContractOffer>(3);
			ContractOffer contractOffer = BuildCollectionContract(region, rewardProgress, random);
			if (contractOffer != null)
			{
				list.Add(contractOffer);
			}
			else
			{
				ContractOffer contractOffer2 = BuildTransportContract(rewardProgress, random);
				if (contractOffer2 != null)
				{
					list.Add(contractOffer2);
				}
			}
			ContractOffer contractOffer3 = BuildTransportContract(rewardProgress, random);
			if (contractOffer3 != null)
			{
				list.Add(contractOffer3);
			}
			while (list.Count < 2)
			{
				ContractOffer contractOffer4 = BuildTransportContract(rewardProgress, random);
				if (contractOffer4 == null)
				{
					break;
				}
				list.Add(contractOffer4);
			}
			ContractOffer contractOffer5 = BuildSpecialContract(region, random, multiplayer, ascent, hasStageAmulet, excludedSpecialTasks);
			if (contractOffer5 != null)
			{
				list.Add(contractOffer5);
			}
			bool flag = mesaSpecialCollectionEligible && region == RouteRegion.Mesa;
			if (!flag)
			{
				bool flag2 = ((region == RouteRegion.Alpine || region == RouteRegion.Gloom) ? true : false);
				flag = flag2;
			}
			if (flag)
			{
				List<CatalogItem> list2 = FindRegionCollectionItems(region);
				List<CatalogItem> list3 = FindSpecialCollectionCandidates(list2, region, hasNapberry);
				CatalogItem catalogItem = ((list3.Count == 0 || random.NextDouble() >= 0.7) ? null : list3[random.Next(list3.Count)]);
				if (catalogItem != null)
				{
					ModTag specialColor = catalogItem.Tags & (ModTag.ColorMushroom | ModTag.ColorApple | ModTag.ColorBerrynana | ModTag.ColorClusterberry | ModTag.ColorKingberry | ModTag.ColorPrickleberry | ModTag.ColorShroomberry | ModTag.ColorWinterberry);
					List<Item> list4 = ((specialColor == ModTag.None) ? null : (from entry in list2
						where (entry.Tags & (ModTag.ColorMushroom | ModTag.ColorApple | ModTag.ColorBerrynana | ModTag.ColorClusterberry | ModTag.ColorKingberry | ModTag.ColorPrickleberry | ModTag.ColorShroomberry | ModTag.ColorWinterberry)) == specialColor
						select entry.Item).ToList());
					ContractOffer contractOffer6 = ((list4 != null && list4.Count > 1) ? CreateCollectionContract(list4, rewardProgress) : CreateCollectionContract(catalogItem.Item, 1, rewardProgress));
					contractOffer6.IsMesaSpecialCollection = region == RouteRegion.Mesa;
					if (list.Count > 0)
					{
						list[0] = contractOffer6;
					}
				}
			}
			return list;
		}

		private static List<CatalogItem> FindSpecialCollectionCandidates(List<CatalogItem> regionItems, RouteRegion region, bool hasNapberry)
		{
			List<CatalogItem> list = regionItems.Where((CatalogItem entry) => Has(entry.Tags, ModTag.SpecialCollection)).ToList();
			if (region == RouteRegion.Alpine && !hasNapberry)
			{
				list.RemoveAll((CatalogItem entry) => CleanPrefabName(entry.Item) == "Napberry");
			}
			return list;
		}

		private static string CleanPrefabName(Item item)
		{
			if (!((Object)(object)item == (Object)null))
			{
				return ((Object)((Component)item).gameObject).name.Replace("(Clone)", string.Empty).Trim();
			}
			return string.Empty;
		}

		internal static ContractOffer CreateSpecialContract(SpecialTaskId task, string localizationKey, int requiredCount, Item visualItem = null)
		{
			if (!specialTaskRewards.TryGetValue(task, out var value))
			{
				value = task switch
				{
					SpecialTaskId.ThrowDifferentBananaPeels => 35, 
					SpecialTaskId.ThrowDynamite => 40, 
					_ => 0, 
				};
				if (value <= 0)
				{
					return null;
				}
			}
			return new ContractOffer
			{
				Kind = ContractKind.Special,
				SpecialTask = task,
				SpecialTaskLocalizationKey = localizationKey,
				TargetItem = visualItem,
				RequiredCount = Math.Max(1, requiredCount),
				Reward = value,
				PenaltyRewardBase = value
			};
		}

		internal static bool IsDeployableMushroom(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			switch (((Object)((Component)item).gameObject).name.Replace("(Clone)", string.Empty).Trim())
			{
			case "BounceShroom":
			case "CloudFungus":
			case "HealingPuffShroom":
			case "ShelfShroom":
			case "WarpFungus":
				return true;
			default:
				return false;
			}
		}

		public static int GetBuyPrice(Item item, int shopProgress, ItemInstanceData data = null)
		{
			CatalogItem entry = GetEntry(item);
			if (entry != null && entry.HasPrice)
			{
				return Math.Max(1, entry.BasePrice.Value + entry.ProgressPriceStep * shopProgress + GetCookingPriceAdjustment(data));
			}
			return 0;
		}

		public static bool IsNaturalFood(Item item)
		{
			//IL_000a: 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_0013: Invalid comparison between Unknown and I4
			if ((Object)(object)item != (Object)null)
			{
				return (item.itemTags & 0xC) > 0;
			}
			return false;
		}

		public static bool IsPackagedFood(Item item)
		{
			//IL_000a: 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)
			//IL_0012: Invalid comparison between Unknown and I4
			if ((Object)(object)item != (Object)null)
			{
				return (item.itemTags & 2) > 0;
			}
			return false;
		}

		public static bool IsMushroomShopItem(Item item)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			if ((Object)(object)item != (Object)null)
			{
				return (item.itemTags & 0x1008) > 0;
			}
			return false;
		}

		public static bool IsHighValueItem(Item item)
		{
			CatalogItem entry = GetEntry(item);
			if (entry == null)
			{
				return false;
			}
			return entry.BasePrice >= 35;
		}

		public static bool IsStockItem(Item item)
		{
			CatalogItem entry = GetEntry(item);
			if (entry != null)
			{
				return Has(entry.Tags, ModTag.Stock);
			}
			return false;
		}

		public static int GetSellValue(Item item, ItemInstanceData data, int shopProgress, float priceRatio = 0.6f)
		{
			CatalogItem entry = GetEntry(item);
			if (entry != null && entry.HasPrice)
			{
				return (int)(Math.Max(1f, (float)GetBuyPrice(item, shopProgress, data) * priceRatio) * GetRemainingUseRatio(item, data));
			}
			return 0;
		}

		public static int GetRecycleValue(Item item, int shopProgress, ItemInstanceData data = null)
		{
			CatalogItem entry = GetEntry(item);
			if (entry != null && Has(entry.Tags, ModTag.RecycleRequest) && entry.HasPrice)
			{
				return (int)((float)GetBuyPrice(item, shopProgress, data) * 1.5f * GetRemainingUseRatio(item, data));
			}
			return 0;
		}

		public static bool IsRestockableProduct(Item item)
		{
			CatalogItem entry = GetEntry(item);
			if (entry != null)
			{
				return (entry.Tags & (ModTag.ColorMushroom | ModTag.ColorApple | ModTag.ColorBerrynana | ModTag.ColorClusterberry | ModTag.ColorKingberry | ModTag.ColorPrickleberry | ModTag.ColorShroomberry | ModTag.ColorWinterberry)) != 0;
			}
			return false;
		}

		public static Item ChooseRestockItem(Item item, Random random)
		{
			CatalogItem entry = GetEntry(item);
			ModTag colorTag = ((entry == null) ? ModTag.None : (entry.Tags & (ModTag.ColorMushroom | ModTag.ColorApple | ModTag.ColorBerrynana | ModTag.ColorClusterberry | ModTag.ColorKingberry | ModTag.ColorPrickleberry | ModTag.ColorShroomberry | ModTag.ColorWinterberry)));
			return ((colorTag == ModTag.None) ? null : ChooseItem(ModTag.Stock, (CatalogItem candidate) => IsRestockableProduct(candidate.Item) && (candidate.Tags & (ModTag.ColorMushroom | ModTag.ColorApple | ModTag.ColorBerrynana | ModTag.ColorClusterberry | ModTag.ColorKingberry | ModTag.ColorPrickleberry | ModTag.ColorShroomberry | ModTag.ColorWinterberry)) == colorTag, random))?.Item ?? item;
		}

		public static ushort GetCollectionVariantId(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return 0;
			}
			CatalogItem entry = GetEntry(item);
			if (entry == null || !Has(entry.Tags, ModTag.ColorMushroom))
			{
				return item.itemID;
			}
			string name = ((Object)((Component)item).gameObject).name;
			if (name.EndsWith(" Poison", StringComparison.Ordinal))
			{
				Dictionary<string, CatalogItem> dictionary = itemsByPrefab;
				string text = name;
				int length = " Poison".Length;
				if (dictionary.TryGetValue(text.Substring(0, text.Length - length), out var value))
				{
					return value.Item.itemID;
				}
			}
			return item.itemID;
		}

		internal static ModTag GetCollectionColorFamily(Item item)
		{
			CatalogItem entry = GetEntry(item);
			if (entry != null)
			{
				return entry.Tags & (ModTag.ColorMushroom | ModTag.ColorApple | ModTag.ColorBerrynana | ModTag.ColorClusterberry | ModTag.ColorKingberry | ModTag.ColorPrickleberry | ModTag.ColorShroomberry | ModTag.ColorWinterberry);
			}
			return ModTag.None;
		}

		public static Item ChooseHighValueRecycleItem(Random random, HashSet<ushort> excluded)
		{
			if (random.NextDouble() < 0.1)
			{
				Item val = ChooseAncientItem(ModTag.RecycleRequest, excluded, random);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return ChooseItem(ModTag.RecycleRequest, (CatalogItem entry) => !IsAncientItem(entry.Item) && IsHighValueItem(entry.Item) && (excluded == null || !excluded.Contains(entry.Item.itemID)), random)?.Item;
		}

		public static Item ChooseOrdinaryRecycleItem(RouteRegion? nextRegion, Random random, HashSet<ushort> excluded)
		{
			ModTag modTag = (nextRegion.HasValue ? CollectionTag(nextRegion.Value) : ModTag.None);
			if (modTag != ModTag.None && random.NextDouble() < 0.6)
			{
				CatalogItem catalogItem = ChooseItem(ModTag.RecycleRequest | modTag, (CatalogItem entry) => !IsAncientItem(entry.Item) && (excluded == null || !excluded.Contains(entry.Item.itemID)), random);
				if (catalogItem != null)
				{
					return catalogItem.Item;
				}
			}
			return ChooseItem(ModTag.Stock | ModTag.RecycleRequest, (CatalogItem entry) => !IsAncientItem(entry.Item) && (excluded == null || !excluded.Contains(entry.Item.itemID)), random)?.Item;
		}

		private static ContractOffer BuildCollectionContract(RouteRegion region, int rewardProgress, Random random)
		{
			List<CatalogItem> list = (from entry in FindRegionCollectionItems(region)
				where !Has(entry.Tags, ModTag.SpecialCollection)
				select entry).ToList();
			if (list.Count == 0)
			{
				return null;
			}
			double num = random.NextDouble();
			if (num < 0.5)
			{
				return CreateCollectionContract(list[random.Next(list.Count)].Item, 1, rewardProgress);
			}
			if (num < 0.8)
			{
				return CreateCollectionContract(list[random.Next(list.Count)].Item, 2, rewardProgress);
			}
			List<Item> list2 = ChooseCollectionColorFamily(region, random);
			if (list2 != null)
			{
				return CreateCollectionContract(list2, rewardProgress);
			}
			return CreateCollectionContract(list[random.Next(list.Count)].Item, 1, rewardProgress);
		}

		private static ContractOffer BuildTransportContract(int rewardProgress, Random random)
		{
			double num = random.NextDouble();
			CatalogItem catalogItem;
			if (!(num < 0.5))
			{
				catalogItem = ((num < 0.7) ? ChooseItem(ModTag.Transport, (CatalogItem entry) => CanStore(entry.Item) && IsFoodOrMapHarvest(entry), random) : ((!(num < 0.9)) ? ChooseItem(ModTag.Transport, (CatalogItem entry) => !CanStore(entry.Item), random) : ChooseItem(ModTag.Transport, (CatalogItem entry) => CanStore(entry.Item) && !IsAncientItem(entry.Item) && !IsFoodOrMapHarvest(entry), random)));
			}
			else
			{
				Item val = ChooseAncientItem(ModTag.Transport, null, random);
				catalogItem = ((val != null) ? GetEntry(val) : null);
			}
			if (catalogItem != null)
			{
				return CreateTransportContract(catalogItem, rewardProgress);
			}
			return null;
		}

		private static ContractOffer BuildSpecialContract(RouteRegion region, Random random, bool multiplayer, int ascent, bool hasStageAmulet, ISet<SpecialTaskId> excludedSpecialTasks)
		{
			List<SpecialTaskId> list = new List<SpecialTaskId>
			{
				SpecialTaskId.EatFood,
				SpecialTaskId.UseConsumableItem,
				SpecialTaskId.NoFoodUntilNextShop,
				SpecialTaskId.NoItemUseUntilNextShop,
				SpecialTaskId.SprintDistance,
				SpecialTaskId.PickDifferentItems,
				SpecialTaskId.DescendWithoutGround,
				SpecialTaskId.CookItems,
				SpecialTaskId.CookDifferentDoneness
			};
			if ((uint)(region - 7) > 1u)
			{
				list.Add(SpecialTaskId.OpenLuggage);
			}
			if (hasStageAmulet)
			{
				list.Add(SpecialTaskId.UseStageAmulet);
			}
			List<SpecialTaskId> list2 = new List<SpecialTaskId>();
			AddRegionSpecialTasks(list2, region);
			if (multiplayer)
			{
				list.Add(SpecialTaskId.FeedTeammate);
				list.Add(SpecialTaskId.PullTeammate);
				if (region == RouteRegion.Alpine || ascent >= 5)
				{
					list.Add(SpecialTaskId.WarmTogether);
				}
			}
			if (excludedSpecialTasks != null)
			{
				list.RemoveAll(excludedSpecialTasks.Contains);
				list2.RemoveAll(excludedSpecialTasks.Contains);
			}
			if (list.Count == 0 && list2.Count == 0)
			{
				return null;
			}
			if (list2.Count > 0 && (list.Count == 0 || random.NextDouble() < 0.7))
			{
				return CreateSpecialContract(list2[random.Next(list2.Count)]);
			}
			return CreateSpecialContract(list[random.Next(list.Count)]);
		}

		private static void AddRegionSpecialTasks(List<SpecialTaskId> tasks, RouteRegion region)
		{
			if (region == RouteRegion.Shore)
			{
				tasks.Add(SpecialTaskId.KnockCoconuts);
			}
			if (region == RouteRegion.Tropics)
			{
				tasks.AddRange(new SpecialTaskId[3]
				{
					SpecialTaskId.RainClimb,
					SpecialTaskId.VineTravel,
					SpecialTaskId.ThrowDifferentBananaPeels
				});
			}
			if (region == RouteRegion.Roots)
			{
				tasks.AddRange(new SpecialTaskId[4]
				{
					SpecialTaskId.VineTravel,
					SpecialTaskId.EatDifferentMushrooms,
					SpecialTaskId.PlaceMushroomItems,
					SpecialTaskId.MushroomBounce
				});
			}
			if ((uint)(region - 3) <= 1u)
			{
				tasks.Add(SpecialTaskId.SoakHotSpring);
			}
			if (region == RouteRegion.Mesa)
			{
				tasks.Add(SpecialTaskId.ThrowDynamite);
			}
			if (region == RouteRegion.Alpine)
			{
				tasks.Add(SpecialTaskId.WarmByGeyser);
			}
			if (region == RouteRegion.Caldera)
			{
				tasks.AddRange(new SpecialTaskId[2]
				{
					SpecialTaskId.BreakCalderaEggs,
					SpecialTaskId.GeothermalCook
				});
			}
			if (region == RouteRegion.Gloom)
			{
				tasks.AddRange(new SpecialTaskId[2]
				{
					SpecialTaskId.LightGloomBells,
					SpecialTaskId.BreakGloomEggs
				});
			}
			if ((uint)(region - 7) <= 1u)
			{
				tasks.AddRange(new SpecialTaskId[2]
				{
					SpecialTaskId.ThrowIntoLava,
					SpecialTaskId.OpenChests
				});
			}
		}

		private static ContractOffer CreateSpecialContract(SpecialTaskId task)
		{
			return task switch
			{
				SpecialTaskId.LightGloomBells => CreateSpecialContract(task, "BINGBONG_SPECIAL_LIGHT_BELLS", 3), 
				SpecialTaskId.BreakCalderaEggs => CreateSpecialContract(task, "BINGBONG_SPECIAL_BREAK_CALDERA_EGGS", 3), 
				SpecialTaskId.BreakGloomEggs => CreateSpecialContract(task, "BINGBONG_SPECIAL_BREAK_GLOOM_EGGS", 4), 
				SpecialTaskId.OpenLuggage => CreateSpecialContract(task, "BINGBONG_SPECIAL_OPEN_LUGGAGE", 5), 
				SpecialTaskId.OpenChests => CreateSpecialContract(task, "BINGBONG_SPECIAL_OPEN_CHESTS", 3), 
				SpecialTaskId.FeedTeammate => CreateSpecialContract(task, "BINGBONG_SPECIAL_FEED_TEAMMATE", 3), 
				SpecialTaskId.PullTeammate => CreateSpecialContract(task, "BINGBONG_SPECIAL_PULL_TEAMMATE", 10), 
				SpecialTaskId.EatFood => CreateSpecialContract(task, "BINGBONG_SPECIAL_EAT_FOOD", 5), 
				SpecialTaskId.UseConsumableItem => CreateSpecialContract(task, "BINGBONG_SPECIAL_USE_ITEM", 5), 
				SpecialTaskId.WarmTogether => CreateSpecialContract(task, "BINGBONG_SPECIAL_WARM_TOGETHER", 20), 
				SpecialTaskId.RainClimb => CreateSpecialContract(task, "BINGBONG_SPECIAL_RAIN_CLIMB", 10), 
				SpecialTaskId.VineTravel => CreateSpecialContract(task, "BINGBONG_SPECIAL_VINE_TRAVEL", 150), 
				SpecialTaskId.EatDifferentMushrooms => CreateSpecialContract(task, "BINGBONG_SPECIAL_EAT_MUSHROOMS", 4), 
				SpecialTaskId.PlaceMushroomItems => CreateSpecialContract(task, "BINGBONG_SPECIAL_PLACE_MUSHROOMS", 2), 
				SpecialTaskId.MushroomBounce => CreateSpecialContract(task, "BINGBONG_SPECIAL_MUSHROOM_BOUNCE", 10), 
				SpecialTaskId.KnockCoconuts => CreateSpecialContract(task, "BINGBONG_SPECIAL_KNOCK_COCONUTS", 4), 
				SpecialTaskId.SoakHotSpring => CreateSpecialContract(task, "BINGBONG_SPECIAL_HOT_SPRING", 20), 
				SpecialTaskId.WarmByGeyser => CreateSpecialContract(task, "BINGBONG_SPECIAL_GEYSER_WARM", 10), 
				SpecialTaskId.GeothermalCook => CreateSpecialContract(task, "BINGBONG_SPECIAL_GEOTHERMAL_COOK", 4), 
				SpecialTaskId.ThrowIntoLava => CreateSpecialContract(task, "BINGBONG_SPECIAL_THROW_INTO_LAVA", 4), 
				SpecialTaskId.NoFoodUntilNextShop => CreateSpecialContract(task, "BINGBONG_SPECIAL_NO_FOOD", 1), 
				SpecialTaskId.NoItemUseUntilNextShop => CreateSpecialContract(task, "BINGBONG_SPECIAL_NO_ITEM_USE", 1), 
				SpecialTaskId.SprintDistance => CreateSpecialContract(task, "BINGBONG_SPECIAL_SPRINT", 500), 
				SpecialTaskId.PickDifferentItems => CreateSpecialContract(task, "BINGBONG_SPECIAL_PICK_ITEMS", 7), 
				SpecialTaskId.UseStageAmulet => CreateSpecialContract(task, "BINGBONG_SPECIAL_USE_AMULET", 1), 
				SpecialTaskId.DescendWithoutGround => CreateSpecialContract(task, "BINGBONG_SPECIAL_DESCEND", 30), 
				SpecialTaskId.CookItems => CreateSpecialContract(task, "BINGBONG_SPECIAL_COOK_ITEMS", 5), 
				SpecialTaskId.CookDifferentDoneness => CreateSpecialContract(task, "BINGBONG_SPECIAL_COOK_DONENESS", 3), 
				SpecialTaskId.ThrowDifferentBananaPeels => CreateSpecialContract(task, "BINGBONG_SPECIAL_THROW_BANANA_PEELS", 3), 
				SpecialTaskId.ThrowDynamite => CreateSpecialContract(task, "BINGBONG_SPECIAL_THROW_DYNAMITE", 5), 
				_ => null, 
			};
		}

		internal static ContractOffer CreateSpecialContractForTest(SpecialTaskId task)
		{
			return CreateSpecialContract(task);
		}

		internal static string GetSpecialTaskChineseNameForTest(SpecialTaskId task)
		{
			string text = CreateSpecialContract(task)?.SpecialTaskLocalizationKey;
			if (!string.IsNullOrEmpty(text) && LocalizedText.mainTable.TryGetValue(text.ToUpperInvariant(), out var value) && value != null && value.Count > 9 && !string.IsNullOrWhiteSpace(value[9]))
			{
				return value[9];
			}
			return task.ToString();
		}

		internal static bool IsMultiplayerOnlySpecialTaskForTest(SpecialTaskId task)
		{
			if ((uint)(task - 6) <= 1u || task == SpecialTaskId.WarmTogether)
			{
				return true;
			}
			return false;
		}

		internal static bool IsRegionSpecialTaskForTest(SpecialTaskId task)
		{
			switch (task)
			{
			case SpecialTaskId.LightGloomBells:
			case SpecialTaskId.BreakCalderaEggs:
			case SpecialTaskId.BreakGloomEggs:
			case SpecialTaskId.OpenChests:
			case SpecialTaskId.RainClimb:
			case SpecialTaskId.VineTravel:
			case SpecialTaskId.EatDifferentMushrooms:
			case SpecialTaskId.PlaceMushroomItems:
			case SpecialTaskId.MushroomBounce:
			case SpecialTaskId.KnockCoconuts:
			case SpecialTaskId.SoakHotSpring:
			case SpecialTaskId.WarmByGeyser:
			case SpecialTaskId.GeothermalCook:
			case SpecialTaskId.ThrowIntoLava:
			case SpecialTaskId.ThrowDifferentBananaPeels:
			case SpecialTaskId.ThrowDynamite:
				return true;
			default:
				return false;
			}
		}

		internal static bool IsSpecialTaskAvailableInRegionForTest(SpecialTaskId task, RouteRegion region)
		{
			if (!IsRegionSpecialTaskForTest(task))
			{
				bool flag = task != SpecialTaskId.OpenLuggage;
				if (!flag)
				{
					bool flag2 = (uint)(region - 7) <= 1u;
					flag = !flag2;
				}
				return flag;
			}
			switch (region)
			{
			case RouteRegion.Shore:
				return task == SpecialTaskId.KnockCoconuts;
			case RouteRegion.Tropics:
				return ((uint)(task - 11) <= 1u || task == SpecialTaskId.ThrowDifferentBananaPeels) ? true : false;
			case RouteRegion.Roots:
				return (uint)(task - 12) <= 3u;
			case RouteRegion.Alpine:
				return (uint)(task - 17) <= 1u;
			case RouteRegion.Mesa:
				return (task == SpecialTaskId.SoakHotSpring || task == SpecialTaskId.ThrowDynamite) ? true : false;
			case RouteRegion.Caldera:
				return (task == SpecialTaskId.BreakCalderaEggs || task == SpecialTaskId.GeothermalCook) ? true : false;
			case RouteRegion.Gloom:
				return (task == SpecialTaskId.LightGloomBells || task == SpecialTaskId.BreakGloomEggs) ? true : false;
			case RouteRegion.Kiln:
			case RouteRegion.Citadel:
				return (task == SpecialTaskId.OpenChests || task == SpecialTaskId.ThrowIntoLava) ? true : false;
			default:
				return false;
			}
		}

		internal static bool IsSpecialCollectionOfferForTest(ContractOffer offer)
		{
			if (offer == null || offer.Kind != ContractKind.Collection)
			{
				return false;
			}
			if (offer.CollectionTargets.Count > 0)
			{
				for (int i = 0; i < offer.CollectionTargets.Count; i++)
				{
					CatalogItem entry = GetEntry(offer.CollectionTargets[i]);
					if (entry != null && Has(entry.Tags, ModTag.SpecialCollection))
					{
						return true;
					}
				}
			}
			CatalogItem entry2 = GetEntry(offer.TargetItem);
			if (entry2 != null)
			{
				return Has(entry2.Tags, ModTag.SpecialCollection);
			}
			return false;
		}

		internal static string DescribeSpecialCollectionCandidatesForTest(RouteRegion region, bool hasNapberry = true)
		{
			List<CatalogItem> list = FindRegionCollectionItems(region);
			List<CatalogItem> list2 = FindSpecialCollectionCandidates(list, region, hasNapberry);
			if (list2.Count == 0)
			{
				return "(none)";
			}
			List<string> list3 = new List<string>(list2.Count);
			for (int i = 0; i < list2.Count; i++)
			{
				CatalogItem catalogItem = list2[i];
				string text = CleanPrefabName(catalogItem.Item);
				ModTag color = catalogItem.Tags & (ModTag.ColorMushroom | ModTag.ColorApple | ModTag.ColorBerrynana | ModTag.ColorClusterberry | ModTag.ColorKingberry | ModTag.ColorPrickleberry | ModTag.ColorShroomberry | ModTag.ColorWinterberry);
				if (color == ModTag.None)
				{
					list3.Add(text);
					continue;
				}
				List<string> list4 = (from entry in list
					where (entry.Tags & (ModTag.ColorMushroom | ModTag.ColorApple | ModTag.ColorBerrynana | ModTag.ColorClusterberry | ModTag.ColorKingberry | ModTag.ColorPrickleberry | ModTag.ColorShroomberry | ModTag.ColorWinterberry)) == color
					select CleanPrefabName(entry.Item)).ToList();
				list3.Add((list4.Count > 1) ? (text + " => [" + string.Join(" / ", list4) + "]") : text);
			}
			return string.Join("; ", list3);
		}

		private static void LoadSpecialTaskRewards()
		{
			string path = Path.Combine(Paths.ConfigPath, "BingBongContracts", "SpecialTasks.csv");
			Directory.CreateDirectory(Path.GetDirectoryName(path));
			if (!File.Exists(path))
			{
				using Stream stream = typeof(ContractCatalog).Assembly.GetManifestResourceStream("BingBongContracts.SpecialTasks.csv");
				using FileStream destination = File.Create(path);
				stream.CopyTo(destination);
			}
			foreach (string[] item in ReadCsv(path).Skip(1))
			{
				SpecialTaskId key = Enum.Parse<SpecialTaskId>(Value(item, 0).Trim());
				specialTaskRewards.Add(key, int.Parse(Value(item, 1).Trim()));
			}
		}

		private static ContractOffer CreateCollectionContract(Item target, int requiredCount, int rewardProgress)
		{
			CatalogItem entry = GetEntry(target);
			ContractOffer obj = new ContractOffer
			{
				Kind = ContractKind.Collection,
				TargetItem = target,
				RequiredCount = requiredCount,
				Reward = GetCollectionReward(entry, requiredCount, rewardProgress)
			};
			obj.PenaltyRewardBase = obj.Reward;
			obj.CollectionTargets.Add(target);
			return obj;
		}

		private static ContractOffer CreateCollectionContract(List<Item> targets, int rewardProgress)
		{
			ContractOffer obj = new ContractOffer
			{
				Kind = ContractKind.Collection,
				TargetItem = targets[0],
				RequiredCount = targets.Count,
				Reward = GetCollectionReward(targets.Select(GetEntry), rewardProgress)
			};
			obj.PenaltyRewardBase = obj.Reward;
			obj.CollectionTargets.AddRange(targets);
			return obj;
		}

		private static int GetCollectionReward(CatalogItem entry, int requiredCount, int rewardProgress)
		{
			return GetCollectionReward(Enumerable.Repeat(entry, requiredCount), rewardProgress);
		}

		private static int GetCollectionReward(IEnumerable<CatalogItem> entries, int rewardProgress)
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			foreach (CatalogItem entry in entries)
			{
				num2 += entry?.BasePrice.GetValueOrDefault() ?? 0;
				num3 = Math.Max(num3, entry?.TransportWeightBonus.GetValueOrDefault() ?? 0);
				num++;
			}
			return num2 + num3 + Math.Max(0, num - 1) * 5;
		}

		private static ContractOffer CreateTransportContract(CatalogItem target, int rewardProgress)
		{
			int contractItemReward = GetContractItemReward(target, rewardProgress);
			return new ContractOffer
			{
				Kind = ContractKind.Transport,
				TargetItem = target.Item,
				RequiredCount = 1,
				Reward = Math.Max(0, contractItemReward - target.TransportValueReverseAdjustment),
				PenaltyRewardBase = contractItemReward
			};
		}

		private static int GetContractItemReward(CatalogItem entry, int deliveryProgress)
		{
			return GetBuyPrice(entry.Item, deliveryProgress) + entry.TransportWeightBonus.GetValueOrDefault();
		}

		private static List<Item> ChooseCollectionColorFamily(RouteRegion region, Random random)
		{
			Dictionary<ModTag, Dictionary<ushort, Item>> dictionary = new Dictionary<ModTag, Dictionary<ushort, Item>>();
			foreach (CatalogItem item in from item in FindRegionCollectionItems(region)
				where !Has(item.Tags, ModTag.SpecialCollection)
				select item)
			{
				ModTag modTag = item.Tags & (ModTag.ColorMushroom | ModTag.ColorApple | ModTag.ColorBerrynana | ModTag.ColorClusterberry | ModTag.ColorKingberry | ModTag.ColorPrickleberry | ModTag.ColorShroomberry | ModTag.ColorWinterberry);
				if (modTag != ModTag.None)
				{
					if (!dictionary.TryGetValue(modTag, out var value))
					{
						value = new Dictionary<ushort, Item>();
						dictionary.Add(modTag, value);
					}
					ushort collectionVariantId = GetCollectionVariantId(item.Item);
					if (!value.ContainsKey(collectionVariantId) || item.Item.itemID == collectionVariantId)
					{
						value[collectionVariantId] = item.Item;
					}
				}
			}
			List<List<Item>> list = (from itemsInFamily in dictionary.Values
				where itemsInFamily.Count > 1
				select itemsInFamily.Values.ToList()).ToList();
			if (list.Count != 0)
			{
				return list[random.Next(list.Count)];
			}
			return null;
		}

		private static List<CatalogItem> FindRegionCollectionItems(RouteRegion region)
		{
			ModTag modTag = CollectionTag(region);
			if (modTag != ModTag.None)
			{
				return FindItems(modTag);
			}
			return new List<CatalogItem>();
		}

		private static Item ChooseAncientItem(ModTag required, HashSet<ushort> excluded, Random random)
		{
			EnsureAncientItems();
			List<Item> list = new List<Item>();
			foreach (Item item in LootData.GetAllItemsInPool((SpawnPool)131072))
			{
				CatalogItem entry = GetEntry(item);
				if (entry != null && entry.HasPrice && entry.TransportWeightBonus.HasValue && Has(entry.Tags, required) && (excluded == null || !excluded.Contains(item.itemID)))
				{
					list.Add(item);
				}
			}
			if (list.Count != 0)
			{
				return list[random.Next(list.Count)];
			}
			return null;
		}

		private static CatalogItem ChooseItem(ModTag required, Func<CatalogItem, bool> filter, Random random)
		{
			List<CatalogItem> list = FindItems(required, filter);
			if (list.Count != 0)
			{
				return list[random.Next(list.Count)];
			}
			return null;
		}

		private static List<CatalogItem> FindItems(ModTag required, Func<CatalogItem, bool> filter = null)
		{
			if (!EnsureItems())
			{
				return new List<CatalogItem>();
			}
			List<CatalogItem> list = new List<CatalogItem>();
			foreach (CatalogItem item in items)
			{
				if (item.HasPrice && (required == ModTag.None || Has(item.Tags, ModTag.PeakStore) || item.TransportWeightBonus.HasValue) && Has(item.Tags, required) && (filter == null || filter(item)))
				{
					list.Add(item);
				}
			}
			return list;
		}

		private static CatalogItem GetEntry(Item item)
		{
			if ((Object)(object)item == (Object)null || !EnsureItems())
			{
				return null;
			}
			itemsById.TryGetValue(item.itemID, out var value);
			return value;
		}

		private static bool EnsureItems()
		{
			if (itemsLoaded)
			{
				return true;
			}
			if ((Object)(object)SingletonAsset<ItemDatabase>.Instance == (Object)null || ((DatabaseAsset<ItemDatabase, Item>)(object)SingletonAsset<ItemDatabase>.Instance).Objects == null || ((DatabaseAsset<ItemDatabase, Item>)(object)SingletonAsset<ItemDatabase>.Instance).Objects.Count == 0)
			{
				return false;
			}
			string path = Path.Combine(Paths.ConfigPath, "BingBongContracts", "CatalogItems.csv");
			Directory.CreateDirectory(Path.GetDirectoryName(path));
			if (!File.Exists(path))
			{
				using Stream stream = typeof(ContractCatalog).Assembly.GetManifestResourceStream("BingBongContracts.CatalogItems.csv");
				using FileStream destination = File.Create(path);
				stream.CopyTo(destination);
			}
			Dictionary<string, Item> originals = ((DatabaseAsset<ItemDatabase, Item>)(object)SingletonAsset<ItemDatabase>.Instance).Objects.Where((Item val) => (Object)(object)val != (Object)null).ToDictionary<Item, string, Item>((Item val) => ((Object)((Component)val).gameObject).name, (Item result) => result, StringComparer.Ordinal);
			foreach (string[] item2 in ReadCsv(path).Skip(1))
			{
				if (TryReadItem(item2, originals, out var item) && !itemsByPrefab.ContainsKey(((Object)((Component)item.Item).gameObject).name))
				{
					items.Add(item);
					itemsByPrefab.Add(((Object)((Component)item.Item).gameObject).name, item);
					itemsById[item.Item.itemID] = item;
				}
			}
			itemsLoaded = true;
			return true;
		}

		private static bool TryReadItem(string[] row, Dictionary<string, Item> originals, out CatalogItem item)
		{
			item = null;
			if (row.Length == 0 || !originals.TryGetValue(row[0].Trim(), out var value))
			{
				return false;
			}
			item = new CatalogItem
			{
				Item = value,
				BasePrice = ParseOptionalInt(Value(row, 3)),
				ProgressPriceStep = ParseOptionalInt(Value(row, 4)).GetValueOrDefault(),
				TransportWeightBonus = ParseOptionalInt(Value(row, 5)),
				TransportValueReverseAdjustment = ParseOptionalInt(Value(row, 6)).GetValueOrDefault(),
				Tags = ParseTags(Value(row, 7))
			};
			return true;
		}

		private static List<string[]> ReadCsv(string path)
		{
			List<string[]> list = new List<string[]>();
			List<string> list2 = new List<string>();
			StringBuilder stringBuilder = new StringBuilder();
			bool flag = false;
			string text = File.ReadAllText(path, Encoding.UTF8);
			foreach (char c in text)
			{
				switch (c)
				{
				case '"':
					flag = !flag;
					continue;
				case ',':
					if (!flag)
					{
						list2.Add(stringBuilder.ToString());
						stringBuilder.Clear();
						continue;
					}
					break;
				}
				if ((c == '\n' || c == '\r') && !flag)
				{
					if (c != '\r')
					{
						list2.Add(stringBuilder.ToString());
						stringBuilder.Clear();
						list.Add(list2.ToArray());
						list2.Clear();
					}
				}
				else
				{
					stringBuilder.Append(c);
				}
			}
			if (stringBuilder.Length > 0 || list2.Count > 0)
			{
				list2.Add(stringBuilder.ToString());
				list.Add(list2.ToArray());
			}
			return list;
		}

		private static ModTag ParseTags(string value)
		{
			ModTag modTag = ModTag.None;
			bool flag = string.IsNullOrWhiteSpace(value);
			string[] array = value.Split(new char[3] { ';', '|', ',' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				if (int.TryParse(array[i].Trim(), out var result))
				{
					switch (result)
					{
					case 0:
						flag = true;
						break;
					case 1:
						modTag |= ModTag.Transport;
						break;
					case 2:
						modTag |= ModTag.SpecialCollection;
						break;
					case 3:
						modTag |= ModTag.PeakStore;
						break;
					case 10:
						modTag |= ModTag.RecommendTropics;
						break;
					case 11:
						modTag |= ModTag.RecommendRoots;
						break;
					case 12:
						modTag |= ModTag.RecommendAlpine;
						break;
					case 13:
						modTag |= ModTag.RecommendMesa;
						break;
					case 14:
						modTag |= ModTag.RecommendCaldera;
						break;
					case 15:
						modTag |= ModTag.RecommendGloom;
						break;
					case 16:
						modTag |= ModTag.RecommendKiln;
						break;
					case 17:
						modTag |= ModTag.RecommendCitadel;
						break;
					case 20:
						modTag |= ModTag.CollectShore;
						break;
					case 21:
						modTag |= ModTag.CollectTropics;
						break;
					case 22:
						modTag |= ModTag.CollectRoots;
						break;
					case 23:
						modTag |= ModTag.CollectAlpine;
						break;
					case 24:
						modTag |= ModTag.CollectMesa;
						break;
					case 25:
						modTag |= ModTag.CollectCaldera;
						break;
					case 26:
						modTag |= ModTag.CollectGloom;
						break;
					case 40:
						modTag |= ModTag.ColorMushroom;
						break;
					case 41:
						modTag |= ModTag.ColorWinterberry;
						break;
					case 42:
						modTag |= ModTag.ColorShroomberry;
						break;
					case 43:
						modTag |= ModTag.ColorPrickleberry;
						break;
					case 44:
						modTag |= ModTag.ColorKingberry;
						break;
					case 45:
						modTag |= ModTag.ColorApple;
						break;
					case 46:
						modTag |= ModTag.ColorClusterberry;
						break;
					case 47:
						modTag |= ModTag.ColorBerrynana;
						break;
					}
				}
			}
			if (flag && !Has(modTag, ModTag.SpecialCollection))
			{
				modTag |= ModTag.Stock | ModTag.RecycleRequest | ModTag.Transport;
			}
			return modTag;
		}

		private static int? ParseOptionalInt(string value)
		{
			if (!int.TryParse(value, out var result))
			{
				return null;
			}
			return result;
		}

		private static string Value(string[] row, int index)
		{
			if (index >= row.Length)
			{
				return string.Empty;
			}
			return row[index].Trim();
		}

		private static ModTag CollectionTag(RouteRegion region)
		{
			return region switch
			{
				RouteRegion.Shore => ModTag.CollectShore, 
				RouteRegion.Tropics => ModTag.CollectTropics, 
				RouteRegion.Roots => ModTag.CollectRoots, 
				RouteRegion.Alpine => ModTag.CollectAlpine, 
				RouteRegion.Mesa => ModTag.CollectMesa, 
				RouteRegion.Caldera => ModTag.CollectCaldera, 
				RouteRegion.Gloom => ModTag.CollectGloom, 
				_ => ModTag.None, 
			};
		}

		internal static ModTag RecommendationTag(RouteRegion region)
		{
			return region switch
			{
				RouteRegion.Tropics => ModTag.RecommendTropics, 
				RouteRegion.Roots => ModTag.RecommendRoots, 
				RouteRegion.Alpine => ModTag.RecommendAlpine, 
				RouteRegion.Mesa => ModTag.RecommendMesa, 
				RouteRegion.Caldera => ModTag.RecommendCaldera, 
				RouteRegion.Gloom => ModTag.RecommendGloom, 
				RouteRegion.Kiln => ModTag.RecommendKiln, 
				RouteRegion.Citadel => ModTag.RecommendCitadel, 
				_ => ModTag.None, 
			};
		}

		private static bool Has(ModTag tags, ModTag required)
		{
			return (tags & required) == required;
		}

		private static bool HasAny(ModTag tags, ModTag required)
		{
			return (tags & required) != 0;
		}

		private static bool CanStore(Item item)
		{
			if (item.UIData != null)
			{
				if (!item.UIData.canPocket)
				{
					return item.UIData.canBackpack;
				}
				return true;
			}
			return false;
		}

		private static bool IsFoodOrMapHarvest(CatalogItem entry)
		{
			//IL_0006: 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)
			if ((entry.Item.itemTags & 0xE) == 0)
			{
				return HasAny(entry.Tags, ModTag.CollectShore | ModTag.CollectTropics | ModTag.CollectRoots | ModTag.CollectAlpine | ModTag.CollectMesa | ModTag.CollectCaldera | ModTag.CollectGloom);
			}
			return true;
		}

		private static bool IsAncientItem(Item item)
		{
			EnsureAncientItems();
			if ((Object)(object)item != (Object)null)
			{
				return AncientItemIds.Contains(item.itemID);
			}
			return false;
		}

		internal static bool IsAncientRecycleItem(Item item)
		{
			return IsAncientItem(item);
		}

		private static void EnsureAncientItems()
		{
			if (ancientItemsInitialized)
			{
				return;
			}
			foreach (Item item in LootData.GetAllItemsInPool((SpawnPool)131072))
			{
				if ((Object)(object)item != (Object)null)
				{
					AncientItemIds.Add(item.itemID);
				}
			}
			ancientItemsInitialized = true;
		}

		private static float GetRemainingUseRatio(Item item, ItemInstanceData data)
		{
			if (data?.data == null)
			{
				return 1f;
			}
			if (data.data.TryGetValue((DataEntryKey)11, out var value))
			{
				FloatItemData val = (FloatItemData)(object)((value is FloatItemData) ? value : null);
				if (val != null)
				{
					return Math.Clamp(val.Value, 0f, 1f);
				}
			}
			if (data.data.TryGetValue((DataEntryKey)2, out var value2))
			{
				DataEntryValue val2 = value2;
				IntItemData val3 = (IntItemData)(object)((val2 is IntItemData) ? val2 : null);
				int num;
				if (val3 == null)
				{
					OptionableIntItemData val4 = (OptionableIntItemData)(object)((val2 is OptionableIntItemData) ? val2 : null);
					num = ((val4 == null || !val4.HasData) ? (-1) : val4.Value);
				}
				else
				{
					num = val3.Value;
				}
				int num2 = num;
				if (num2 >= 0 && item.totalUses > 0)
				{
					return Math.Clamp((float)num2 / (float)item.totalUses, 0f, 1f);
				}
			}
			return 1f;
		}

		private static int GetCookingPriceAdjustment(ItemInstanceData data)
		{
			if (data?.data != null && data.data.TryGetValue((DataEntryKey)1, out var value))
			{
				IntItemData val = (IntItemData)(object)((value is IntItemData) ? value : null);
				if (val != null)
				{
					return GetCookingPriceAdjustment(val.Value);
				}
			}
			return 0;
		}

		private static int GetCookingPriceAdjustment(int cookedAmount)
		{
			if ((uint)(cookedAmount - 1) <= 1u)
			{
				return 5;
			}
			if (cookedAmount < 4)
			{
				if (cookedAmount != 3)
				{
					return 0;
				}
				return -5;
			}
			return -10;
		}
	}
	internal sealed class ContractShopManager : MonoBehaviour
	{
		private readonly struct ShopPlacement
		{
			public Vector3 NpcGround { get; }

			public Quaternion NpcRotation { get; }

			public DisplayLuggagePlan[] Luggage { get; }

			public ShopPlacement(Vector3 npcGround, Quaternion npcRotation, DisplayLuggagePlan[] luggage)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				NpcGround = npcGround;
				NpcRotation = npcRotation;
				Luggage = luggage;
			}
		}

		private readonly struct DisplayLuggagePlan
		{
			public Luggage Prefab { get; }

			public Vec