using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Agents;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using GTFO.API;
using GameData;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Player;
using SNetwork;
using SpreadStartingAmmo.Dependencies;
using SpreadStartingAmmo.Patches;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SpreadStartingAmmo")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SpreadStartingAmmo")]
[assembly: AssemblyTitle("SpreadStartingAmmo")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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]
[Microsoft.CodeAnalysis.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;
}
}
}
namespace SpreadStartingAmmo
{
internal static class AmmoSpreadManager
{
private static readonly HashSet<ulong> _playerLookups = new HashSet<ulong>();
public static void PullStartingAmmo(PlayerAgent player, out List<float> ammoMods)
{
if (SNet.HubPlayerCount == 0)
{
DinoLogger.Error("Tried to pull starting ammo when there were no players in the lobby!");
ammoMods = new List<float> { 1f, 1f, 1f };
return;
}
float mod = 4f / (float)((_playerLookups.Count > 0) ? _playerLookups.Count : SNet.HubPlayerCount);
ammoMods = new List<float> { mod, mod, mod };
if (_playerLookups.Count == 0 || _playerLookups.Contains(player.Owner.Lookup))
{
return;
}
_playerLookups.Add(player.Owner.Lookup);
mod = 4f / (float)_playerLookups.Count;
for (int i = 0; i < ammoMods.Count; i++)
{
ammoMods[i] = mod;
}
PlayerDataBlock block = GameDataBlockBase<PlayerDataBlock>.GetBlock(1u);
SpecialExpeditionOverridesData specialOverrideData = RundownManager.ActiveExpedition.SpecialOverrideData;
List<float> list = new List<float>
{
(float)block.AmmoStandardInitial * specialOverrideData.StandardAmmoAtExpeditionStart,
(float)block.AmmoSpecialInitial * specialOverrideData.SpecialAmmoAtExpeditionStart,
(float)block.AmmoClassInitial * specialOverrideData.ToolAmmoAtExpeditionStart
};
List<float> list2 = list.ConvertAll((float ammo) => mod * ammo);
if (list2.All((float x) => x == 0f))
{
return;
}
List<(PlayerBackpack, List<float>)> list3 = new List<(PlayerBackpack, List<float>)>();
List<int> list4 = new List<int> { 0, 0, 0 };
Enumerator<PlayerAgent> enumerator = PlayerManager.PlayerAgentsInLevel.GetEnumerator();
PlayerBackpack val = default(PlayerBackpack);
BackpackItem val2 = default(BackpackItem);
while (enumerator.MoveNext())
{
PlayerAgent current = enumerator.Current;
if (((Il2CppObjectBase)current).Pointer == ((Il2CppObjectBase)player).Pointer || !PlayerBackpackManager.TryGetBackpack(current.Owner, ref val))
{
continue;
}
PlayerAmmoStorage ammoStorage = val.AmmoStorage;
if (((Agent)current).IsLocallyOwned || (SNet.IsMaster && current.Owner.IsBot))
{
ToggleMagsInReserves(val, putInReserves: true);
}
List<float> list5 = new List<float>
{
ammoStorage.StandardAmmo.AmmoInPack,
ammoStorage.SpecialAmmo.AmmoInPack,
ammoStorage.ClassAmmo.AmmoInPack
};
if (val.TryGetBackpackItem((InventorySlot)3, ref val2) && (Object)(object)val2.Instance != (Object)null && val2.Instance.ItemDataBlock.BlockToolAmmoRefill)
{
list5[2] = 0f;
}
list3.Add((val, list5));
for (int j = 0; j < list5.Count; j++)
{
if (list5[j] > 0f)
{
list4[j]++;
}
}
}
if (list4.All((int x) => x == 0))
{
for (int k = 0; k < ammoMods.Count; k++)
{
ammoMods[k] = 0f;
}
return;
}
List<float> list6 = new List<float>(list2);
for (int l = 0; l < 3; l++)
{
while (list4[l] > 0 && list6[l] > 0f)
{
float val3 = list6[l] / (float)list4[l];
foreach (var item3 in list3)
{
List<float> item = item3.Item2;
if (!(item[l] <= 0f))
{
float num = Math.Min(item[l], val3);
item[l] -= num;
list6[l] -= num;
if (item[l] <= 0f)
{
list4[l]--;
}
}
}
}
}
if (!((Agent)player).IsLocallyOwned)
{
PlayerBackpack localBackpack = PlayerBackpackManager.LocalBackpack;
List<float> item2 = list3.First<(PlayerBackpack, List<float>)>(((PlayerBackpack backpack, List<float> ammoList) x) => ((Il2CppObjectBase)x.backpack).Pointer == ((Il2CppObjectBase)localBackpack).Pointer).Item2;
PlayerAmmoStorage ammoStorage2 = localBackpack.AmmoStorage;
ammoStorage2.SetAmmo((AmmoType)0, item2[0]);
ammoStorage2.SetAmmo((AmmoType)1, item2[1]);
ammoStorage2.SetAmmo((AmmoType)2, item2[2]);
ToggleMagsInReserves(localBackpack, putInReserves: false);
}
else if (SNet.IsMaster)
{
foreach (var (val4, list7) in list3)
{
if (val4.Owner.IsBot)
{
PlayerAmmoStorage ammoStorage3 = val4.AmmoStorage;
ammoStorage3.SetAmmo((AmmoType)0, list7[0]);
ammoStorage3.SetAmmo((AmmoType)1, list7[1]);
ammoStorage3.SetAmmo((AmmoType)2, list7[2]);
ToggleMagsInReserves(val4, putInReserves: false);
}
}
}
for (int m = 0; m < ammoMods.Count; m++)
{
ammoMods[m] = (list2[m] - list6[m]) / list[m];
}
}
private static void ToggleMagsInReserves(PlayerBackpack backpack, bool putInReserves)
{
PlayerBackpack backpack2 = backpack;
PlayerAmmoStorage storage = backpack2.AmmoStorage;
ToggleForSlot((InventorySlot)1);
ToggleForSlot((InventorySlot)2);
ToggleForSlot((InventorySlot)3);
void ToggleForSlot(InventorySlot slot)
{
//IL_0006: 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)
BackpackItem val = default(BackpackItem);
if (backpack2.TryGetBackpackItem(slot, ref val))
{
ItemEquippable val2 = ((Il2CppObjectBase)val.Instance).Cast<ItemEquippable>();
InventorySlotAmmo inventorySlotAmmo = storage.GetInventorySlotAmmo(slot);
if (inventorySlotAmmo.BulletClipSize != 0)
{
if (putInReserves)
{
inventorySlotAmmo.AmmoInPack += (float)val2.GetCurrentClip() * inventorySlotAmmo.CostOfBullet;
}
else
{
int num = Math.Min(inventorySlotAmmo.BulletsInPack, val2.GetCurrentClip());
val2.SetCurrentClip(num);
inventorySlotAmmo.AmmoInPack -= (float)num * inventorySlotAmmo.CostOfBullet;
}
}
}
}
}
public static void OnLevelStart()
{
Enumerator<SNet_Player> enumerator = SNet.SessionHub.PlayersInSession.GetEnumerator();
while (enumerator.MoveNext())
{
SNet_Player current = enumerator.Current;
_playerLookups.Add(current.Lookup);
}
}
public static void OnLevelCleanup()
{
_playerLookups.Clear();
}
}
internal static class DinoLogger
{
private static ManualLogSource logger = Logger.CreateLogSource("SpreadStartingAmmo");
public static void Log(string format, params object[] args)
{
Log(string.Format(format, args));
}
public static void Log(string str)
{
if (logger != null)
{
logger.Log((LogLevel)8, (object)str);
}
}
public static void Warning(string format, params object[] args)
{
Warning(string.Format(format, args));
}
public static void Warning(string str)
{
if (logger != null)
{
logger.Log((LogLevel)4, (object)str);
}
}
public static void Error(string format, params object[] args)
{
Error(string.Format(format, args));
}
public static void Error(string str)
{
if (logger != null)
{
logger.Log((LogLevel)2, (object)str);
}
}
public static void Debug(string format, params object[] args)
{
Debug(string.Format(format, args));
}
public static void Debug(string str)
{
if (logger != null)
{
logger.Log((LogLevel)32, (object)str);
}
}
}
[BepInPlugin("Dinorush.SpreadStartingAmmo", "SpreadStartingAmmo", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal sealed class EntryPoint : BasePlugin
{
public const string MODNAME = "SpreadStartingAmmo";
public override void Load()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
Harmony val = new Harmony("SpreadStartingAmmo");
val.PatchAll();
if (!ETCWrapper.HasETC)
{
val.PatchAll(typeof(ETC_ToolAmmoPatches));
}
LevelAPI.OnEnterLevel += AmmoSpreadManager.OnLevelStart;
LevelAPI.OnLevelCleanup += AmmoSpreadManager.OnLevelCleanup;
((BasePlugin)this).Log.LogMessage((object)"Loaded SpreadStartingAmmo");
}
}
}
namespace SpreadStartingAmmo.Patches
{
[HarmonyPatch]
internal static class AmmoStoragePatches
{
[HarmonyPatch(typeof(InventorySlotAmmo), "AddAmmo")]
[HarmonyWrapSafe]
[HarmonyPrefix]
private static bool FixAmmoOverflow(InventorySlotAmmo __instance, float ammoAmount)
{
float ammoInPack = __instance.AmmoInPack;
float ammoMaxCap = __instance.AmmoMaxCap;
if (ammoInPack + ammoAmount < ammoMaxCap)
{
return true;
}
if (ammoAmount > 0f && ammoInPack > 0f)
{
if (ammoInPack >= ammoMaxCap)
{
return false;
}
__instance.AmmoInPack = ammoMaxCap;
}
else
{
__instance.AmmoInPack += ammoAmount;
}
__instance.OnBulletsUpdateCallback?.Invoke(__instance.BulletsInPack);
return false;
}
[HarmonyPatch(typeof(PlayerAmmoStorage), "AddLevelDefaultAmmoModifications")]
[HarmonyWrapSafe]
[HarmonyPrefix]
private static bool Pre_SetStorage(PlayerAmmoStorage __instance, PlayerAgent owner)
{
if (RundownManager.ActiveExpedition == null)
{
return true;
}
AmmoSpreadManager.PullStartingAmmo(owner, out List<float> ammoMods);
Il2CppStructArray<uint> ammoModificationIDs = __instance.m_ammoModificationIDs;
SpecialExpeditionOverridesData specialOverrideData = RundownManager.ActiveExpedition.SpecialOverrideData;
if (((Il2CppArrayBase<uint>)(object)ammoModificationIDs)[0] != 0)
{
AgentModifierManager.ClearModifierChange(((Il2CppArrayBase<uint>)(object)ammoModificationIDs)[0]);
}
((Il2CppArrayBase<uint>)(object)ammoModificationIDs)[0] = AgentModifierManager.AddModifierValue((Agent)(object)owner, (AgentModifier)152, specialOverrideData.StandardAmmoAtExpeditionStart * ammoMods[0] - 1f, 0f);
if (((Il2CppArrayBase<uint>)(object)ammoModificationIDs)[1] != 0)
{
AgentModifierManager.ClearModifierChange(((Il2CppArrayBase<uint>)(object)ammoModificationIDs)[1]);
}
((Il2CppArrayBase<uint>)(object)ammoModificationIDs)[1] = AgentModifierManager.AddModifierValue((Agent)(object)owner, (AgentModifier)153, specialOverrideData.SpecialAmmoAtExpeditionStart * ammoMods[1] - 1f, 0f);
if (((Il2CppArrayBase<uint>)(object)ammoModificationIDs)[2] != 0)
{
AgentModifierManager.ClearModifierChange(((Il2CppArrayBase<uint>)(object)ammoModificationIDs)[2]);
}
((Il2CppArrayBase<uint>)(object)ammoModificationIDs)[2] = AgentModifierManager.AddModifierValue((Agent)(object)owner, (AgentModifier)154, specialOverrideData.ToolAmmoAtExpeditionStart * ammoMods[2] - 1f, 0f);
return false;
}
}
internal static class ETC_ToolAmmoPatches
{
[HarmonyPatch(typeof(PlayerAmmoStorage), "UpdateBulletsInPack")]
[HarmonyWrapSafe]
[HarmonyPrefix]
private static bool Unclamp_UpdateBullets(PlayerAmmoStorage __instance, AmmoType ammoType, int bulletCount, ref float __result)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Invalid comparison between Unknown and I4
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
if ((int)ammoType != 2)
{
return true;
}
InventorySlotAmmo inventorySlotAmmo = __instance.GetInventorySlotAmmo(ammoType);
float ammoInPack = inventorySlotAmmo.AmmoInPack;
float ammoMaxCap = inventorySlotAmmo.AmmoMaxCap;
float num = (float)bulletCount * inventorySlotAmmo.CostOfBullet;
if (ammoInPack + num < ammoMaxCap)
{
return true;
}
float num4;
if (num > 0f && ammoInPack > 0f)
{
if (ammoInPack >= ammoMaxCap || num >= ammoMaxCap)
{
float num3 = (inventorySlotAmmo.AmmoInPack = Math.Max(ammoInPack, num));
num4 = num3;
}
else
{
float num3 = (inventorySlotAmmo.AmmoInPack = ammoMaxCap);
num4 = num3;
}
}
else
{
float num3 = (inventorySlotAmmo.AmmoInPack += num);
num4 = num3;
}
inventorySlotAmmo.OnBulletsUpdateCallback?.Invoke(inventorySlotAmmo.BulletsInPack);
__instance.NeedsSync = true;
__instance.UpdateSlotAmmoUI(inventorySlotAmmo, 0);
__result = num4;
return false;
}
[HarmonyPatch(typeof(PlayerAmmoStorage), "UpdateAmmoInPack")]
[HarmonyWrapSafe]
[HarmonyPrefix]
private static bool Unclamp_UpdateAmmo(PlayerAmmoStorage __instance, AmmoType ammoType, float delta, ref float __result)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Invalid comparison between Unknown and I4
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
if ((int)ammoType != 2)
{
return true;
}
InventorySlotAmmo inventorySlotAmmo = __instance.GetInventorySlotAmmo(ammoType);
float ammoInPack = inventorySlotAmmo.AmmoInPack;
float ammoMaxCap = inventorySlotAmmo.AmmoMaxCap;
if (ammoInPack + delta < ammoMaxCap)
{
return true;
}
float num3;
if (delta > 0f && ammoInPack > 0f)
{
if (ammoInPack >= ammoMaxCap || delta >= ammoMaxCap)
{
float num2 = (inventorySlotAmmo.AmmoInPack = Math.Max(ammoInPack, delta));
num3 = num2;
}
else
{
float num2 = (inventorySlotAmmo.AmmoInPack = ammoMaxCap);
num3 = num2;
}
}
else
{
float num2 = (inventorySlotAmmo.AmmoInPack += delta);
num3 = num2;
}
inventorySlotAmmo.OnBulletsUpdateCallback?.Invoke(inventorySlotAmmo.BulletsInPack);
__instance.NeedsSync = true;
__instance.UpdateSlotAmmoUI(inventorySlotAmmo, 0);
__result = num3;
return false;
}
}
}
namespace SpreadStartingAmmo.Dependencies
{
internal static class ETCWrapper
{
public const string GUID = "Dinorush.ExtraToolCustomization";
public static bool HasETC { get; private set; }
static ETCWrapper()
{
HasETC = ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("Dinorush.ExtraToolCustomization");
}
}
}