Decompiled source of PeakTeamRace v1.0.2

_​​PeakTeamRace.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DG.Tweening;
using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("\u200b\u200bPeakTeamRace")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("\u200b\u200bPeakTeamRace")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("bffd4bcb-a83c-4d1f-a0f8-44899c7289b0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace _PeakTeamRace;

[BepInPlugin("com.xiaohai.peakteamrace", "\u200b\u200bPeakTeamRace", "1.0.2")]
public class Plugin : BaseUnityPlugin
{
	public const string PluginGUID = "com.xiaohai.peakteamrace";

	public const string PluginName = "\u200b\u200bPeakTeamRace";

	public const string PluginVersion = "1.0.2";

	public ConfigEntry<float> rewardMultiplier;

	public ConfigEntry<float> penaltyMax;

	public ConfigEntry<bool> useTeamColor;

	public ConfigEntry<bool> useChain;

	public static Plugin Instance { get; private set; }

	public static ManualLogSource Log { get; private set; }

	public void Awake()
	{
		//IL_002a: 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)
		//IL_00cc: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin \u200b\u200bPeakTeamRace v 1.0.2is loaded!");
		new Harmony("com.xiaohai.peakteamrace").PatchAll();
		rewardMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "RewardMultiplier", 1f, "Multiplier for the extra stamina reward after winning(0-1).获胜方获得额外体力奖励的倍率(0 到 1)");
		penaltyMax = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "PenaltyFloor", 0.65f, "Maximum penalty for losing (0 - 0.9),失败惩罚异常状态最大值(0 - 0.9)");
		useTeamColor = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "useTeamColor/是否使用队伍颜色", false, "true =Sets the team's color for all players.  如果填写true,则将所有玩家的颜色设置成队伍颜色..");
		useChain = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "useChain/是否使用链条", true, "true =Players on the same team are connected by chains.  如果填写true,则同队玩家之间会被链条连接.");
		GameObject val = new GameObject("TeamChainSystem");
		TeamChainSystem teamChainSystem = val.AddComponent<TeamChainSystem>();
		Object.DontDestroyOnLoad((Object)(object)val);
	}
}
public class TeamRaceManager : Singleton<TeamRaceManager>
{
	[CompilerGenerated]
	private sealed class <>c__DisplayClass32_0
	{
		public Random rng;

		internal int <RandomlyAssignTeamsCoroutine>b__1(int x)
		{
			return rng.Next();
		}
	}

	[CompilerGenerated]
	private sealed class <RandomlyAssignTeamsCoroutine>d__32 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public TeamRaceManager <>4__this;

		private List<Character> <allPlayers>5__1;

		private TeamChainSystem <system>5__2;

		private object[] <serializedData>5__3;

		private List<Character>.Enumerator <>s__4;

		private Character <player>5__5;

		private <>c__DisplayClass32_0 <>8__6;

		private List<int> <indices>5__7;

		private int <teamSplitIndex>5__8;

		private int <i>5__9;

		private int <playerId>5__10;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <RandomlyAssignTeamsCoroutine>d__32(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<allPlayers>5__1 = null;
			<system>5__2 = null;
			<serializedData>5__3 = null;
			<>s__4 = default(List<Character>.Enumerator);
			<player>5__5 = null;
			<>8__6 = null;
			<indices>5__7 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				if (!PhotonNetwork.IsMasterClient)
				{
					return false;
				}
				<>2__current = <>4__this.WaitForResultProcessing();
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<>4__this.PlayerTeams.Clear();
				<allPlayers>5__1 = Character.AllCharacters.Where((Character p) => (Object)(object)p != (Object)null && (Object)(object)((MonoBehaviourPun)p).photonView != (Object)null).ToList();
				if (<allPlayers>5__1.Count < 2)
				{
					<>s__4 = <allPlayers>5__1.GetEnumerator();
					try
					{
						while (<>s__4.MoveNext())
						{
							<player>5__5 = <>s__4.Current;
							<>4__this.PlayerTeams[((MonoBehaviourPun)<player>5__5).photonView.ViewID] = 0;
							<player>5__5 = null;
						}
					}
					finally
					{
						((IDisposable)<>s__4).Dispose();
					}
					<>s__4 = default(List<Character>.Enumerator);
				}
				else
				{
					<>8__6 = new <>c__DisplayClass32_0();
					<indices>5__7 = Enumerable.Range(0, <allPlayers>5__1.Count).ToList();
					<>8__6.rng = new Random();
					<indices>5__7 = <indices>5__7.OrderBy((int x) => <>8__6.rng.Next()).ToList();
					<teamSplitIndex>5__8 = <allPlayers>5__1.Count / 2;
					<i>5__9 = 0;
					while (<i>5__9 < <indices>5__7.Count)
					{
						<playerId>5__10 = ((MonoBehaviourPun)<allPlayers>5__1[<indices>5__7[<i>5__9]]).photonView.ViewID;
						<>4__this.PlayerTeams[<playerId>5__10] = ((<i>5__9 >= <teamSplitIndex>5__8) ? 1 : 0);
						<i>5__9++;
					}
					<>8__6 = null;
					<indices>5__7 = null;
				}
				<system>5__2 = TeamChainSystem.Instance;
				if ((Object)(object)<system>5__2 != (Object)null)
				{
					<system>5__2.ClearAllChains();
				}
				if (Plugin.Instance.useChain.Value)
				{
					<>4__this.CreateTeamChains();
				}
				<serializedData>5__3 = <>4__this.SerializeTeamsForRPC();
				<>4__this._photonView.RPC("RPC_AssignTeams", (RpcTarget)0, <serializedData>5__3);
				<>4__this.DebugLogTeamAssignments(<allPlayers>5__1);
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	[CompilerGenerated]
	private sealed class <WaitForResultProcessing>d__33 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public TeamRaceManager <>4__this;

		private float <timeout>5__1;

		private float <startTime>5__2;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <WaitForResultProcessing>d__33(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<timeout>5__1 = 10f;
				<startTime>5__2 = Time.time;
				break;
			case 1:
				<>1__state = -1;
				break;
			}
			if (<>4__this.IsProcessingResults)
			{
				if (Time.time - <startTime>5__2 > <timeout>5__1)
				{
					return false;
				}
				<>2__current = (object)new WaitForSeconds(0.5f);
				<>1__state = 1;
				return true;
			}
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	public readonly Dictionary<int, float> PlayerFinishTimes = new Dictionary<int, float>();

	public readonly Dictionary<int, int> PlayerScores = new Dictionary<int, int>();

	public readonly int[] TeamScores = new int[2];

	private PhotonView _photonView;

	private HashSet<int> _activePlayersAtStart;

	public readonly Color[] TeamColors = (Color[])(object)new Color[2]
	{
		new Color(1f, 0.3f, 0.3f),
		new Color(0.3f, 0.3f, 1f)
	};

	private bool reachedCampfire = false;

	public STATUSTYPE shouldStatus;

	public float shouldStatusValue = -1f;

	public Dictionary<int, int> PlayerTeams { get; private set; } = new Dictionary<int, int>();


	public float FirstPlaceTime { get; private set; } = float.MaxValue;


	public int LocalPlayerTeamId { get; private set; } = -1;


	public bool IsProcessingResults { get; private set; }

	private TeamRaceTimer timer => TeamRaceTimer.Instance;

	public bool isChinese => (int)LocalizedText.CURRENT_LANGUAGE == 9;

	protected override void Awake()
	{
		base.Awake();
		_photonView = ((Component)this).GetComponentInChildren<PhotonView>();
		if ((Object)(object)_photonView == (Object)null)
		{
			_photonView = ((Component)this).gameObject.AddComponent<PhotonView>();
			PhotonNetwork.AllocateViewID(_photonView);
		}
		PlayerTeams = new Dictionary<int, int>();
	}

	private void Update()
	{
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Character.localCharacter == (Object)null || (Object)(object)((MonoBehaviourPun)Character.localCharacter).photonView == (Object)null)
		{
			return;
		}
		if ((Object)(object)Patch.nextCampfire != (Object)null)
		{
			float num = Vector3.Distance(Character.localCharacter.Center, ((Component)Patch.nextCampfire).transform.position);
			if (num < 3f && !reachedCampfire)
			{
				PlayerReachedCampfire();
			}
			return;
		}
		_ = Patch.nextPoint;
		if (true)
		{
			float num2 = Vector3.Distance(Character.localCharacter.Center, Patch.nextPoint);
			if (num2 <= 1f && !reachedCampfire)
			{
				PlayerReachedCampfire();
			}
		}
	}

	public void StartTeamAssignment()
	{
		((MonoBehaviour)this).StartCoroutine(RandomlyAssignTeamsCoroutine());
	}

	[IteratorStateMachine(typeof(<RandomlyAssignTeamsCoroutine>d__32))]
	private IEnumerator RandomlyAssignTeamsCoroutine()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <RandomlyAssignTeamsCoroutine>d__32(0)
		{
			<>4__this = this
		};
	}

	[IteratorStateMachine(typeof(<WaitForResultProcessing>d__33))]
	private IEnumerator WaitForResultProcessing()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <WaitForResultProcessing>d__33(0)
		{
			<>4__this = this
		};
	}

	private object[] SerializeTeamsForRPC()
	{
		return new object[3]
		{
			PlayerTeams.Count,
			PlayerTeams.Keys.ToArray(),
			PlayerTeams.Values.ToArray()
		};
	}

	[PunRPC]
	private void RPC_AssignTeams(object[] data)
	{
		PlayerTeams.Clear();
		PlayerFinishTimes.Clear();
		PlayerScores.Clear();
		Array.Clear(TeamScores, 0, TeamScores.Length);
		FirstPlaceTime = float.MaxValue;
		reachedCampfire = false;
		_activePlayersAtStart = new HashSet<int>(PlayerTeams.Keys);
		int num = (int)data[0];
		int[] array = (int[])data[1];
		int[] array2 = (int[])data[2];
		for (int i = 0; i < num; i++)
		{
			PlayerTeams[array[i]] = array2[i];
		}
		UpdateLocalPlayerTeam();
	}

	public void UpdateLocalPlayerTeam()
	{
		if (!((Object)(object)Character.localCharacter != (Object)null) || !((Object)(object)((MonoBehaviourPun)Character.localCharacter).photonView != (Object)null))
		{
			return;
		}
		int viewID = ((MonoBehaviourPun)Character.localCharacter).photonView.ViewID;
		if (PlayerTeams.TryGetValue(viewID, out var value))
		{
			LocalPlayerTeamId = value;
			Plugin.Log.LogInfo((object)$"你的队伍ID是: Team{LocalPlayerTeamId} (红队0/蓝队1)");
			string text = (isChinese ? ("你的队伍是: " + ((value == 0) ? "<color=red>红队</color>" : "<color=blue>蓝队</color>")) : ("Your team is: " + ((value == 0) ? "<color=red>Red Team</color>" : "<color=blue>Blue Team</color>")));
			TeamRaceTimer.SetMessage("<size=40>" + text + "</size>", 15f);
			ResultUI.ShowResultUI("<size=45>" + text + "</size>", 15f);
			if (!timer.isRunning)
			{
				timer.StartTimer();
			}
			if (Plugin.Instance.useTeamColor.Value)
			{
				SetTeamColor(value);
			}
		}
		else
		{
			Plugin.Log.LogWarning((object)"本地玩家未分配到队伍!");
		}
	}

	private void SetTeamColor(int teamID)
	{
		//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)
		Singleton<Customization>.Instance.skins[1].color = TeamColors[teamID];
		CharacterCustomization.SetCharacterSkinColor(1);
	}

	public int GetPlayerTeam(int playerViewId)
	{
		int value;
		return PlayerTeams.TryGetValue(playerViewId, out value) ? value : (-1);
	}

	public List<int> GetTeammates(int playerViewId)
	{
		if (!PlayerTeams.TryGetValue(playerViewId, out var myTeamId))
		{
			return new List<int>();
		}
		return (from pair in PlayerTeams
			where pair.Value == myTeamId
			select pair.Key).ToList();
	}

	private void PlayerReachedCampfire()
	{
		reachedCampfire = true;
		float num = timer.StopTimer();
		_photonView.RPC("RPC_SyncPlayerReachedCampfire", (RpcTarget)2, new object[2]
		{
			((MonoBehaviourPun)Character.localCharacter).photonView.ViewID,
			num
		});
		string msg = (isChinese ? ("<size=30><color=green>你到达了篝火! 完成时间: " + timer.FormatTime(num) + "</size></color>") : ("<size=30><color=green>You reached the campfire! Finish time: " + timer.FormatTime(num) + "</size></color>"));
		TeamRaceTimer.SetMessage(msg, 5f);
	}

	[PunRPC]
	private void RPC_SyncPlayerReachedCampfire(int playerViewId, float finishTime)
	{
		if (PhotonNetwork.IsMasterClient)
		{
			IsProcessingResults = true;
			HandleResult(GetCharacterByViewId(playerViewId), finishTime);
		}
	}

	[PunRPC]
	private void RPC_SyncResult(object[] data)
	{
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0336: Unknown result type (might be due to invalid IL or missing references)
		//IL_031c: Unknown result type (might be due to invalid IL or missing references)
		IsProcessingResults = true;
		FirstPlaceTime = (float)data[0];
		TeamScores[0] = (int)data[1];
		TeamScores[1] = (int)data[2];
		int num = (int)data[3];
		int[] array = (int[])data[4];
		float[] array2 = (float[])data[5];
		PlayerFinishTimes.Clear();
		for (int i = 0; i < num; i++)
		{
			PlayerFinishTimes[array[i]] = array2[i];
		}
		int num2 = (int)data[6];
		int[] array3 = (int[])data[7];
		int[] array4 = (int[])data[8];
		PlayerScores.Clear();
		for (int j = 0; j < num2; j++)
		{
			PlayerScores[array3[j]] = array4[j];
		}
		bool flag = false;
		string text = "";
		if ((TeamScores[0] > TeamScores[1] && LocalPlayerTeamId == 0) || (TeamScores[0] < TeamScores[1] && LocalPlayerTeamId == 1))
		{
			flag = true;
		}
		else if (TeamScores[0] == TeamScores[1])
		{
			flag = true;
		}
		int value;
		int num3 = (PlayerScores.TryGetValue(((MonoBehaviourPun)Character.localCharacter).photonView.ViewID, out value) ? value : 0);
		if (flag)
		{
			float num4 = num3 / 100;
			if (Character.localCharacter.data.dead)
			{
				shouldStatusValue = num4;
				shouldStatus = (STATUSTYPE)7;
			}
			else
			{
				Character.localCharacter.AddExtraStamina(num4 * Plugin.Instance.rewardMultiplier.Value);
			}
			text = (isChinese ? $"<size=35><color=green>你赢了! 获得额外耐力: {num4 * 100f:F2}%</color></size>" : $"<size=35><color=green>You win! Add extra stamina: {num4 * 100f:F2}%</color></size>");
		}
		else
		{
			List<STATUSTYPE> list = new List<STATUSTYPE>
			{
				(STATUSTYPE)8,
				(STATUSTYPE)2,
				(STATUSTYPE)6,
				(STATUSTYPE)3
			};
			int index = Random.Range(0, list.Count);
			float num5 = 1f - (float)(num3 / 100);
			num5 = Mathf.Clamp(num5, 0f, Plugin.Instance.penaltyMax.Value);
			if (Character.localCharacter.refs.afflictions.statusSum + num5 >= 1f)
			{
				num5 = 0.9f - Character.localCharacter.refs.afflictions.statusSum;
			}
			if (Character.localCharacter.data.dead)
			{
				shouldStatus = list[index];
				shouldStatusValue = num5;
			}
			else
			{
				Character.localCharacter.refs.afflictions.AddStatus(list[index], num5, false);
			}
			text = (isChinese ? $"<size=35><color=red>你输了! 获得负面状态: {list[index]}</color></size>" : $"<size=35><color=red>You lose! Add Affliction: {list[index]}</color></size>");
		}
		Plugin.Log.LogInfo((object)$"已同步比赛结果: 第一名时间={FirstPlaceTime:F2}s, 红队={TeamScores[0]}, 蓝队={TeamScores[1]}");
		string result = GenerateResultText(text);
		ResultUI.ShowResultUI(result, 15f, useEffects: false);
		IsProcessingResults = false;
	}

	public void HandleResult(Character player, float finishTime)
	{
		if (PhotonNetwork.IsMasterClient && !((Object)(object)player == (Object)null))
		{
			int viewID = ((MonoBehaviourPun)player).photonView.ViewID;
			PlayerFinishTimes[viewID] = finishTime;
			if (finishTime < FirstPlaceTime)
			{
				FirstPlaceTime = finishTime;
			}
			int num = CalculatePlayerScore(viewID, finishTime);
			PlayerScores[viewID] = num;
			if (PlayerTeams.TryGetValue(viewID, out var value))
			{
				TeamScores[value] += num;
			}
			Plugin.Log.LogInfo((object)$"玩家{player.characterName}完成! 时间: {timer.FormatTime(finishTime)}, 积分: {num}");
			if (CheckAllPlayersFinished())
			{
				object[] array = SerializeResultsForRPC();
				_photonView.RPC("RPC_SyncResult", (RpcTarget)0, array);
			}
		}
	}

	private bool CheckAllPlayersFinished()
	{
		HashSet<int> second = PhotonNetwork.CurrentRoom.Players.Values.Select((Player p) => p.ActorNumber).ToHashSet();
		IEnumerable<int> source = _activePlayersAtStart.Intersect(second);
		return source.All((int playerId) => PlayerFinishTimes.ContainsKey(playerId));
	}

	private int CalculatePlayerScore(int playerViewId, float finishTime)
	{
		List<float> list = PlayerFinishTimes.Values.ToList();
		if (list.Count == 1)
		{
			return 100;
		}
		int num = 1;
		foreach (float item in list)
		{
			if (item < finishTime)
			{
				num++;
			}
		}
		int count = list.Count;
		int num2 = 0;
		int num3 = 100;
		int num4 = num3 - (num - 1) * (num3 - num2) / (count - 1);
		return Mathf.Clamp(num4, num2, num3);
	}

	private object[] SerializeResultsForRPC()
	{
		int[] array = PlayerFinishTimes.Keys.ToArray();
		float[] array2 = PlayerFinishTimes.Values.ToArray();
		int[] array3 = PlayerScores.Keys.ToArray();
		int[] array4 = PlayerScores.Values.ToArray();
		return new object[9]
		{
			FirstPlaceTime,
			TeamScores[0],
			TeamScores[1],
			array.Length,
			array,
			array2,
			array3.Length,
			array3,
			array4
		};
	}

	private Character GetCharacterByViewId(int viewId)
	{
		foreach (Character allCharacter in Character.AllCharacters)
		{
			if ((Object)(object)allCharacter != (Object)null && (Object)(object)((MonoBehaviourPun)allCharacter).photonView != (Object)null && ((MonoBehaviourPun)allCharacter).photonView.ViewID == viewId)
			{
				return allCharacter;
			}
		}
		return null;
	}

	private string GenerateResultText(string extraText)
	{
		StringBuilder stringBuilder = new StringBuilder();
		string text = ((TeamScores[1] > TeamScores[0]) ? "<size=30>win</size>" : "");
		string text2 = ((TeamScores[1] < TeamScores[0]) ? "<size=30>win</size>" : "");
		string value = ((!isChinese) ? $"<size=60><color=blue>Team Blue</color>: {TeamScores[1]}</size>{text}   <size=60><color=red>Team Red</color>: {TeamScores[0]}</size>{text2}" : $"<size=60><color=blue>蓝队</color>: {TeamScores[1]}分</size>{text}     <size=60><color=red>红队</color>: {TeamScores[0]}分</size>{text2}");
		stringBuilder.AppendLine(value);
		stringBuilder.AppendLine();
		stringBuilder.AppendLine("<size=40>Player            Time              Score</size>");
		stringBuilder.AppendLine();
		int value3;
		var list = (from p in PlayerFinishTimes
			orderby p.Value
			select new
			{
				ViewID = p.Key,
				Time = p.Value,
				Score = (PlayerScores.TryGetValue(p.Key, out value3) ? value3 : 0)
			}).ToList();
		for (int i = 0; i < list.Count; i++)
		{
			var anon = list[i];
			Character characterByViewId = GetCharacterByViewId(anon.ViewID);
			string text3 = (((Object)(object)characterByViewId != (Object)null) ? characterByViewId.characterName : "Unknown");
			int value2;
			string text4 = ((!PlayerTeams.TryGetValue(anon.ViewID, out value2)) ? "white" : ((value2 == 0) ? "red" : "blue"));
			string text5 = TeamRaceTimer.Instance.FormatTime(anon.Time);
			stringBuilder.Append($"<size=32>{i + 1}.");
			stringBuilder.Append("<color=" + text4 + ">" + text3 + "</color></size>");
			int num = 15 - text3.Length;
			if (num > 0)
			{
				stringBuilder.Append(new string(' ', num));
			}
			int num2 = 15 - text5.Length;
			if (num2 > 0)
			{
				stringBuilder.Append(new string(' ', num2));
			}
			stringBuilder.Append(text5);
			int num3 = 17 - anon.Score.ToString().Length;
			if (num3 > 0)
			{
				stringBuilder.Append(new string(' ', num3));
			}
			stringBuilder.Append($"<size=32>{anon.Score}</size>");
			stringBuilder.AppendLine();
		}
		stringBuilder.AppendLine(extraText);
		return stringBuilder.ToString();
	}

	private void CreateTeamChains()
	{
		if ((Object)(object)TeamChainSystem.Instance == (Object)null)
		{
			return;
		}
		TeamChainSystem instance = TeamChainSystem.Instance;
		Dictionary<int, List<Character>> dictionary = new Dictionary<int, List<Character>>();
		foreach (Character allCharacter in Character.AllCharacters)
		{
			if ((Object)(object)((MonoBehaviourPun)allCharacter).photonView == (Object)null)
			{
				continue;
			}
			int viewID = ((MonoBehaviourPun)allCharacter).photonView.ViewID;
			if (PlayerTeams.TryGetValue(viewID, out var value))
			{
				if (!dictionary.ContainsKey(value))
				{
					dictionary[value] = new List<Character>();
				}
				dictionary[value].Add(allCharacter);
			}
		}
		foreach (KeyValuePair<int, List<Character>> item in dictionary)
		{
			instance.CreateChainsForTeam(item.Key, item.Value);
		}
	}

	private void DebugLogTeamAssignments(List<Character> players)
	{
		string text = "红队(0): ";
		string text2 = "蓝队(1): ";
		foreach (Character player in players)
		{
			if ((Object)(object)((MonoBehaviourPun)player).photonView == (Object)null)
			{
				continue;
			}
			int viewID = ((MonoBehaviourPun)player).photonView.ViewID;
			if (PlayerTeams.TryGetValue(viewID, out var value))
			{
				string text3 = player.characterName;
				if (string.IsNullOrEmpty(text3))
				{
					text3 = "未命名玩家";
				}
				if (value == 0)
				{
					text += $"{text3}({viewID}), ";
				}
				else
				{
					text2 += $"{text3}({viewID}), ";
				}
			}
		}
		Plugin.Log.LogInfo((object)text.TrimEnd(',', ' '));
		Plugin.Log.LogInfo((object)text2.TrimEnd(',', ' '));
		Plugin.Log.LogInfo((object)$"队伍分配完成! 总计: {players.Count}名玩家");
	}
}
public class TeamRaceTimer : MonoBehaviour
{
	private float messageTimer;

	private TMP_Text timerText;

	private float startTime;

	private float pausedTime;

	public bool isRunning;

	private bool isPaused;

	public string message = "";

	public float CurrentTime => isRunning ? (Time.time - startTime) : pausedTime;

	public static TeamRaceTimer Instance { get; private set; }

	private void Start()
	{
		timerText = ((Component)this).GetComponentInChildren<TMP_Text>();
		if ((Object)(object)timerText == (Object)null)
		{
			Debug.LogError((object)"无法找到计时器文本组件!");
			((Behaviour)this).enabled = false;
			return;
		}
		timerText.text = "00:00.00";
		timerText.alignment = (TextAlignmentOptions)514;
		timerText.richText = true;
		SetVisible(visible: false);
		Instance = this;
	}

	public void StartTimer()
	{
		SetVisible(visible: true);
		if (isPaused)
		{
			startTime = Time.time - pausedTime;
			isPaused = false;
		}
		else
		{
			startTime = Time.time;
			pausedTime = 0f;
		}
		isRunning = true;
	}

	public void PauseTimer()
	{
		if (isRunning)
		{
			pausedTime = CurrentTime;
			isRunning = false;
			isPaused = true;
		}
	}

	public float StopTimer()
	{
		float currentTime = CurrentTime;
		isRunning = false;
		isPaused = false;
		return currentTime;
	}

	public void ResetTimer()
	{
		startTime = Time.time;
		pausedTime = 0f;
		isRunning = false;
		isPaused = false;
		timerText.text = message + "\n\n " + FormatTime(0f);
	}

	public string FormatTime(float time)
	{
		int num = Mathf.FloorToInt(time / 60f);
		int num2 = Mathf.FloorToInt(time % 60f);
		int num3 = Mathf.FloorToInt(time * 100f % 100f);
		string text = ((Singleton<TeamRaceManager>.Instance.LocalPlayerTeamId == 0) ? "red" : "blue");
		return $"<size=32><color={text}>{num:00}:{num2:00}.{num3:00}</size></color>";
	}

	public void SetVisible(bool visible)
	{
		CanvasGroup component = ((Component)this).GetComponent<CanvasGroup>();
		if ((Object)(object)component != (Object)null)
		{
			component.alpha = (visible ? 1f : 0f);
		}
		else
		{
			((Component)this).gameObject.SetActive(visible);
		}
	}

	private void Update()
	{
		messageTimer -= Time.deltaTime;
		if (messageTimer <= 0f)
		{
			message = "";
		}
		timerText.text = message + "\n\n" + FormatTime(CurrentTime);
	}

	public static void SetMessage(string msg, float time)
	{
		if ((Object)(object)Instance != (Object)null)
		{
			Instance.message = msg;
			Instance.messageTimer = time;
		}
	}
}
public class ResultUI : MonoBehaviour
{
	private static ResultUI _instance;

	private TMP_Text _resultText;

	private CanvasGroup _canvasGroup;

	private float _showTime = 5f;

	private float _timer;

	private bool _isShowing;

	public static ResultUI Instance => _instance;

	private void Awake()
	{
		if ((Object)(object)_instance != (Object)null && (Object)(object)_instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		_instance = this;
		_resultText = ((Component)this).GetComponentInChildren<TMP_Text>();
		_resultText.richText = true;
		_resultText.text = "";
		_canvasGroup = ((Component)this).gameObject.GetComponentInChildren<CanvasGroup>();
		if ((Object)(object)_canvasGroup == (Object)null)
		{
			_canvasGroup = ((Component)this).gameObject.AddComponent<CanvasGroup>();
		}
		_canvasGroup.alpha = 0f;
		_canvasGroup.blocksRaycasts = false;
		_canvasGroup.interactable = false;
	}

	public static void ShowResultUI(string result, float time, bool useEffects = true)
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)Instance == (Object)null))
		{
			Instance._resultText.text = result;
			Instance._showTime = time;
			Instance._isShowing = true;
			Instance._resultText.transform.localScale = Vector3.one;
			Instance._canvasGroup.alpha = 0f;
			if (useEffects)
			{
				Instance.PlayAnimatedSequence(time);
				return;
			}
			Instance._canvasGroup.alpha = 1f;
			Instance._timer = time;
			((Behaviour)Instance).enabled = true;
		}
	}

	private void PlayAnimatedSequence(float displayTime)
	{
		//IL_0031: 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_0111: Expected O, but got Unknown
		DOTween.Kill((object)_resultText.transform, false);
		DOTween.Kill((object)_canvasGroup, false);
		Sequence val = DOTween.Sequence();
		_resultText.transform.localScale = Vector3.zero;
		_canvasGroup.alpha = 0f;
		TweenSettingsExtensions.Append(val, (Tween)(object)TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale(_resultText.transform, 1.2f, 0.5f), (Ease)27));
		TweenSettingsExtensions.Append(val, (Tween)(object)TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale(_resultText.transform, 1f, 0.3f), (Ease)3));
		TweenSettingsExtensions.Join(val, (Tween)(object)DOTween.To((DOGetter<float>)(() => _canvasGroup.alpha), (DOSetter<float>)delegate(float x)
		{
			_canvasGroup.alpha = x;
		}, 1f, 0.5f));
		TweenSettingsExtensions.AppendInterval(val, displayTime - 1f);
		TweenSettingsExtensions.Append(val, (Tween)(object)TweenSettingsExtensions.OnComplete<TweenerCore<float, float, FloatOptions>>(DOTween.To((DOGetter<float>)(() => _canvasGroup.alpha), (DOSetter<float>)delegate(float x)
		{
			_canvasGroup.alpha = x;
		}, 0f, 1f), (TweenCallback)delegate
		{
			_resultText.text = "";
			_isShowing = false;
			((Behaviour)this).enabled = false;
		}));
		TweenExtensions.Play<Sequence>(val);
	}

	private void Update()
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Expected O, but got Unknown
		if (!_isShowing)
		{
			return;
		}
		_timer -= Time.deltaTime;
		if (_timer <= 0f)
		{
			TweenSettingsExtensions.OnComplete<TweenerCore<float, float, FloatOptions>>(DOTween.To((DOGetter<float>)(() => _canvasGroup.alpha), (DOSetter<float>)delegate(float x)
			{
				_canvasGroup.alpha = x;
			}, 0f, 0.5f), (TweenCallback)delegate
			{
				_resultText.text = "";
				_isShowing = false;
			});
		}
	}
}
[HarmonyPatch]
public static class Patch
{
	[HarmonyPatch(typeof(GUIManager), "Start")]
	private static class PatchGUIManager
	{
		public static void Postfix(GUIManager __instance)
		{
			InitTimerUI(__instance);
			InitResultUI(__instance);
		}

		private static void InitTimerUI(GUIManager __instance)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			AscentUI componentInChildren = ((Component)__instance).GetComponentInChildren<AscentUI>();
			Transform val = ((componentInChildren != null) ? ((Component)componentInChildren).transform : null);
			if (!((Object)(object)val == (Object)null))
			{
				RectTransform val2 = (RectTransform)Object.Instantiate<Transform>(val, val.parent);
				((Object)val2).name = "TeamRaceTimer";
				Object.Destroy((Object)(object)((Component)val2).GetComponent<AscentUI>());
				((Component)val2).gameObject.AddComponent<TeamRaceTimer>();
				val2.anchorMin = new Vector2(1f, 0.5f);
				val2.anchorMax = new Vector2(1f, 0.5f);
				val2.pivot = new Vector2(1f, 0.5f);
				val2.anchoredPosition = new Vector2(-50f, 0f);
				val2.sizeDelta = new Vector2(200f, 50f);
			}
		}

		private static void InitResultUI(GUIManager __instance)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			AscentUI componentInChildren = ((Component)__instance).GetComponentInChildren<AscentUI>();
			Transform val = ((componentInChildren != null) ? ((Component)componentInChildren).transform : null);
			if (!((Object)(object)val == (Object)null))
			{
				Transform val2 = Object.Instantiate<Transform>(val, val.parent);
				((Object)val2).name = "ResultUI";
				Object.Destroy((Object)(object)((Component)val2).GetComponent<AscentUI>());
				((Component)val2).gameObject.AddComponent<ResultUI>();
				RectTransform component = ((Component)val2).GetComponent<RectTransform>();
				component.anchorMin = new Vector2(0.5f, 0.5f);
				component.anchorMax = new Vector2(0.5f, 0.5f);
				component.pivot = new Vector2(0.5f, 0.5f);
				component.anchoredPosition = Vector2.zero;
				component.sizeDelta = new Vector2(800f, 600f);
				TMP_Text componentInChildren2 = ((Component)val2).GetComponentInChildren<TMP_Text>();
				if ((Object)(object)componentInChildren2 != (Object)null)
				{
					componentInChildren2.alignment = (TextAlignmentOptions)257;
					componentInChildren2.fontSize = 24f;
					((Graphic)componentInChildren2).color = Color.white;
				}
			}
		}
	}

	[HarmonyPatch(typeof(MapHandler))]
	private static class PatchMapHandler
	{
		[HarmonyPatch("GoToSegment")]
		public static void Postfix(MapHandler __instance, ref Segment s)
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance.segments[(int)s]._segmentCampfire == (Object)null)
			{
				nextCampfire = null;
				Plugin.Log.LogInfo((object)"无篝火位置,直奔顶点吧!");
				GameObject val = GameObject.Find("Flag_planted_seagull");
				if ((Object)(object)val != (Object)null)
				{
					nextPoint = val.transform.position;
					Plugin.Log.LogInfo((object)$"已设置下一个点为: {nextPoint}");
				}
				else
				{
					nextPoint = (nextPoint = Singleton<MountainProgressHandler>.Instance.progressPoints.Last().transform.position);
				}
			}
			else
			{
				nextCampfire = __instance.segments[(int)s]._segmentCampfire.gameObject.GetComponentInChildren<Campfire>(true);
				if (!((Object)(object)nextCampfire != (Object)null))
				{
					return;
				}
				float num = Vector3.Distance(((Component)nextCampfire).transform.position, ((Component)Character.localCharacter).transform.position);
				Plugin.Log.LogInfo((object)$"下一个篝火位置: {nextCampfire},距离玩家{num:F2}M");
			}
			Singleton<TeamRaceManager>.Instance.StartTeamAssignment();
		}
	}

	[HarmonyPatch(typeof(RunManager))]
	private static class PatchRunManager
	{
		[HarmonyPatch("Awake")]
		public static void Postfix(RunManager __instance)
		{
			if ((Object)(object)((Component)__instance).gameObject.GetComponent<TeamRaceManager>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<TeamRaceManager>();
				Plugin.Log.LogInfo((object)"已添加TeamRaceManager组件到RunManager对象上");
			}
		}
	}

	[HarmonyPatch(typeof(MountainProgressHandler))]
	private static class PatchMountainProgressHandler
	{
		[HarmonyPatch("CheckAreaAchievement")]
		public static void Prefix(MountainProgressHandler __instance, ref ProgressPoint pointReached)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Invalid comparison between Unknown and I4
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			if (pointReached.title.ToLower() != "shore")
			{
				return;
			}
			List<Campfire> list = Object.FindObjectsByType<Campfire>((FindObjectsSortMode)0).ToList();
			Plugin.Log.LogInfo((object)$"已经到达海岸!,共找到{list.Count}个篝火!");
			foreach (Campfire item in list)
			{
				if ((Object)(object)nextCampfire == (Object)null && (int)item.state != 1 && (Object)(object)Character.localCharacter != (Object)null)
				{
					float num = Vector3.Distance(((Component)item).transform.position, Character.localCharacter.Center);
					if (num > 50f)
					{
						nextCampfire = item;
						Plugin.Log.LogInfo((object)("已设置nextCampfire为当前Campfire: " + ((Object)item).name));
						Singleton<TeamRaceManager>.Instance.StartTeamAssignment();
						break;
					}
				}
			}
		}
	}

	[HarmonyPatch(typeof(Character))]
	private static class PatchCharacter
	{
		[HarmonyPatch("RPCA_Revive")]
		[HarmonyPostfix]
		private static void RevivePatch(Character __instance)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Invalid comparison between Unknown and I4
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)(object)Character.localCharacter && Singleton<TeamRaceManager>.Instance.shouldStatusValue != -1f)
			{
				if ((int)Singleton<TeamRaceManager>.Instance.shouldStatus != 7)
				{
					__instance.refs.afflictions.AddStatus(Singleton<TeamRaceManager>.Instance.shouldStatus, Singleton<TeamRaceManager>.Instance.shouldStatusValue, false);
					Singleton<TeamRaceManager>.Instance.shouldStatusValue = -1f;
				}
				else
				{
					__instance.AddExtraStamina(Singleton<TeamRaceManager>.Instance.shouldStatusValue);
					Singleton<TeamRaceManager>.Instance.shouldStatusValue = -1f;
				}
			}
		}
	}

	public static Campfire nextCampfire;

	public static Vector3 nextPoint;
}
public class TeamChainSystem : MonoBehaviour
{
	public class ChainLink
	{
		public Character playerA;

		public Character playerB;

		public LineRenderer lineRenderer;

		public SpringJoint springJoint;

		private int teamId;

		public ChainLink(Character a, Character b, int team)
		{
			playerA = a;
			playerB = b;
			teamId = team;
			CreateVisualChain();
			CreatePhysicsConnection();
		}

		private void CreateVisualChain()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject($"Team{teamId}_Chain_{((MonoBehaviourPun)playerA).photonView.ViewID}-{((MonoBehaviourPun)playerB).photonView.ViewID}");
			lineRenderer = val.AddComponent<LineRenderer>();
			lineRenderer.positionCount = 2;
			((Renderer)lineRenderer).material = new Material(Shader.Find("Sprites/Default"));
			lineRenderer.startColor = Instance.ChainColor;
			lineRenderer.endColor = Instance.ChainColor;
			lineRenderer.startWidth = Instance.ChainWidth;
			lineRenderer.endWidth = Instance.ChainWidth;
		}

		private void CreatePhysicsConnection()
		{
			Rigidbody hipRigidbody = GetHipRigidbody(playerA);
			Rigidbody hipRigidbody2 = GetHipRigidbody(playerB);
			if ((Object)(object)hipRigidbody != (Object)null && (Object)(object)hipRigidbody2 != (Object)null)
			{
				springJoint = ((Component)hipRigidbody).gameObject.AddComponent<SpringJoint>();
				((Joint)springJoint).connectedBody = hipRigidbody2;
				springJoint.spring = 15f;
				springJoint.damper = 0.5f;
				springJoint.minDistance = 2f;
				springJoint.maxDistance = Instance.ChainLength;
				((Joint)springJoint).enableCollision = true;
			}
		}

		private Rigidbody GetHipRigidbody(Character character)
		{
			Transform val = ((Component)character).transform.FindRecursive("Hip");
			return (val != null) ? ((Component)val).GetComponent<Rigidbody>() : null;
		}

		public void Update()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)playerA == (Object)null || (Object)(object)playerB == (Object)null)
			{
				Destroy();
				return;
			}
			Vector3 hipPosition = GetHipPosition(playerA);
			Vector3 hipPosition2 = GetHipPosition(playerB);
			lineRenderer.SetPosition(0, hipPosition);
			lineRenderer.SetPosition(1, hipPosition2);
			float num = Vector3.Distance(hipPosition, hipPosition2);
			if (num > Instance.ChainLength && (Object)(object)springJoint != (Object)null)
			{
				Rigidbody hipRigidbody = GetHipRigidbody(playerA);
				if ((Object)(object)hipRigidbody != (Object)null)
				{
					Vector3 val = hipPosition2 - hipPosition;
					Vector3 normalized = ((Vector3)(ref val)).normalized;
					float num2 = (num - Instance.ChainLength) * 10f;
					hipRigidbody.AddForce(normalized * num2, (ForceMode)2);
				}
			}
		}

		private Vector3 GetHipPosition(Character character)
		{
			//IL_0037: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)character).transform.FindRecursive("Hip");
			return (val != null) ? val.position : (((Component)character).transform.position + Vector3.up * 0.5f);
		}

		public void Destroy()
		{
			if ((Object)(object)lineRenderer != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)lineRenderer).gameObject);
			}
			if ((Object)(object)springJoint != (Object)null)
			{
				Object.Destroy((Object)(object)springJoint);
			}
		}
	}

	public float ChainLength = 5f;

	public Color ChainColor = new Color(0.36f, 0.22f, 0.09f);

	public float ChainWidth = 0.1f;

	private Dictionary<int, List<ChainLink>> teamChains = new Dictionary<int, List<ChainLink>>();

	public static TeamChainSystem Instance { get; private set; }

	private void Awake()
	{
		if ((Object)(object)Instance == (Object)null)
		{
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}
		else
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
	}

	public void CreateChainsForTeam(int teamId, List<Character> members)
	{
		RemoveTeamChains(teamId);
		members.Sort((Character a, Character b) => ((MonoBehaviourPun)a).photonView.ViewID.CompareTo(((MonoBehaviourPun)b).photonView.ViewID));
		List<ChainLink> list = new List<ChainLink>();
		for (int i = 0; i < members.Count - 1; i++)
		{
			ChainLink item = new ChainLink(members[i], members[i + 1], teamId);
			list.Add(item);
		}
		if (members.Count > 2)
		{
			list.Add(new ChainLink(members[0], members[members.Count - 1], teamId));
		}
		teamChains[teamId] = list;
	}

	public void RemoveTeamChains(int teamId)
	{
		if (!teamChains.TryGetValue(teamId, out var value))
		{
			return;
		}
		foreach (ChainLink item in value)
		{
			item.Destroy();
		}
		teamChains.Remove(teamId);
	}

	private void LateUpdate()
	{
		foreach (KeyValuePair<int, List<ChainLink>> teamChain in teamChains)
		{
			foreach (ChainLink item in teamChain.Value)
			{
				item.Update();
			}
		}
	}

	public void ClearAllChains()
	{
		List<int> list = teamChains.Keys.ToList();
		foreach (int item in list)
		{
			RemoveTeamChains(item);
		}
		teamChains.Clear();
	}
}
public static class TransformExtensions
{
	public static Transform FindRecursive(this Transform parent, string name)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected O, but got Unknown
		if (((Object)parent).name == name)
		{
			return parent;
		}
		foreach (Transform item in parent)
		{
			Transform parent2 = item;
			Transform val = parent2.FindRecursive(name);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
		}
		return null;
	}
}