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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Il2CppInterop.Runtime.Injection;
using Microsoft.CodeAnalysis;
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("ProperSmoke")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ProperSmoke")]
[assembly: AssemblyTitle("ProperSmoke")]
[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.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 ProperSmoke
{
[BepInPlugin("ekem.propersmoke", "Proper Smoke", "1.0.0")]
public class Plugin : BasePlugin
{
public static ManualLogSource Log { get; private set; }
public static Settings Cfg { get; private set; }
public override void Load()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Expected O, but got Unknown
Log = ((BasePlugin)this).Log;
Cfg = new Settings(((BasePlugin)this).Config);
ClassInjector.RegisterTypeInIl2Cpp<Heartbeat>();
GameObject val = new GameObject("Proper Smoke Heartbeat");
Object.DontDestroyOnLoad((Object)val);
((Object)val).hideFlags = (HideFlags)61;
val.AddComponent<Heartbeat>();
ManualLogSource log = Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(9, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("Proper Smoke");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("1.0.0");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" loaded.");
}
log.LogInfo(val2);
}
}
public class Heartbeat : MonoBehaviour
{
public Heartbeat(IntPtr pointer)
: base(pointer)
{
}
private void Update()
{
SmokeFix.Tick();
}
}
public class Settings
{
public readonly ConfigEntry<bool> DebugLogging;
public Settings(ConfigFile config)
{
DebugLogging = config.Bind<bool>("Debug", "DebugLogging", false, "Logs which particle systems were found and what was done with them.");
}
}
public static class PluginInfo
{
public const string Guid = "ekem.propersmoke";
public const string Name = "Proper Smoke";
public const string Version = "1.0.0";
}
public static class SmokeFix
{
private sealed class Cigarette
{
public ParticleSystem Source;
public ParticleSystem Emitter;
public float Size;
public float Lifetime;
public float BreathFrom;
public float Rate = -1f;
public float EmitSize = -1f;
public float Speed = -1f;
}
private const float ScanEvery = 0.5f;
private const float SmolderRate = 8f;
private const float BreathRate = 30f;
private const float BreathSize = 1.6f;
private const float BreathSpeed = 0.35f;
private const float BreathPeriod = 8f;
private const float InhaleShare = 0.3f;
private const float ExhaleShare = 0.35f;
private const float AfterDraw = 3f;
private const float DrawExhaleRate = 45f;
private const float DrawExhaleSize = 2.5f;
private const float DrawExhaleSpeed = 0.5f;
private const float MaxLifetime = 4f;
private const int MaxParticles = 400;
private const float Alpha = 0.25f;
private const float RiseSpeed = 0.08f;
private const float ShapeScale = 0.02f;
private static float _nextScan;
private static readonly HashSet<int> Seen = new HashSet<int>();
private static readonly List<Cigarette> Lit = new List<Cigarette>();
private static bool _toking;
private static float _scanUntil;
public static void Tick()
{
if (Time.unscaledTime >= _nextScan || Time.time < _scanUntil)
{
_nextScan = Time.unscaledTime + 0.5f;
FirstPersonItemController instance = FirstPersonItemController.Instance;
if ((Object)(object)instance != (Object)null)
{
Scan(((Component)instance).gameObject);
}
Camera main = Camera.main;
if ((Object)(object)main != (Object)null)
{
Scan(((Component)main).gameObject);
}
}
for (int num = Lit.Count - 1; num >= 0; num--)
{
if (!Smoke(Lit[num]))
{
Lit.RemoveAt(num);
}
}
}
private static void Scan(GameObject root)
{
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Expected O, but got Unknown
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Expected O, but got Unknown
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
bool flag = default(bool);
foreach (ParticleSystem componentsInChild in root.GetComponentsInChildren<ParticleSystem>(true))
{
if ((Object)(object)componentsInChild == (Object)null || !Seen.Add(((Object)componentsInChild).GetInstanceID()))
{
continue;
}
string name = ((Object)((Component)componentsInChild).gameObject).name;
string text = name.ToLowerInvariant();
if (text.Contains("cigar"))
{
Replace(componentsInChild);
}
else if (text.Contains("smok"))
{
componentsInChild.emission.enabled = false;
componentsInChild.Stop(true, (ParticleSystemStopBehavior)0);
if (Plugin.Cfg.DebugLogging.Value)
{
ManualLogSource log = Plugin.Log;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(17, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("smoke '");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' silenced");
}
log.LogInfo(val);
}
}
else if (Plugin.Cfg.DebugLogging.Value)
{
ManualLogSource log2 = Plugin.Log;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(26, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("particles '");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<ParticleSystemSimulationSpace>(componentsInChild.main.simulationSpace);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(") left as is");
}
log2.LogInfo(val);
}
}
}
private static void Replace(ParticleSystem source)
{
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Expected O, but got Unknown
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
MainModule main = source.main;
MinMaxCurve startLifetime = main.startLifetime;
float num = Mathf.Max(new float[3] { startLifetime.m_ConstantMax, startLifetime.m_ConstantMin, 1f }) * Mathf.Max(main.startLifetimeMultiplier, 0.01f);
if (Plugin.Cfg.DebugLogging.Value)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(61, 4, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("cigarette smoke: was rate ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(source.emission.rateOverTimeMultiplier, "0.##");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("/s, ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("size x");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(main.startSizeMultiplier, "0.###");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", lifetime ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num, "0.##");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("s, ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("lossyScale ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(((Component)source).transform.lossyScale.x, "0.###");
}
log.LogInfo(val);
}
ParticleSystem val2 = NewEmitter(source);
if (!((Object)(object)val2 == (Object)null))
{
source.emission.enabled = false;
Lit.Add(new Cigarette
{
Source = source,
Emitter = val2,
Size = Mathf.Max(main.startSizeMultiplier, 0.03f),
Lifetime = Mathf.Min(num, 4f),
BreathFrom = Time.time
});
}
}
private static ParticleSystem? NewEmitter(ParticleSystem source)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Expected O, but got Unknown
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: 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_0040: 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)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Expected O, but got Unknown
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Expected O, but got Unknown
Step("create");
GameObject val = new GameObject("Proper SmokeCigaretteSmoke");
Object.DontDestroyOnLoad((Object)(object)val);
val.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
val.transform.rotation = Quaternion.FromToRotation(Vector3.forward, Vector3.up);
val.transform.localScale = Vector3.one * 0.02f;
ParticleSystem val2 = val.AddComponent<ParticleSystem>();
val2.emission.rateOverTime = new MinMaxCurve(0f);
MainModule main = val2.main;
main.simulationSpace = (ParticleSystemSimulationSpace)1;
main.scalingMode = (ParticleSystemScalingMode)2;
main.maxParticles = 400;
main.startSpeedMultiplier = 0.08f;
main.startLifetimeMultiplier = Mathf.Min(source.main.startLifetimeMultiplier, 4f);
main.startSizeMultiplier = Mathf.Max(source.main.startSizeMultiplier, 0.03f);
main.startColor = new MinMaxGradient(new Color(1f, 1f, 1f, 0.25f));
Step("material");
ParticleSystemRenderer component = val.GetComponent<ParticleSystemRenderer>();
ParticleSystemRenderer component2 = ((Component)source).GetComponent<ParticleSystemRenderer>();
if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)((Renderer)component2).sharedMaterial == (Object)null)
{
Plugin.Log.LogWarning((object)"no smoke material to borrow, leaving the game's smoke alone");
Object.Destroy((Object)(object)val);
return null;
}
((Renderer)component).sharedMaterial = ((Renderer)component2).sharedMaterial;
val2.Play();
Step("ready");
return val2;
}
private static void Step(string what)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
if (Plugin.Cfg.DebugLogging.Value)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(15, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("smoke emitter: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(what);
}
log.LogInfo(val);
}
}
private static bool Smoke(Cigarette c)
{
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Expected O, but got Unknown
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Expected O, but got Unknown
//IL_026e: Unknown result type (might be due to invalid IL or missing references)
//IL_0278: Expected O, but got Unknown
//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
//IL_032d: Unknown result type (might be due to invalid IL or missing references)
//IL_0332: Unknown result type (might be due to invalid IL or missing references)
//IL_0334: Unknown result type (might be due to invalid IL or missing references)
//IL_0354: Unknown result type (might be due to invalid IL or missing references)
//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0307: Unknown result type (might be due to invalid IL or missing references)
//IL_030c: Unknown result type (might be due to invalid IL or missing references)
//IL_0311: Unknown result type (might be due to invalid IL or missing references)
//IL_0315: Unknown result type (might be due to invalid IL or missing references)
//IL_031b: Unknown result type (might be due to invalid IL or missing references)
//IL_0320: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)c.Emitter == (Object)null)
{
return false;
}
if ((Object)(object)c.Source == (Object)null)
{
Object.Destroy((Object)(object)((Component)c.Emitter).gameObject, c.Lifetime + 1f);
return false;
}
if (!((Component)c.Source).gameObject.activeInHierarchy)
{
if (c.Rate != 0f)
{
c.Rate = 0f;
c.Emitter.emission.rateOverTime = new MinMaxCurve(0f);
}
return true;
}
float num = 0f;
FirstPersonItemController instance = FirstPersonItemController.Instance;
bool flag = (Object)(object)instance != (Object)null && instance.smokingTokeActive;
if (flag != _toking)
{
_toking = flag;
if (Plugin.Cfg.DebugLogging.Value)
{
ManualLogSource log = Plugin.Log;
bool flag2 = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(11, 1, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("cigarette: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(flag ? "drawing" : "not drawing");
}
log.LogInfo(val);
}
}
float num2 = 0f;
float num3;
if (flag)
{
num3 = 0f;
c.BreathFrom = Time.time + 3f;
_scanUntil = c.BreathFrom;
}
else if (Time.time < c.BreathFrom)
{
float num4 = 1f - (c.BreathFrom - Time.time) / 3f;
num2 = Mathf.Sin((float)Math.PI * Mathf.Clamp01(num4));
num = num2;
num3 = Mathf.Lerp(8f, 45f, num2);
}
else
{
float num5 = (Time.time - c.BreathFrom) % 8f / 8f;
if (num5 < 0.3f)
{
num3 = 0f;
}
else
{
float num6 = num5 - 0.3f;
if (num6 < 0.35f)
{
num = Mathf.Sin((float)Math.PI * num6 / 0.35f);
}
num3 = Mathf.Lerp(8f, 30f, num);
}
}
float num7 = c.Size * ((num2 > 0f) ? Mathf.Lerp(1f, 2.5f, num2) : Mathf.Lerp(1f, 1.6f, num));
float num8 = ((num2 > 0f) ? Mathf.Lerp(0.08f, 0.5f, num2) : Mathf.Lerp(0.08f, 0.35f, num));
if (Mathf.Abs(num3 - c.Rate) > 0.5f)
{
c.Rate = num3;
c.Emitter.emission.rateOverTime = new MinMaxCurve(num3);
}
if (Mathf.Abs(num7 - c.EmitSize) > 0.005f || Mathf.Abs(num8 - c.Speed) > 0.01f)
{
c.EmitSize = num7;
c.Speed = num8;
MainModule main = c.Emitter.main;
main.startSizeMultiplier = num7;
main.startSpeedMultiplier = num8;
}
Camera main2 = Camera.main;
Vector3 val2 = Vector3.up;
if ((Object)(object)main2 != (Object)null && num > 0f)
{
Vector3 up = Vector3.up;
Vector3 val3 = ((Component)main2).transform.forward + Vector3.up * 0.2f;
val2 = Vector3.Slerp(up, ((Vector3)(ref val3)).normalized, num);
}
((Component)c.Emitter).transform.rotation = Quaternion.FromToRotation(Vector3.forward, val2);
((Component)c.Emitter).transform.position = ((Component)c.Source).transform.position;
return true;
}
}
}