using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using Agents;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CellMenu;
using GameData;
using Gear;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem;
using Il2CppSystem.Collections;
using Microsoft.CodeAnalysis;
using Player;
using SNetwork;
using StateMachines;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("FriendlyFireMessages")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FriendlyFireMessages")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b0712c2b-49df-441c-9f83-fd449f9cf0df")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("1.0.0.0")]
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;
}
}
}
namespace ReTFO.GeoSpy
{
[BepInPlugin("RoboRyGuy.FriendlyFireMessages", "FriendlyFireMessages", "1.0.0")]
[BepInProcess("GTFO.exe")]
public class Plugin : BasePlugin
{
public class UpdateComponent : MonoBehaviour
{
public Coroutine? UpdateCoroutine;
}
public class UpdateCoroutine : Object
{
private Plugin plugin;
public Object Current => (Object)new WaitForSeconds(0.1f);
public UpdateCoroutine(Plugin plugin)
: base(ClassInjector.DerivedConstructorPointer<UpdateCoroutine>())
{
ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this);
this.plugin = plugin;
}
public UpdateCoroutine(IntPtr ptr)
: base(ptr)
{
}
public bool MoveNext()
{
plugin.Update();
return true;
}
public void Reset()
{
}
}
public class SimpleComparer : IComparer<(PlayerAgent?, PlayerAgent, bool)>
{
public int Compare((PlayerAgent?, PlayerAgent, bool) x, (PlayerAgent?, PlayerAgent, bool) y)
{
PlayerAgent? item = x.Item1;
IntPtr intPtr = ((item != null) ? ((Il2CppObjectBase)item).Pointer : IntPtr.Zero);
PlayerAgent? item2 = y.Item1;
int num = intPtr.CompareTo((item2 != null) ? ((Il2CppObjectBase)item2).Pointer : IntPtr.Zero);
if (num != 0)
{
return num;
}
num = ((Il2CppObjectBase)x.Item2).Pointer.CompareTo(((Il2CppObjectBase)y.Item2).Pointer);
if (num != 0)
{
return num;
}
return x.Item3.CompareTo(y.Item3);
}
}
public const string Name = "FriendlyFireMessages";
public const string Author = "RoboRyGuy";
public const string GUID = "RoboRyGuy.FriendlyFireMessages";
public const string Version = "1.0.0";
private static Plugin? _plugin;
protected Harmony harmony = new Harmony("RoboRyGuy.FriendlyFireMessages");
private const float UPDATE_DELAY = 0.1f;
private const float TIMEOUT = 0.4f;
private static uint s_cachedGearID;
public SortedList<(PlayerAgent?, PlayerAgent, bool), (float, float, int)> cumulativeDamage { get; private init; } = new SortedList<(PlayerAgent, PlayerAgent, bool), (float, float, int)>(new SimpleComparer());
public static Plugin Get()
{
return TryGet() ?? throw new NullReferenceException("Tried to retrieve FriendlyFireMessages, but it was not loaded!");
}
public static Plugin? TryGet()
{
return _plugin ?? (_plugin = ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.FirstOrDefault((KeyValuePair<string, PluginInfo> p) => p.Key == "RoboRyGuy.FriendlyFireMessages").Value.Instance as Plugin);
}
public static bool TryGet([NotNullWhen(true)] out Plugin? plugin)
{
plugin = TryGet();
return plugin != null;
}
public override void Load()
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Expected O, but got Unknown
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Expected O, but got Unknown
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Expected O, but got Unknown
_plugin = this;
ClassInjector.RegisterTypeInIl2Cpp(typeof(UpdateComponent));
Type? typeFromHandle = typeof(UpdateCoroutine);
RegisterTypeOptions val = new RegisterTypeOptions();
val.set_Interfaces(Il2CppInterfaceCollection.op_Implicit(new Type[1] { typeof(IEnumerator) }));
ClassInjector.RegisterTypeInIl2Cpp(typeFromHandle, val);
harmony.PatchAll(((object)this).GetType());
UpdateComponent updateComponent = ((BasePlugin)this).AddComponent<UpdateComponent>();
UpdateCoroutine updateCoroutine = new UpdateCoroutine(this);
updateComponent.UpdateCoroutine = ((MonoBehaviour)updateComponent).StartCoroutine(new IEnumerator(((Il2CppObjectBase)updateCoroutine).Pointer));
ManualLogSource log = ((BasePlugin)this).Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(11, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("RoboRyGuy.FriendlyFireMessages");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" is loaded!");
}
log.LogInfo(val2);
}
public override bool Unload()
{
harmony.UnpatchSelf();
return true;
}
public static void ReceiveBullet(Dam_PlayerDamageBase __instance, pBulletDamageData data)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
Agent val = default(Agent);
if (!((pAgent)(ref data.source)).TryGet(ref val) || (int)val.Type != 0)
{
return;
}
Plugin plugin = Get();
PlayerAgent val2 = ((Il2CppObjectBase)val).TryCast<PlayerAgent>();
bool item = (Object)(object)val2 != (Object)null && data.gearCategoryId != 0 && GameDataBlockBase<GearCategoryDataBlock>.GetBlock(data.gearCategoryId).BaseItem == 97;
(PlayerAgent, PlayerAgent, bool) key = (val2, __instance.Owner, item);
if (!(((Il2CppObjectBase)((StateMachine<PLOC_Base>)(object)__instance.Owner.Locomotion).CurrentState).Pointer == ((Il2CppObjectBase)__instance.Owner.Locomotion.Downed).Pointer) || plugin.cumulativeDamage.ContainsKey(key))
{
float num = ((UFloat16)(ref data.damage)).Get(((Dam_SyncedDamageBase)__instance).DamageMax);
int num2 = 1;
if (plugin.cumulativeDamage.TryGetValue(key, out var value))
{
num += value.Item2;
num2 += value.Item3;
}
plugin.cumulativeDamage[key] = (Time.fixedTime, num, num2);
}
}
[HarmonyPatch(typeof(Dam_PlayerDamageBase), "ReceiveBulletDamage")]
[HarmonyPostfix]
public static void ReceiveBullet_Synced(Dam_PlayerDamageBase __instance, pBulletDamageData data)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
ReceiveBullet(__instance, data);
}
[HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveBulletDamage")]
[HarmonyPostfix]
public static void ReceiveBullet_Local(Dam_PlayerDamageLocal __instance, pBulletDamageData data)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
ReceiveBullet((Dam_PlayerDamageBase)(object)__instance, data);
}
public void LogForLobby(string message)
{
((BasePlugin)this).Log.LogInfo((object)message);
IEnumerable<PUI_GameEventLog> source = Enumerable.Empty<PUI_GameEventLog>();
CM_PageLoadout pageLoadout = MainMenuGuiLayer.Current.PageLoadout;
IEnumerable<PUI_GameEventLog> source2 = source.Append((pageLoadout != null) ? pageLoadout.m_gameEventLog : null);
CM_PageMap pageMap = MainMenuGuiLayer.Current.PageMap;
IEnumerable<PUI_GameEventLog> source3 = source2.Append((pageMap != null) ? pageMap.m_gameEventLog : null);
PlayerGuiLayer playerLayer = GuiManager.PlayerLayer;
IEnumerable<PUI_GameEventLog> enumerable = source3.Append((playerLayer != null) ? playerLayer.m_gameEventLog : null);
foreach (PUI_GameEventLog item in enumerable)
{
if (!((Object)(object)item == (Object)null))
{
item.AddLogItem(message, (eGameEventChatLogType)2);
item.UpdateHeightOffset();
}
}
}
public void Update()
{
float num = Time.fixedTime - 0.4f;
for (int i = 0; i < cumulativeDamage.Count; i++)
{
(float, float, int) tuple = cumulativeDamage.Values[i];
if (!(tuple.Item1 > num))
{
(PlayerAgent, PlayerAgent, bool) tuple2 = cumulativeDamage.Keys[i];
cumulativeDamage.RemoveAt(i--);
float value = tuple.Item2 / tuple2.Item2.Damage.m_playerData.health * 100f;
LogForLobby($"{(((Object)(object)tuple2.Item1 == (Object)null) ? "<i>Unknown</i>" : name(tuple2.Item1.Owner))}{(tuple2.Item3 ? "'s sentry" : string.Empty)} shot {name(tuple2.Item2.Owner)} for {value:0.0}% ({tuple.Item3} bullets)");
}
}
static char hex(float x)
{
return $"{(int)((double)x * 255.0):X2}"[0];
}
static string name(SNet_Player player)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
return $"<#{hex(player.PlayerColor.r)}{hex(player.PlayerColor.g)}{hex(player.PlayerColor.b)}>{player.NickName}</color>";
}
}
[HarmonyPatch(typeof(BulletWeapon), "Fire")]
[HarmonyPrefix]
public static void PreBulletFire(BulletWeapon __instance)
{
s_cachedGearID = ((GameDataBlockBase<GearCategoryDataBlock>)(object)((ItemEquippable)__instance).GearCategoryData).persistentID;
}
[HarmonyPatch(typeof(BulletWeaponSynced), "Fire")]
[HarmonyPrefix]
public static void PreBulletFire_Synced(BulletWeapon __instance)
{
s_cachedGearID = ((GameDataBlockBase<GearCategoryDataBlock>)(object)((ItemEquippable)__instance).GearCategoryData).persistentID;
}
[HarmonyPatch(typeof(SentryGunInstance_Firing_Bullets), "FireBullet")]
[HarmonyPrefix]
public static void PreBulletHit(SentryGunInstance_Firing_Bullets __instance)
{
SentryGunInstance obj = ((Il2CppObjectBase)__instance.m_core).TryCast<SentryGunInstance>();
s_cachedGearID = ((obj != null) ? ((GameDataBlockBase<GearCategoryDataBlock>)(object)((ItemEquippable)obj).GearCategoryData).persistentID : 0u);
}
[HarmonyPatch(typeof(Dam_SyncedDamageBase), "BulletDamage")]
[HarmonyPrefix]
public static bool PreBulletDamage(Dam_SyncedDamageBase __instance, float dam, Agent sourceAgent, Vector3 position, Vector3 direction, Vector3 normal, bool allowDirectionalBonus, float staggerMulti, float precisionMulti, uint gearCategoryId)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
gearCategoryId = s_cachedGearID;
pBulletDamageData val = new pBulletDamageData
{
allowDirectionalBonus = allowDirectionalBonus
};
((UFloat16)(ref val.damage)).Set(dam, __instance.DamageMax);
((LowResVector3_Normalized)(ref val.direction)).Value = direction;
val.gearCategoryId = gearCategoryId;
val.limbID = 0;
((LowResVector3)(ref val.localPosition)).Set(((Component)__instance).transform.InverseTransformPoint(position), 10f);
((UFloat16)(ref val.precisionMulti)).Set(precisionMulti, 10f);
((pAgent)(ref val.source)).Set(sourceAgent);
((UFloat16)(ref val.staggerMulti)).Set(staggerMulti, 10f);
if (__instance.SendLocally())
{
__instance.ReceiveBulletDamage(val);
}
else if (__instance.SendPacket())
{
if (__instance.m_onlyToMaster)
{
__instance.m_bulletDamagePacket.Send(val, (SNet_ChannelType)2, SNet.Master);
}
else
{
__instance.m_bulletDamagePacket.Send(val, (SNet_ChannelType)2);
}
}
return false;
}
}
}