using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BleedingMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("BleedingMod")]
[assembly: AssemblyTitle("BleedingMod")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 BleedingMod
{
[BepInPlugin("com.tambistudios.bleeding", "Bleeding", "0.1.0")]
public class BleedingPlugin : BaseUnityPlugin
{
public const string MOD_GUID = "com.tambistudios.bleeding";
public const string MOD_NAME = "Bleeding";
public const string MOD_VERSION = "0.1.0";
public static BleedingPlugin Instance;
public static ManualLogSource Logger;
public const float THRESHOLD_NORMAL = 20f;
public const float THRESHOLD_LOW = 30f;
public const float THRESHOLD_HIGH = 10f;
public const float DURATION_NORMAL = 30f;
public const float DURATION_LOW = 20f;
public const float DURATION_HIGH = 60f;
internal static readonly Color ColRed = new Color(0.85f, 0.05f, 0.05f, 1f);
internal static readonly Color ColBrt = new Color(1f, 0.25f, 0.25f, 1f);
private Texture2D _guiTex;
private Texture2D _dropTex;
private float _pulseTimer;
private float _flashTimer;
private void Awake()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
Instance = this;
Logger = ((BaseUnityPlugin)this).Logger;
new Harmony("com.tambistudios.bleeding").PatchAll();
Logger.LogInfo((object)"[Bleeding 0.1.0] Loaded.");
}
public static float GetFallThreshold()
{
try
{
float fallDamageMultiplier = Ascents.fallDamageMultiplier;
if (fallDamageMultiplier <= 0.001f)
{
return -1f;
}
if (fallDamageMultiplier <= 0.6f)
{
return 30f;
}
if (fallDamageMultiplier <= 1.5f)
{
return 20f;
}
return 10f;
}
catch
{
return 20f;
}
}
public static float GetBleedDuration()
{
try
{
float fallDamageMultiplier = Ascents.fallDamageMultiplier;
if (fallDamageMultiplier <= 0.001f)
{
return 30f;
}
if (fallDamageMultiplier <= 0.6f)
{
return 20f;
}
if (fallDamageMultiplier <= 1.5f)
{
return 30f;
}
return 60f;
}
catch
{
return 30f;
}
}
private void Update()
{
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
Character localCharacter = Character.localCharacter;
if ((Object)(object)localCharacter != (Object)null && (Object)(object)((Component)localCharacter).GetComponent<BleedingTracker>() == (Object)null)
{
((Component)localCharacter).gameObject.AddComponent<BleedingTracker>();
}
if (Input.GetKeyDown((KeyCode)285) && (Object)(object)localCharacter != (Object)null)
{
Rigidbody componentInChildren = ((Component)localCharacter).GetComponentInChildren<Rigidbody>();
if ((Object)(object)componentInChildren != (Object)null)
{
Vector3 linearVelocity = componentInChildren.linearVelocity;
linearVelocity.y = 22f;
componentInChildren.linearVelocity = linearVelocity;
Logger.LogInfo((object)"[Bleeding] DEBUG: launched up ~25m");
}
}
BleedingTracker localInstance = BleedingTracker.LocalInstance;
if ((Object)(object)localInstance != (Object)null && localInstance.isBleeding)
{
float num = 0.8f + localInstance.severity * 0.35f;
_pulseTimer += Time.deltaTime * num;
}
else
{
_pulseTimer = 0f;
}
if (_flashTimer > 0f)
{
_flashTimer = Mathf.Max(0f, _flashTimer - Time.deltaTime);
}
}
private static Texture2D LoadDropTexture()
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Expected O, but got Unknown
try
{
string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "assets", "blood.png");
if (File.Exists(path))
{
byte[] array = File.ReadAllBytes(path);
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
((Texture)val).filterMode = (FilterMode)1;
if (ImageConversion.LoadImage(val, array))
{
Logger.LogInfo((object)"[Bleeding] Loaded blood.png from assets.");
return val;
}
}
}
catch (Exception ex)
{
Logger.LogWarning((object)("[Bleeding] LoadDropTexture: " + ex.Message));
}
Logger.LogInfo((object)"[Bleeding] assets/blood.png not found, using procedural drop.");
return MakeDropTexture(64);
}
private static Texture2D MakeDropTexture(int size)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Expected O, but got Unknown
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
Texture2D val = new Texture2D(size, size, (TextureFormat)4, false);
((Texture)val).filterMode = (FilterMode)1;
((Texture)val).wrapMode = (TextureWrapMode)1;
float num = (float)size * 0.5f;
float num2 = (float)size * 0.42f;
float num3 = (float)size * 0.3f;
float num4 = (float)size * 0.94f;
Color32[] array = (Color32[])(object)new Color32[size * size];
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
float num5 = (float)j + 0.5f;
float num6 = (float)i + 0.5f;
float num7 = num5 - num;
float num8 = num6 - num2;
bool flag = num7 * num7 + num8 * num8 <= num3 * num3;
float num9 = ((num6 >= num2 && num6 <= num4) ? ((num4 - num6) / (num4 - num2) * num3) : 0f);
bool num10 = num6 > num2 && num6 <= num4 && Mathf.Abs(num5 - num) <= num9;
float num11 = Mathf.Sqrt(num7 * num7 + num8 * num8);
float num12 = Mathf.Clamp01(1f - (num11 - num3 + 1.5f) / 1.5f);
byte b = (num10 ? byte.MaxValue : (flag ? byte.MaxValue : ((byte)(num12 * 255f))));
array[i * size + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, b);
}
}
val.SetPixels32(array);
val.Apply();
return val;
}
internal void TriggerHurtEffect(Character local)
{
_flashTimer = 1f;
try
{
Type typeFromHandle = typeof(IllegalScreenEffect);
FieldInfo field = typeFromHandle.GetField("character", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
MethodInfo method = typeFromHandle.GetMethod("AddStatus", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2]
{
typeof(string),
typeof(float)
}, null);
IllegalScreenEffect[] array = Object.FindObjectsOfType<IllegalScreenEffect>();
foreach (IllegalScreenEffect obj in array)
{
object? obj2 = field?.GetValue(obj);
if (!((Object)((obj2 is Character) ? obj2 : null) != (Object)(object)local))
{
method?.Invoke(obj, new object[2] { "Injury", 1f });
Logger.LogInfo((object)"[Bleeding] Game hurt screen effect triggered.");
break;
}
}
}
catch (Exception ex)
{
Logger.LogWarning((object)("[Bleeding] HurtEffect err: " + ex.Message));
}
}
private void OnGUI()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Invalid comparison between Unknown and I4
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
//IL_0149: 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_01a7: Unknown result type (might be due to invalid IL or missing references)
if ((int)Event.current.type != 7)
{
return;
}
if ((Object)(object)_guiTex == (Object)null)
{
_guiTex = new Texture2D(1, 1);
_guiTex.SetPixel(0, 0, Color.white);
_guiTex.Apply();
}
Color color = GUI.color;
BleedingTracker localInstance = BleedingTracker.LocalInstance;
bool num = (Object)(object)localInstance != (Object)null && localInstance.isBleeding;
float num2 = _pulseTimer % 1f;
float num3 = ((num2 < 0.2f) ? (num2 / 0.2f) : (1f - (num2 - 0.2f) / 0.8f));
if (num)
{
float num4 = Mathf.Min(localInstance.severity, 5f);
float num5 = 0.2f + num4 * 0.03f;
GUI.color = new Color(0.6f, 0f, 0f, num5 + num3 * 0.04f);
GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)_guiTex);
}
if (_flashTimer > 0f)
{
GUI.color = new Color(0.55f, 0f, 0f, _flashTimer * 0.5f);
GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)_guiTex);
}
if (num)
{
if ((Object)(object)_dropTex == (Object)null)
{
_dropTex = LoadDropTexture();
}
if ((Object)(object)_dropTex != (Object)null)
{
GUI.color = Color.white;
GUI.DrawTexture(new Rect((float)Screen.width - 112f, 16f, 96f, 96f), (Texture)(object)_dropTex);
}
}
GUI.color = color;
}
}
public class BleedingTracker : MonoBehaviour
{
public static BleedingTracker LocalInstance;
public static bool s_isBleeding = false;
public static float s_severity = 0f;
public static float s_bleedStart = -999f;
private float _peakFallSpeed;
private bool _wasFalling;
private Character _char;
private Rigidbody _rb;
private bool _loggedInit;
public bool isBleeding
{
get
{
return s_isBleeding;
}
set
{
s_isBleeding = value;
}
}
public float severity
{
get
{
return s_severity;
}
set
{
s_severity = value;
}
}
public float bleedStart
{
get
{
return s_bleedStart;
}
set
{
s_bleedStart = value;
}
}
private void Awake()
{
_char = ((Component)this).GetComponent<Character>();
_rb = ((Component)this).GetComponentInChildren<Rigidbody>();
}
private void Update()
{
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_char == (Object)null || (Object)(object)Character.localCharacter != (Object)(object)_char)
{
return;
}
LocalInstance = this;
if (!_loggedInit)
{
_loggedInit = true;
BleedingPlugin.Logger.LogInfo((object)("[Bleeding] Tracker active. rb=" + (((Object)(object)_rb != (Object)null) ? ((Object)_rb).name : "NULL")));
}
if (s_isBleeding && Time.time - s_bleedStart >= BleedingPlugin.GetBleedDuration())
{
s_isBleeding = false;
s_severity = 0f;
s_bleedStart = -999f;
BleedingPlugin.Logger.LogInfo((object)"[Bleeding] Naturally healed.");
}
if ((Object)(object)_rb == (Object)null)
{
return;
}
float y = _rb.linearVelocity.y;
if (y < -4f)
{
_wasFalling = true;
_peakFallSpeed = Mathf.Max(_peakFallSpeed, 0f - y);
}
else
{
if (!_wasFalling || !(y > -2f))
{
return;
}
float num = _peakFallSpeed * _peakFallSpeed / 19.62f;
float fallThreshold = BleedingPlugin.GetFallThreshold();
BleedingPlugin.Logger.LogInfo((object)$"[Bleeding] Impact detected: peakSpeed={_peakFallSpeed:F1} m/s, fallH≈{num:F1}m, thresh={fallThreshold}m");
if (fallThreshold > 0f && num >= fallThreshold)
{
float num2 = Mathf.Min(num / fallThreshold, 5f);
if (!s_isBleeding)
{
s_bleedStart = Time.time;
}
s_isBleeding = true;
s_severity = Mathf.Max(s_severity, num2);
BleedingPlugin.Logger.LogInfo((object)$"[Bleeding] Bleeding triggered! Severity={s_severity:F2}");
BleedingPlugin.Instance?.TriggerHurtEffect(_char);
}
_wasFalling = false;
_peakFallSpeed = 0f;
}
}
public void CureBleeding()
{
if (s_isBleeding)
{
s_isBleeding = false;
s_severity = 0f;
s_bleedStart = -999f;
BleedingPlugin.Logger.LogInfo((object)"[Bleeding] Cured by item.");
}
}
}
[HarmonyPatch(typeof(Character), "Awake")]
internal static class Patch_Character_Awake
{
[HarmonyPostfix]
private static void Postfix(Character __instance)
{
if ((Object)(object)((Component)__instance).GetComponent<BleedingTracker>() == (Object)null)
{
((Component)__instance).gameObject.AddComponent<BleedingTracker>();
}
}
}
[HarmonyPatch(typeof(Character), "CanRegenStamina")]
internal static class Patch_CanRegenStamina
{
[HarmonyPostfix]
private static void Postfix(Character __instance, ref bool __result)
{
if (__instance.IsLocal)
{
BleedingTracker component = ((Component)__instance).GetComponent<BleedingTracker>();
if ((Object)(object)component != (Object)null && component.isBleeding)
{
__result = false;
}
}
}
}
[HarmonyPatch(typeof(Action_ClearAllStatus), "RunAction")]
internal static class Patch_ClearAllStatus
{
private static readonly FieldInfo _itemField = AccessTools.Field(typeof(Action_ClearAllStatus), "item");
[HarmonyPostfix]
private static void Postfix(Action_ClearAllStatus __instance)
{
try
{
object? obj = _itemField?.GetValue(__instance);
object? obj2 = ((obj is Item) ? obj : null);
Character val = ((obj2 != null) ? ((Item)obj2).holderCharacter : null);
if (!((Object)(object)val == (Object)null) && val.IsLocal)
{
((Component)val).GetComponent<BleedingTracker>()?.CureBleeding();
}
}
catch (Exception ex)
{
BleedingPlugin.Logger.LogWarning((object)("[Bleeding] ClearAllStatus patch error: " + ex.Message));
}
}
}
}