using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using UnityEngine.SceneManagement;
using UnityEngine.VFX;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BloodColor")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BloodColor")]
[assembly: AssemblyTitle("BloodColor")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[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 BloodColor
{
public enum TintMode
{
Replace,
Multiply,
Vanilla
}
internal class BloodConfig
{
public const string DefaultHex = "B01C1C";
private const int DefaultR = 176;
private const int DefaultG = 28;
private const int DefaultB = 28;
public ConfigEntry<string> Hex;
public ConfigEntry<int> R;
public ConfigEntry<int> G;
public ConfigEntry<int> B;
public ConfigEntry<TintMode> Mode;
public ConfigEntry<float> Opacity;
public ConfigEntry<float> Intensity;
public ConfigEntry<bool> EnableBlood;
public ConfigEntry<bool> DoParticles;
public ConfigEntry<bool> DoDecals;
public ConfigEntry<bool> LogEffects;
public Color Tint = Color.red;
private bool _syncing;
public float AlphaFactor => ((Mode.Value == TintMode.Vanilla) ? 1f : Tint.a) * Opacity.Value;
public event Action Changed;
public BloodConfig(ConfigFile file)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: 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_0061: Expected O, but got Unknown
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Expected O, but got Unknown
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Expected O, but got Unknown
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Expected O, but got Unknown
//IL_0149: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Expected O, but got Unknown
Hex = file.Bind<string>("Blood", "Color", "B01C1C", "Blood colour as a hex code, like B01C1C. Paste one from any colour picker. RGB, RRGGBB or RRGGBBAA, # optional, and names like 'red' or 'lime' work too.\nThis and the R/G/B sliders below are the same setting - change either one and the other follows.\nHeads up: you can't type letters into this box from the in-game Mod Menu. Use the sliders there, or edit this file.");
R = file.Bind<int>("Blood", "R", 176, new ConfigDescription("Red, 0-255. Moves with the Color setting.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 255), Array.Empty<object>()));
G = file.Bind<int>("Blood", "G", 28, new ConfigDescription("Green, 0-255. Moves with the Color setting.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 255), Array.Empty<object>()));
B = file.Bind<int>("Blood", "B", 28, new ConfigDescription("Blue, 0-255. Moves with the Color setting.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 255), Array.Empty<object>()));
Mode = file.Bind<TintMode>("Blood", "Mode", TintMode.Replace, "Replace = use your colour as-is.\nMultiply = tint the original, which keeps the built-in shading but can only darken.\nVanilla = don't recolour. Opacity, Intensity and EnableBlood still work.");
Opacity = file.Bind<float>("Blood", "Opacity", 1f, new ConfigDescription("How visible blood is. 1 is normal, 0 is invisible.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
Intensity = file.Bind<float>("Blood", "Intensity", 1f, new ConfigDescription("Brightness. Above 1 goes HDR, which is how you get blood that glows. A hex code can't describe anything brighter than 1 on its own, hence this.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 8f), Array.Empty<object>()));
EnableBlood = file.Bind<bool>("Blood", "EnableBlood", true, "Turn this off for no blood at all. Separate from the game's own Blood option - either one being off means no blood.");
DoParticles = file.Bind<bool>("Targets", "Particles", true, "Recolour the blood spray.");
DoDecals = file.Bind<bool>("Targets", "Decals", true, "Recolour the splatter left on the ground.");
LogEffects = file.Bind<bool>("Advanced", "LogEffects", false, "Dump the blood effects the mod found to the BepInEx log - shaders, materials, VFX properties. Turn this on before reporting a problem.");
PullFromHex();
file.SettingChanged += delegate(object _, SettingChangedEventArgs e)
{
if (!_syncing)
{
if ((object)e.ChangedSetting == Hex)
{
PullFromHex();
}
else if ((object)e.ChangedSetting == R || (object)e.ChangedSetting == G || (object)e.ChangedSetting == B)
{
PullFromSliders();
}
this.Changed?.Invoke();
}
};
}
private void PullFromHex()
{
//IL_0046: 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)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
if (!TryParse(Hex.Value, out var color))
{
Plugin.Log.LogWarning((object)("Couldn't read colour '" + Hex.Value + "', using B01C1C instead."));
TryParse("B01C1C", out color);
}
Tint = color;
_syncing = true;
R.Value = To255(color.r);
G.Value = To255(color.g);
B.Value = To255(color.b);
_syncing = false;
}
private void PullFromSliders()
{
//IL_0042: 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)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
Tint = new Color((float)R.Value / 255f, (float)G.Value / 255f, (float)B.Value / 255f, Tint.a);
_syncing = true;
Hex.Value = ((Tint.a >= 1f) ? ColorUtility.ToHtmlStringRGB(Tint) : ColorUtility.ToHtmlStringRGBA(Tint));
_syncing = false;
}
private static int To255(float v)
{
return Mathf.Clamp(Mathf.RoundToInt(v * 255f), 0, 255);
}
public static bool TryParse(string raw, out Color color)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
color = Color.red;
if (string.IsNullOrEmpty(raw))
{
return false;
}
string text = raw.Trim();
if (text.Length == 0)
{
return false;
}
if (text[0] != '#' && !char.IsLetter(text[0]))
{
text = "#" + text;
}
return ColorUtility.TryParseHtmlString(text, ref color);
}
public Color CombineRgb(Color original)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: 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_00b6: 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)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: 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)
Color val = default(Color);
switch (Mode.Value)
{
case TintMode.Replace:
((Color)(ref val))..ctor(Tint.r, Tint.g, Tint.b, original.a);
break;
case TintMode.Multiply:
((Color)(ref val))..ctor(original.r * Tint.r, original.g * Tint.g, original.b * Tint.b, original.a);
break;
default:
val = original;
break;
}
float value = Intensity.Value;
return new Color(val.r * value, val.g * value, val.b * value, original.a);
}
public Color Combine(Color original)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
Color result = CombineRgb(original);
result.a = Mathf.Clamp01(original.a * AlphaFactor);
return result;
}
}
internal static class BloodTinter
{
private class ParticleTarget
{
public ParticleSystem System;
public string Owner;
public MinMaxGradient Original;
public ParticleSystemRenderer Renderer;
public int ColorProp = -1;
public Color OriginalMaterialColor;
}
private class DecalTarget
{
public string Name;
public List<DecalProjector> Projectors;
public Material Material;
public int ColorProp = -1;
public Color OriginalColor;
public float OriginalFade;
}
private class VfxTarget
{
public VisualEffect Effect;
public string Property;
public bool IsGradient;
public Color OriginalColor;
public Gradient OriginalGradient;
}
private class Original
{
public Material Material;
public float Fade;
}
public static readonly string[] ParticleNames = new string[3] { "Blood", "BloodSmall", "BloodDirectional" };
public const string DecalPrefix = "BloodDecal";
private static readonly string[] DecalNames = new string[3] { "BloodDecal1", "BloodDecal2", "BloodDecal3" };
public const string VfxName = "SmallBloodExplosion";
private static readonly string[] ColorProps = new string[5] { "_BaseColor", "_Color", "_TintColor", "_MainColor", "_UnlitColor" };
private static readonly List<ParticleTarget> Particles = new List<ParticleTarget>();
private static readonly List<DecalTarget> Decals = new List<DecalTarget>();
private static readonly Dictionary<string, Original> Pristine = new Dictionary<string, Original>();
private static VfxTarget Vfx;
private static readonly MaterialPropertyBlock Block = new MaterialPropertyBlock();
private static bool _warnedVfx;
private static bool _warnedDecal;
private static BloodConfig Cfg => Plugin.Cfg;
public static int FindParticles()
{
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: 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_0142: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
List<ParticleTarget> list = new List<ParticleTarget>(Particles);
Particles.Clear();
Dictionary<string, ParticleType> particles = ParticleManager._particles;
if (particles == null || particles.Count == 0)
{
return 0;
}
string[] particleNames = ParticleNames;
foreach (string text in particleNames)
{
if (!particles.TryGetValue(text, out var value) || (Object)(object)value?.ParticleSystem == (Object)null)
{
continue;
}
ParticleSystem[] componentsInChildren = ((Component)value.ParticleSystem).GetComponentsInChildren<ParticleSystem>(true);
foreach (ParticleSystem ps in componentsInChildren)
{
ParticleTarget particleTarget = list.Find((ParticleTarget x) => x.System == ps);
if (particleTarget == null)
{
ParticleTarget obj = new ParticleTarget
{
System = ps,
Owner = text
};
MainModule main = ps.main;
obj.Original = Copy(((MainModule)(ref main)).startColor);
obj.Renderer = ((Component)ps).GetComponent<ParticleSystemRenderer>();
particleTarget = obj;
Material val = (Object.op_Implicit((Object)(object)particleTarget.Renderer) ? ((Renderer)particleTarget.Renderer).sharedMaterial : null);
if ((Object)(object)val != (Object)null)
{
particleTarget.ColorProp = FindColorProp(val);
if (particleTarget.ColorProp >= 0)
{
particleTarget.OriginalMaterialColor = val.GetColor(particleTarget.ColorProp);
}
}
}
Particles.Add(particleTarget);
}
}
return Particles.Count;
}
public static int FindDecals()
{
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Expected O, but got Unknown
//IL_01a2: 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)
List<DecalTarget> list = new List<DecalTarget>(Decals);
Decals.Clear();
Dictionary<string, List<DecalProjector>> decals = DecalManager._decals;
if (decals == null || decals.Count == 0)
{
DestroyMaterials(list);
return 0;
}
string[] decalNames = DecalNames;
foreach (string text in decalNames)
{
if (!decals.TryGetValue(text, out var pool) || pool == null || pool.Count == 0)
{
continue;
}
DecalTarget decalTarget = list.Find((DecalTarget x) => x.Projectors == pool);
if (decalTarget != null)
{
Decals.Add(decalTarget);
continue;
}
DecalProjector val = pool[0];
if ((Object)(object)val == (Object)null)
{
continue;
}
if (!Pristine.TryGetValue(text, out var value) || (Object)(object)value.Material == (Object)null)
{
if ((Object)(object)val.material == (Object)null)
{
continue;
}
value = new Original
{
Material = val.material,
Fade = val.fadeFactor
};
Pristine[text] = value;
}
DecalTarget decalTarget2 = new DecalTarget
{
Name = text,
Projectors = pool,
Material = new Material(value.Material)
{
name = ((Object)value.Material).name + " (BloodColor)"
},
OriginalFade = value.Fade
};
decalTarget2.ColorProp = FindColorProp(decalTarget2.Material);
if (decalTarget2.ColorProp >= 0)
{
decalTarget2.OriginalColor = decalTarget2.Material.GetColor(decalTarget2.ColorProp);
}
else if (!_warnedDecal)
{
_warnedDecal = true;
ManualLogSource log = Plugin.Log;
string[] obj = new string[5] { "Decal ", text, " uses shader '", null, null };
Shader shader = decalTarget2.Material.shader;
obj[3] = ((shader != null) ? ((Object)shader).name : null);
obj[4] = "' and I can't find a colour property on it. Turn on LogEffects and send me the shader name.";
log.LogWarning((object)string.Concat(obj));
}
foreach (DecalProjector item in pool)
{
if ((Object)(object)item != (Object)null)
{
item.material = decalTarget2.Material;
}
}
Decals.Add(decalTarget2);
}
list.RemoveAll((DecalTarget x) => Decals.Contains(x));
DestroyMaterials(list);
return Decals.Count;
}
public static int FindVfx()
{
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: 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)
VfxTarget vfx = Vfx;
Vfx = null;
Dictionary<string, VisualEffect> allVfx = VFXManager._allVfx;
if (allVfx == null || !allVfx.TryGetValue("SmallBloodExplosion", out var value) || (Object)(object)value == (Object)null)
{
return 0;
}
if (vfx != null && vfx.Effect == value)
{
Vfx = vfx;
return 1;
}
foreach (string item in ExposedNames(value))
{
if (value.HasVector4(item))
{
Vfx = new VfxTarget
{
Effect = value,
Property = item,
OriginalColor = Color.op_Implicit(value.GetVector4(item))
};
break;
}
if (value.HasGradient(item))
{
Vfx = new VfxTarget
{
Effect = value,
Property = item,
IsGradient = true,
OriginalGradient = value.GetGradient(item)
};
break;
}
}
if (Vfx == null)
{
if (!_warnedVfx)
{
_warnedVfx = true;
Plugin.Log.LogDebug((object)"SmallBloodExplosion exposes no colour property; gib burst left alone.");
}
return 0;
}
Plugin.Log.LogInfo((object)("SmallBloodExplosion: using property '" + Vfx.Property + "'."));
return 1;
}
public static void ResetVfxWarning()
{
_warnedVfx = false;
}
private static List<string> ExposedNames(VisualEffect effect)
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
List<string> list = new List<string>();
VisualEffectAsset visualEffectAsset = effect.visualEffectAsset;
if ((Object)(object)visualEffectAsset == (Object)null)
{
return list;
}
List<VFXExposedProperty> list2 = new List<VFXExposedProperty>();
try
{
visualEffectAsset.GetExposedProperties(list2);
}
catch (Exception ex)
{
Plugin.Log.LogDebug((object)("Couldn't read exposed properties off SmallBloodExplosion: " + ex.Message));
return list;
}
foreach (VFXExposedProperty item in list2)
{
if (item.type == typeof(Vector4) || item.type == typeof(Color) || item.type == typeof(Gradient))
{
list.Add(item.name);
}
}
return list;
}
public static void Apply()
{
if (Cfg.DoParticles.Value)
{
ApplyParticles();
}
if (Cfg.DoDecals.Value)
{
ApplyDecals();
}
if (Vfx != null && (Object)(object)Vfx.Effect != (Object)null)
{
ApplyVfx();
}
}
private static void ApplyParticles()
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: 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)
//IL_003d: 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)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: 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)
foreach (ParticleTarget particle in Particles)
{
if (!((Object)(object)particle.System == (Object)null))
{
MainModule main = particle.System.main;
((MainModule)(ref main)).startColor = BuildStartColor(particle.Original);
if (!((Object)(object)particle.Renderer == (Object)null) && particle.ColorProp >= 0)
{
Color val = Cfg.CombineRgb(particle.OriginalMaterialColor);
val.a = particle.OriginalMaterialColor.a;
((Renderer)particle.Renderer).GetPropertyBlock(Block);
Block.SetColor(particle.ColorProp, val);
((Renderer)particle.Renderer).SetPropertyBlock(Block);
}
}
}
}
private static void ApplyDecals()
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: 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_005e: Unknown result type (might be due to invalid IL or missing references)
foreach (DecalTarget decal in Decals)
{
if ((Object)(object)decal.Material != (Object)null && decal.ColorProp >= 0)
{
Color val = Cfg.Combine(decal.OriginalColor);
val.a = decal.OriginalColor.a;
decal.Material.SetColor(decal.ColorProp, val);
}
float fadeFactor = Mathf.Clamp01(decal.OriginalFade * Cfg.AlphaFactor);
foreach (DecalProjector projector in decal.Projectors)
{
if ((Object)(object)projector != (Object)null)
{
projector.fadeFactor = fadeFactor;
}
}
}
}
private static void ApplyVfx()
{
//IL_0053: 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_005d: Unknown result type (might be due to invalid IL or missing references)
if (Vfx.IsGradient)
{
Vfx.Effect.SetGradient(Vfx.Property, TintGradient(Vfx.OriginalGradient));
}
else
{
Vfx.Effect.SetVector4(Vfx.Property, Color.op_Implicit(Cfg.Combine(Vfx.OriginalColor)));
}
}
private static MinMaxGradient BuildStartColor(MinMaxGradient src)
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: 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)
//IL_0061: Expected I4, but got Unknown
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
bool flag = Cfg.Mode.Value == TintMode.Vanilla;
float alphaFactor = Cfg.AlphaFactor;
float scale = (flag ? 1f : (1f / Mathf.Max(0.0001f, MaxLuminance(src))));
ParticleSystemGradientMode mode = ((MinMaxGradient)(ref src)).mode;
switch ((int)mode)
{
case 0:
return new MinMaxGradient(Flatten(((MinMaxGradient)(ref src)).color, flag, scale, alphaFactor));
case 2:
return new MinMaxGradient(Flatten(((MinMaxGradient)(ref src)).colorMin, flag, scale, alphaFactor), Flatten(((MinMaxGradient)(ref src)).colorMax, flag, scale, alphaFactor));
case 1:
case 4:
{
MinMaxGradient result = default(MinMaxGradient);
((MinMaxGradient)(ref result))..ctor(FlattenGradient(((MinMaxGradient)(ref src)).gradient, flag, scale, alphaFactor));
((MinMaxGradient)(ref result)).mode = ((MinMaxGradient)(ref src)).mode;
return result;
}
case 3:
return new MinMaxGradient(FlattenGradient(((MinMaxGradient)(ref src)).gradientMin, flag, scale, alphaFactor), FlattenGradient(((MinMaxGradient)(ref src)).gradientMax, flag, scale, alphaFactor));
default:
return src;
}
}
private static Color Flatten(Color c, bool vanilla, float scale, float alpha)
{
//IL_0000: 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_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
float num = Mathf.Clamp01(c.a * alpha);
if (vanilla)
{
return new Color(c.r, c.g, c.b, num);
}
float num2 = Mathf.Clamp01(((Color)(ref c)).grayscale * scale);
return new Color(num2, num2, num2, num);
}
private static Gradient FlattenGradient(Gradient src, bool vanilla, float scale, float alpha)
{
//IL_0022: 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)
//IL_0033: 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)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Expected O, but got Unknown
if (src == null)
{
return null;
}
GradientColorKey[] colorKeys = src.colorKeys;
GradientColorKey[] array = (GradientColorKey[])(object)new GradientColorKey[colorKeys.Length];
for (int i = 0; i < colorKeys.Length; i++)
{
Color val = Flatten(colorKeys[i].color, vanilla, scale, 1f);
array[i] = new GradientColorKey(val, colorKeys[i].time);
}
GradientAlphaKey[] alphaKeys = src.alphaKeys;
GradientAlphaKey[] array2 = (GradientAlphaKey[])(object)new GradientAlphaKey[alphaKeys.Length];
for (int j = 0; j < alphaKeys.Length; j++)
{
array2[j] = new GradientAlphaKey(Mathf.Clamp01(alphaKeys[j].alpha * alpha), alphaKeys[j].time);
}
Gradient val2 = new Gradient
{
mode = src.mode
};
val2.SetKeys(array, array2);
return val2;
}
private static float MaxLuminance(MinMaxGradient g)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected I4, but got Unknown
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//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_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
ParticleSystemGradientMode mode = ((MinMaxGradient)(ref g)).mode;
Color val;
switch ((int)mode)
{
case 0:
val = ((MinMaxGradient)(ref g)).color;
return ((Color)(ref val)).grayscale;
case 2:
{
val = ((MinMaxGradient)(ref g)).colorMin;
float grayscale = ((Color)(ref val)).grayscale;
val = ((MinMaxGradient)(ref g)).colorMax;
return Mathf.Max(grayscale, ((Color)(ref val)).grayscale);
}
case 1:
case 4:
return MaxLuminance(((MinMaxGradient)(ref g)).gradient);
case 3:
return Mathf.Max(MaxLuminance(((MinMaxGradient)(ref g)).gradientMin), MaxLuminance(((MinMaxGradient)(ref g)).gradientMax));
default:
return 1f;
}
}
private static float MaxLuminance(Gradient g)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
if (g == null)
{
return 1f;
}
float num = 0f;
GradientColorKey[] colorKeys = g.colorKeys;
for (int i = 0; i < colorKeys.Length; i++)
{
GradientColorKey val = colorKeys[i];
num = Mathf.Max(num, ((Color)(ref val.color)).grayscale);
}
return num;
}
private static Gradient TintGradient(Gradient src)
{
//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_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: 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_00cf: Expected O, but got Unknown
if (src == null)
{
return null;
}
GradientColorKey[] colorKeys = src.colorKeys;
GradientColorKey[] array = (GradientColorKey[])(object)new GradientColorKey[colorKeys.Length];
for (int i = 0; i < colorKeys.Length; i++)
{
array[i] = new GradientColorKey(Cfg.CombineRgb(colorKeys[i].color), colorKeys[i].time);
}
GradientAlphaKey[] alphaKeys = src.alphaKeys;
GradientAlphaKey[] array2 = (GradientAlphaKey[])(object)new GradientAlphaKey[alphaKeys.Length];
float alphaFactor = Cfg.AlphaFactor;
for (int j = 0; j < alphaKeys.Length; j++)
{
array2[j] = new GradientAlphaKey(Mathf.Clamp01(alphaKeys[j].alpha * alphaFactor), alphaKeys[j].time);
}
Gradient val = new Gradient
{
mode = src.mode
};
val.SetKeys(array, array2);
return val;
}
private static MinMaxGradient Copy(MinMaxGradient src)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected I4, but got Unknown
//IL_0039: 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_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
ParticleSystemGradientMode mode = ((MinMaxGradient)(ref src)).mode;
switch (mode - 1)
{
case 0:
case 3:
{
MinMaxGradient result = default(MinMaxGradient);
((MinMaxGradient)(ref result))..ctor(Copy(((MinMaxGradient)(ref src)).gradient));
((MinMaxGradient)(ref result)).mode = ((MinMaxGradient)(ref src)).mode;
return result;
}
case 2:
return new MinMaxGradient(Copy(((MinMaxGradient)(ref src)).gradientMin), Copy(((MinMaxGradient)(ref src)).gradientMax));
default:
return src;
}
}
private static Gradient Copy(Gradient src)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
if (src == null)
{
return null;
}
Gradient val = new Gradient
{
mode = src.mode
};
val.SetKeys(src.colorKeys, src.alphaKeys);
return val;
}
private static int FindColorProp(Material mat)
{
string[] colorProps = ColorProps;
for (int i = 0; i < colorProps.Length; i++)
{
int num = Shader.PropertyToID(colorProps[i]);
if (mat.HasProperty(num))
{
return num;
}
}
return -1;
}
public static void Clear()
{
Particles.Clear();
DestroyMaterials(Decals);
Decals.Clear();
Pristine.Clear();
Vfx = null;
}
private static void DestroyMaterials(IEnumerable<DecalTarget> targets)
{
foreach (DecalTarget target in targets)
{
if ((Object)(object)target.Material != (Object)null)
{
Object.Destroy((Object)(object)target.Material);
}
}
}
public static void LogEffects()
{
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("---- BloodColor: what I found ----");
stringBuilder.AppendLine($"Particles ({Particles.Count}):");
foreach (ParticleTarget particle in Particles)
{
if (!((Object)(object)particle.System == (Object)null))
{
Material val = (Object.op_Implicit((Object)(object)particle.Renderer) ? ((Renderer)particle.Renderer).sharedMaterial : null);
stringBuilder.AppendLine(" [" + particle.Owner + "] " + PathOf(((Component)particle.System).transform));
stringBuilder.AppendLine($" startColor : {((MinMaxGradient)(ref particle.Original)).mode} {DescribeStartColor(particle.Original)}");
stringBuilder.AppendLine(" material : " + (Object.op_Implicit((Object)(object)val) ? ((Object)val).name : "none"));
stringBuilder.AppendLine(" shader : " + ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.shader)) ? ((Object)val.shader).name : "none"));
stringBuilder.AppendLine(" mat colour : " + MaterialColor(val));
}
}
stringBuilder.AppendLine($"Decals ({Decals.Count}):");
foreach (DecalTarget decal in Decals)
{
stringBuilder.AppendLine($" [{decal.Name}] {decal.Projectors.Count} projectors");
stringBuilder.AppendLine(" shader : " + ((Object.op_Implicit((Object)(object)decal.Material) && Object.op_Implicit((Object)(object)decal.Material.shader)) ? ((Object)decal.Material.shader).name : "none"));
stringBuilder.AppendLine(" colour : " + ((decal.ColorProp >= 0) ? ((object)Unsafe.As<Color, Color>(ref decal.OriginalColor)/*cast due to .constrained prefix*/).ToString() : "no property found"));
stringBuilder.AppendLine($" fade : {decal.OriginalFade}");
}
stringBuilder.AppendLine("VFX SmallBloodExplosion:");
stringBuilder.AppendLine((Vfx == null) ? " no colour property found" : (" using '" + Vfx.Property + "'"));
stringBuilder.Append(VfxProperties());
Plugin.Log.LogInfo((object)stringBuilder.ToString());
}
private static string DescribeStartColor(MinMaxGradient g)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected I4, but got Unknown
//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)
//IL_0044: 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)
ParticleSystemGradientMode mode = ((MinMaxGradient)(ref g)).mode;
switch ((int)mode)
{
case 0:
return ((object)((MinMaxGradient)(ref g)).color/*cast due to .constrained prefix*/).ToString();
case 2:
return $"{((MinMaxGradient)(ref g)).colorMin} .. {((MinMaxGradient)(ref g)).colorMax}";
case 1:
case 4:
{
Gradient gradient = ((MinMaxGradient)(ref g)).gradient;
return $"{((gradient != null) ? gradient.colorKeys.Length : 0)} colour key(s)";
}
case 3:
{
Gradient gradientMin = ((MinMaxGradient)(ref g)).gradientMin;
object arg = ((gradientMin != null) ? gradientMin.colorKeys.Length : 0);
Gradient gradientMax = ((MinMaxGradient)(ref g)).gradientMax;
return $"{arg} + {((gradientMax != null) ? gradientMax.colorKeys.Length : 0)} key(s)";
}
default:
return string.Empty;
}
}
private static string MaterialColor(Material mat)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)mat == (Object)null)
{
return "none";
}
string[] colorProps = ColorProps;
foreach (string text in colorProps)
{
int num = Shader.PropertyToID(text);
if (mat.HasProperty(num))
{
return $"{text} = {mat.GetColor(num)}";
}
}
return "no known colour property";
}
private static string VfxProperties()
{
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: 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)
Dictionary<string, VisualEffect> allVfx = VFXManager._allVfx;
if (allVfx == null || !allVfx.TryGetValue("SmallBloodExplosion", out var value) || (Object)(object)value == (Object)null)
{
return " (not in this scene)\n";
}
StringBuilder stringBuilder = new StringBuilder();
VisualEffectAsset visualEffectAsset = value.visualEffectAsset;
stringBuilder.AppendLine(" asset : " + (((Object)(object)visualEffectAsset != (Object)null) ? ((Object)visualEffectAsset).name : "none"));
if ((Object)(object)visualEffectAsset == (Object)null)
{
return stringBuilder.ToString();
}
List<VFXExposedProperty> list = new List<VFXExposedProperty>();
try
{
visualEffectAsset.GetExposedProperties(list);
}
catch (Exception ex)
{
stringBuilder.AppendLine(" (couldn't read exposed properties: " + ex.Message + ")");
return stringBuilder.ToString();
}
if (list.Count == 0)
{
stringBuilder.AppendLine(" exposes nothing at all - this effect can't be recoloured");
return stringBuilder.ToString();
}
stringBuilder.AppendLine($" exposes ({list.Count}):");
foreach (VFXExposedProperty item in list)
{
stringBuilder.AppendLine(" " + item.name + " : " + item.type?.Name);
}
return stringBuilder.ToString();
}
private static string PathOf(Transform t)
{
StringBuilder stringBuilder = new StringBuilder(((Object)t).name);
Transform parent = t.parent;
while ((Object)(object)parent != (Object)null)
{
stringBuilder.Insert(0, ((Object)parent).name + "/");
parent = parent.parent;
}
return stringBuilder.ToString();
}
}
[HarmonyPatch(typeof(ParticleManager), "Awake")]
internal static class ParticleManagerAwake
{
private static void Postfix()
{
Plugin.QueueRefresh();
}
}
[HarmonyPatch(typeof(DecalManager), "Awake")]
internal static class DecalManagerAwake
{
private static void Postfix()
{
Plugin.QueueRefresh();
}
}
[HarmonyPatch(typeof(VFXManager), "Awake")]
internal static class VfxManagerAwake
{
private static void Postfix()
{
Plugin.QueueRefresh();
}
}
[HarmonyPatch(typeof(ParticleManager), "Play", new Type[]
{
typeof(string),
typeof(Vector3),
typeof(Vector3)
})]
internal static class ParticleManagerPlay
{
private static bool Prefix(string type)
{
if (!Plugin.BloodOff)
{
return true;
}
string[] particleNames = BloodTinter.ParticleNames;
foreach (string b in particleNames)
{
if (string.Equals(type, b, StringComparison.Ordinal))
{
return false;
}
}
return true;
}
}
[HarmonyPatch(typeof(DecalManager), "SpawnDecal")]
internal static class DecalManagerSpawnDecal
{
private static bool Prefix(string decalName)
{
if (Plugin.BloodOff && decalName != null)
{
return !decalName.StartsWith("BloodDecal", StringComparison.Ordinal);
}
return true;
}
}
[HarmonyPatch(typeof(VFXManager), "Play", new Type[]
{
typeof(string),
typeof(Vector3),
typeof(Vector3)
})]
internal static class VfxManagerPlay
{
private static bool Prefix(string type)
{
if (Plugin.BloodOff)
{
return !string.Equals(type, "SmallBloodExplosion", StringComparison.Ordinal);
}
return true;
}
}
[BepInPlugin("com.zoe.howtofish.bloodcolor", "BloodColor", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public const string Guid = "com.zoe.howtofish.bloodcolor";
public const string Name = "BloodColor";
public const string Version = "1.0.0";
internal static ManualLogSource Log;
internal static BloodConfig Cfg;
internal static bool BloodOff;
private Harmony _harmony;
private static bool _refreshQueued;
private bool _loggedFailure;
private void Awake()
{
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
Cfg = new BloodConfig(((BaseUnityPlugin)this).Config);
BloodOff = !Cfg.EnableBlood.Value;
Cfg.Changed += OnConfigChanged;
try
{
_harmony = new Harmony("com.zoe.howtofish.bloodcolor");
_harmony.PatchAll(typeof(Plugin).Assembly);
}
catch (Exception ex)
{
Log.LogError((object)("Couldn't apply patches, BloodColor is doing nothing this session. Probably a game update moved something, see Patches.cs.\n" + ex));
return;
}
SceneManager.sceneLoaded += OnSceneLoaded;
QueueRefresh();
Log.LogInfo((object)string.Format("{0} {1} loaded. Colour {2}, mode {3}.", "BloodColor", "1.0.0", Cfg.Hex.Value, Cfg.Mode.Value));
}
private void OnDestroy()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
if (Cfg != null)
{
Cfg.Changed -= OnConfigChanged;
}
BloodTinter.Clear();
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
internal static void QueueRefresh()
{
_refreshQueued = true;
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
QueueRefresh();
}
private void Update()
{
if (!_refreshQueued)
{
return;
}
_refreshQueued = false;
try
{
Refresh();
}
catch (Exception arg)
{
if (!_loggedFailure)
{
_loggedFailure = true;
Log.LogError((object)$"Refresh failed, not going to report this again: {arg}");
}
}
}
private void Refresh()
{
int num = BloodTinter.FindParticles();
int num2 = BloodTinter.FindDecals();
int num3 = BloodTinter.FindVfx();
if (num + num2 + num3 != 0)
{
BloodTinter.Apply();
string arg = ((num3 > 0) ? $", {num3} vfx" : string.Empty);
Log.LogInfo((object)$"Recoloured {num} particle systems, {num2} decal pools{arg}.");
if (Cfg.LogEffects.Value)
{
BloodTinter.LogEffects();
}
}
}
private void OnConfigChanged()
{
BloodOff = !Cfg.EnableBlood.Value;
try
{
BloodTinter.Apply();
if (Cfg.LogEffects.Value)
{
BloodTinter.LogEffects();
}
Log.LogInfo((object)($"Config changed: {Cfg.Hex.Value}, {Cfg.Mode.Value}, opacity {Cfg.Opacity.Value}, " + string.Format("intensity {0}, blood {1}.", Cfg.Intensity.Value, Cfg.EnableBlood.Value ? "on" : "off")));
}
catch (Exception arg)
{
Log.LogError((object)$"Couldn't apply that config change: {arg}");
}
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}