using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
[assembly: AssemblyProduct("Pixel Smoke Fx")]
[assembly: AssemblyDescription("Low-poly 3D smoke for Ravenfield bullet hits - zero assets, zero particles. Player-fire exemption, distance/frustum culling, pooled.")]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyTitle("Pixel Smoke Fx")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("1.1.0.0")]
namespace PixelSmokeFx;
[BepInPlugin("com.local.pixelsmokefx", "Pixel Smoke Fx", "1.1.0")]
public class FxPlugin : BaseUnityPlugin
{
public static class SpawnDecal_Patch
{
private static void Prefix(Projectile __instance, RaycastHit hitInfo)
{
//IL_027c: Unknown result type (might be due to invalid IL or missing references)
//IL_0273: Unknown result type (might be due to invalid IL or missing references)
//IL_0281: Unknown result type (might be due to invalid IL or missing references)
//IL_0285: Unknown result type (might be due to invalid IL or missing references)
//IL_0286: Unknown result type (might be due to invalid IL or missing references)
//IL_0287: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
try
{
if (!EnabledCfg)
{
return;
}
if ((Object)(object)TemplatePlugin == (Object)null)
{
if (++_hitNoTemplate % 500 == 0 && Log != null)
{
Log.LogWarning((object)("PixelSmokeFx: " + _hitNoTemplate + " hits arrived while template missing"));
}
}
else
{
if (__instance is ExplodingProjectile)
{
return;
}
string text = (((Object)(object)__instance.sourceWeapon != (Object)null) ? ((Object)__instance.sourceWeapon).name : null);
if (TargetWeapon.Length > 0 && (string.IsNullOrEmpty(text) || text.IndexOf(TargetWeapon, StringComparison.OrdinalIgnoreCase) < 0))
{
return;
}
Vector3 point = ((RaycastHit)(ref hitInfo)).point;
Vector3 normal = ((RaycastHit)(ref hitInfo)).normal;
bool flag = AlwaysRenderPlayer && IsPlayerFire(__instance);
Camera val = MainCam();
float num = (((Object)(object)val != (Object)null) ? Vector3.Distance(((Component)val).transform.position, point) : 0f);
if ((!flag && num >= HalfDist) || (!flag && !IsOnScreen(point)))
{
return;
}
float time = Time.time;
string key = ((text != null) ? text : "");
if (!_lastGunTime.TryGetValue(key, out var value) || !(time - value < BurstWindow))
{
if (time - _lastGlobalTime < GlobalCooldown || (_lastGunTime.TryGetValue(key, out value) && time - value < GunCooldown))
{
return;
}
_lastGlobalTime = time;
}
_lastGunTime[key] = time;
float caliber = 800f;
float num2 = -1f;
try
{
if (__instance.configuration != null)
{
Type type = ((object)__instance.configuration).GetType();
num2 = ReadDamage(__instance.configuration);
if (num2 < 0f)
{
num2 = ReadDamage(__instance);
}
if (_speedProp == null || _speedPropType != type)
{
_speedPropType = type;
_speedProp = type.GetProperty("speed");
}
if (_speedProp != null)
{
object value2 = _speedProp.GetValue(__instance.configuration, null);
if (value2 != null && value2 is float && (float)value2 > 50f)
{
caliber = (float)value2;
}
}
}
}
catch (Exception)
{
}
Transform transform = ((Component)__instance).transform;
Vector3 flight = (((Object)(object)transform != (Object)null) ? transform.forward : Vector3.up);
SpawnEffect(key, point, normal, flight, num, caliber, num2);
}
}
catch (Exception ex2)
{
if (Log != null)
{
Log.LogWarning((object)("PixelSmokeFx: spawn: " + ex2));
}
}
}
}
private const int TEMPLATE_ATTEMPT_LIMIT = 10;
internal static FxPlugin Instance;
internal static ManualLogSource Log;
internal static string TargetWeapon = "";
internal static int PoolSize = 120;
internal static float GlobalCooldown = 0.005f;
internal static float GunCooldown = 0.02f;
internal static float BurstWindow = 0.08f;
internal static float FullDist = 60f;
internal static float HalfDist = 200f;
internal static float Lifetime = 1.5f;
internal static float ExpandTime = 0.15f;
internal static float DecayRate = 2.2f;
internal static float BaseScale = 0.7f;
internal static float DamageRef = 40f;
internal static float MinSizeFactor = 0.5f;
internal static float MaxSizeFactor = 1.5f;
internal static float ShotgunFactor = 0.25f;
internal static bool EnabledCfg = true;
internal static bool AlwaysRenderPlayer = true;
internal static bool AutoTestCfg;
private static bool _autoTestStarted;
internal static GameObject TemplatePlugin;
private static float _nextTemplateAttempt = -100f;
private static int _templateAttempts;
private static bool _templateFailedPermanent;
private static Plane[] _planes;
private static int _planeFrame = -1;
private static PropertyInfo _speedProp;
private static Type _speedPropType;
private static MemberInfo _dmgMember;
private static Type _dmgMemberType;
private static float _lastGlobalTime = -1f;
private static readonly Dictionary<string, float> _lastGunTime = new Dictionary<string, float>();
internal static int SpawnCount;
private static int _spawnLogThrottle;
internal static int _hitNoTemplate;
private static Camera _cachedMain;
private static int _cachedMainFrame = -1;
private static FieldInfo _firedByPlayerField;
private static bool _firedByPlayerResolved;
private static MethodInfo _userIsPlayerMethod;
private static bool _userIsPlayerResolved;
private static bool _playerFireLogged;
private readonly List<GameObject> _pool = new List<GameObject>();
private readonly Dictionary<GameObject, SmokeBlob> _slotBlobs = new Dictionary<GameObject, SmokeBlob>();
private bool _toppingUp;
internal static float ReadDamage(object target)
{
if (target == null)
{
return -1f;
}
Type type = target.GetType();
if (_dmgMember == null || _dmgMemberType != type)
{
_dmgMemberType = type;
_dmgMember = FindDamageMember(type);
}
if (_dmgMember == null)
{
return -1f;
}
try
{
object obj = ((_dmgMember is PropertyInfo) ? ((PropertyInfo)_dmgMember).GetValue(target, null) : ((FieldInfo)_dmgMember).GetValue(target));
if (obj == null)
{
return -1f;
}
float num = Convert.ToSingle(obj);
return (num > 0f) ? num : (-1f);
}
catch (Exception)
{
return -1f;
}
}
private static MemberInfo FindDamageMember(Type t)
{
string[] array = new string[5] { "damage", "damageMax", "maxDamage", "damagePerProjectile", "baseDamage" };
try
{
string[] array2 = array;
foreach (string name in array2)
{
PropertyInfo property = t.GetProperty(name);
if (property != null && (property.PropertyType == typeof(float) || property.PropertyType == typeof(int)))
{
return property;
}
}
string[] array3 = array;
foreach (string name2 in array3)
{
FieldInfo field = t.GetField(name2);
if (field != null && (field.FieldType == typeof(float) || field.FieldType == typeof(int)))
{
return field;
}
}
}
catch (Exception)
{
}
return null;
}
internal static bool IsPlayerFire(Projectile proj)
{
try
{
if (!_firedByPlayerResolved)
{
_firedByPlayerResolved = true;
_firedByPlayerField = AccessTools.Field(typeof(Projectile), "firedByPlayer");
if (Log != null && !_playerFireLogged)
{
_playerFireLogged = true;
Log.LogInfo((object)("PixelSmokeFx: player-fire resolver uses " + ((_firedByPlayerField != null) ? "Projectile.firedByPlayer" : "Weapon.UserIsPlayer() fallback")));
}
}
if (_firedByPlayerField != null)
{
object value = _firedByPlayerField.GetValue(proj);
if (value != null && value is bool result)
{
return result;
}
}
if ((Object)(object)proj.sourceWeapon != (Object)null)
{
if (!_userIsPlayerResolved)
{
_userIsPlayerResolved = true;
_userIsPlayerMethod = AccessTools.Method(typeof(Weapon), "UserIsPlayer", (Type[])null, (Type[])null);
}
if (_userIsPlayerMethod != null)
{
object obj = _userIsPlayerMethod.Invoke(proj.sourceWeapon, null);
if (obj != null && obj is bool result2)
{
return result2;
}
}
}
}
catch (Exception)
{
}
return false;
}
private static float SafeFloat(string key, float value, float min, float max, float fallback)
{
if (float.IsNaN(value) || float.IsInfinity(value))
{
Log.LogWarning((object)("PixelSmokeFx: cfg " + key + " is not a number (" + value + "), using " + fallback));
return fallback;
}
if (value < min || value > max)
{
Log.LogWarning((object)("PixelSmokeFx: cfg " + key + "=" + value + " out of range [" + min + "," + max + "], clamped"));
return Mathf.Clamp(value, min, max);
}
return value;
}
private static int SafeInt(string key, int value, int min, int max, int fallback)
{
if (value < min || value > max)
{
Log.LogWarning((object)("PixelSmokeFx: cfg " + key + "=" + value + " out of range [" + min + "," + max + "], clamped"));
return Math.Max(min, Math.Min(max, value));
}
return value;
}
private void Awake()
{
//IL_05ce: Unknown result type (might be due to invalid IL or missing references)
//IL_05d4: Expected O, but got Unknown
//IL_063f: Unknown result type (might be due to invalid IL or missing references)
//IL_064d: Expected O, but got Unknown
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
try
{
EnabledCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch.").Value;
TargetWeapon = ((BaseUnityPlugin)this).Config.Bind<string>("General", "TargetWeapon", "", "Weapon-name substring that sourceWeapon.name must contain; empty = all non-explosive guns.").Value;
AlwaysRenderPlayer = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AlwaysRenderPlayer", true, "Effects from shots FIRED BY THE PLAYER render regardless of distance and viewport; other shots keep distance + frustum culling.").Value;
PoolSize = SafeInt("PoolSize", ((BaseUnityPlugin)this).Config.Bind<int>("Performance", "PoolSize", 120, "Pool slots (= concurrent alive blob cap).").Value, 1, 400, 120);
GlobalCooldown = SafeFloat("GlobalCooldown", ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "GlobalCooldown", 0.005f, "Min seconds between any two bursts (same-burst hits bypass this).").Value, 0f, 10f, 0.005f);
GunCooldown = SafeFloat("GunCooldown", ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "GunCooldown", 0.02f, "Min seconds between bursts of the same weapon (auto-fire pacifier).").Value, 0f, 10f, 0.02f);
BurstWindow = SafeFloat("BurstWindow", ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "BurstWindow", 0.08f, "Hits from one weapon within this many seconds count as ONE shot (shotgun pellets land on different frames when angled) and all render.").Value, 0f, 10f, 0.08f);
FullDist = SafeFloat("FullDist", ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "FullDist", 60f, "Blobs closer than this are full size.").Value, 1f, 10000f, 60f);
HalfDist = Math.Max(FullDist, SafeFloat("HalfDist", ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "HalfDist", 200f, "Blobs closer than this are half size; further = skipped.").Value, 1f, 20000f, 200f));
Lifetime = SafeFloat("Lifetime", ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "Lifetime", 1.5f, "Seconds a blob lives (alpha fades 1 -> 0 linearly across this).").Value, 0.1f, 60f, 1.5f);
ExpandTime = SafeFloat("ExpandTime", ((BaseUnityPlugin)this).Config.Bind<float>("Fx", "ExpandTime", 0.15f, "Rapid-expansion window: scale 0.04 -> 1.0 over this many seconds.").Value, 0.01f, 30f, 0.15f);
DecayRate = SafeFloat("DecayRate", ((BaseUnityPlugin)this).Config.Bind<float>("Fx", "DecayRate", 2.2f, "Exponential shrink rate after ExpandTime (higher = snappier).").Value, 0.05f, 100f, 2.2f);
BaseScale = SafeFloat("BaseScale", ((BaseUnityPlugin)this).Config.Bind<float>("Fx", "BaseScale", 0.7f, "Master blob size multiplier (damage/speed + distance LOD still scale it).").Value, 0.01f, 100f, 0.7f);
DamageRef = SafeFloat("DamageRef", ((BaseUnityPlugin)this).Config.Bind<float>("Fx", "DamageRef", 40f, "Projectile damage that maps to size factor 1.0 (rifle-size smoke).").Value, 1f, 10000f, 40f);
MinSizeFactor = SafeFloat("MinSizeFactor", ((BaseUnityPlugin)this).Config.Bind<float>("Fx", "MinSizeFactor", 0.5f, "Smallest damage size factor (shotgun pellets - many hits per shot - can shrink to 0.25).").Value, 0.05f, 1f, 0.5f);
MaxSizeFactor = SafeFloat("MaxSizeFactor", ((BaseUnityPlugin)this).Config.Bind<float>("Fx", "MaxSizeFactor", 1.5f, "Largest damage size factor (sniper hits billow big).").Value, 0.1f, 10f, 1.5f);
ShotgunFactor = SafeFloat("ShotgunFactor", ((BaseUnityPlugin)this).Config.Bind<float>("Fx", "ShotgunFactor", 0.25f, "Size floor for low-damage pellets (shotguns fire many; each pellet stays tiny).").Value, 0.05f, 1f, 0.25f);
AutoTestCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Testing", "AutoTest", false, "True = run built-in AutoTest once at boot (spawns blobs at several distances/angles in front of the camera, captures screenshots).").Value;
Log.LogInfo((object)("PixelSmokeFx: cfg Target='" + TargetWeapon + "' Pool=" + PoolSize + " cd=" + GlobalCooldown + "/" + GunCooldown + " burst=" + BurstWindow + " dist=" + FullDist + "/" + HalfDist + " expand=" + ExpandTime + " decay=" + DecayRate + " base=" + BaseScale + " dmgRef=" + DamageRef + " size=" + MinSizeFactor + "/" + MaxSizeFactor + " pellet=" + ShotgunFactor));
}
catch (Exception ex)
{
Log.LogError((object)("PixelSmokeFx cfg: " + ex));
}
try
{
Harmony val = new Harmony("com.local.pixelsmokefx");
MethodInfo methodInfo = AccessTools.Method(typeof(Projectile), "SpawnDecal", (Type[])null, (Type[])null);
MethodInfo method = typeof(SpawnDecal_Patch).GetMethod("Prefix", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (methodInfo == null)
{
Log.LogError((object)"PixelSmokeFx: target Projectile::SpawnDecal not found");
return;
}
if (method == null)
{
Log.LogError((object)"PixelSmokeFx: prefix method not found");
return;
}
val.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
bool flag = false;
foreach (MethodBase patchedMethod in val.GetPatchedMethods())
{
if (patchedMethod != null && patchedMethod.DeclaringType == typeof(Projectile) && patchedMethod.Name == "SpawnDecal")
{
flag = true;
break;
}
}
if (flag)
{
Log.LogInfo((object)"PixelSmokeFx: harmony hook CONFIRMED on Projectile::SpawnDecal");
}
else
{
Log.LogError((object)"PixelSmokeFx: harmony hook NOT registered (SpawnDecal missing from patched list)");
}
}
catch (Exception ex2)
{
Log.LogError((object)("PixelSmokeFx: harmony patch failed: " + ex2));
}
}
private void Update()
{
if ((Object)(object)TemplatePlugin == (Object)null && !_templateFailedPermanent && Time.time >= _nextTemplateAttempt)
{
_templateAttempts++;
_nextTemplateAttempt = Time.time + ((_templateAttempts <= 5) ? 3f : 30f);
if (_templateAttempts > 10)
{
_templateFailedPermanent = true;
try
{
if (Log != null)
{
Log.LogWarning((object)("PixelSmokeFx: mesh template failed " + 10 + " times - disabled. Delete BepInEx/config/com.local.pixelsmokefx.cfg and check the log."));
}
return;
}
catch (Exception)
{
return;
}
}
LoadTemplate();
}
if (AutoTestCfg && !_autoTestStarted)
{
_autoTestStarted = true;
((MonoBehaviour)this).StartCoroutine(AutoTestRoutine());
}
}
private IEnumerator AutoTestRoutine()
{
Camera cam = null;
bool textOnly = true;
float deadline = Time.time + 60f;
float lastDiag = 0f;
while (Time.time < deadline)
{
cam = MainCam();
if ((Object)(object)cam == (Object)null)
{
cam = FallbackTestCam();
if ((Object)(object)cam != (Object)null)
{
textOnly = ((Object)cam).name != null && ((Object)cam).name.IndexOf("Text", StringComparison.OrdinalIgnoreCase) >= 0;
if (!textOnly)
{
break;
}
cam = null;
}
}
else
{
textOnly = ((Object)cam).name != null && ((Object)cam).name.IndexOf("Text", StringComparison.OrdinalIgnoreCase) >= 0;
if (!textOnly)
{
break;
}
}
if (Time.time - lastDiag > 10f)
{
lastDiag = Time.time;
try
{
Camera[] array = Object.FindObjectsOfType<Camera>();
string[] array2 = new string[array.Length];
for (int i = 0; i < array.Length; i++)
{
array2[i] = ((Object)array[i]).name + "[" + (((Component)array[i]).tag ?? "?") + "," + (((Behaviour)array[i]).enabled ? "on" : "off") + "]";
}
Log.LogInfo((object)("PixelSmokeFx: AutoTest waiting for camera, found: " + string.Join(", ", array2)));
}
catch (Exception ex)
{
Log.LogWarning((object)("PixelSmokeFx AutoTest cam diag: " + ex));
}
}
yield return null;
}
if ((Object)(object)cam == (Object)null)
{
Log.LogWarning((object)"PixelSmokeFx: AutoTest aborted - no camera within 60s");
_autoTestStarted = true;
yield break;
}
if (textOnly)
{
Log.LogWarning((object)"PixelSmokeFx: AutoTest proceeding with text/loading camera - shots may be blank");
}
Log.LogInfo((object)("PixelSmokeFx: AutoTest start, camera=" + ((Object)cam).name));
string dir = Path.Combine(Paths.BepInExRootPath, "PixelSmokeFxTest", DateTime.Now.ToString("yyyyMMdd_HHmmss"));
try
{
Directory.CreateDirectory(dir);
}
catch (Exception ex2)
{
Log.LogError((object)("PixelSmokeFx: AutoTest dir: " + ex2));
dir = null;
}
float[] dists = new float[3] { 8f, 24f, 60f };
try
{
bool built;
try
{
built = SmokeMeshFactory.BuildMainTemplate();
}
catch (Exception ex3)
{
Log.LogError((object)("PixelSmokeFx: AutoTest template build: " + ex3));
built = false;
}
if (!built)
{
Log.LogWarning((object)"PixelSmokeFx: AutoTest template build failed, skipped");
yield break;
}
TemplatePlugin = SmokeMeshFactory.TemplateRoot;
RebuildPoolForTemplate();
Log.LogInfo((object)"PixelSmokeFx: AutoTest evaluating mesh template");
Vector3 fwd = ((Component)cam).transform.forward;
Vector3 right = ((Component)cam).transform.right;
for (int d = 0; d < dists.Length; d++)
{
Vector3 basePos = ((Component)cam).transform.position + fwd * dists[d];
Vector3[] burstPts = (Vector3[])(object)new Vector3[3];
Vector3[] burstNs = (Vector3[])(object)new Vector3[3];
float[] offsets = new float[3] { -2.2f, 0f, 2.2f };
float[] yOff = new float[3] { -0.4f, 0f, 0.4f };
for (int j = 0; j < 3; j++)
{
Vector3 val = basePos + right * offsets[j] + Vector3.up * yOff[j];
Vector3 val2 = ((Component)cam).transform.position - val;
Vector3 normalized = ((Vector3)(ref val2)).normalized;
Vector3 val3;
switch (j)
{
default:
{
Vector3 val4 = Vector3.up + normalized;
val3 = ((Vector3)(ref val4)).normalized;
break;
}
case 1:
val3 = normalized;
break;
case 0:
val3 = Vector3.up;
break;
}
Vector3 val5 = val3;
burstPts[j] = val;
burstNs[j] = val5;
SpawnEffect("autotest", val, val5, fwd, dists[d], 800f, 40f);
}
yield return (object)new WaitForSeconds(0.4f);
if (dir == null)
{
continue;
}
string file = Path.Combine(dir, "d" + dists[d] + "m.png");
float content = -1f;
for (int attempt = 0; attempt < 8; attempt++)
{
for (int k = 0; k < 3; k++)
{
SpawnEffect("autotest", burstPts[k], burstNs[k], fwd, dists[d], 800f, 40f);
}
yield return (object)new WaitForSeconds(0.4f);
TakeScreenshot(file);
yield return (object)new WaitForEndOfFrame();
Thread.Sleep(120);
content = ScreenshotContent(file);
if (content >= 0.25f)
{
break;
}
Log.LogInfo((object)("PixelSmokeFx: AutoTest re-shoot " + (attempt + 1) + " for " + file + " (content=" + content + ")"));
try
{
if (File.Exists(file))
{
File.Delete(file);
}
}
catch (Exception)
{
}
}
Log.LogInfo((object)("PixelSmokeFx: AutoTest shot -> " + file + " (content=" + content + ")"));
}
yield return (object)new WaitForSeconds(0.8f);
}
finally
{
for (int array = _pool.Count - 1; array >= 0; array--)
{
GameObject array2 = _pool[array];
if ((Object)(object)array2 != (Object)null)
{
DropSlot(array2);
Object.Destroy((Object)(object)array2);
}
}
_pool.Clear();
Instance._slotBlobs.Clear();
TemplatePlugin = null;
SmokeMeshFactory.ReleaseTemplate();
_nextTemplateAttempt = 0f;
_templateAttempts = 0;
_templateFailedPermanent = false;
if (dir != null)
{
Log.LogInfo((object)("PixelSmokeFx: AutoTest done - screenshots in " + dir));
}
else
{
Log.LogInfo((object)"PixelSmokeFx: AutoTest done (no screenshots taken)");
}
}
}
private void RebuildPoolForTemplate()
{
for (int num = _pool.Count - 1; num >= 0; num--)
{
GameObject val = _pool[num];
if ((Object)(object)val != (Object)null)
{
DropSlot(val);
Object.Destroy((Object)(object)val);
}
}
_pool.Clear();
_slotBlobs.Clear();
if (!((Object)(object)TemplatePlugin == (Object)null))
{
int num2 = Math.Min(PoolSize, 12);
for (int i = 0; i < num2; i++)
{
GameObject val2 = Object.Instantiate<GameObject>(TemplatePlugin);
Object.DontDestroyOnLoad((Object)(object)val2);
val2.SetActive(false);
_pool.Add(val2);
}
Log.LogInfo((object)("PixelSmokeFx: AutoTest pool rebuilt (" + num2 + ")"));
}
}
private static float ScreenshotContent(string path)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
//IL_0054: 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)
try
{
if (!File.Exists(path))
{
return -1f;
}
Texture2D val = new Texture2D(2, 2);
if (!ImageConversion.LoadImage(val, File.ReadAllBytes(path)))
{
Object.Destroy((Object)(object)val);
return -1f;
}
Color32[] pixels = val.GetPixels32();
int num = 0;
int num2 = 0;
for (int i = 0; i < pixels.Length; i += 5)
{
Color32 val2 = pixels[i];
if (val2.r < 70 && val2.g < 70 && val2.b < 70)
{
num++;
}
if (val2.r > 110 && val2.g > 110 && val2.b > 110)
{
num2++;
}
}
Object.Destroy((Object)(object)val);
int num3 = (pixels.Length + 4) / 5;
float num4 = (float)num / (float)num3;
float num5 = (float)num2 / (float)num3;
return Mathf.Min(1f, num4 * 2.5f) + ((num5 > 0.15f) ? 0.5f : 0f);
}
catch (Exception ex)
{
if (Log != null)
{
Log.LogWarning((object)("PixelSmokeFx: content check " + path + ": " + ex));
}
return -1f;
}
}
private static void TakeScreenshot(string path)
{
try
{
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
Type type = null;
for (int i = 0; i < assemblies.Length; i++)
{
if (!(type == null))
{
break;
}
if (assemblies[i].FullName.StartsWith("UnityEngine.ScreenCaptureModule", StringComparison.Ordinal))
{
type = assemblies[i].GetType("UnityEngine.ScreenCapture");
}
}
if (type == null)
{
Log.LogWarning((object)"PixelSmokeFx: ScreenCapture type not found, no shot");
return;
}
MethodInfo method = type.GetMethod("CaptureScreenshot", new Type[2]
{
typeof(string),
typeof(int)
});
if (method == null)
{
method = type.GetMethod("CaptureScreenshot", new Type[1] { typeof(string) });
}
if (method == null)
{
Log.LogWarning((object)"PixelSmokeFx: CaptureScreenshot not found, no shot");
return;
}
object[] parameters = ((method.GetParameters().Length == 2) ? new object[2] { path, 1 } : new object[1] { path });
method.Invoke(null, parameters);
}
catch (Exception ex)
{
Log.LogWarning((object)("PixelSmokeFx: screenshot " + path + ": " + ex));
}
}
private void LoadTemplate()
{
try
{
if (SmokeMeshFactory.BuildMainTemplate())
{
TemplatePlugin = SmokeMeshFactory.TemplateRoot;
Log.LogInfo((object)"PixelSmokeFx: mesh template ready");
((MonoBehaviour)this).StartCoroutine(WarmPool());
}
else
{
Log.LogError((object)"PixelSmokeFx: mesh template build failed, retrying in 3s");
}
}
catch (Exception ex)
{
Log.LogError((object)("PixelSmokeFx: template load failed: " + ex));
}
}
private IEnumerator WarmPool()
{
while (_pool.Count < PoolSize && (Object)(object)TemplatePlugin != (Object)null)
{
GameObject go = Object.Instantiate<GameObject>(TemplatePlugin);
Object.DontDestroyOnLoad((Object)(object)go);
go.SetActive(false);
_pool.Add(go);
if (_pool.Count % 10 == 0)
{
yield return null;
}
}
Log.LogInfo((object)("PixelSmokeFx: pool warmed to " + _pool.Count));
}
internal static SmokeBlob BlobOf(GameObject go)
{
if (Instance._slotBlobs.TryGetValue(go, out var value))
{
return value;
}
value = go.GetComponent<SmokeBlob>();
if ((Object)(object)value == (Object)null)
{
value = go.AddComponent<SmokeBlob>();
}
Instance._slotBlobs[go] = value;
return value;
}
private static void DropSlot(GameObject go)
{
if ((Object)(object)Instance != (Object)null && go != null)
{
Instance._slotBlobs.Remove(go);
}
}
internal static GameObject GetFromPool()
{
List<GameObject> pool = Instance._pool;
for (int num = pool.Count - 1; num >= 0; num--)
{
if ((Object)(object)pool[num] == (Object)null)
{
DropSlot(pool[num]);
pool.RemoveAt(num);
}
else if (!pool[num].activeSelf)
{
return pool[num];
}
}
return null;
}
private IEnumerator TopUpPool()
{
while (_pool.Count < PoolSize && (Object)(object)TemplatePlugin != (Object)null)
{
GameObject go = Object.Instantiate<GameObject>(TemplatePlugin);
Object.DontDestroyOnLoad((Object)(object)go);
go.SetActive(false);
_pool.Add(go);
yield return null;
}
}
internal static void RequestTopUp()
{
if (!Instance._toppingUp)
{
Instance._toppingUp = true;
((MonoBehaviour)Instance).StartCoroutine(Instance.TopUpPoolAndUnset());
}
}
private IEnumerator TopUpPoolAndUnset()
{
yield return TopUpPool();
_toppingUp = false;
}
internal static void SpawnEffect(string key, Vector3 point, Vector3 normal, Vector3 flight, float dist, float caliber, float damage)
{
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((Object)(object)TemplatePlugin == (Object)null)
{
return;
}
float num = ((dist < FullDist) ? 1f : 0.5f);
float num4;
if (damage > 0f)
{
float num2 = ((damage * 2f < DamageRef) ? ShotgunFactor : MinSizeFactor);
float num3 = Mathf.Clamp(damage / DamageRef, num2, MaxSizeFactor);
num4 = num3 * 0.7f * num * BaseScale;
}
else
{
num4 = Mathf.Clamp((float)Math.Sqrt(caliber / 800f) * 0.7f, 0.45f, 1.6f) * num * BaseScale;
}
num4 = Mathf.Clamp(num4, 0.001f, 3f);
GameObject fromPool = GetFromPool();
if ((Object)(object)fromPool == (Object)null)
{
RequestTopUp();
return;
}
fromPool.transform.position = point + normal * 0.3f;
fromPool.transform.rotation = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f);
SmokeBlob smokeBlob = BlobOf(fromPool);
smokeBlob.Launch(num4, Lifetime);
fromPool.SetActive(true);
SpawnCount++;
if (++_spawnLogThrottle % 200 == 0 && Log != null)
{
Log.LogInfo((object)("PixelSmokeFx: spawned " + SpawnCount + " total, key=" + key + " dist=" + dist.ToString("F0") + " cal=" + caliber.ToString("F0") + " scale=" + num4.ToString("F2")));
}
}
catch (Exception ex)
{
if (Log != null)
{
Log.LogWarning((object)("PixelSmokeFx: spawn: " + ex));
}
}
}
internal static Camera MainCam()
{
if ((Object)(object)_cachedMain == (Object)null || _cachedMainFrame != Time.frameCount)
{
_cachedMain = Camera.main;
_cachedMainFrame = Time.frameCount;
}
return _cachedMain;
}
private static Camera FallbackTestCam()
{
Camera val = null;
try
{
Camera[] array = Object.FindObjectsOfType<Camera>();
foreach (Camera val2 in array)
{
if ((Object)(object)val2 == (Object)null || !((Behaviour)val2).enabled)
{
continue;
}
string name = ((Object)val2).name;
if (name == null || (name.IndexOf("Text", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Icon", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Post-process", StringComparison.OrdinalIgnoreCase) < 0))
{
if ((Object)(object)val == (Object)null)
{
val = val2;
}
if (name != null && name.IndexOf("Main", StringComparison.OrdinalIgnoreCase) >= 0)
{
return val2;
}
}
}
}
catch (Exception)
{
}
return val;
}
internal static bool IsOnScreen(Vector3 point)
{
//IL_003e: 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_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
Camera val = MainCam();
if ((Object)(object)val == (Object)null)
{
return false;
}
if (_planes == null || _planeFrame != Time.frameCount)
{
_planes = GeometryUtility.CalculateFrustumPlanes(val);
_planeFrame = Time.frameCount;
}
return GeometryUtility.TestPlanesAABB(_planes, new Bounds(point, Vector3.one * 0.4f));
}
}
public static class SmokeMeshFactory
{
public static GameObject TemplateRoot;
private static Material _sharedMat;
private static readonly Dictionary<int, Mesh> _cache = new Dictionary<int, Mesh>();
private static readonly int[] PUFF_SEEDS = new int[3] { 20260808, 20260809, 20260810 };
internal static readonly float[] PUFF_BASE_SCALE = new float[3] { 1f, 0.62f, 0.45f };
internal static readonly float[] PUFF_DELAY = new float[3] { 0f, 0.1f, 0.16f };
public static bool BuildMainTemplate()
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
//IL_0049: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
try
{
Material val = MakeBlobMaterial();
if ((Object)(object)val == (Object)null)
{
return false;
}
_sharedMat = val;
GameObject val2 = new GameObject("PixelSmokeFxBlobExplosion");
val2.SetActive(false);
Object.DontDestroyOnLoad((Object)(object)val2);
MakePuff(val2, "SmokePuff0", new Vector3(0f, 0f, 0f), GetOrBuild(PUFF_SEEDS[0], 3));
MakePuff(val2, "SmokePuff1", new Vector3(0.26f, -0.1f, 0.14f), GetOrBuild(PUFF_SEEDS[1], 3));
MakePuff(val2, "SmokePuff2", new Vector3(-0.24f, 0.07f, 0.12f), GetOrBuild(PUFF_SEEDS[2], 3));
val2.AddComponent<SmokeBlob>();
TemplateRoot = val2;
return true;
}
catch (Exception ex)
{
if (FxPlugin.Log != null)
{
FxPlugin.Log.LogWarning((object)("PixelSmokeFx: mesh template build: " + ex));
}
return false;
}
}
private static GameObject MakePuff(GameObject parent, string name, Vector3 localPos, Mesh mesh)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
//IL_001f: 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)
GameObject val = new GameObject(name);
val.transform.SetParent(parent.transform, false);
val.transform.localPosition = localPos;
val.transform.localRotation = Quaternion.identity;
MeshFilter val2 = val.AddComponent<MeshFilter>();
val2.sharedMesh = mesh;
MeshRenderer val3 = val.AddComponent<MeshRenderer>();
((Renderer)val3).sharedMaterial = _sharedMat;
return val;
}
public static void ReleaseTemplate()
{
if ((Object)(object)TemplateRoot != (Object)null)
{
Object.Destroy((Object)(object)TemplateRoot);
}
TemplateRoot = null;
if ((Object)(object)_sharedMat != (Object)null)
{
Object.Destroy((Object)(object)_sharedMat);
}
_sharedMat = null;
}
private static Mesh GetOrBuild(int seed, int subdiv)
{
if (_cache.TryGetValue(seed, out var value) && (Object)(object)value != (Object)null)
{
return value;
}
value = BuildIcosphere(seed, subdiv);
_cache[seed] = value;
return value;
}
private static Mesh BuildIcosphere(int seed, int subdiv)
{
//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_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: 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_005e: 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_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: 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_00b4: 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_00bd: 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_00dc: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0113: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011c: Unknown result type (might be due to invalid IL or missing references)
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
//IL_0171: Unknown result type (might be due to invalid IL or missing references)
//IL_0176: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_0191: Unknown result type (might be due to invalid IL or missing references)
//IL_0196: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Unknown result type (might be due to invalid IL or missing references)
//IL_020c: Unknown result type (might be due to invalid IL or missing references)
//IL_0211: Unknown result type (might be due to invalid IL or missing references)
//IL_022d: Unknown result type (might be due to invalid IL or missing references)
//IL_0232: Unknown result type (might be due to invalid IL or missing references)
//IL_024e: Unknown result type (might be due to invalid IL or missing references)
//IL_0253: Unknown result type (might be due to invalid IL or missing references)
//IL_026f: Unknown result type (might be due to invalid IL or missing references)
//IL_0274: Unknown result type (might be due to invalid IL or missing references)
//IL_0290: Unknown result type (might be due to invalid IL or missing references)
//IL_0295: Unknown result type (might be due to invalid IL or missing references)
//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
//IL_02f3: 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_0331: Unknown result type (might be due to invalid IL or missing references)
//IL_0336: Unknown result type (might be due to invalid IL or missing references)
//IL_0340: Unknown result type (might be due to invalid IL or missing references)
//IL_0345: Unknown result type (might be due to invalid IL or missing references)
//IL_034a: Unknown result type (might be due to invalid IL or missing references)
//IL_034e: Unknown result type (might be due to invalid IL or missing references)
//IL_0353: Unknown result type (might be due to invalid IL or missing references)
//IL_0358: Unknown result type (might be due to invalid IL or missing references)
//IL_0366: Unknown result type (might be due to invalid IL or missing references)
//IL_0371: Unknown result type (might be due to invalid IL or missing references)
//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
//IL_0413: Unknown result type (might be due to invalid IL or missing references)
//IL_0418: Unknown result type (might be due to invalid IL or missing references)
//IL_0422: Unknown result type (might be due to invalid IL or missing references)
//IL_0427: Unknown result type (might be due to invalid IL or missing references)
//IL_0431: Unknown result type (might be due to invalid IL or missing references)
//IL_0436: Unknown result type (might be due to invalid IL or missing references)
//IL_0438: Unknown result type (might be due to invalid IL or missing references)
//IL_043a: Unknown result type (might be due to invalid IL or missing references)
//IL_043c: Unknown result type (might be due to invalid IL or missing references)
//IL_0441: Unknown result type (might be due to invalid IL or missing references)
//IL_0443: Unknown result type (might be due to invalid IL or missing references)
//IL_0445: Unknown result type (might be due to invalid IL or missing references)
//IL_044a: Unknown result type (might be due to invalid IL or missing references)
//IL_044f: Unknown result type (might be due to invalid IL or missing references)
//IL_0453: Unknown result type (might be due to invalid IL or missing references)
//IL_0458: Unknown result type (might be due to invalid IL or missing references)
//IL_0463: Unknown result type (might be due to invalid IL or missing references)
//IL_0465: Unknown result type (might be due to invalid IL or missing references)
//IL_0473: Unknown result type (might be due to invalid IL or missing references)
//IL_0475: Unknown result type (might be due to invalid IL or missing references)
//IL_0485: Unknown result type (might be due to invalid IL or missing references)
//IL_0487: Unknown result type (might be due to invalid IL or missing references)
//IL_0497: Unknown result type (might be due to invalid IL or missing references)
//IL_0499: Unknown result type (might be due to invalid IL or missing references)
//IL_04a9: Unknown result type (might be due to invalid IL or missing references)
//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
//IL_04bb: Unknown result type (might be due to invalid IL or missing references)
//IL_04bd: Unknown result type (might be due to invalid IL or missing references)
//IL_0504: Unknown result type (might be due to invalid IL or missing references)
//IL_0509: Unknown result type (might be due to invalid IL or missing references)
//IL_0600: Unknown result type (might be due to invalid IL or missing references)
//IL_0607: Expected O, but got Unknown
//IL_05c4: Unknown result type (might be due to invalid IL or missing references)
//IL_05c6: Unknown result type (might be due to invalid IL or missing references)
//IL_05d6: Unknown result type (might be due to invalid IL or missing references)
//IL_05d8: Unknown result type (might be due to invalid IL or missing references)
//IL_05e8: Unknown result type (might be due to invalid IL or missing references)
//IL_05ea: Unknown result type (might be due to invalid IL or missing references)
Random random = new Random(seed);
List<Vector3> list = new List<Vector3>();
List<int> list2 = new List<int>();
float num = (1f + Mathf.Sqrt(5f)) * 0.5f;
Vector3 val = new Vector3(-1f, num, 0f);
list.Add(((Vector3)(ref val)).normalized);
Vector3 val2 = new Vector3(1f, num, 0f);
list.Add(((Vector3)(ref val2)).normalized);
Vector3 val3 = new Vector3(-1f, 0f - num, 0f);
list.Add(((Vector3)(ref val3)).normalized);
Vector3 val4 = new Vector3(1f, 0f - num, 0f);
list.Add(((Vector3)(ref val4)).normalized);
Vector3 val5 = new Vector3(0f, -1f, num);
list.Add(((Vector3)(ref val5)).normalized);
Vector3 val6 = new Vector3(0f, 1f, num);
list.Add(((Vector3)(ref val6)).normalized);
Vector3 val7 = new Vector3(0f, -1f, 0f - num);
list.Add(((Vector3)(ref val7)).normalized);
Vector3 val8 = new Vector3(0f, 1f, 0f - num);
list.Add(((Vector3)(ref val8)).normalized);
Vector3 val9 = new Vector3(num, 0f, -1f);
list.Add(((Vector3)(ref val9)).normalized);
Vector3 val10 = new Vector3(num, 0f, 1f);
list.Add(((Vector3)(ref val10)).normalized);
Vector3 val11 = new Vector3(0f - num, 0f, -1f);
list.Add(((Vector3)(ref val11)).normalized);
Vector3 val12 = new Vector3(0f - num, 0f, 1f);
list.Add(((Vector3)(ref val12)).normalized);
int[] array = new int[60]
{
0, 11, 5, 0, 5, 1, 0, 1, 7, 0,
7, 10, 0, 10, 11, 1, 5, 9, 5, 11,
4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
3, 9, 4, 3, 4, 2, 3, 2, 6, 3,
6, 8, 3, 8, 9, 4, 9, 5, 2, 4,
11, 6, 2, 10, 8, 6, 7, 9, 8, 1
};
for (int i = 0; i < array.Length; i++)
{
list2.Add(array[i]);
}
for (int j = 0; j < subdiv; j++)
{
SubdivideOnce(list, list2);
}
Vector3[] array2 = (Vector3[])(object)new Vector3[8]
{
new Vector3(1f, 0.35f, 0.1f),
new Vector3(-0.72f, 0.5f, 0.42f),
new Vector3(0.2f, -0.9f, 0.3f),
new Vector3(-0.4f, -0.5f, -0.85f),
new Vector3(0.5f, 0.62f, -0.6f),
new Vector3(-0.82f, 0.2f, -0.45f),
new Vector3(0.3f, 0.8f, 0.5f),
new Vector3(0.75f, -0.45f, -0.5f)
};
float[] array3 = new float[8] { 0.17f, 0.15f, 0.14f, 0.16f, 0.13f, 0.14f, 0.12f, 0.11f };
Quaternion val13 = Quaternion.Euler((float)(seed % 360), (float)(seed / 7 % 360), (float)(seed / 13 % 360));
for (int k = 0; k < list.Count; k++)
{
Vector3 val14 = list[k];
Vector3 val15 = val13 * ((Vector3)(ref val14)).normalized;
float num2 = 1f;
for (int l = 0; l < array2.Length; l++)
{
float num3 = Vector3.Dot(val15, ((Vector3)(ref array2[l])).normalized);
float num4 = Mathf.Clamp01((num3 - 0.3f) / 0.7f);
num4 = num4 * num4 * (3f - 2f * num4);
num2 += array3[l] * num4;
}
list[k] = val15 * num2;
}
int[] array4 = list2.ToArray();
Vector3[] array5 = (Vector3[])(object)new Vector3[array4.Length];
Vector3[] array6 = (Vector3[])(object)new Vector3[array4.Length];
for (int m = 0; m < array4.Length; m += 3)
{
Vector3 val16 = list[array4[m]];
Vector3 val17 = list[array4[m + 1]];
Vector3 val18 = list[array4[m + 2]];
Vector3 val19 = Vector3.Cross(val17 - val16, val18 - val16);
Vector3 normalized = ((Vector3)(ref val19)).normalized;
array5[m] = val16;
array6[m] = normalized;
array5[m + 1] = val17;
array6[m + 1] = normalized;
array5[m + 2] = val18;
array6[m + 2] = normalized;
}
int[] array7 = new int[array4.Length];
for (int n = 0; n < array7.Length; n++)
{
array7[n] = n;
}
Color[] array8 = (Color[])(object)new Color[array5.Length];
Color val20 = BaseTintFor(seed);
Color val21 = default(Color);
for (int num5 = 0; num5 < array5.Length; num5 += 3)
{
float num6 = array6[num5].y * 0.5f + 0.5f;
float num7 = ((num6 < 0.3f) ? 0.14f : ((num6 < 0.62f) ? 0.26f : 0.44f));
float num8 = (float)(random.NextDouble() * 0.1 - 0.05);
float num9 = Mathf.Clamp01(num7 + num8);
((Color)(ref val21))..ctor(val20.r * num9 * 0.5f, val20.g * num9 * 0.5f, val20.b * num9 * 0.5f, 1f);
array8[num5] = val21;
array8[num5 + 1] = val21;
array8[num5 + 2] = val21;
}
Mesh val22 = new Mesh();
((Object)val22).name = "SmokeBlob_" + seed;
val22.vertices = array5;
val22.normals = array6;
val22.colors = array8;
val22.triangles = array7;
val22.RecalculateBounds();
return val22;
}
private static Color BaseTintFor(int seed)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
return (Color)(seed switch
{
20260809 => new Color(0.42f, 0.4f, 0.37f),
20260810 => new Color(0.38f, 0.38f, 0.4f),
_ => new Color(0.34f, 0.34f, 0.36f),
});
}
private static void SubdivideOnce(List<Vector3> verts, List<int> tris)
{
Dictionary<int, int> midMap = new Dictionary<int, int>();
int count = tris.Count;
List<int> list = new List<int>(count * 4);
for (int i = 0; i < count; i += 3)
{
int num = tris[i];
int num2 = tris[i + 1];
int num3 = tris[i + 2];
int item = MidPoint(verts, midMap, num, num2);
int item2 = MidPoint(verts, midMap, num2, num3);
int item3 = MidPoint(verts, midMap, num3, num);
list.Add(num);
list.Add(item);
list.Add(item3);
list.Add(num2);
list.Add(item2);
list.Add(item);
list.Add(num3);
list.Add(item3);
list.Add(item2);
list.Add(item);
list.Add(item2);
list.Add(item3);
}
tris.Clear();
tris.AddRange(list);
}
private static int MidPoint(List<Vector3> verts, Dictionary<int, int> midMap, int i1, int i2)
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//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_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_004d: Unknown result type (might be due to invalid IL or missing references)
int key = ((i1 < i2) ? ((i1 << 16) | i2) : ((i2 << 16) | i1));
if (midMap.TryGetValue(key, out var value))
{
return value;
}
Vector3 item = (verts[i1] + verts[i2]) * 0.5f;
((Vector3)(ref item)).Normalize();
int count = verts.Count;
verts.Add(item);
midMap[key] = count;
return count;
}
private static Material MakeBlobMaterial()
{
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Expected O, but got Unknown
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
string[] array = new string[3] { "Particles/Alpha Blended", "Legacy Shaders/Particles/Alpha Blended", "Sprites/Default" };
Shader val = null;
for (int i = 0; i < array.Length; i++)
{
if (!((Object)(object)val == (Object)null))
{
break;
}
val = Shader.Find(array[i]);
}
if ((Object)(object)val == (Object)null)
{
return null;
}
Material val2 = new Material(val);
if (val2.HasProperty("_TintColor"))
{
val2.SetColor("_TintColor", new Color(1f, 1f, 1f, 0.5f));
}
else if (val2.HasProperty("_Color"))
{
val2.SetColor("_Color", new Color(1f, 1f, 1f, 1f));
}
return val2;
}
}
public class SmokeBlob : MonoBehaviour
{
private static readonly int TINT_ID = Shader.PropertyToID("_TintColor");
private static readonly int COLOR_ID = Shader.PropertyToID("_Color");
private Transform[] _puffs;
private Renderer[] _renderers;
private MaterialPropertyBlock[] _blocks;
private int _intPropId = TINT_ID;
private bool _live;
private float _t0;
private float _life;
private float _scale;
public void Launch(float scale, float life)
{
//IL_0058: 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)
_scale = Mathf.Max(0.001f, scale);
_life = Mathf.Max(0.2f, life);
_t0 = Time.time;
_live = true;
if (_puffs == null)
{
return;
}
for (int i = 0; i < _puffs.Length; i++)
{
if ((Object)(object)_puffs[i] != (Object)null)
{
_puffs[i].localScale = Vector3.one * 0.001f;
}
}
}
private void Awake()
{
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Expected O, but got Unknown
int childCount = ((Component)this).transform.childCount;
_puffs = (Transform[])(object)new Transform[childCount];
_renderers = (Renderer[])(object)new Renderer[childCount];
_blocks = (MaterialPropertyBlock[])(object)new MaterialPropertyBlock[childCount];
for (int i = 0; i < childCount; i++)
{
Transform child = ((Component)this).transform.GetChild(i);
_puffs[i] = child;
_renderers[i] = (((Object)(object)child != (Object)null) ? ((Component)child).GetComponent<Renderer>() : null);
_blocks[i] = new MaterialPropertyBlock();
}
Renderer val = ((_renderers.Length > 0) ? _renderers[0] : null);
if ((Object)(object)val != (Object)null && (Object)(object)val.sharedMaterial != (Object)null)
{
if (val.sharedMaterial.HasProperty("_Color") && !val.sharedMaterial.HasProperty("_TintColor"))
{
_intPropId = COLOR_ID;
}
else
{
_intPropId = TINT_ID;
}
}
}
private void Update()
{
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
if (!_live || _puffs == null || _puffs.Length == 0)
{
return;
}
float num = Time.time - _t0;
if (num >= _life)
{
_live = false;
((Component)this).gameObject.SetActive(false);
return;
}
float expandTime = FxPlugin.ExpandTime;
float num3;
if (num < expandTime)
{
float num2 = Mathf.Clamp01(num / expandTime);
num3 = 0.04f + 0.96f * num2;
}
else
{
num3 = Mathf.Exp((0f - FxPlugin.DecayRate) * (num - expandTime));
}
float num4 = Mathf.Clamp01(1f - num / _life);
for (int i = 0; i < _puffs.Length; i++)
{
Transform val = _puffs[i];
if ((Object)(object)val == (Object)null)
{
continue;
}
float num5 = num - ((i < SmokeMeshFactory.PUFF_DELAY.Length) ? SmokeMeshFactory.PUFF_DELAY[i] : 0f);
float num6;
float num7;
if (num5 <= 0f)
{
num6 = 0.001f;
num7 = 0f;
}
else
{
float num8 = num3;
float num9 = expandTime;
if (num5 < num9)
{
float num10 = Mathf.Clamp01(num5 / num9);
num8 = 0.04f + 0.96f * num10;
}
else
{
num8 = Mathf.Exp((0f - FxPlugin.DecayRate) * (num5 - num9));
}
num6 = num8 * ((i < SmokeMeshFactory.PUFF_BASE_SCALE.Length) ? SmokeMeshFactory.PUFF_BASE_SCALE[i] : 1f) * _scale;
num7 = num4;
}
val.localScale = new Vector3(num6, num6, num6);
Renderer val2 = _renderers[i];
if (!((Object)(object)val2 == (Object)null) && val2.isVisible)
{
MaterialPropertyBlock val3 = _blocks[i];
val3.SetColor(_intPropId, new Color(1f, 1f, 1f, num7 * 0.5f));
val2.SetPropertyBlock(val3);
}
}
}
}