Decompiled source of ChromeCompany v1.0.1

plugins/ChromeCompany.dll

Decompiled 10 hours ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ChromeCompany.Sheets;
using DunGen;
using DunGen.Graph;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.AI.Navigation;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.Networking;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[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 ChromeCompany
{
	internal static class Acoustics
	{
		public static int Shots;

		public static int Muffled;

		public static int Indoors;

		public static string Last = "none";

		private static AcousticsRow Row => ChromeCompany.Sheets.Acoustics.Gunshots;

		public static bool InsideAt(Vector3 at)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return at.y < -80f;
		}

		public static float Tail(bool inside)
		{
			if (!inside)
			{
				return 0f;
			}
			return Row.inDecay;
		}

		public static void Echo(GameObject speaker, bool inside)
		{
			AudioReverbFilter val = speaker.GetComponent<AudioReverbFilter>();
			if ((Object)(object)val == (Object)null)
			{
				val = speaker.AddComponent<AudioReverbFilter>();
			}
			((Behaviour)val).enabled = inside;
			if (inside)
			{
				val.reverbPreset = (AudioReverbPreset)27;
				val.dryLevel = 0f;
				val.room = Row.inRoom;
				val.roomHF = -400f;
				val.roomLF = 0f;
				val.decayTime = Row.inDecay;
				val.decayHFRatio = 0.7f;
				val.reflectionsLevel = -1500f;
				val.reflectionsDelay = 0.01f;
				val.reverbLevel = Row.inReverb;
				val.reverbDelay = 0.02f;
				val.hfReference = 5000f;
				val.lfReference = 250f;
				val.diffusion = 100f;
				val.density = 100f;
			}
		}

		public static void ShotAt(Vector3 at, string assetId, float reach, float gain)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			ShotAt(at, assetId, reach, gain, muffle: true, 0f);
		}

		public static void ShotAt(Vector3 at, string assetId, float reach, float gain, bool muffle)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			ShotAt(at, assetId, reach, gain, muffle, 0f);
		}

		public static void ShotAt(Vector3 at, string assetId, float reach, float gain, bool muffle, float bassCut)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: 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_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			AudioClip[] array = Content.Clips(assetId, gain, bassCut);
			if (array.Length == 0)
			{
				return;
			}
			bool flag = InsideAt(at);
			GameObject val = new GameObject("ChromeCompany_Shot");
			val.transform.position = at;
			AudioSource val2 = val.AddComponent<AudioSource>();
			val2.spatialBlend = 1f;
			val2.rolloffMode = (AudioRolloffMode)1;
			val2.minDistance = 3f;
			val2.maxDistance = reach;
			val2.dopplerLevel = 0f;
			PlayerControllerB val3 = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null);
			if ((Object)(object)val3 != (Object)null && (Object)(object)val3.movementAudio != (Object)null)
			{
				val2.outputAudioMixerGroup = val3.movementAudio.outputAudioMixerGroup;
			}
			float num = 1f;
			StartOfRound instance = StartOfRound.Instance;
			Transform val4 = (((Object)(object)instance != (Object)null && (Object)(object)instance.audioListener != (Object)null) ? ((Component)instance.audioListener).transform : null);
			bool flag2 = false;
			if ((Object)(object)val4 != (Object)null && muffle)
			{
				flag2 = Physics.Linecast(at, val4.position, 256, (QueryTriggerInteraction)1);
				val.AddComponent<AudioLowPassFilter>().cutoffFrequency = (flag2 ? Mathf.Clamp(2500f / Mathf.Max(0.01f, Vector3.Distance(val4.position, at) / (reach / 2f)), 900f, 4000f) : 10000f);
				if (flag2)
				{
					Muffled++;
				}
				try
				{
					val.AddComponent<OccludeAudio>();
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Shot muffling: " + ex.Message));
				}
			}
			Echo(val, flag);
			AudioClip val5 = array[Random.Range(0, array.Length)];
			val2.PlayOneShot(val5, num);
			Shots++;
			if (flag)
			{
				Indoors++;
			}
			Last = assetId + (flag ? ", indoors" : ", outdoors") + (flag2 ? ", behind a wall" : ", in the open");
			Object.Destroy((Object)(object)val, val5.length + Tail(flag) + 0.5f);
		}
	}
	internal class Arcs : MonoBehaviour
	{
		public static int Started;

		private Bounds box;

		private float until;

		private float nextBolt;

		private float nextSpark;

		private Transform follow;

		private Vector3 followOffset;

		private readonly List<LineRenderer> bolts = new List<LineRenderer>();

		private readonly List<float> boltDies = new List<float>();

		private static Material paint;

		public static void On(ulong id, float seconds)
		{
			NetworkManager singleton = NetworkManager.Singleton;
			NetworkObject value = null;
			if (!((Object)(object)singleton == (Object)null) && singleton.SpawnManager != null && singleton.SpawnManager.SpawnedObjects.TryGetValue(id, out value) && !((Object)(object)value == (Object)null))
			{
				On(((Component)value).gameObject, seconds);
			}
		}

		public static void On(GameObject thing, float seconds)
		{
			On(thing, seconds, 2.3f);
		}

		public static void On(GameObject thing, float seconds, float most)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: 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_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_007c: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)thing == (Object)null)
			{
				return;
			}
			bool flag = false;
			Bounds bounds = default(Bounds);
			((Bounds)(ref bounds))..ctor(thing.transform.position, Vector3.one * 0.5f);
			Renderer[] componentsInChildren = thing.GetComponentsInChildren<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				if (!val.enabled || (!(val is MeshRenderer) && !(val is SkinnedMeshRenderer)) || ((Object)val).name == "ChromeCompany_Scan")
				{
					continue;
				}
				Bounds bounds2 = val.bounds;
				Vector3 size = ((Bounds)(ref bounds2)).size;
				if (((Vector3)(ref size)).magnitude > most * 1.6f)
				{
					continue;
				}
				bounds2 = val.bounds;
				if (!(Vector3.Distance(((Bounds)(ref bounds2)).center, thing.transform.position) > most * 1.1f))
				{
					if (!flag)
					{
						bounds = val.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val.bounds);
					}
				}
			}
			((Bounds)(ref bounds)).size = new Vector3(Mathf.Clamp(((Bounds)(ref bounds)).size.x * 0.8f, 0.3f, most), Mathf.Clamp(((Bounds)(ref bounds)).size.y * 0.85f, 0.3f, most + 0.2f), Mathf.Clamp(((Bounds)(ref bounds)).size.z * 0.8f, 0.3f, most));
			Arcs arcs = new GameObject("ChromeCompany_Arcs").AddComponent<Arcs>();
			arcs.box = bounds;
			arcs.until = Time.time + seconds;
			arcs.follow = thing.transform;
			arcs.followOffset = ((Bounds)(ref bounds)).center - thing.transform.position;
			Started++;
		}

		private Vector3 OnSurface()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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)
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(Random.Range(-0.5f, 0.5f), Random.Range(-0.5f, 0.5f), Random.Range(-0.5f, 0.5f));
			int num = Random.Range(0, 3);
			((Vector3)(ref val))[num] = ((Random.value < 0.5f) ? (-0.5f) : 0.5f);
			return ((Bounds)(ref box)).center + Vector3.Scale(val, ((Bounds)(ref box)).size);
		}

		private void Bolt()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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_0121: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: 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_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: 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)
			if ((Object)(object)paint == (Object)null)
			{
				paint = new Material(Shader.Find("Sprites/Default") ?? Shader.Find("UI/Default"));
			}
			GameObject val = new GameObject("bolt");
			val.transform.SetParent(((Component)this).transform, false);
			LineRenderer val2 = val.AddComponent<LineRenderer>();
			((Renderer)val2).sharedMaterial = paint;
			val2.useWorldSpace = true;
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
			Color val3 = (val2.startColor = ((Random.value < 0.45f) ? new Color(0.95f, 0.98f, 1f, 1f) : new Color(0.35f, 0.65f, 1f, 1f)));
			val2.endColor = new Color(val3.r, val3.g, val3.b, 0.6f);
			float num = (val2.startWidth = Random.Range(0.012f, 0.03f));
			val2.endWidth = num * 0.5f;
			Vector3 val5 = OnSurface();
			Vector3 val6 = ((Bounds)(ref box)).ClosestPoint(val5 + Random.onUnitSphere * Random.Range(0.2f, 0.55f));
			if (Vector3.Distance(val5, val6) < 0.1f)
			{
				val6 = OnSurface();
			}
			int num3 = (val2.positionCount = Random.Range(5, 9));
			float num5 = Vector3.Distance(val5, val6) * 0.2f + 0.02f;
			for (int i = 0; i < num3; i++)
			{
				Vector3 val7 = Vector3.Lerp(val5, val6, (float)i / (float)(num3 - 1));
				if (i > 0 && i < num3 - 1)
				{
					val7 += Random.insideUnitSphere * num5;
				}
				val2.SetPosition(i, val7);
			}
			bolts.Add(val2);
			boltDies.Add(Time.time + Random.Range(0.04f, 0.1f));
		}

		private void Update()
		{
			//IL_0020: 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_002b: 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_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			float time = Time.time;
			if ((Object)(object)follow != (Object)null)
			{
				((Bounds)(ref box)).center = follow.position + followOffset;
			}
			for (int num = bolts.Count - 1; num >= 0; num--)
			{
				if (time >= boltDies[num])
				{
					if ((Object)(object)bolts[num] != (Object)null)
					{
						Object.Destroy((Object)(object)((Component)bolts[num]).gameObject);
					}
					bolts.RemoveAt(num);
					boltDies.RemoveAt(num);
				}
			}
			if (time >= until)
			{
				if (bolts.Count == 0)
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				}
				return;
			}
			if (time >= nextBolt)
			{
				nextBolt = time + Random.Range(0.015f, 0.05f);
				Bolt();
				if (Random.value < 0.5f)
				{
					Bolt();
				}
			}
			if (time >= nextSpark)
			{
				nextSpark = time + Random.Range(0.08f, 0.2f);
				Vector3 val = OnSurface();
				Vector3 val2 = val - ((Bounds)(ref box)).center;
				Fx.Burst(val, ((Vector3)(ref val2)).normalized, 70f, 5, 1f, 4f, 0.01f, 0.025f, 0.25f, new Color(0.85f, 0.93f, 1f, 1f), new Color(0.2f, 0.5f, 1f, 0f), 0.8f, 0f);
				Fx.Light(null, val, new Color(0.55f, 0.75f, 1f), 16f, 5f, 0.06f);
			}
		}
	}
	internal class AutoTest : MonoBehaviour
	{
		private const string TestSave = "ChromeCompanyTestSave";

		private string dir;

		private static readonly string Role = Environment.GetEnvironmentVariable("CHROMECOMPANY_ROLE") ?? "";

		private static readonly string Script = Environment.GetEnvironmentVariable("CHROMECOMPANY_SCRIPT") ?? "";

		private readonly StringBuilder results = new StringBuilder();

		private float worst;

		private string worstAt = "";

		private void Start()
		{
			DevLock.Open = true;
			dir = Path.Combine(Path.GetDirectoryName(Content.DataDir), "autotest");
			if (Role.Length > 0)
			{
				dir = Path.Combine(dir, Role);
			}
			Directory.CreateDirectory(dir);
			Rig.IgnoreInput = true;
			string[] files = Directory.GetFiles(dir);
			for (int i = 0; i < files.Length; i++)
			{
				File.Delete(files[i]);
			}
			((MonoBehaviour)this).StartCoroutine(Guarded());
		}

		private IEnumerator Guarded()
		{
			IEnumerator run = Run();
			while (true)
			{
				object current;
				try
				{
					if (!run.MoveNext())
					{
						break;
					}
					current = run.Current;
					goto IL_0067;
				}
				catch (Exception ex)
				{
					Note("FAIL exception", ex.ToString());
				}
				break;
				IL_0067:
				yield return current;
			}
			Time.timeScale = 1f;
			File.WriteAllText(Path.Combine(dir, "results.txt"), results.ToString());
			yield return (object)new WaitForSecondsRealtime(1f);
			Application.Quit();
		}

		private void Note(string name, object value)
		{
			string text = ((Role.Length > 0) ? (DateTime.Now.ToString("HH:mm:ss.f") + "  ") : "") + name + " = " + value;
			results.AppendLine(text);
			Plugin.Log.LogInfo((object)("[autotest] " + text));
			File.WriteAllText(Path.Combine(dir, "results.txt"), results.ToString());
		}

		private IEnumerator OpticsOnly(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			Terminal val = Object.FindObjectOfType<Terminal>();
			if (player.inTerminalMenu && (Object)(object)val != (Object)null)
			{
				val.QuitTerminal(true);
			}
			yield return (object)new WaitForSecondsRealtime(2f);
			Note("optics.before_buying", (rig.Scan.TryStart() ? "scanned (wrong)" : "scan does nothing") + ", " + (rig.EyeLight.Toggle() ? "torch lit (wrong)" : "torch does nothing"));
			Object.FindObjectOfType<StartMatchLever>().StartGame();
			float waited = 0f;
			float num;
			while (!StartOfRound.Instance.shipHasLanded)
			{
				yield return (object)new WaitForSecondsRealtime(1f);
				waited = (num = waited + 1f);
				if (num > 90f)
				{
					Note("FAIL landing", "never landed");
					yield break;
				}
			}
			yield return (object)new WaitForSecondsRealtime(3f);
			StartOfRound.Instance.allowLocalPlayerDeath = false;
			Cyberware.Grant(Optics.KiroshiOptics.id);
			Cyberware.Grant(Optics.EyeLight.id);
			Transform cam = ((Component)player.gameplayCamera).transform;
			EnemyType val2 = ((IEnumerable<EnemyType>)Resources.FindObjectsOfTypeAll<EnemyType>()).FirstOrDefault((Func<EnemyType, bool>)((EnemyType x) => (Object)(object)x != (Object)null && (Object)(object)x.enemyPrefab != (Object)null && (Object)(object)x.enemyPrefab.GetComponent<CrawlerAI>() != (Object)null));
			NavMeshHit val3 = default(NavMeshHit);
			bool flag = false;
			NavMeshHit val5 = default(NavMeshHit);
			for (int num2 = 0; num2 < 24; num2++)
			{
				if (flag)
				{
					break;
				}
				Vector3 val4 = Quaternion.Euler(0f, (float)num2 * 15f, 0f) * Vector3.forward;
				float[] array = new float[3] { 10f, 14f, 18f };
				foreach (float num4 in array)
				{
					if (NavMesh.SamplePosition(cam.position + val4 * num4, ref val5, 4f, -1) && Physics.Linecast(cam.position, ((NavMeshHit)(ref val5)).position + Vector3.up * 0.6f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
					{
						val3 = val5;
						flag = true;
						break;
					}
				}
			}
			if ((Object)(object)val2 == (Object)null || !flag)
			{
				Note("FAIL optics", "could not place a monster behind a wall");
				yield break;
			}
			RoundManager.Instance.SpawnEnemyGameObject(((NavMeshHit)(ref val3)).position, 0f, -1, val2);
			yield return (object)new WaitForSecondsRealtime(1.5f);
			EnemyAI enemy = ((IEnumerable<EnemyAI>)RoundManager.Instance.SpawnedEnemies).LastOrDefault((Func<EnemyAI, bool>)((EnemyAI x) => x is CrawlerAI));
			if ((Object)(object)enemy != (Object)null)
			{
				enemy.agent.speed = 0f;
				cam.rotation = Quaternion.LookRotation(((Component)enemy).transform.position + Vector3.up * 0.6f - cam.position);
			}
			bool wall = (Object)(object)enemy != (Object)null && Physics.Linecast(cam.position, ((Component)enemy).transform.position + Vector3.up * 0.6f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1);
			yield return (object)new WaitForEndOfFrame();
			yield return Shot("optics_before");
			bool flag2 = rig.Scan.TryStart();
			Note("optics.scan", "started " + flag2 + ", monsters highlighted " + rig.Scan.Highlighted + " of " + RoundManager.Instance.SpawnedEnemies.Count((EnemyAI x) => (Object)(object)x != (Object)null && !x.isEnemyDead) + " alive, drawn " + rig.Scan.MaterialInfo + "; test monster " + (((Object)(object)enemy != (Object)null) ? (Vector3.Distance(((Component)enemy).transform.position, cam.position).ToString("0.0") + " m away, something solid in between: " + wall) : "missing"));
			yield return (object)new WaitForSeconds(1f);
			if ((Object)(object)enemy != (Object)null)
			{
				cam.rotation = Quaternion.LookRotation(((Component)enemy).transform.position + Vector3.up * 0.6f - cam.position);
			}
			yield return (object)new WaitForEndOfFrame();
			yield return (object)new WaitForSeconds(0.5f);
			AutoTest autoTest = this;
			string text = rig.Scan.Blend.ToString("0.00");
			num = Optics.KiroshiOptics.screenAlpha;
			autoTest.Note("optics.screen_wash", "blend " + text + ", strength " + num);
			yield return Shot("optics_scanning");
			Note("optics.second_scan_at_once", rig.Scan.TryStart() ? "allowed (wrong)" : "refused");
			yield return (object)new WaitForSeconds(Optics.KiroshiOptics.duration);
			AutoTest autoTest2 = this;
			string[] obj = new string[9]
			{
				"still scanning ",
				rig.Scan.Active.ToString(),
				", copies left in the level ",
				Object.FindObjectsOfType<Transform>().Count((Transform x) => ((Object)x).name == "ChromeCompany_Scan").ToString(),
				", cooldown ",
				rig.Scan.CooldownLeft.ToString("0"),
				" s (sheet ",
				null,
				null
			};
			num = Optics.KiroshiOptics.cooldown;
			obj[7] = num.ToString();
			obj[8] = ")";
			autoTest2.Note("optics.after", string.Concat(obj));
			yield return Shot("optics_after");
			Note("optics.torch_on", rig.EyeLight.Toggle() + ", " + rig.EyeLight.Info);
			HDAdditionalLightData val6 = ((player.allHelmetLights != null && player.allHelmetLights.Length != 0) ? ((Component)player.allHelmetLights[0]).GetComponent<HDAdditionalLightData>() : null);
			Note("optics.headlamp_copies", rig.EyeLight.Copied + "; before this change it copied the helmet light, intensity " + (((Object)(object)val6 != (Object)null) ? (val6.intensity.ToString("0") + " " + ((object)val6.lightUnit/*cast due to .constrained prefix*/).ToString()) : "?"));
			yield return (object)new WaitForSecondsRealtime(0.6f);
			yield return Shot("optics_torch_on");
			Note("optics.torch_off", rig.EyeLight.Toggle() + ", " + rig.EyeLight.Info);
			yield return (object)new WaitForSecondsRealtime(0.4f);
			yield return Shot("optics_torch_off");
		}

		private IEnumerator RemoveOnly(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			Terminal terminal = Object.FindObjectOfType<Terminal>();
			yield return (object)new WaitForSecondsRealtime(2f);
			int credits = terminal.groupCredits;
			List<string> had = (from r in Shop.All
				where r.gives == "item" && Cyberware.Has(r.grants)
				select r.grants).ToList();
			ShopRow[] all = Shop.All;
			for (int num = 0; num < all.Length; num++)
			{
				Cyberware.Revoke(all[num].grants);
			}
			terminal.groupCredits = 1000;
			Func<string, string> type = delegate(string s)
			{
				TerminalNode val = TerminalShop.Handle(terminal, s);
				return (!((Object)(object)val == (Object)null)) ? val.displayText.Trim().Replace("\n", " | ") : "(not ours)";
			};
			Note("skins", Skins.Report);
			Note("remove.not_installed", type("remove mantis"));
			type("mantis");
			type("sandevistan");
			type("launcher");
			Note("remove.after_buying_3", "credits " + terminal.groupCredits + " (1000 - 150 - 220 - 350 = 280), load " + Psychosis.Load);
			rig.Blades.Toggle();
			yield return (object)new WaitForSecondsRealtime(1.5f);
			Note("remove.mantis", type("remove mantis") + "  // owned " + Cyberware.Has("mantis_blades") + ", blades still out " + rig.Blades.Deployed + ", credits " + terminal.groupCredits + " (355)");
			Note("remove.sandevistan", type("uninstall sandevistan") + "  // credits " + terminal.groupCredits + " (465), load " + Psychosis.Load);
			int hp0 = player.health;
			player.DamagePlayer(60, false, true, (CauseOfDeath)0, 0, false, default(Vector3));
			int lostBare = hp0 - player.health;
			player.health = hp0;
			Note("armor.buy", type("armor") + "  // max health " + Cyberware.MaxHealth + ", load " + Psychosis.Load);
			yield return (object)new WaitForSecondsRealtime(0.5f);
			yield return Shot("armor_icon");
			player.DamagePlayer(60, false, true, (CauseOfDeath)0, 0, false, default(Vector3));
			Note("armor.hit_60", "took " + (hp0 - player.health) + " of the game's 100 with armor, " + lostBare + " without (expected 20 and 30)");
			player.health = hp0;
			Note("armor.remove", type("remove armor") + "  // max health " + Cyberware.MaxHealth);
			TimeOfDay day = TimeOfDay.Instance;
			int q = day.profitQuota;
			int done = day.quotaFulfilled;
			int times = day.timesFulfilledQuota;
			int c0 = terminal.groupCredits;
			float until = day.timeUntilDeadline;
			day.quotaFulfilled = q;
			day.SetNewProfitQuota();
			yield return (object)new WaitForSecondsRealtime(1f);
			Note("quota.payout", "quota was " + q + ", paid " + Bounty.LastQuotaPayout + ", credits " + c0 + " -> " + terminal.groupCredits + " (the rest is the game's overtime bonus), new quota " + day.profitQuota);
			day.profitQuota = q;
			day.quotaFulfilled = done;
			day.timesFulfilledQuota = times;
			day.timeUntilDeadline = until;
			day.UpdateProfitQuotaCurrentTime();
			all = Shop.All;
			for (int num = 0; num < all.Length; num++)
			{
				Cyberware.Revoke(all[num].grants);
			}
			terminal.groupCredits = 2000;
			Note("holsters.none", Carry.Used + " / " + Carry.Max + ", speed x" + Carry.MoveSpeed);
			type("bat");
			type("unity");
			Note("holsters.two", Carry.Used + " / " + Carry.Max + ", over " + Carry.Over + ", speed x" + Carry.MoveSpeed);
			Note("holsters.third_weapon", type("saratoga").Replace("\r", ""));
			Note("holsters.three", Carry.Used + " / " + Carry.Max + ", over " + Carry.Over + ", speed x" + Carry.MoveSpeed);
			type("mantis");
			Note("holsters.blades_take_none", Carry.Used + " / " + Carry.Max);
			Vector3 from = ((Component)player).transform.position;
			yield return Hold(2f, (Key)37);
			until = Vector3.Distance(from, ((Component)player).transform.position);
			yield return (object)new WaitForSecondsRealtime(0.5f);
			yield return Shot("holsters_over");
			Note("holsters.buy_system", type("holster").Replace("\r", ""));
			yield return (object)new WaitForSecondsRealtime(0.5f);
			yield return Shot("holsters_militech");
			Note("holsters.with_system", Carry.Used + " / " + Carry.Max + ", over " + Carry.Over + ", cyberware load " + Psychosis.Load);
			from = ((Component)player).transform.position;
			yield return Hold(2f, (Key)33);
			float num2 = Vector3.Distance(from, ((Component)player).transform.position);
			AutoTest autoTest = this;
			string[] obj = new string[6]
			{
				until.ToString("0.00"),
				" m overloaded, ",
				num2.ToString("0.00"),
				" m with room (sheet speed x",
				null,
				null
			};
			float overSpeed = Holsters.Belt.overSpeed;
			obj[4] = overSpeed.ToString();
			obj[5] = ")";
			autoTest.Note("holsters.walked_2s", string.Concat(obj));
			all = Shop.All;
			for (int num = 0; num < all.Length; num++)
			{
				Cyberware.Revoke(all[num].grants);
			}
			Note("remove.ammo", type("remove ammo"));
			Note("remove.unknown", type("remove banana"));
			Note("remove.listing", type("ripperdoc").Replace("\r", ""));
			Note("gunshop.listing", type("budget arms").Replace("\r", ""));
			Note("gunshop.by_other_words", (type("gunshop").StartsWith("BUDGET ARMS") ? "gunshop ok" : "gunshop WRONG") + ", " + (type("guns").StartsWith("BUDGET ARMS") ? "guns ok" : "guns WRONG") + ", " + (type("budget").StartsWith("BUDGET ARMS") ? "budget ok" : "budget WRONG"));
			Note("gunshop.buy_bat", type("bat").Replace("\r", ""));
			Note("gunshop.sell_bat", type("remove bat").Replace("\r", ""));
			all = Shop.All;
			for (int num = 0; num < all.Length; num++)
			{
				ShopRow shopRow = all[num];
				if (shopRow.gives == "item")
				{
					if (had.Contains(shopRow.grants))
					{
						Cyberware.Grant(shopRow.grants);
					}
					else
					{
						Cyberware.Revoke(shopRow.grants);
					}
				}
			}
			terminal.groupCredits = credits;
			terminal.SyncGroupCreditsServerRpc(terminal.groupCredits, terminal.numberOfItemsInDropship);
		}

		private IEnumerator LauncherOnly(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			Terminal val = Object.FindObjectOfType<Terminal>();
			if (player.inTerminalMenu && (Object)(object)val != (Object)null)
			{
				val.QuitTerminal(true);
			}
			yield return (object)new WaitForSecondsRealtime(2f);
			StartOfRound.Instance.allowLocalPlayerDeath = false;
			bool had = Cyberware.Has(Launchers.ProjectileLauncher.id);
			Cyberware.Grant(Launchers.ProjectileLauncher.id);
			Note("launcher.fire", rig.TryLauncher(tips: false) ?? "fired");
			float t0 = Time.unscaledTime;
			float goneAt = -1f;
			int shown = 0;
			int hidden = 0;
			bool was = false;
			string states = "";
			string last = "";
			float nextShot = 0f;
			int shots = 0;
			while (Time.unscaledTime - t0 < 6f)
			{
				yield return (object)new WaitForEndOfFrame();
				float num = Time.unscaledTime - t0;
				bool visible = rig.Launcher.Visible;
				if (visible && !was)
				{
					shown++;
				}
				if (!visible && was)
				{
					hidden++;
					goneAt = num;
				}
				was = visible;
				string stateName = rig.Launcher.StateName;
				if (stateName != last)
				{
					states = states + ((states.Length > 0) ? " -> " : "") + num.ToString("0.00") + "s " + stateName;
					last = stateName;
				}
				if (visible && num >= nextShot && shots < 8)
				{
					nextShot = num + 0.35f;
					yield return Shot("launcher_" + shots++.ToString("00") + "_" + (num * 100f).ToString("000"));
				}
			}
			Note("launcher.arm", "came into view " + shown + " time(s), left " + hidden + " time(s), gone at " + goneAt.ToString("0.00") + " s; rockets " + Rocket.Launched);
			Note("launcher.states", states);
			if (!had)
			{
				Cyberware.Revoke(Launchers.ProjectileLauncher.id);
			}
		}

		private IEnumerator NewGunsOnly(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			Terminal val = Object.FindObjectOfType<Terminal>();
			if (player.inTerminalMenu && (Object)(object)val != (Object)null)
			{
				val.QuitTerminal(true);
			}
			yield return (object)new WaitForSecondsRealtime(2f);
			bool hadUnity = Cyberware.Has(Guns.Unity.id);
			bool hadBat = Cyberware.Has(Weapons.BaseballBat.id);
			Cyberware.Grant(Guns.Unity.id);
			Cyberware.Grant(Weapons.BaseballBat.id);
			Note("unity.view_model", rig.Unity.HasViewModel);
			rig.Unity.Toggle();
			yield return (object)new WaitForSecondsRealtime(1.5f);
			Note("unity.deployed", rig.Unity.Deployed + " (" + rig.Unity.StateName + "), meshes " + rig.Unity.MeshesDrawn + ", magazine " + rig.Unity.Magazine + " / reserve " + rig.Unity.Reserve);
			yield return Shot("unity_idle");
			int mag = rig.Unity.Magazine;
			for (int i = 0; i < 3; i++)
			{
				rig.Unity.TryFire();
				yield return (object)new WaitForEndOfFrame();
				if (i == 0)
				{
					yield return Shot("unity_fire");
				}
				yield return (object)new WaitForSecondsRealtime(0.3f);
			}
			AutoTest autoTest = this;
			string[] obj = new string[10]
			{
				"magazine ",
				mag.ToString(),
				" -> ",
				rig.Unity.Magazine.ToString(),
				", shots ",
				rig.Unity.ShotsFired.ToString(),
				", ",
				rig.Unity.FlashInfo,
				", damage ",
				null
			};
			float damage = Guns.Unity.damage;
			obj[9] = damage.ToString();
			autoTest.Note("unity.fired_3", string.Concat(obj));
			Note("unity.reload_started", rig.Unity.TryReload() + " (" + rig.Unity.StateName + ")");
			yield return (object)new WaitForSecondsRealtime(1f);
			yield return Shot("unity_reload");
			yield return (object)new WaitForSecondsRealtime(2.5f);
			Note("unity.after_reload", "magazine " + rig.Unity.Magazine + ", reserve " + rig.Unity.Reserve + " (" + rig.Unity.StateName + ")");
			Note("bat.view_model", rig.Bat.HasViewModel);
			rig.Bat.Toggle();
			yield return (object)new WaitForSecondsRealtime(1.5f);
			AutoTest autoTest2 = this;
			string[] obj2 = new string[12]
			{
				rig.Bat.Deployed.ToString(),
				" (",
				rig.Bat.StateName,
				"), meshes ",
				rig.Bat.MeshesDrawn.ToString(),
				", pistol away ",
				(!rig.Unity.Deployed).ToString(),
				", damage ",
				null,
				null,
				null,
				null
			};
			int damage2 = Weapons.BaseballBat.damage;
			obj2[8] = damage2.ToString();
			obj2[9] = " (blades ";
			damage2 = Weapons.MantisBlades.damage;
			obj2[10] = damage2.ToString();
			obj2[11] = ")";
			autoTest2.Note("bat.deployed", string.Concat(obj2));
			yield return Shot("bat_idle");
			for (int i = 0; i < 3; i++)
			{
				Note("bat.swing_" + (i + 1), rig.Bat.TrySwing() + " (" + rig.Bat.StateName + ")");
				yield return (object)new WaitForSecondsRealtime(0.12f);
				yield return Shot("bat_swing_" + (i + 1));
				yield return (object)new WaitForSecondsRealtime(1f);
			}
			rig.Blades.Toggle();
			yield return (object)new WaitForSecondsRealtime(0.3f);
			Note("bat.swapped", "bat away " + !rig.Bat.Deployed + " when another weapon is drawn (blades owned " + Cyberware.Has(Weapons.MantisBlades.id) + ")");
			rig.Bat.Retract();
			rig.Blades.Retract();
			if (!hadUnity)
			{
				Cyberware.Revoke(Guns.Unity.id);
			}
			if (!hadBat)
			{
				Cyberware.Revoke(Weapons.BaseballBat.id);
			}
		}

		private IEnumerator UnityOnly(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			Terminal terminal = Object.FindObjectOfType<Terminal>();
			if (player.inTerminalMenu && (Object)(object)terminal != (Object)null)
			{
				terminal.QuitTerminal(true);
			}
			yield return (object)new WaitForSecondsRealtime(2f);
			bool had = Cyberware.Has(Guns.Unity.id);
			int credits = terminal.groupCredits;
			Cyberware.Revoke(Guns.Unity.id);
			rig.Unity.Toggle();
			yield return (object)new WaitForSecondsRealtime(0.5f);
			Note("unity.before_buying", rig.Unity.Deployed ? "drawn (wrong)" : "does nothing");
			terminal.groupCredits = 500;
			Note("unity.buy", TerminalShop.Handle(terminal, "unity").displayText.Trim().Replace("\r", "").Replace("\n", " | "));
			Note("unity.buy_ammo", TerminalShop.Handle(terminal, "unityammo").displayText.Trim().Replace("\r", "").Replace("\n", " | "));
			Object.FindObjectOfType<StartMatchLever>().StartGame();
			float waited = 0f;
			while (!StartOfRound.Instance.shipHasLanded)
			{
				yield return (object)new WaitForSecondsRealtime(1f);
				float num;
				waited = (num = waited + 1f);
				if (num > 90f)
				{
					Note("FAIL landing", "never landed");
					yield break;
				}
			}
			yield return (object)new WaitForSecondsRealtime(3f);
			StartOfRound.Instance.allowLocalPlayerDeath = false;
			rig.Unity.Toggle();
			yield return (object)new WaitForSecondsRealtime(1.5f);
			Note("unity.deployed", rig.Unity.Deployed + " (" + rig.Unity.StateName + "), meshes " + rig.Unity.MeshesDrawn + ", magazine " + rig.Unity.Magazine + " / reserve " + rig.Unity.Reserve);
			Transform cam = ((Component)player.gameplayCamera).transform;
			EnemyType val = ((IEnumerable<EnemyType>)Resources.FindObjectsOfTypeAll<EnemyType>()).FirstOrDefault((Func<EnemyType, bool>)((EnemyType x) => (Object)(object)x != (Object)null && (Object)(object)x.enemyPrefab != (Object)null && (Object)(object)x.enemyPrefab.GetComponent<CrawlerAI>() != (Object)null));
			NavMeshHit val2 = default(NavMeshHit);
			bool flag = false;
			NavMeshHit val4 = default(NavMeshHit);
			for (int num2 = 0; num2 < 24; num2++)
			{
				if (flag)
				{
					break;
				}
				Vector3 val3 = Quaternion.Euler(0f, (float)num2 * 15f, 0f) * Vector3.forward;
				if (NavMesh.SamplePosition(cam.position + val3 * 9f, ref val4, 3f, -1) && !Physics.Linecast(cam.position, ((NavMeshHit)(ref val4)).position + Vector3.up * 0.6f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
				{
					val2 = val4;
					flag = true;
				}
			}
			if ((Object)(object)val == (Object)null || !flag)
			{
				Note("FAIL unity", "could not place a monster in view");
				yield break;
			}
			RoundManager.Instance.SpawnEnemyGameObject(((NavMeshHit)(ref val2)).position, 0f, -1, val);
			yield return (object)new WaitForSecondsRealtime(1.5f);
			EnemyAI enemy = ((IEnumerable<EnemyAI>)RoundManager.Instance.SpawnedEnemies).LastOrDefault((Func<EnemyAI, bool>)((EnemyAI x) => x is CrawlerAI));
			if ((Object)(object)enemy == (Object)null)
			{
				Note("FAIL unity", "monster did not spawn");
				yield break;
			}
			enemy.agent.speed = 0f;
			int hp0 = enemy.enemyHP;
			int shots = 0;
			_ = Psychosis.Value;
			int quota0 = TimeOfDay.Instance.quotaFulfilled;
			while (!enemy.isEnemyDead && shots < 10)
			{
				enemy.agent.speed = 0f;
				cam.rotation = Quaternion.LookRotation(((Component)enemy).transform.position + Vector3.up * 0.5f - cam.position);
				yield return (object)new WaitForEndOfFrame();
				int before = enemy.enemyHP;
				if (shots == 0)
				{
					Note("unity.bullet_path", rig.Unity.DescribeRay());
				}
				bool fired = rig.Unity.TryFire();
				shots++;
				yield return (object)new WaitForEndOfFrame();
				if (shots == 1)
				{
					yield return Shot("unity_shot_at_monster");
					AutoTest autoTest = this;
					string[] obj = new string[11]
					{
						"fired ",
						fired.ToString(),
						", monster health ",
						before.ToString(),
						" -> ",
						enemy.enemyHP.ToString(),
						" (damage ",
						null,
						null,
						null,
						null
					};
					float num = Guns.Unity.damage;
					obj[7] = num.ToString();
					obj[8] = "), ";
					obj[9] = Vector3.Distance(cam.position, ((Component)enemy).transform.position).ToString("0.0");
					obj[10] = " m away";
					autoTest.Note("unity.first_shot", string.Concat(obj));
				}
				yield return (object)new WaitForSecondsRealtime(Guns.Unity.fireInterval + 0.1f);
			}
			Note("unity.kill", "monster health " + hp0 + ", dead " + enemy.isEnemyDead + " after " + shots + " shots; hits landed " + rig.Unity.HitsLanded + ", tracers " + rig.Unity.Tracers + ", " + rig.Unity.FlashInfo + "; bounty toward quota +" + (TimeOfDay.Instance.quotaFulfilled - quota0));
			cam.rotation = Quaternion.LookRotation(Vector3.up * 0.3f + ((Component)player).transform.forward);
			int guard = 0;
			while (rig.Unity.Magazine > 0 && guard++ < 20)
			{
				rig.Unity.TryFire();
				yield return (object)new WaitForSecondsRealtime(Guns.Unity.fireInterval + 0.05f);
			}
			Note("unity.empty", "magazine " + rig.Unity.Magazine + ", pulling the trigger again fires: " + rig.Unity.TryFire());
			yield return (object)new WaitForSecondsRealtime(0.4f);
			Note("unity.reload_started", rig.Unity.TryReload() + " (" + rig.Unity.StateName + ")");
			yield return (object)new WaitForSecondsRealtime(1.2f);
			yield return Shot("unity_reloading");
			yield return (object)new WaitForSecondsRealtime(2.5f);
			AutoTest autoTest2 = this;
			string[] obj2 = new string[9]
			{
				"magazine ",
				rig.Unity.Magazine.ToString(),
				" (sheet ",
				null,
				null,
				null,
				null,
				null,
				null
			};
			int magSize = Guns.Unity.magSize;
			obj2[3] = magSize.ToString();
			obj2[4] = "), reserve ";
			obj2[5] = rig.Unity.Reserve.ToString();
			obj2[6] = " (";
			obj2[7] = rig.Unity.StateName;
			obj2[8] = ")";
			autoTest2.Note("unity.after_reload", string.Concat(obj2));
			rig.Smg.Toggle();
			yield return (object)new WaitForSecondsRealtime(0.3f);
			Note("unity.swap", "Unity away " + !rig.Unity.Deployed + " when the Saratoga key is pressed (Saratoga owned " + Cyberware.Has(Guns.Saratoga.id) + ")");
			rig.Unity.Toggle();
			yield return (object)new WaitForSecondsRealtime(1.2f);
			rig.Unity.Toggle();
			yield return (object)new WaitForSecondsRealtime(1.2f);
			Note("unity.holstered", "away " + !rig.Unity.Visible);
			if (!had)
			{
				Cyberware.Revoke(Guns.Unity.id);
			}
			terminal.groupCredits = credits;
		}

		private IEnumerator MultiplayerOnly(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			Terminal terminal = Object.FindObjectOfType<Terminal>();
			if (player.inTerminalMenu && (Object)(object)terminal != (Object)null)
			{
				terminal.QuitTerminal(true);
			}
			yield return (object)new WaitForSecondsRealtime(2f);
			int credits = terminal.groupCredits;
			List<string> had = (from r in Shop.All
				where r.gives == "item" && Cyberware.Has(r.grants)
				select r.grants).ToList();
			ShopRow[] all = Shop.All;
			int num;
			for (num = 0; num < all.Length; num++)
			{
				Cyberware.Revoke(all[num].grants);
			}
			Note("mp.channel", "open " + Net.Bound + ", this machine decides shared things " + Net.IsHost + ", players connected " + (StartOfRound.Instance.connectedPlayersAmount + 1));
			Note("mp.packet", Net.RoundTrip() + " (expected Shot 2 -7 1.5 (1, 2, 3) (4, 5, 6))");
			Note("mp.prices", string.Join(", ", Shop.All.Select((ShopRow r) => r.word + " " + r.price).ToArray()) + "; starter credits top up to " + (Economy.StarterCredits.amount + 60));
			terminal.groupCredits = 1000;
			Func<string, string> func = delegate(string s)
			{
				TerminalNode val2 = TerminalShop.Handle(terminal, s);
				return (!((Object)(object)val2 == (Object)null)) ? val2.displayText.Trim().Replace("\r", "").Replace("\n", " | ") : "(not ours)";
			};
			Note("mp.buy_berserk", func("berserk"));
			func("mantis");
			func("unity");
			int groupCredits = terminal.groupCredits;
			int num2 = Cyberware.SellAllOnDeath();
			Note("mp.death_sale", "credits 1000 -> " + groupCredits + " after buying berserk, mantis and unity; dying sold them for " + num2 + " -> " + terminal.groupCredits + "; still owned: " + Shop.All.Count((ShopRow r) => r.gives == "item" && Cyberware.Has(r.grants)));
			Cyberware.Grant(Abilities.Sandevistan.id);
			Object.FindObjectOfType<StartMatchLever>().StartGame();
			float waited = 0f;
			float num3;
			while (!StartOfRound.Instance.shipHasLanded)
			{
				yield return (object)new WaitForSecondsRealtime(1f);
				waited = (num3 = waited + 1f);
				if (num3 > 90f)
				{
					Note("FAIL landing", "never landed");
					yield break;
				}
			}
			yield return (object)new WaitForSecondsRealtime(3f);
			StartOfRound.Instance.allowLocalPlayerDeath = false;
			int hp = player.health;
			player.DamagePlayer(40, false, true, (CauseOfDeath)0, 0, false, default(Vector3));
			int num4 = hp - player.health;
			player.health = hp;
			Note("berserk.start", rig.Sandevistan.TryStart() + ", time scale " + Time.timeScale);
			player.DamagePlayer(40, false, true, (CauseOfDeath)0, 0, false, default(Vector3));
			Note("berserk.hit_40", "took " + (hp - player.health) + " while active (0 expected), " + num4 + " without; hits turned away " + PlayerDamagePatch.Blocked);
			yield return (object)new WaitForSecondsRealtime(1f);
			yield return Shot("berserk_active");
			yield return (object)new WaitForSecondsRealtime(Abilities.Sandevistan.duration);
			AutoTest autoTest = this;
			string[] obj = new string[10]
			{
				"active ",
				rig.Sandevistan.Active.ToString(),
				" after ",
				null,
				null,
				null,
				null,
				null,
				null,
				null
			};
			num3 = Abilities.Sandevistan.duration;
			obj[3] = num3.ToString();
			obj[4] = " s, recharge ";
			obj[5] = rig.Sandevistan.CooldownLeft.ToString("0");
			obj[6] = " s (sheet ";
			num3 = Abilities.Sandevistan.cooldown;
			obj[7] = num3.ToString();
			obj[8] = "), second use at once: ";
			obj[9] = rig.Sandevistan.TryStart().ToString();
			autoTest.Note("berserk.after", string.Concat(obj));
			player.health = hp;
			ImplantsRow[] all2 = Implants.All;
			for (num = 0; num < all2.Length; num++)
			{
				Cyberware.Grant(all2[num].ware);
			}
			Psychosis.Value = 30f;
			yield return null;
			PlayerControllerB other = StartOfRound.Instance.allPlayerScripts[1];
			Note("pvp.psychotic", Psychosis.Psychotic + " (load " + Psychosis.Load + " / " + Psychosis.Limit + ")");
			Psychosis.NoteAttack(other);
			other.isPlayerDead = true;
			yield return null;
			yield return null;
			AutoTest autoTest2 = this;
			string[] obj2 = new string[6]
			{
				"sanity 30 -> ",
				Psychosis.Value.ToString("0"),
				" (+",
				null,
				null,
				null
			};
			num3 = Sanity.Meter.killPlayerGain;
			obj2[3] = num3.ToString();
			obj2[4] = "% expected, less a moment of drain), kills counted ";
			obj2[5] = Psychosis.PlayerKills.ToString();
			autoTest2.Note("pvp.kill", string.Concat(obj2));
			other.isPlayerDead = false;
			all2 = Implants.All;
			for (num = 0; num < all2.Length; num++)
			{
				Cyberware.Revoke(all2[num].ware);
			}
			Psychosis.Value = 100f;
			Cyberware.SetInt("smasher_kills", 0);
			string lives = "";
			for (int life = 0; life < 3; life++)
			{
				Vector3 forward = ((Component)player).transform.forward;
				forward.y = 0f;
				rig.Bosses.Spawn(((Component)player).transform.position + ((Vector3)(ref forward)).normalized * 14f, announce: false);
				Boss boss = rig.Bosses.Boss;
				if (boss == null)
				{
					break;
				}
				lives = lives + "life " + (life + 1) + ": health " + boss.MaxHealth + ", damage x" + boss.DamageNow.ToString("0.00") + " (melee " + Mathf.RoundToInt((float)Enemies.AdamSmasher.meleeDamage * boss.DamageNow) + "); ";
				boss.TakeHit(100000);
				yield return (object)new WaitForSecondsRealtime(0.5f);
				rig.Bosses.Destroy();
			}
			AutoTest autoTest3 = this;
			string[] obj3 = new string[7]
			{
				lives,
				"kills saved ",
				Boss.Kills.ToString(),
				"; sheet base health ",
				null,
				null,
				null
			};
			num = Enemies.AdamSmasher.health;
			obj3[4] = num.ToString();
			obj3[5] = ", melee ";
			num = Enemies.AdamSmasher.meleeDamage;
			obj3[6] = num.ToString();
			autoTest3.Note("boss.grows", string.Concat(obj3));
			Cyberware.SetInt("smasher_kills", 0);
			Vector3 forward2 = ((Component)player).transform.forward;
			forward2.y = 0f;
			Note("boss.spawned", rig.Bosses.Spawn(((Component)player).transform.position + ((Vector3)(ref forward2)).normalized * 14f, announce: false));
			Boss boss2 = rig.Bosses.Boss;
			bool authority;
			if (boss2 != null)
			{
				yield return (object)new WaitForSecondsRealtime(2.5f);
				AutoTest autoTest4 = this;
				string[] obj4 = new string[11]
				{
					"decides ", null, null, null, null, null, null, null, null, null,
					null
				};
				authority = boss2.Authority;
				obj4[1] = authority.ToString();
				obj4[2] = ", target player ";
				obj4[3] = boss2.TargetId.ToString();
				obj4[4] = " (local is ";
				obj4[5] = player.playerClientId.ToString();
				obj4[6] = "), ";
				obj4[7] = boss2.StateName;
				obj4[8] = ", ";
				obj4[9] = Vector3.Distance(boss2.Position, ((Component)player).transform.position).ToString("0.0");
				obj4[10] = " m away";
				autoTest4.Note("boss.host", string.Concat(obj4));
				player.isInsideFactory = true;
				yield return (object)new WaitForSecondsRealtime(1.5f);
				Note("boss.player_inside", "target player " + boss2.TargetId + " (-1 = nobody), " + boss2.StateName);
				player.isInsideFactory = false;
				float health = boss2.Health;
				boss2.TakeHit(5);
				boss2.TakeHit(5, fromAnotherPlayer: true);
				Note("boss.hits", "health " + health + " -> " + boss2.Health + " after one local hit and one passed on from another player (5 each)");
				int life = Net.Sent;
				yield return (object)new WaitForSecondsRealtime(1f);
				Note("boss.updates_sent", Net.Sent - life + " in a second (0 expected with nobody else connected)");
				rig.Bosses.Destroy();
			}
			Vector3 val = ((Component)player).transform.position + ((Vector3)(ref forward2)).normalized * 10f + Vector3.up * 0.1f;
			Boss guest = new Boss(player, val, new List<AudioClip>(), authority: false);
			Vector3 told = val + ((Component)player).transform.right * 4f;
			for (int life = 0; life < 40; life++)
			{
				guest.FromHost(65537, (int)player.playerClientId, 70f, told, 90f, 0f);
				guest.Tick();
				yield return null;
			}
			AutoTest autoTest5 = this;
			string[] obj5 = new string[8] { "decides ", null, null, null, null, null, null, null };
			authority = guest.Authority;
			obj5[1] = authority.ToString();
			obj5[2] = ", ";
			obj5[3] = guest.StateName;
			obj5[4] = ", ";
			obj5[5] = Vector3.Distance(guest.Position, told).ToString("0.00");
			obj5[6] = " m from where the host said, health shown ";
			obj5[7] = guest.Health.ToString();
			autoTest5.Note("boss.guest_follow", string.Concat(obj5));
			for (int life = 0; life < 30; life++)
			{
				guest.FromHost(131330, (int)player.playerClientId, 70f, told, 90f, 0f);
				guest.Tick();
				yield return null;
			}
			Note("boss.guest_melee", guest.StateName);
			yield return Shot("boss_guest_copy");
			int sent = Net.Sent;
			guest.TakeHit(3);
			Note("boss.guest_hit", "health shown stays " + guest.Health + " until the host answers; hit sent to the host: " + (Net.Sent - sent) + " message(s) (0 here: alone, this machine is the host)");
			for (int life = 0; life < 20; life++)
			{
				guest.FromHost(196614, -1, 0f, told, 90f, 0f);
				guest.Tick();
				yield return null;
			}
			Note("boss.guest_dead", guest.StateName + ", alive " + guest.Alive);
			guest.Destroy();
			Note("horde.spawn", Horde.Spawn(((Component)player).transform.position, announce: false) + " spawned; " + Horde.LastReport);
			yield return (object)new WaitForSecondsRealtime(1f);
			Note("horde.music", HordeMusic.State);
			all = Shop.All;
			for (num = 0; num < all.Length; num++)
			{
				ShopRow shopRow = all[num];
				if (shopRow.gives == "item")
				{
					if (had.Contains(shopRow.grants))
					{
						Cyberware.Grant(shopRow.grants);
					}
					else
					{
						Cyberware.Revoke(shopRow.grants);
					}
				}
			}
			terminal.groupCredits = credits;
		}

		private static string Where(Boss boss)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (boss != null)
			{
				string[] obj = new string[7] { boss.StateName, " at ", null, null, null, null, null };
				Vector3 position = boss.Position;
				obj[2] = ((Vector3)(ref position)).ToString("0.0");
				obj[3] = ", health ";
				obj[4] = boss.Health.ToString("0");
				obj[5] = ", target player ";
				obj[6] = boss.TargetId.ToString();
				return string.Concat(obj);
			}
			return "no boss";
		}

		private IEnumerator WornHost(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			float waited = 0f;
			while (StartOfRound.Instance.connectedPlayersAmount < 1)
			{
				yield return (object)new WaitForSecondsRealtime(1f);
				float num;
				waited = (num = waited + 1f);
				if (num > 150f)
				{
					Note("FAIL host", "nobody joined");
					yield break;
				}
			}
			yield return (object)new WaitForSecondsRealtime(10f);
			GunsRow[] all = Guns.All;
			for (int i = 0; i < all.Length; i++)
			{
				Cyberware.Grant(all[i].id);
			}
			WeaponsRow[] all2 = Weapons.All;
			for (int i = 0; i < all2.Length; i++)
			{
				Cyberware.Grant(all2[i].id);
			}
			Cyberware.Grant(Upgrades.HolsterSystem.id);
			PlayerControllerB val = ((IEnumerable<PlayerControllerB>)StartOfRound.Instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB p) => (Object)(object)p != (Object)null && (Object)(object)p != (Object)(object)player && p.isPlayerControlled));
			if ((Object)(object)val != (Object)null)
			{
				Vector3 val2 = ((Component)val).transform.position - ((Component)player).transform.position;
				val2.y = 0f;
				((Component)player).transform.rotation = Quaternion.LookRotation(val2);
			}
			WornRow[] all3 = ChromeCompany.Sheets.Worn.All;
			for (int num2 = 0; num2 < all3.Length; num2++)
			{
				WornRow row = all3[num2];
				Gun gun = rig.Guns.FirstOrDefault((Gun g) => g.Row.id == row.weapon);
				Blades blade = rig.Melee.FirstOrDefault((Blades m) => m.Row.id == row.weapon);
				if (gun != null)
				{
					gun.Toggle();
				}
				else
				{
					blade?.Toggle();
				}
				yield return (object)new WaitForSecondsRealtime(5f);
				string text = "";
				for (int num3 = 0; num3 < player.playerBodyAnimator.layerCount; num3++)
				{
					AnimatorClipInfo[] currentAnimatorClipInfo = player.playerBodyAnimator.GetCurrentAnimatorClipInfo(num3);
					if (currentAnimatorClipInfo.Length != 0)
					{
						text = text + player.playerBodyAnimator.GetLayerName(num3) + "=" + ((Object)((AnimatorClipInfo)(ref currentAnimatorClipInfo[0])).clip).name + " ";
					}
				}
				Note("worn.host_" + row.weapon, "out " + ((gun != null && gun.Deployed) || (blade?.Deployed ?? false)) + ", pose " + Worn.LastPose + ", body playing " + text.Trim());
				if (gun != null)
				{
					gun.Retract();
				}
				else
				{
					blade?.Retract();
				}
				yield return (object)new WaitForSecondsRealtime(2.5f);
			}
			Blades errata = rig.Melee.FirstOrDefault((Blades m) => m.Row.id == "errata");
			if (errata != null)
			{
				int num2 = Blades.Told;
				errata.Toggle();
				yield return (object)new WaitForSecondsRealtime(3f);
				for (int i2 = 0; i2 < 3; i2++)
				{
					errata.TrySwing();
					yield return (object)new WaitForSecondsRealtime(1.3f);
				}
				Note("swing.host", "told the others " + (Blades.Told - num2) + " sound(s)");
				errata.Retract();
				yield return (object)new WaitForSecondsRealtime(3f);
			}
			Cyberware.Grant(Launchers.ProjectileLauncher.id);
			yield return (object)new WaitForSecondsRealtime(1f);
			Note("launch.host", "fired " + (rig.Launcher != null && rig.Launcher.TryFire()));
			yield return (object)new WaitForSecondsRealtime(6f);
			Cyberware.Grant(Optics.EyeLight.id);
			Note("lamp.host_on", rig.EyeLight.Toggle() + ", " + rig.EyeLight.Info);
			yield return (object)new WaitForSecondsRealtime(6f);
			Note("lamp.host_off", rig.EyeLight.Toggle() + ", " + rig.EyeLight.Info);
			yield return (object)new WaitForSecondsRealtime(3f);
			Note("worn.host_done", "pose after putting everything away: " + Worn.LastPose + ", sent " + Net.Sent);
			yield return (object)new WaitForSecondsRealtime(4f);
		}

		private IEnumerator WornGuest(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			PlayerControllerB host = StartOfRound.Instance.allPlayerScripts[0];
			Note("worn.guest_joined", "player " + player.playerClientId + ", host " + Vector3.Distance(((Component)player).transform.position, ((Component)host).transform.position).ToString("0.0") + " m away");
			int shownWas = 0;
			int lampsWas = 0;
			int swingsWas = 0;
			int posesWas = 0;
			float changedAt = -1f;
			float started = Time.unscaledTime;
			bool pictured = true;
			while (Time.unscaledTime - started < 200f)
			{
				yield return null;
				NetworkManager singleton = NetworkManager.Singleton;
				if ((Object)(object)singleton == (Object)null || !singleton.IsConnectedClient)
				{
					Note("worn.guest_disconnected", "the host has gone");
					break;
				}
				Vector3 val = ((Component)host).transform.position - ((Component)player).transform.position;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude > 0.01f)
				{
					((Component)player).transform.rotation = Quaternion.LookRotation(val);
				}
				if (Net.Seen[18] != swingsWas)
				{
					swingsWas = Net.Seen[18];
					Note("swing.guest_hears_" + swingsWas, "melee sound message " + swingsWas + " arrived, " + Object.FindObjectsOfType<AudioSource>().Count((AudioSource x) => ((Object)x).name == "ChromeCompany_Sound" && x.isPlaying) + " mod sound(s) playing in the world");
					if (swingsWas == 1)
					{
						player.TeleportPlayer(((Component)host).transform.position + ((Component)host).transform.forward * 1.6f - ((Component)host).transform.right * 2.4f, false, 0f, false, true);
					}
				}
				if (LaunchPose.Shown != posesWas)
				{
					posesWas = LaunchPose.Shown;
					yield return (object)new WaitForSecondsRealtime(0.3f);
					Note("launch.guest_sees", LaunchPose.Last + "; launch messages " + Net.Seen[19]);
					yield return Shot("launch_pose");
				}
				if (EyeLight.OthersLit != lampsWas)
				{
					lampsWas = EyeLight.OthersLit;
					Note("lamp.guest_sees", lampsWas + " other player's headlamp lit, lamp messages received " + Net.Seen[11]);
					if (lampsWas > 0)
					{
						yield return (object)new WaitForSecondsRealtime(1f);
						yield return Shot("lamp_on_host");
					}
				}
				Worn.Shown.TryGetValue((int)host.playerClientId, out var value);
				if (value != shownWas)
				{
					shownWas = value;
					changedAt = Time.unscaledTime;
					pictured = false;
					if (value == 0)
					{
						Note("worn.guest_sees_nothing", Worn.Describe((int)host.playerClientId));
					}
				}
				if (pictured || value == 0 || !(Time.unscaledTime - changedAt > 2.5f))
				{
					continue;
				}
				pictured = true;
				WornRow row = ChromeCompany.Sheets.Worn.All[value - 1];
				string text = "";
				for (int num = 0; num < host.playerBodyAnimator.layerCount; num++)
				{
					AnimatorClipInfo[] currentAnimatorClipInfo = host.playerBodyAnimator.GetCurrentAnimatorClipInfo(num);
					if (currentAnimatorClipInfo.Length != 0)
					{
						text = text + host.playerBodyAnimator.GetLayerName(num) + "=" + ((Object)((AnimatorClipInfo)(ref currentAnimatorClipInfo[0])).clip).name + " ";
					}
				}
				Note("worn.guest_sees_" + row.weapon, Worn.Describe((int)host.playerClientId) + "; host body playing " + text.Trim());
				string[] array = new string[2] { "front", "side" };
				foreach (string side in array)
				{
					Vector3 val2 = ((side == "front") ? ((Component)host).transform.forward : ((Component)host).transform.right);
					player.TeleportPlayer(((Component)host).transform.position + val2 * 2.9f, false, 0f, false, true);
					for (int f = 0; f < 20; f++)
					{
						Vector3 val3 = ((Component)host).transform.position - ((Component)player).transform.position;
						val3.y = 0f;
						if (((Vector3)(ref val3)).sqrMagnitude > 0.01f)
						{
							((Component)player).transform.rotation = Quaternion.LookRotation(val3);
						}
						yield return null;
					}
					yield return Shot("worn_" + row.weapon + "_" + side);
				}
			}
		}

		private IEnumerator RoleHost(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			Terminal terminal = Object.FindObjectOfType<Terminal>();
			if (player.inTerminalMenu && (Object)(object)terminal != (Object)null)
			{
				terminal.QuitTerminal(true);
			}
			float waited = 0f;
			while (StartOfRound.Instance.connectedPlayersAmount < 1)
			{
				yield return (object)new WaitForSecondsRealtime(1f);
				float num;
				waited = (num = waited + 1f);
				if (num > 150f)
				{
					Note("FAIL host", "nobody joined");
					yield break;
				}
			}
			yield return (object)new WaitForSecondsRealtime(8f);
			PlayerControllerB guest = ((IEnumerable<PlayerControllerB>)StartOfRound.Instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB p) => (Object)(object)p != (Object)null && (Object)(object)p != (Object)(object)player && p.isPlayerControlled));
			if ((Object)(object)guest == (Object)null)
			{
				Note("FAIL host", "no second player object");
				yield break;
			}
			Note("host.guest_joined", "players " + (StartOfRound.Instance.connectedPlayersAmount + 1) + ", guest is player " + guest.playerClientId + ", channel open " + Net.Bound + ", host " + Net.IsHost);
			terminal.groupCredits = 1000;
			terminal.SyncGroupCreditsServerRpc(1000, terminal.numberOfItemsInDropship);
			yield return (object)new WaitForSecondsRealtime(10f);
			Note("host.credits_after_guest_shopping", terminal.groupCredits + " (1000 less the guest's bat 40 and berserk 110 = 850)");
			Cyberware.Grant(Guns.Unity.id);
			Cyberware.Grant(Launchers.ProjectileLauncher.id);
			Object.FindObjectOfType<StartMatchLever>().StartGame();
			waited = 0f;
			while (!StartOfRound.Instance.shipHasLanded)
			{
				yield return (object)new WaitForSecondsRealtime(1f);
				float num;
				waited = (num = waited + 1f);
				if (num > 120f)
				{
					Note("FAIL landing", "never landed");
					yield break;
				}
			}
			yield return (object)new WaitForSecondsRealtime(6f);
			StartOfRound.Instance.allowLocalPlayerDeath = false;
			Transform cam = ((Component)player.gameplayCamera).transform;
			rig.Unity.Toggle();
			yield return (object)new WaitForSecondsRealtime(1.5f);
			EnemyType val = ((IEnumerable<EnemyType>)Resources.FindObjectsOfTypeAll<EnemyType>()).FirstOrDefault((Func<EnemyType, bool>)((EnemyType x) => (Object)(object)x != (Object)null && (Object)(object)x.enemyPrefab != (Object)null && (Object)(object)x.enemyPrefab.GetComponent<CrawlerAI>() != (Object)null));
			NavMeshHit val2 = default(NavMeshHit);
			bool flag = false;
			NavMeshHit val4 = default(NavMeshHit);
			for (int num2 = 0; num2 < 24; num2++)
			{
				if (flag)
				{
					break;
				}
				Vector3 val3 = Quaternion.Euler(0f, (float)num2 * 15f, 0f) * Vector3.forward;
				if (NavMesh.SamplePosition(cam.position + val3 * 8f, ref val4, 3f, -1) && !Physics.Linecast(cam.position, ((NavMeshHit)(ref val4)).position + Vector3.up * 0.6f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
				{
					val2 = val4;
					flag = true;
				}
			}
			int quota0 = TimeOfDay.Instance.quotaFulfilled;
			int sent0 = Net.Sent;
			if ((Object)(object)val != (Object)null && flag)
			{
				RoundManager.Instance.SpawnEnemyGameObject(((NavMeshHit)(ref val2)).position, 0f, -1, val);
				yield return (object)new WaitForSecondsRealtime(1.5f);
				EnemyAI enemy = ((IEnumerable<EnemyAI>)RoundManager.Instance.SpawnedEnemies).LastOrDefault((Func<EnemyAI, bool>)((EnemyAI x) => x is CrawlerAI));
				int shots = 0;
				while ((Object)(object)enemy != (Object)null && !enemy.isEnemyDead && shots < 11)
				{
					enemy.agent.speed = 0f;
					cam.rotation = Quaternion.LookRotation(((Component)enemy).transform.position + Vector3.up * 0.5f - cam.position);
					yield return (object)new WaitForEndOfFrame();
					if (shots < 2)
					{
						Note("host.A_bullet_path", rig.Unity.DescribeRay() + "; thumper health " + enemy.enemyHP + ", " + Vector3.Distance(cam.position, ((Component)enemy).transform.position).ToString("0.0") + " m away, magazine " + rig.Unity.Magazine + ", " + rig.Unity.StateName);
					}
					bool flag2 = rig.Unity.TryFire();
					shots++;
					if (shots <= 2)
					{
						Note("host.A_fired", flag2 + ", thumper health " + enemy.enemyHP + ", hits landed " + rig.Unity.HitsLanded);
					}
					yield return (object)new WaitForSecondsRealtime(Guns.Unity.fireInterval + 0.1f);
				}
				yield return (object)new WaitForSecondsRealtime(1f);
				Note("host.A_shots", shots + " Unity shots, thumper dead " + ((Object)(object)enemy == (Object)null || enemy.isEnemyDead) + ", quota " + quota0 + " -> " + TimeOfDay.Instance.quotaFulfilled + ", messages sent " + (Net.Sent - sent0));
			}
			else
			{
				Note("FAIL host.A", "could not place a thumper in view");
			}
			rig.Unity.TryReload();
			yield return (object)new WaitForSecondsRealtime(3.5f);
			int guestHealth = guest.health;
			int hits0 = rig.Unity.HitsLanded;
			cam.rotation = Quaternion.LookRotation(((Component)guest).transform.position + Vector3.up * 1.2f - cam.position);
			yield return (object)new WaitForEndOfFrame();
			rig.Unity.TryFire();
			yield return (object)new WaitForSecondsRealtime(1f);
			Note("host.B_sane_shot_at_guest", "psychotic " + Psychosis.Psychotic + ", hits " + (rig.Unity.HitsLanded - hits0) + ", guest health " + guestHealth + " -> " + guest.health + " (no hit expected), guest " + Vector3.Distance(cam.position, ((Component)guest).transform.position).ToString("0.0") + " m away");
			ImplantsRow[] all = Implants.All;
			for (int num3 = 0; num3 < all.Length; num3++)
			{
				Cyberware.Grant(all[num3].ware);
			}
			Psychosis.Value = 50f;
			StartOfRound.Instance.allowLocalPlayerDeath = true;
			yield return null;
			guestHealth = guest.health;
			hits0 = rig.Unity.HitsLanded;
			cam.rotation = Quaternion.LookRotation(((Component)guest).transform.position + Vector3.up * 1.2f - cam.position);
			yield return (object)new WaitForEndOfFrame();
			Note("host.B_bullet_path", rig.Unity.DescribeRay());
			rig.Unity.TryFire();
			yield return (object)new WaitForSecondsRealtime(1.5f);
			Note("host.B_psychotic_shot_at_guest", "psychotic " + Psychosis.Psychotic + ", hits " + (rig.Unity.HitsLanded - hits0) + ", guest health " + guestHealth + " -> " + guest.health);
			StartOfRound.Instance.allowLocalPlayerDeath = false;
			all = Implants.All;
			for (int num3 = 0; num3 < all.Length; num3++)
			{
				ImplantsRow implantsRow = all[num3];
				if (implantsRow.ware != Launchers.ProjectileLauncher.id)
				{
					Cyberware.Revoke(implantsRow.ware);
				}
			}
			Psychosis.Value = 100f;
			rig.Unity.Retract();
			yield return (object)new WaitForSecondsRealtime(1.2f);
			cam.rotation = Quaternion.LookRotation(-((Component)player).transform.forward + Vector3.up * 0.05f);
			yield return (object)new WaitForEndOfFrame();
			sent0 = Net.Sent;
			Note("host.C_rocket", rig.TryLauncher(tips: false) ?? "fired");
			yield return (object)new WaitForSecondsRealtime(4f);
			Note("host.C_blast", Rocket.LastBlast + ", messages sent " + (Net.Sent - sent0));
			Vector3 forward = ((Component)player).transform.forward;
			forward.y = 0f;
			Note("host.D_boss_spawned", rig.Bosses.Spawn(((Component)player).transform.position + ((Vector3)(ref forward)).normalized * 16f, announce: false));
			for (int shots = 0; shots < 4; shots++)
			{
				yield return (object)new WaitForSecondsRealtime(1f);
				Note("host.D_boss", Where(rig.Bosses.Boss));
			}
			player.isInsideFactory = true;
			for (int shots = 0; shots < 10; shots++)
			{
				yield return (object)new WaitForSecondsRealtime(1f);
				Note("host.D_boss_host_inside", Where(rig.Bosses.Boss) + "; guest health " + guest.health + ", guest dead " + guest.isPlayerDead + ", hits on players " + ((rig.Bosses.Boss != null) ? rig.Bosses.Boss.HitsOnPlayer : 0));
			}
			player.isInsideFactory = false;
			quota0 = TimeOfDay.Instance.quotaFulfilled;
			int credits0 = terminal.groupCredits;
			if (rig.Bosses.Boss != null)
			{
				rig.Bosses.Boss.TakeHit(1000);
			}
			yield return (object)new WaitForSecondsRealtime(2f);
			Note("host.D_boss_killed", Where(rig.Bosses.Boss) + "; quota " + quota0 + " -> " + TimeOfDay.Instance.quotaFulfilled + ", credits " + credits0 + " -> " + terminal.groupCredits);
			Note("host.E_horde", Horde.Spawn(((Component)player).transform.position, announce: true) + " spawned");
			yield return (object)new WaitForSecondsRealtime(2f);
			Note("host.E_music", HordeMusic.State);
			credits0 = terminal.groupCredits;
			for (int shots = 0; shots < 14; shots++)
			{
				yield return (object)new WaitForSecondsRealtime(1f);
				if (guest.isPlayerDead && shots > 2)
				{
					break;
				}
			}
			yield return (object)new WaitForSecondsRealtime(3f);
			Note("host.F_guest_death", "guest dead " + guest.isPlayerDead + ", credits " + credits0 + " -> " + terminal.groupCredits + ", messages received in all " + Net.Received + ", sent " + Net.Sent);
			yield return (object)new WaitForSecondsRealtime(3f);
		}

		private IEnumerator RoleGuest(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			Terminal terminal = Object.FindObjectOfType<Terminal>();
			Note("guest.joined", "player " + player.playerClientId + ", channel open " + Net.Bound + ", decides shared things " + Net.IsHost + ", owns " + Shop.All.Count((ShopRow r) => r.gives == "item" && Cyberware.Has(r.grants)) + " items, sanity " + Psychosis.Value.ToString("0"));
			float waited = 0f;
			while (terminal.groupCredits < 900)
			{
				yield return (object)new WaitForSecondsRealtime(0.5f);
				float num;
				waited = (num = waited + 0.5f);
				if (num > 60f)
				{
					break;
				}
			}
			Func<string, string> func = delegate(string s)
			{
				TerminalNode val = TerminalShop.Handle(terminal, s);
				return (!((Object)(object)val == (Object)null)) ? val.displayText.Trim().Replace("\r", "").Replace("\n", " | ") : "(not ours)";
			};
			Note("guest.buy_bat", "credits seen " + terminal.groupCredits + "; " + func("bat"));
			Note("guest.buy_berserk", func("berserk"));
			bool landed = false;
			bool bossSeen = false;
			bool bossHit = false;
			bool musicSeen = false;
			bool berserkUsed = false;
			bool died = false;
			int quota = TimeOfDay.Instance.quotaFulfilled;
			int shots = 0;
			int blasts = 0;
			int health = player.health;
			int credits = terminal.groupCredits;
			float bossSince = 0f;
			float musicSince = 0f;
			float berserkAt = -1f;
			float nextBossNote = 0f;
			int healthAtBerserk = 0;
			string bossState = "";
			float started = Time.unscaledTime;
			while (Time.unscaledTime - started < 330f)
			{
				yield return (object)new WaitForSecondsRealtime(0.25f);
				NetworkManager singleton = NetworkManager.Singleton;
				if ((Object)(object)singleton == (Object)null || !singleton.IsConnectedClient)
				{
					Note("guest.disconnected", "the host has gone");
					break;
				}
				if (!landed && StartOfRound.Instance.shipHasLanded)
				{
					landed = true;
					Note("guest.landed", "sanity " + Psychosis.Value.ToString("0") + ", load " + Psychosis.Load);
				}
				if (Net.Seen[3] != shots)
				{
					shots = Net.Seen[3];
					Note("guest.shot_seen", shots + " so far");
				}
				if (Net.Seen[4] != blasts)
				{
					blasts = Net.Seen[4];
					Note("guest.blast_seen", blasts + ", " + Vector3.Distance(((Component)player).transform.position, ((Component)StartOfRound.Instance.allPlayerScripts[0]).transform.position).ToString("0.0") + " m from the host");
				}
				if (TimeOfDay.Instance.quotaFulfilled != quota)
				{
					Note("guest.quota", quota + " -> " + TimeOfDay.Instance.quotaFulfilled + ", notice \"" + Bounty.Line + "\"");
					quota = TimeOfDay.Instance.quotaFulfilled;
				}
				if (terminal.groupCredits != credits)
				{
					Note("guest.credits", credits + " -> " + terminal.groupCredits);
					credits = terminal.groupCredits;
				}
				if (player.health != health)
				{
					Note("guest.health", health + " -> " + player.health + (rig.Sandevistan.Active ? " (BERSERK ACTIVE - wrong)" : ""));
					health = player.health;
				}
				Boss boss = rig.Bosses.Boss;
				if (boss != null)
				{
					if (!bossSeen)
					{
						bossSeen = true;
						bossSince = Time.unscaledTime;
						AutoTest autoTest = this;
						string[] obj = new string[6] { "decides ", null, null, null, null, null };
						bool authority = boss.Authority;
						obj[1] = authority.ToString();
						obj[2] = ", model ";
						obj[3] = boss.HasModel.ToString();
						obj[4] = ", ";
						obj[5] = Where(boss);
						autoTest.Note("guest.boss_appeared", string.Concat(obj));
						yield return Shot("guest_boss");
					}
					if (boss.StateName != bossState || Time.unscaledTime >= nextBossNote)
					{
						bossState = boss.StateName;
						nextBossNote = Time.unscaledTime + 1f;
						Note("guest.boss", Where(boss) + ", " + Vector3.Distance(boss.Position, ((Component)player).transform.position).ToString("0.0") + " m from me");
					}
					if (!bossHit && Time.unscaledTime - bossSince > 2.5f && boss.Alive)
					{
						bossHit = true;
						float was = boss.Health;
						boss.TakeHit(5);
						yield return (object)new WaitForSecondsRealtime(0.6f);
						Note("guest.boss_hit", "hit him for 5: health shown " + was + " -> " + boss.Health + " once the host answered");
					}
					if (!berserkUsed && Net.Seen[6] > 0 && !player.isPlayerDead)
					{
						berserkUsed = true;
						berserkAt = Time.unscaledTime;
						healthAtBerserk = player.health;
						Note("guest.berserk", "started " + rig.Sandevistan.TryStart() + " at health " + player.health);
					}
				}
				else if (bossSeen && bossState != "gone")
				{
					bossState = "gone";
					Note("guest.boss", "gone");
				}
				if (berserkAt > 0f && Time.unscaledTime - berserkAt > Abilities.Sandevistan.duration)
				{
					Note("guest.berserk_over", "health " + healthAtBerserk + " -> " + player.health + " during it, hits turned away " + PlayerDamagePatch.Blocked + ", messages BossHurt received " + Net.Seen[6]);
					berserkAt = -1f;
				}
				if (!musicSeen && HordeMusic.Playing)
				{
					musicSeen = true;
					musicSince = Time.unscaledTime;
					Note("guest.horde", "music " + HordeMusic.State);
				}
				if (musicSeen && !died && Time.unscaledTime - musicSince > 4f)
				{
					died = true;
					int before = terminal.groupCredits;
					Note("guest.dying", "owns " + Shop.All.Count((ShopRow r) => r.gives == "item" && Cyberware.Has(r.grants)) + " items, credits " + before);
					if (!player.isPlayerDead)
					{
						player.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 0, default(Vector3), false);
					}
					yield return (object)new WaitForSecondsRealtime(2f);
					Note("guest.died", "dead " + player.isPlayerDead + ", sale raised " + rig.DeathSale + ", owns " + Shop.All.Count((ShopRow r) => r.gives == "item" && Cyberware.Has(r.grants)) + " items, credits " + before + " -> " + terminal.groupCredits + ", music " + HordeMusic.State);
				}
			}
			Note("guest.totals", "messages received " + Net.Received + " (boss updates " + Net.Seen[5] + ", boss hurts " + Net.Seen[6] + ", boss voice " + Net.Seen[7] + ", quota " + Net.Seen[1] + ", horde " + Net.Seen[2] + ", shots " + Net.Seen[3] + ", blasts " + Net.Seen[4] + "), sent " + Net.Sent);
		}

		private IEnumerator SorOnly(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			Terminal terminal = Object.FindObjectOfType<Terminal>();
			if (player.inTerminalMenu && (Object)(object)terminal != (Object)null)
			{
				terminal.QuitTerminal(true);
			}
			yield return (object)new WaitForSecondsRealtime(2f);
			ShopRow[] all = Shop.All;
			int i;
			for (i = 0; i < all.Length; i++)
			{
				Cyberware.Revoke(all[i].grants);
			}
			terminal.groupCredits = 1000;
			Note("sor.buy", TerminalShop.Handle(terminal, "sor22").displayText.Trim().Replace("\r", "").Replace("\n", " | "));
			Note("sor.holsters", Carry.Used + " / " + Carry.Max + ", over " + Carry.Over);
			TerminalShop.Handle(terminal, "bat");
			Note("sor.holsters_with_bat", Carry.Used + " / " + Carry.Max + ", over " + Carry.Over);
			Cyberware.Revoke(Weapons.BaseballBat.id);
			Object.FindObjectOfType<StartMatchLever>().StartGame();
			float waited = 0f;
			while (!StartOfRound.Instance.shipHasLanded)
			{
				yield return (object)new WaitForSecondsRealtime(1f);
				float num;
				waited = (num = waited + 1f);
				if (num > 90f)
				{
					Note("FAIL landing", "never landed");
					yield break;
				}
			}
			yield return (object)new WaitForSecondsRealtime(3f);
			StartOfRound.Instance.allowLocalPlayerDeath = false;
			Note("sor.view_model", rig.Sor.HasViewModel);
			rig.Sor.Toggle();
			yield return (object)new WaitForSecondsRealtime(1.8f);
			Note("sor.deployed", rig.Sor.Deployed + " (" + rig.Sor.StateName + "), meshes " + rig.Sor.MeshesDrawn + ", magazine " + rig.Sor.Magazine + " / reserve " + rig.Sor.Reserve);
			Note("sor.left_forearm_bones", rig.Sor.BonesLike("LeftForeArm"));
			Note("sor.left_hand_bones", (rig.Sor.BonesLike("LeftHand").Length > 600) ? rig.Sor.BonesLike("LeftHand").Substring(0, 600) : rig.Sor.BonesLike("LeftHand"));
			Note("sor.left_roll_bones", rig.Sor.BonesLike("Roll") + " || twist: " + rig.Sor.BonesLike("Twist"));
			Note("sor.wrists", rig.Sor.WristInfo);
			Note("sor.idle_hand", "left hand to Cyberpunk's grip marker: " + rig.Sor.BoneGap("LeftHand", "arm_left_ik") + " cm, turned " + rig.Sor.BoneTurn("LeftHand", "arm_left_ik").ToString("0") + " degrees; marker chain: " + rig.Sor.BoneChain("arm_left_ik") + "; forearm to hand turn " + rig.Sor.BoneTurn("LeftForeArm", "LeftHand").ToString("0"));
			yield return Shot("sor_idle");
			Transform cam = ((Component)player.gameplayCamera).transform;
			EnemyType val = ((IEnumerable<EnemyType>)Resources.FindObjectsOfTypeAll<EnemyType>()).FirstOrDefault((Func<EnemyType, bool>)((EnemyType x) => (Object)(object)x != (Object)null && (Object)(object)x.enemyPrefab != (Object)null && (Object)(object)x.enemyPrefab.GetComponent<MouthDogAI>() != (Object)null));
			GameObject[] outsideAINodes = RoundManager.Instance.outsideAINodes;
			Vector3 at = Vector3.zero;
			bool flag = false;
			foreach (GameObject item in from x in outsideAINodes
				where (Object)(object)x != (Object)null
				orderby Vector3.Distance(x.transform.position, cam.position)
				select x)
			{
				if (!(Vector3.Distance(item.transform.position, cam.position) < 12f) && !Physics.Linecast(cam.position, item.transform.position + Vector3.up * 3f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
				{
					at = item.transform.position;
					flag = true;
					break;
				}
			}
			if ((Object)(object)val == (Object)null || !flag)
			{
				Note("FAIL grad", "could not place a forest giant in view");
				yield break;
			}
			RoundManager.Instance.SpawnEnemyGameObject(at, 0f, -1, val);
			yield return (object)new WaitForSecondsRealtime(2f);
			EnemyAI giant = ((IEnumerable<EnemyAI>)RoundManager.Instance.SpawnedEnemies).LastOrDefault((Func<EnemyAI, bool>)((EnemyAI x) => x is MouthDogAI));
			if ((Object)(object)giant == (Object)null)
			{
				Note("FAIL grad", "giant did not spawn");
				yield break;
			}
			AutoTest autoTest = this;
			string[] obj = new string[12]
			{
				"asked for ",
				((Vector3)(ref at)).ToString("0"),
				" (",
				Vector3.Distance(at, cam.position).ToString("0"),
				" m), he is at ",
				null,
				null,
				null,
				null,
				null,
				null,
				null
			};
			Vector3 val2 = ((Component)giant).transform.position;
			obj[5] = ((Vector3)(ref val2)).ToString("0");
			obj[6] = " (";
			obj[7] = Vector3.Distance(((Component)giant).transform.position, cam.position).ToString("0");
			obj[8] = " m), player at ";
			val2 = ((Component)player).transform.position;
			obj[9] = ((Vector3)(ref val2)).ToString("0");
			obj[10] = ", camera forward ";
			val2 = cam.forward;
			obj[11] = ((Vector3)(ref val2)).ToString("0.00");
			autoTest.Note("sor.giant_placed", string.Concat(obj));
			int hp0 = giant.enemyHP;
			int shots = 0;
			int quota0 = TimeOfDay.Instance.quotaFulfilled;
			while (!giant.isEnemyDead && shots < 5)
			{
				giant.agent.speed = 0f;
				EnemyAICollisionDetect componentInChildren = ((Component)giant).GetComponentInChildren<EnemyAICollisionDetect>();
				Collider hitShape = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).GetComponent<Collider>() : null);
				yield return (object)new WaitForEndOfFrame();
				Transform obj2 = cam;
				Vector3 val3;
				Bounds bounds;
				if (!((Object)(object)hitShape != (Object)null))
				{
					val3 = ((Component)giant).transform.position + Vector3.up * 3f;
				}
				else
				{
					bounds = hitShape.bounds;
					val3 = ((Bounds)(ref bounds)).center;
				}
				obj2.rotation = Quaternion.LookRotation(val3 - cam.position);
				int before = giant.enemyHP;
				AutoTest autoTest2 = this;
				string name = "sor.aim_" + (shots + 1);
				string[] obj3 = new string[8] { "camera forward ", null, null, null, null, null, null, null };
				val2 = cam.forward;
				obj3[1] = ((Vector3)(ref val2)).ToString("0.00");
				obj3[2] = ", wanted ";
				Vector3 val4;
				if (!((Object)(object)hitShape != (Object)null))
				{
					val4 = ((Component)giant).transform.position;
				}
				else
				{
					bounds = hitShape.bounds;
					val4 = ((Bounds)(ref bounds)).center;
				}
				val2 = val4 - cam.position;
				val2 = ((Vector3)(ref val2)).normalized;
				obj3[3] = ((Vector3)(ref val2)).ToString("0.00");
				obj3[4] = ", player controlled ";
				obj3[5] = player.isPlayerControlled.ToString();
				obj3[6] = ", in terminal ";
				obj3[7] = player.inTerminalMenu.ToString();
				autoTest2.Note(name, string.Concat(obj3));
				AutoTest autoTest3 = this;
				string name2 = "sor.bullet_path_" + (shots + 1);
				string text = rig.Sor.DescribeRay();
				object obj4;
				if (!((Object)(object)hitShape != (Object)null))
				{
					obj4 = "none";
				}
				else
				{
					string[] obj5 = new string[5]
					{
						((Object)hitShape).name,
						" ",
						null,
						null,
						null
					};
					bounds = hitShape.bounds;
					val2 = ((Bounds)(ref bounds)).size;
					obj5[2] = ((Vector3)(ref val2)).ToString("0.0");
					obj5[3] = " enabled ";
					obj5[4] = hitShape.enabled.ToString();
					obj4 = string.Concat(obj5);
				}
				autoTest3.Note(name2, text + "; hit shape " + (string?)obj4);
				bool fired = rig.Sor.TryFire();
				shots++;
				yield return (object)new WaitForEndOfFrame();
				Note("sor.shot_" + shots, "fired " + fired + ", dog health " + before + " -> " + giant.enemyHP + ", " + Vector3.Distance(cam.position, ((Component)giant).transform.position).ToString("0") + " m away");
				if (shots == 1)
				{
					float rest = 0f;
					float far = 0f;
					float.TryParse(rig.Sor.BoneGap("LeftHand", "WeaponRight"), out rest);
					float markRest = 0f;
					float markFar = 0f;
					float handOff = 0f;
					float heldFor = 0f;
					float heldWorst = 0f;
					float.TryParse(rig.Sor.BoneGap("arm_left_ik", "WeaponRight"), out markRest);
					Note("sor.weapon_bones", rig.Sor.BonesLike("w:"));
					Note("sor.arm", "upper " + rig.Sor.BoneGap("LeftArm", "LeftForeArm") + " cm + fore " + rig.Sor.BoneGap("LeftForeArm", "LeftHand") + " cm; rest: hand in gun space " + rig.Sor.BoneIn("LeftHand", "WeaponRight") + ", marker " + rig.Sor.BoneIn("arm_left_ik", "WeaponRight"));
					string series = "";
					float seriesNext = 0f;
					float seriesStart = Time.unscaledTime;
					for (int still = 0; still < 8; still++)
					{
						for (float t = 0f; t < 0.35f; t += Time.unscaledDeltaTime)
						{
							if (float.TryParse(rig.Sor.BoneGap("LeftHand", "WeaponRight"), out var result))
							{
								far = Mathf.Max(far, Mathf.Abs(result - rest));
							}
							if (float.TryParse(rig.Sor.BoneGap("arm_left_ik", "WeaponRight"), out var result2))
							{
								markFar = Mathf.Max(markFar, Mathf.Abs(result2 - markRest));
							}
							if (float.TryParse(rig.Sor.BoneGap("LeftHand", "arm_left_ik"), out var result3))
							{
								handOff = Mathf.Max(handOff, result3);
							}
							giant.agent.speed = 0f;
							if (rig.Sor.BoltHeld)
							{
								heldFor += Time.unscaledDeltaTime;
								if (float.TryParse(rig.Sor.BoneGap("LeftHandMiddle1", "w:handle"), out var result4))
								{
									heldWorst = Mathf.Max(heldWorst, result4);
								}
							}
							if (Time.unscaledTime >= seriesNext)
							{
								seriesNext = Time.unscaledTime + 0.12f;
								series = series + " | " + (Time.unscaledTime - seriesStart).ToString("0.00") + "s w" + rig.Sor.BoltWeight.ToString("0.0") + " hand " + rig.Sor.BoneIn("LeftHand", "WeaponRight") + " marker " + rig.Sor.BoneIn("arm_left_ik", "WeaponRight") + " held " + rig.Sor.BoltHeld + " clip-gap " + rig.Sor.BoltGap.ToString("0") + " knuckle-handle " + rig.Sor.BoneGap("LeftHandMiddle1", "w:handle") + " handle " + rig.Sor.BoneIn("w:handle", "WeaponRight");
							}
							yield return null;
						}
						if (still < 4)
						{
							yield return Shot("sor_bolt_" + still);
						}
					}
					Note("sor.bolt_series", series);
					Note("sor.bolt_grip", "hand on the bolt handle for " + heldFor.ToString("0.00") + " s of the cycle; knuckles never more than " + heldWorst.ToString("0.0") + " cm from the handle in that time");
					Note("sor.bolt_marker", "Cyberpunk's grip marker moved up to " + markFar.ToString("0.0") + " cm along the gun during the bolt; the hand was up to " + handOff.ToString("0.0") + " cm away from it");
					Note("sor.bolt_hand", "left hand moved up to " + far.ToString("0.0") + " cm from where it rests on the gun while the bolt was worked (0 = it never let go)");
				}
				yield return (object)new WaitForSecondsRealtime(Guns.Sor22.fireInterval + 0.15f);
			}
			yield return (object)new WaitForSecondsRealtime(1f);
			Note("sor.bolt_every_shot", "hand took the bolt handle " + rig.Sor.BoltGrabs + " times and the rack sound played " + rig.Sor.BoltSounds + " times in " + rig.Sor.Cycles + " rackings (the same number wanted)");
			Note("sor.giant", "health " + hp0 + ", dead " + giant.isEnemyDead + " after " + shots + " shots (2 wanted: an eyeless dog), bolt worked " + rig.Sor.Cycles + " times, tracers " + rig.Sor.Tracers + ", " + rig.Sor.FlashInfo + ", bounty +" + (TimeOfDay.Instance.quotaFulfilled - quota0));
			Note("sor.too_soon", "a second shot straight after one: " + ((rig.Sor.TryFire() && rig.Sor.TryFire()) ? "fired (wrong)" : "refused"));
			yield return (object)new WaitForSecondsRealtime(1.6f);
			Note("sor.reload_started", rig.Sor.TryReload() + " (" + rig.Sor.StateName + ")");
			yield return (object)new WaitForSecondsRealtime(1.5f);
			yield return Shot("sor_reload");
			yield return (object)new WaitForSecondsRealtime(3.5f);
			AutoTest autoTest4 = this;
			string[] obj6 = new string[9]
			{
				"magazine ",
				rig.Sor.Magazine.ToString(),
				" (sheet ",
				null,
				null,
				null,
				null,
				null,
				null
			};
			i = Guns.Sor22.magSize;
			obj6[3] = i.ToString();
			obj6[4] = "), reserve ";
			obj6[5] = rig.Sor.Reserve.ToString();
			obj6[6] = " (";
			obj6[7] = rig.Sor.StateName;
			obj6[8] = ")";
			autoTest4.Note("sor.after_reload", string.Concat(obj6));
			all = Shop.All;
			for (i = 0; i < all.Length; i++)
			{
				Cyberware.Revoke(all[i].grants);
			}
		}

		private IEnumerator KatanaOnly(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			Terminal terminal = Object.FindObjectOfType<Terminal>();
			if (player.inTerminalMenu && (Object)(object)terminal != (Object)null)
			{
				terminal.QuitTerminal(true);
			}
			yield return (object)new WaitForSecondsRealtime(2f);
			ShopRow[] all = Shop.All;
			int i;
			for (i = 0; i < all.Length; i++)
			{
				Cyberware.Revoke(all[i].grants);
			}
			terminal.groupCredits = 1000;
			Note("errata.buy", TerminalShop.Handle(terminal, "errata").displayText.Trim().Replace("\r", "").Replace("\n", " | "));
			AutoTest autoTest = this;
			string[] obj = new string[8]
			{
				Carry.Used.ToString(),
				" / ",
				Carry.Max.ToString(),
				", damage ",
				null,
				null,
				null,
				null
			};
			i = Weapons.Errata.damage;
			obj[4] = i.ToString();
			obj[5] = " (blades ";
			i = Weapons.MantisBlades.damage;
			obj[6] = i.ToString();
			obj[7] = ")";
			autoTest.Note("errata.holsters", string.Concat(obj));
			Note("errata.view_model", rig.Katana.HasViewModel);
			rig.Katana.Toggle();
			yield return (object)new WaitForSecondsRealtime(1.8f);
			Note("errata.glow", rig.Katana.GlowReport);
			Note("errata.deployed", rig.Katana.Deployed + " (" + rig.Katana.StateName + "), meshes " + rig.Katana.MeshesDrawn + ", " + rig.Katana.GlowInfo);
			yield return Shot("errata_idle");
			StartOfRound.Instance.shipRoomLights.SetShipLightsBoolean(false);
			yield return (object)new WaitForSecondsRealtime(1f);
			yield return Shot("errata_dark");
			StartOfRound.Instance.shipRoomLights.SetShipLightsBoolean(true);
			for (int j = 0; j < 3; j++)
			{
				Note("errata.swing_" + (j + 1), rig.Katana.TrySwing() + " (" + rig.Katana.StateName + ")");
				yield return (object)new WaitForSecondsRealtime(0.15f);
				yield return Shot("errata_swing_" + (j + 1));
				yield return (object)new WaitForSecondsRealtime(0.9f);
			}
			rig.Katana.Retract();
			yield return (object)new WaitForSecondsRealtime(1f);
			Note("errata.sheathed", "away " + !rig.Katana.Visible);
			all = Shop.All;
			for (i = 0; i < all.Length; i++)
			{
				Cyberware.Revoke(all[i].grants);
			}
		}

		private IEnumerator KnifeOnly(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			Terminal terminal = Object.FindObjectOfType<Terminal>();
			if (player.inTerminalMenu && (Object)(object)terminal != (Object)null)
			{
				terminal.QuitTerminal(true);
			}
			yield return (object)new WaitForSecondsRealtime(2f);
			ShopRow[] all = Shop.All;
			int i;
			for (i = 0; i < all.Length; i++)
			{
				Cyberware.Revoke(all[i].grants);
			}
			terminal.groupCredits = 1000;
			int used = Carry.Used;
			Note("knife.buy", TerminalShop.Handle(terminal, "knife").displayText.Trim().Replace("\r", "").Replace("\n", " | ") + " || credits " + terminal.groupCredits + " (965 wanted)");
			AutoTest autoTest = this;
			string[] obj = new string[7]
			{
				Carry.Used.ToString(),
				" / ",
				Carry.Max.ToString(),
				" (was ",
				used.ToString(),
				", unchanged wanted), damage ",
				null
			};
			i = Weapons.CombatKnife.damage;
			obj[6] = i.ToString();
			autoTest.Note("knife.holsters", string.Concat(obj));
			Note("knife.view_model", rig.Knife.HasViewModel);
			rig.Knife.Toggle();
			yield return (object)new WaitForSecondsRealtime(1.8f);
			Note("knife.deployed", rig.Knife.Deployed + " (" + rig.Knife.StateName + "), meshes " + rig.Knife.MeshesDrawn);
			yield return Shot("knife_idle");
			for (int j = 0; j < 3; j++)
			{
				Note("knife.swing_" + (j + 1), rig.Knife.TrySwing() + " (" + rig.Knife.StateName + ")");
				yield return (object)new WaitForSecondsRealtime(0.15f);
				yield return Shot("knife_swing_" + (j + 1));
				yield return (object)new WaitForSecondsRealtime(0.9f);
			}
			rig.Knife.Retract();
			yield return (object)new WaitForSecondsRealtime(1f);
			Note("knife.sheathed", "away " + !rig.Knife.Visible);
			all = Shop.All;
			for (i = 0; i < all.Length; i++)
			{
				Cyberware.Revoke(all[i].grants);
			}
		}

		private IEnumerator ShowOnly(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			Terminal val = Object.FindObjectOfType<Terminal>();
			if (player.inTerminalMenu && (Object)(object)val != (Object)null)
			{
				val.QuitTerminal(true);
			}
			yield return (object)new WaitForSecondsRealtime(2f);
			List<string> had = (from r in Shop.All
				where r.gives == "item" && Cyberware.Has(r.grants)
				select r.grants).ToList();
			Cyberware.Grant(Guns.Sor22.id);
			Cyberware.Grant(Weapons.Errata.id);
			Cyberware.Grant(Upgrades.HolsterSystem.id);
			StartOfRound.Instance.allowLocalPlayerDeath = false;
			Action<string, string> say = delegate(string title, string body)
			{
				HUDManager.Instance.DisplayTip(title, body, false, false, "LC_Tip1");
			};
			say("SOR-22", "Drawing the rifle, then holding it still.");
			rig.Sor.Toggle();
			yield return (object)new WaitForSecondsRealtime(5f);
			yield return Shot("show_sor_hold");
			for (int i = 0; i < 3; i++)
			{
				say("SOR-22", "Shot " + (i + 1) + " of 3, then the recoil.");
				yield return (object)new WaitForSecondsRealtime(1f);
				rig.Sor.TryFire();
				for (int still = 0; still < 6; still++)
				{
					yield return (object)new WaitForSecondsRealtime(0.45f);
					yield return Shot("show_sor_bolt_" + (i + 1) + "_" + still);
				}
				yield return (object)new WaitForSecondsRealtime(1.5f);
			}
			say("SOR-22", "Walking and sprinting with it.");
			yield return Hold(2f, (Key)15);
			yield return Hold(2f, (Key)18);
			yield return Hold(2.5f, (Key)15, (Key)51);
			yield return Hold(2.5f, (Key)18, (Key)51);
			say("SOR-22", "Reloading.");
			yield return (object)new WaitForSecondsRealtime(1f);
			rig.Sor.TryReload();
			yield return (object)new WaitForSecondsRealtime(6.5f);
			say("SOR-22", "Putting it away.");
			rig.Sor.Retract();
			yield return (object)new WaitForSecondsRealtime(2.5f);
			say("ERRATA", "Drawing the katana, then holding it still.");
			rig.Katana.Toggle();
			yield return (object)new WaitForSecondsRealtime(5f);
			yield return Shot("show_errata_hold");
			say("ERRATA", "Three cuts in a row.");
			yield return (object)new WaitForSecondsRealtime(1f);
			for (int i = 0; i < 3; i++)
			{
				rig.Katana.TrySwing();
				yield return (object)new WaitForSecondsRealtime(0.25f);
				yield return Shot("show_errata_cut_" + (i + 1));
				yield return (object)new WaitForSecondsRealtime(0.35f);
			}
			yield return (object)new WaitForSecondsRealtime(2f);
			say("ERRATA", "Walking and sprinting with it.");
			yield return Hold(2f, (Key)15);
			yield return Hold(2.5f, (Key)18, (Key)51);
			say("ERRATA", "Lights off, to see the glow.");
			StartOfRound.Instance.shipRoomLights.SetShipLightsBoolean(false);
			yield return (object)new WaitForSecondsRealtime(4f);
			yield return Shot("show_errata_dark");
			for (int i = 0; i < 2; i++)
			{
				rig.Katana.TrySwing();
				yield return (object)new WaitForSecondsRealtime(1.2f);
			}
			StartOfRound.Instance.shipRoomLights.SetShipLightsBoolean(true);
			say("ERRATA", "Putting it away. End of the walk-through.");
			rig.Katana.Retract();
			yield return (object)new WaitForSecondsRealtime(3f);
			Note("show.done", "grad bolt worked " + rig.Sor.Cycles + " times, wrists " + rig.Sor.WristInfo + ", errata glow " + rig.Katana.GlowReport);
			ShopRow[] all = Shop.All;
			for (int num = 0; num < all.Length; num++)
			{
				ShopRow shopRow = all[num];
				if (shopRow.gives == "item" && !had.Contains(shopRow.grants))
				{
					Cyberware.Revoke(shopRow.grants);
				}
			}
		}

		private unsafe IEnumerator ScrapOnly(Rig rig, PlayerControllerB player)
		{
			Rig.IgnoreInput = true;
			Terminal terminal = Object.FindObjectOfType<Terminal>();
			if (player.inTerminalMenu && (Object)(object)terminal != (Object)null)
			{
				terminal.QuitTerminal(true);
			}
			yield return (object)new WaitForSecondsRealtime(2f);
			ShopRow[] all = Shop.All;
			int i;
			for (i = 0; i < all.Length; i++)
			{
				Cyberware.Revoke(all[i].grants);
			}
			Func<string, string> type = delegate(string s)
			{
				TerminalNode val4 = TerminalShop.Handle(terminal, s);
				return (!((Object)(object)val4 == (Object)null)) ? val4.displayText.Trim().Replace("\r", "").Replace("\n", " | ") : "(not ours)";
			};
			int c0 = terminal.groupCredits;
			Note("dev.panel", type("dev"));
			Note("dev.money", type("dev money"));
			yield return (object)new WaitForSecondsRealtime(0.5f);
			AutoTest autoTest = this;
			string[] obj = new string[6]
			{
				c0.ToString(),
				" -> ",
				terminal.groupCredits.ToString(),
				" (+",
				null,
				null
			};
			i = Economy.DevGrant.amount;
			obj[4] = i.ToString();
			obj[5] = " wanted)";
			autoTest.Note("dev.credits", string.Concat(obj));
			Note("scrap.buy", type("zetatech"));
			Note("pump.buy", type("bloodpump"));
			Note("pump.load", "cyberware load " + Psychosis.Load + " (3 + 8)");
			Note("amino.before_buying", rig.TryStim(rig.Amino) ? "used (wrong)" : "does nothing");
			Note("amino.buy", type("amino"));
			Psychosis.Value = 100f;
			Note("amino.at_full_sanity", rig.TryStim(rig.Amino) ? "used (wrong)" : ("refused, dose kept: " + rig.Amino.Charges));
			Psychosis.Value = 35f;
			bool flag = rig.TryStim(rig.Amino);
			AutoTest autoTest2 = this;
			string[] obj2 = new string[13]
			{
				flag.ToString(),
				", sanity 35 -> ",
				Psychosis.Value.ToString("0"),
				", doses left ",
				rig.Amino.Charges.ToString(),
				", recharge ",
				rig.Amino.RechargeLeft.ToString("0"),
				" s (sheet ",
				null,
				null,
				null,
				null,
				null
			};
			float rechargeTime = Heals.Amino.rechargeTime;
			obj2[8] = rechargeTime.ToString();
			obj2[9] = "), bare arms showing ";
			obj2[10] = rig.Hands.Visible.ToString();
			obj2[11] = ", injector tint ";
			Color propTint = rig.Hands.PropTint;
			obj2[12] = ((object)(*(Color*)(&propTint))/*cast due to .constrained prefix*/).ToString();
			autoTest2.Note("amino.use", string.Concat(obj2));
			yield return (object)new WaitForSecondsRealtime(0.45f);
			yield return Shot("amino_injecting");
			AutoTest autoTest3 = this;
			string[] obj3 = new string[8]
			{
				"screen pulse ",
				rig.Amino.FxBlend.ToString("0.00"),
				" in ",
				null,
				null,
				null,
				null,
				null
			};
			rechargeTime = Heals.Amino.fxR;
			obj3[3] = rechargeTime.ToString();
			obj3[4] = ", ";
			rechargeTime = Heals.Amino.fxG;
			obj3[5] = rechargeTime.ToString();
			obj3[6] = ", ";
			rechargeTime = Heals.Amino.fxB;
			obj3[7] = rechargeTime.ToString();
			autoTest3.Note("amino.glow", string.Concat(obj3));
			Psychosis.Value = 35f;
			Note("amino.second_at_once", rig.TryStim(rig.Amino) ? "used (wrong)" : "refused while recharging");
			Psychosis.Value = 100f;
			yield return (object)new WaitForSecondsRealtime(2f);
			Cyberware.Revoke(Heals.Amino.id);
			AutoTest autoTest4 = this;
			string[] obj4 = new string[5]
			{
				string.Join(", ", Shop.All.Select((ShopRow r) => r.word + " " + r.price).ToArray()),
				"; launcher recharge ",
				null,
				null,
				null
			};
			rechargeTime = Launchers.ProjectileLauncher.cooldown;
			obj4[2] = rechargeTime.ToString();
			obj4[3] = " s; mantis damage ";
			i = Weapons.MantisBlades.damage;
			obj4[4] = i.ToString();
			autoTest4.Note("prices", string.Concat(obj4));
			player.health = 40;
			rig.Regenerated = 0;
			yield return (object)new WaitForSeconds(5f);
			Note("pump.5s", "health 40 -> " + player.health + " of the game's 100 (+10 wanted at 2% a second); shown on the HUD as " + Mathf.RoundToInt((float)(player.health * Cyberware.MaxHealth) / 100f) + " / " + Cyberware.MaxHealth);
			Cyberware.Grant(Upgrades.SubdermalArmor.id);
			player.health = 40;
			yield return (object)new WaitForSeconds(5f);
			Note("pump.5s_with_armor", "health 40 -> " + player.health + " of the game's 100; shown as " + Mathf.RoundToInt((float)(player.health * Cyberware.MaxHealth) / 100f) + " / " + Cyberware.MaxHealth + " (the same 2% a second of the larger maximum)");
			player.health = 100;
			yield return (object)new WaitForSeconds(2f);
			Note("pump.full", "stays at " + player.health + " when full");
			Cyberware.Revoke(Upgrades.SubdermalArmor.id);
			Object.FindObjectOfType<StartMatchLever>().StartGame();
			float waited = 0f;
			while (!StartOfRound.Instance.shipHasLanded)
			{
				yield return (object)new WaitForSecondsRealtime(1f);
				waited = (rechargeTime = waited + 1f);
				if (rechargeTime > 90f)
				{
					Note("FAIL landing", "never landed");
					yield break;
				}
			}
			yield return (object)new WaitForSecondsRealtime(4f);
			StartOfRound.Instance.allowLocalPlayerDeath = false;
			List<GrabbableObject> pieces = (from x in Object.FindObjectsOfType<GrabbableObject>()
				where (Object)(object)x.itemProperties != (Object)null && x.itemProperties.isScrap && !x.isInShipRoom && x.scrapValue > 0
				select x).ToList();
			float num = ((pieces.Count > 0) ? pieces.Average((GrabbableObject x) => (float)x.scrapValue / Mathf.Max(1f, (float)(x.itemProperties.minValue + x.itemProperties.maxValue) * 0.5f * RoundManager.Instance.scrapValueMultiplier)) : 0f);
			int num2 = pieces.Count((GrabbableObject x) => (float)x.scrapValue > (float)x.itemProperties.maxValue * RoundManager.Instance.scrapValueMultiplier);
			AutoTest autoTest5 = this;
			string[] obj5 = new string[13]
			{
				Salvage.Raised.ToString(),
				" pieces raised, ",
				Salvage.Kept.ToString(),