Decompiled source of SailingProgression v0.1.6

plugins/SailingProgression/SailingProgression.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("SailingProgression")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.6.0")]
[assembly: AssemblyInformationalVersion("0.1.6")]
[assembly: AssemblyProduct("SailingProgression")]
[assembly: AssemblyTitle("SailingProgression")]
[assembly: AssemblyVersion("0.1.6.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 SailingProgression
{
	public static class Balance
	{
		public static float Level(float value)
		{
			if (!float.IsNaN(value) && !float.IsInfinity(value))
			{
				return Math.Max(0f, Math.Min(100f, value));
			}
			return 0f;
		}

		public static float BonusPercent(float value)
		{
			if (!float.IsNaN(value) && !float.IsInfinity(value))
			{
				return Math.Max(0f, Math.Min(100f, value));
			}
			return 0f;
		}

		public static float SpeedTarget(float level, float maximumPercent = 40f)
		{
			float num = Level(level);
			return 1f + (0.015f * Math.Min(num, 50f) + 0.005f * Math.Max(num - 50f, 0f)) * BonusPercent(maximumPercent) / 100f;
		}

		public static float SailForce(float level, float maximumPercent = 40f)
		{
			return SpeedTarget(level, maximumPercent) * SpeedTarget(level, maximumPercent);
		}

		public static float Endurance(float level, float maximumPercent = 30f)
		{
			return 1f + BonusPercent(maximumPercent) / 100f * Level(level) / 100f;
		}

		public static bool ValidSample(float seconds, float distance)
		{
			if (seconds >= 0.75f && seconds <= 2f && distance >= 0f)
			{
				return distance <= 20f * seconds;
			}
			return false;
		}

		public static float ExperienceMultiplier(float value)
		{
			if (!float.IsNaN(value) && !float.IsInfinity(value))
			{
				return Math.Max(1f, Math.Min(10f, value));
			}
			return 1f;
		}

		public static bool ValidJourney(float seconds, float netDistance)
		{
			if (seconds >= 10f && netDistance >= seconds && netDistance <= 20f * seconds && !float.IsNaN(netDistance))
			{
				return !float.IsInfinity(netDistance);
			}
			return false;
		}

		public static bool ValidTravel(float seconds, float horizontalDistance, float speed)
		{
			if (seconds >= 0.75f && seconds <= 2f && horizontalDistance >= 0.75f * seconds && horizontalDistance <= 20f * seconds && Math.Abs(speed) >= 0.75f && !float.IsNaN(horizontalDistance))
			{
				return !float.IsInfinity(horizontalDistance);
			}
			return false;
		}
	}
	[BepInPlugin("branchofyore.sailingprogression", "Sailing Progression", "0.1.6")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(Ship), "GetSailForce")]
		private static class SailPatch
		{
			private static void Postfix(Ship __instance, ref Vector3 __result)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				if (__instance.IsOwner())
				{
					__result *= Balance.SailForce(CaptainLevel(__instance), instance.MaximumSpeedBonus.Value);
				}
			}
		}

		[HarmonyPatch(typeof(WearNTear), "ApplyDamage")]
		private static class HullPatch
		{
			private static void Prefix(WearNTear __instance, ref float damage)
			{
				Ship component = ((Component)__instance).GetComponent<Ship>();
				if (Object.op_Implicit((Object)(object)component) && component.IsOwner() && damage > 0f)
				{
					damage /= Balance.Endurance(CaptainLevel(component), instance.MaximumEnduranceBonus.Value);
				}
			}
		}

		[HarmonyPatch(typeof(Ship), "CustomFixedUpdate")]
		private static class RowingPatch
		{
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				FieldInfo field = AccessTools.Field(typeof(Ship), "m_backwardForce");
				MethodInfo replacement = AccessTools.Method(typeof(Plugin), "RowingForce", (Type[])null, (Type[])null);
				int replaced = 0;
				foreach (CodeInstruction instruction in instructions)
				{
					CodeInstruction val = new CodeInstruction(instruction);
					if (CodeInstructionExtensions.LoadsField(val, field, false))
					{
						val.opcode = OpCodes.Call;
						val.operand = replacement;
						replaced++;
					}
					yield return val;
				}
				if (replaced != 2)
				{
					throw new InvalidOperationException("Unsupported Ship rowing code: expected two propulsion reads.");
				}
			}
		}

		public const string Id = "branchofyore.sailingprogression";

		public const string LevelKey = "branchofyore.sailingprogression.level";

		private static Plugin instance = null;

		private Harmony harmony;

		private Player? sampledPlayer;

		private Ship? sampledShip;

		private Vector3 previousPosition;

		private Vector3 journeyStart;

		private float nextSample;

		private float previousTime;

		private float qualifyingSeconds;

		private static readonly FieldRef<Ship, List<Player>> Players = AccessTools.FieldRefAccess<Ship, List<Player>>("m_players");

		public static SkillType Sailing { get; private set; }

		public ConfigEntry<float> ExperienceMultiplier { get; private set; }

		public ConfigEntry<float> MaximumSpeedBonus { get; private set; }

		public ConfigEntry<float> MaximumEnduranceBonus { get; private set; }

		private void Awake()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_00d4: 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)
			//IL_00e1: Expected O, but got Unknown
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: 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_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Expected O, but got Unknown
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Expected O, but got Unknown
			instance = this;
			MaximumSpeedBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Bonuses", "Maximum Speed Bonus", 40f, new ConfigDescription("Maximum speed bonus in percent at Sailing level 100, for sails and rowing (including reverse). Level 50 receives 75% of this bonus. Default 40 means +30% at level 50 and approximately +40% at level 100. Server synchronized.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			MaximumEnduranceBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Bonuses", "Maximum Endurance Bonus", 30f, new ConfigDescription("Extra damage the hull can endure, in percent at Sailing level 100. Scales evenly with skill level. Default 30 means +15% at level 50 and +30% at level 100. Does not repair the boat. Server synchronized.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			ExperienceMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Progression", "Sailing XP Multiplier", 1f, new ConfigDescription("Sailing experience for everyone aboard. 1 = normal, 10 = ten times the experience. The server value applies to all players. Does not change speed or endurance per level.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			Texture2D val = new Texture2D(2, 2);
			using (Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("SailingProgression.Icon.png"))
			{
				using MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				AssetUtils.LoadImage(val, memoryStream.ToArray());
			}
			Sprite icon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
			Sailing = SkillManager.Instance.AddSkill(new SkillConfig
			{
				Identifier = "branchofyore.sailingprogression.sailing",
				Name = "Sailing",
				Description = "Sailing speed and endurance",
				IncreaseStep = 1f,
				Icon = icon
			});
			harmony = new Harmony("branchofyore.sailingprogression");
			harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Sailing Progression 0.1.6 loaded.");
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		public static Player? Captain(Ship ship)
		{
			if (!Object.op_Implicit((Object)(object)ship) || !Object.op_Implicit((Object)(object)ship.m_shipControlls))
			{
				return null;
			}
			long user = ship.m_shipControlls.GetUser();
			if (user == 0L)
			{
				return null;
			}
			foreach (Player item in Players.Invoke(ship))
			{
				if (Object.op_Implicit((Object)(object)item) && !((Character)item).IsDead() && item.GetPlayerID() == user)
				{
					return item;
				}
			}
			return null;
		}

		public static float CaptainLevel(Ship ship)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			Player val = Captain(ship);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return 0f;
			}
			if ((Object)(object)val == (Object)(object)Player.m_localPlayer)
			{
				return Balance.Level(((Character)val).GetSkills().GetSkillLevel(Sailing));
			}
			ZNetView component = ((Component)val).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid())
			{
				return 0f;
			}
			return Balance.Level(component.GetZDO().GetFloat("branchofyore.sailingprogression.level", 0f));
		}

		private void Update()
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: 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_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			float time = Time.time;
			if (time < nextSample)
			{
				return;
			}
			nextSample = time + 1f;
			Player localPlayer = Player.m_localPlayer;
			Ship localShip = Ship.GetLocalShip();
			if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || !Object.op_Implicit((Object)(object)localShip) || !localShip.IsPlayerInBoat(localPlayer) || !Riding(localPlayer, localShip))
			{
				ResetSample();
				return;
			}
			ZNetView component = ((Component)localPlayer).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || !component.IsOwner())
			{
				ResetSample();
				return;
			}
			component.GetZDO().Set("branchofyore.sailingprogression.level", Balance.Level(((Character)localPlayer).GetSkills().GetSkillLevel(Sailing)));
			Vector3 position = ((Component)localShip).transform.position;
			if ((Object)(object)sampledPlayer != (Object)(object)localPlayer || (Object)(object)sampledShip != (Object)(object)localShip)
			{
				sampledPlayer = localPlayer;
				sampledShip = localShip;
				previousPosition = position;
				previousTime = time;
				journeyStart = position;
				qualifyingSeconds = 0f;
				return;
			}
			float num = time - previousTime;
			Vector3 val = position - previousPosition;
			val.y = 0f;
			previousPosition = position;
			previousTime = time;
			if ((int)localShip.GetSpeedSetting() == 0 || !Balance.ValidSample(num, ((Vector3)(ref val)).magnitude))
			{
				qualifyingSeconds = 0f;
				journeyStart = position;
				return;
			}
			qualifyingSeconds += num;
			if (!(qualifyingSeconds < 10f))
			{
				Vector3 val2 = position - journeyStart;
				val2.y = 0f;
				bool num2 = Balance.ValidJourney(qualifyingSeconds, ((Vector3)(ref val2)).magnitude);
				qualifyingSeconds = 0f;
				journeyStart = position;
				if (num2)
				{
					((Character)localPlayer).RaiseSkill(Sailing, 3f * Balance.ExperienceMultiplier(ExperienceMultiplier.Value));
					component.GetZDO().Set("branchofyore.sailingprogression.level", Balance.Level(((Character)localPlayer).GetSkills().GetSkillLevel(Sailing)));
				}
			}
		}

		private void ResetSample()
		{
			sampledPlayer = null;
			sampledShip = null;
			qualifyingSeconds = 0f;
		}

		public static bool Riding(Player player, Ship ship)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			if ((object)player.GetDoodadController() == ship.m_shipControlls || (Object)(object)((Character)player).GetStandingOnShip() == (Object)(object)ship || (((Character)player).IsAttachedToShip() && Object.op_Implicit((Object)(object)player.GetAttachPoint()) && (Object)(object)((Component)player.GetAttachPoint()).GetComponentInParent<Ship>() == (Object)(object)ship))
			{
				return true;
			}
			RaycastHit? val = null;
			RaycastHit[] array = Physics.RaycastAll(((Component)player).transform.position + Vector3.up * 0.3f, Vector3.down, 1.5f, -5, (QueryTriggerInteraction)1);
			RaycastHit value2;
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit value = array[i];
				if ((Object)(object)((Component)((RaycastHit)(ref value)).collider).GetComponentInParent<Player>() == (Object)(object)player)
				{
					continue;
				}
				if (val.HasValue)
				{
					float distance = ((RaycastHit)(ref value)).distance;
					value2 = val.Value;
					if (!(distance < ((RaycastHit)(ref value2)).distance))
					{
						continue;
					}
				}
				val = value;
			}
			if (val.HasValue)
			{
				value2 = val.Value;
				return (Object)(object)((Component)((RaycastHit)(ref value2)).collider).GetComponentInParent<Ship>() == (Object)(object)ship;
			}
			return false;
		}

		public static float ObservedSpeed(Ship ship)
		{
			//IL_0037: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			if (ship.IsOwner())
			{
				return ship.GetSpeed();
			}
			ZNetView component = ((Component)ship).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid())
			{
				return 0f;
			}
			return Vector3.Dot(component.GetZDO().GetVec3(ZDOVars.s_velHash, Vector3.zero), ((Component)ship).transform.forward);
		}

		public static float RowingForce(Ship ship)
		{
			return ship.m_backwardForce * (ship.IsOwner() ? Balance.SailForce(CaptainLevel(ship), instance.MaximumSpeedBonus.Value) : 1f);
		}
	}
}