using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ShotgunMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ShotgunMod")]
[assembly: AssemblyTitle("ShotgunMod")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ShotgunMod
{
[BepInPlugin("com.liuta.shotgunmod", "Shotgun Mod", "0.1.0")]
public class Plugin : BaseUnityPlugin
{
public static GameObject ShotgunPrefab;
public static Item_Object ShotgunTemplate;
public static ManualLogSource Log;
public static AudioClip ShotgunFireClip;
public static Material OutlineMaterial;
public static Sprite SpriteLoaded;
public static Sprite SpriteRecoil;
public static Sprite SpriteEmpty;
private Harmony _harmony;
private void Awake()
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
//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_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
Log.LogInfo((object)"Shotgun Mod loading...");
LoadAssetBundle();
LoadCustomAudio();
_harmony = new Harmony("com.liuta.shotgunmod");
_harmony.PatchAll();
Log.LogInfo((object)"Harmony patches applied.");
GameObject val = new GameObject("ShotgunMod_Handler")
{
hideFlags = (HideFlags)61
};
Object.DontDestroyOnLoad((Object)val);
val.AddComponent<ShotgunModHandler>();
Log.LogInfo((object)"Press F9 in-game to test-spawn shotgun.");
}
public static void EnsureShotgunTemplate()
{
if (!((Object)(object)ShotgunTemplate != (Object)null) && !((Object)(object)ShotgunPrefab == (Object)null))
{
GameObject obj = Object.Instantiate<GameObject>(ShotgunPrefab);
obj.SetActive(false);
((Object)obj).name = "ShotgunMod_Template";
((Object)obj).hideFlags = (HideFlags)61;
Object.DontDestroyOnLoad((Object)(object)obj);
ShotgunTemplate = obj.AddComponent<Item_Object>();
ShotgunModHandler.ConfigureAsPickup(obj);
ApplyGameShader(obj);
ManualLogSource log = Log;
if (log != null)
{
log.LogInfo((object)$"Shotgun template built lazily: Item_Object={(Object)(object)ShotgunTemplate != (Object)null}");
}
}
}
public static void ApplyGameShader(GameObject target)
{
string[] obj = new string[1] { "Dark Machine/SHDR_Base" };
Shader val = null;
string[] array = obj;
foreach (string text in array)
{
val = Shader.Find(text);
if ((Object)(object)val != (Object)null)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogInfo((object)("Using shader: " + text));
}
break;
}
}
if ((Object)(object)val == (Object)null)
{
ManualLogSource log2 = Log;
if (log2 != null)
{
log2.LogWarning((object)"No game shader found, falling back to Unlit/Texture");
}
val = Shader.Find("Unlit/Texture");
}
if ((Object)(object)val == (Object)null)
{
return;
}
Renderer[] componentsInChildren = target.GetComponentsInChildren<Renderer>(true);
foreach (Renderer val2 in componentsInChildren)
{
Material[] materials = val2.materials;
for (int j = 0; j < materials.Length; j++)
{
if (!((Object)(object)materials[j] == (Object)null))
{
Texture val3 = (materials[j].HasProperty("_MainTex") ? materials[j].GetTexture("_MainTex") : null);
materials[j].shader = val;
if ((Object)(object)val3 != (Object)null && materials[j].HasProperty("_MainTex"))
{
materials[j].SetTexture("_MainTex", val3);
}
}
}
val2.materials = materials;
}
}
private void LoadCustomAudio()
{
string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "shotgun_fire.wav");
if (!File.Exists(text))
{
Log.LogWarning((object)("Custom shotgun_fire.wav not found at " + text + ", will fall back to game sounds"));
return;
}
try
{
ShotgunFireClip = WavLoader.LoadFromFile(text);
ManualLogSource log = Log;
AudioClip shotgunFireClip = ShotgunFireClip;
string arg = ((shotgunFireClip != null) ? ((Object)shotgunFireClip).name : null);
AudioClip shotgunFireClip2 = ShotgunFireClip;
log.LogInfo((object)$"Loaded custom shotgun fire audio: {arg} ({((shotgunFireClip2 != null) ? new float?(shotgunFireClip2.length) : null):F2}s)");
}
catch (Exception arg2)
{
Log.LogError((object)$"WAV load failed: {arg2}");
}
}
private void LoadAssetBundle()
{
string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "shotgunmod");
if (!File.Exists(text))
{
Log.LogError((object)("Asset bundle not found at: " + text));
return;
}
AssetBundle val = AssetBundle.LoadFromFile(text);
if ((Object)(object)val == (Object)null)
{
Log.LogError((object)"Failed to load asset bundle (LoadFromFile returned null)");
return;
}
string[] allAssetNames = val.GetAllAssetNames();
Log.LogInfo((object)("Bundle loaded. Assets inside: " + string.Join(", ", allAssetNames)));
GameObject[] array = val.LoadAllAssets<GameObject>();
if (array == null || array.Length == 0)
{
Log.LogError((object)"No GameObject assets found in bundle");
return;
}
ShotgunPrefab = array[0];
Log.LogInfo((object)$"Shotgun prefab loaded: {((Object)ShotgunPrefab).name} (picked from {array.Length} GameObjects)");
Material[] array2 = val.LoadAllAssets<Material>();
foreach (Material val2 in array2)
{
if ((Object)(object)val2 != (Object)null && ((Object)val2).name == "ShotgunOutlineMat")
{
OutlineMaterial = val2;
Log.LogInfo((object)("Loaded outline material: " + ((Object)OutlineMaterial).name));
break;
}
}
if ((Object)(object)OutlineMaterial == (Object)null)
{
Log.LogWarning((object)"ShotgunOutlineMat not found in bundle");
}
Sprite[] array3 = val.LoadAllAssets<Sprite>();
foreach (Sprite val3 in array3)
{
if (!((Object)(object)val3 == (Object)null))
{
if (((Object)val3).name.EndsWith("Loaded"))
{
SpriteLoaded = val3;
}
else if (((Object)val3).name.EndsWith("Recoil"))
{
SpriteRecoil = val3;
}
else if (((Object)val3).name.EndsWith("Empty"))
{
SpriteEmpty = val3;
}
}
}
Log.LogInfo((object)$"Custom sprites loaded: Loaded={(Object)(object)SpriteLoaded != (Object)null} Recoil={(Object)(object)SpriteRecoil != (Object)null} Empty={(Object)(object)SpriteEmpty != (Object)null}");
}
public static Item CreateShotgunItem()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: 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_0047: 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_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: 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_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: 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_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Expected O, but got Unknown
Item val = new Item
{
itemName = "Shotgun",
itemTag = "shotgun",
itemTags = new List<string> { "weapon", "shotgun" },
prefabName = "Item_Flaregun",
upDirection = Vector3.up,
pocketable = true,
pouchable = true,
worth = 2,
inventoryScale = 1f,
itemWeight = 1f,
data = new List<string>(),
dataModules = new List<Item_Data>(),
dataModuleSaves = new List<DataModuleSave>(),
pickupSounds = new List<AudioClip>(),
executionModules = new List<ItemExecutionModule>()
};
try
{
EnsureShotgunTemplate();
}
catch (Exception ex)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogWarning((object)("Template build deferred: " + ex.Message));
}
}
if ((Object)(object)ShotgunTemplate != (Object)null)
{
val.itemAsset = ShotgunTemplate;
}
try
{
GameObject assetGameObject = CL_AssetManager.GetAssetGameObject("Item_Flaregun", "");
if ((Object)(object)assetGameObject != (Object)null)
{
Item_Object component = assetGameObject.GetComponent<Item_Object>();
if ((Object)(object)component != (Object)null && component.itemData != null)
{
val.handItemAsset = component.itemData.handItemAsset;
}
}
}
catch (Exception ex2)
{
ManualLogSource log2 = Log;
if (log2 != null)
{
log2.LogWarning((object)("Flare hand lookup failed: " + ex2.Message));
}
}
return val;
}
}
[HarmonyPatch(typeof(Inventory), "Initialize")]
public static class InventoryInitPatch
{
public static bool needsStartingItems;
public static Inventory pendingInventory;
[HarmonyPostfix]
public static void Postfix(Inventory __instance)
{
needsStartingItems = true;
pendingInventory = __instance;
Plugin.Log.LogInfo((object)"[InventoryInitPatch] Inventory initialized, scheduling starting items add");
}
}
[HarmonyPatch(typeof(HandItem_Shoot), "Shoot")]
public static class ShotgunBuckshotPatch
{
private const int PelletCount = 8;
private const float SpreadDeg = 5f;
private const float MaxRange = 30f;
private const float DamagePerPellet = 2f;
private static Shader _unlitShader;
[HarmonyPrefix]
public static void Prefix(HandItem_Shoot __instance, out GameObject __state)
{
__state = null;
if (((HandItem)(__instance?)).item?.itemTag == "shotgun")
{
__state = __instance.projectile;
__instance.projectile = null;
}
}
[HarmonyPostfix]
public static void Postfix(HandItem_Shoot __instance, GameObject __state)
{
if (!(((HandItem)(__instance?)).item?.itemTag != "shotgun"))
{
if ((Object)(object)__state != (Object)null)
{
__instance.projectile = __state;
}
FireBuckshot(__instance);
if (__instance.GetAmmo() > 0)
{
ShotgunModHandler.RecordShotTime(__instance);
ShotgunModHandler.QueueSnapBack(__instance, 0.7f);
}
}
}
private static void FireBuckshot(HandItem_Shoot shooter)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//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)
//IL_0087: 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_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: 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_0104: 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)
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: 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)
Camera main = Camera.main;
if ((Object)(object)main == (Object)null)
{
return;
}
Vector3 position = ((Component)main).transform.position;
Vector3 forward = ((Component)main).transform.forward;
SpawnMuzzleFlash(main);
int num = -5;
int num2 = 0;
int num3 = 0;
RaycastHit val2 = default(RaycastHit);
for (int i = 0; i < 8; i++)
{
float num4 = Random.Range(-5f, 5f);
float num5 = Random.Range(-5f, 5f);
Vector3 val = Quaternion.AngleAxis(num4, ((Component)main).transform.right) * Quaternion.AngleAxis(num5, ((Component)main).transform.up) * forward;
if (Physics.Raycast(position, val, ref val2, 30f, num, (QueryTriggerInteraction)1))
{
num2++;
SpawnHitFx(((RaycastHit)(ref val2)).point, ((RaycastHit)(ref val2)).normal);
Damageable component = ((Component)((RaycastHit)(ref val2)).collider).GetComponent<Damageable>();
if (component != null)
{
DamageInfo val3 = DamageInfo.CreateDamageInfo(2f, "Shotgun", new List<string> { "Shotgun", "buckshot" }, (GameEntity)(object)ENT_Player.playerObject);
val3.position = ((RaycastHit)(ref val2)).point;
val3.force = val * 5f;
component.Damage(val3);
num3++;
}
}
}
Plugin.Log.LogInfo((object)$"[ShotgunBuckshotPatch] fired {8} pellets, {num2} surface hits, {num3} damage hits");
}
private static void SpawnMuzzleFlash(Camera cam)
{
SpawnTintFlash();
SpawnEnvironmentalLight(cam);
}
private static void SpawnTintFlash()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: 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_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: 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_0088: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("ShotgunMod_MuzzleFlash_Tint");
Canvas obj = val.AddComponent<Canvas>();
obj.renderMode = (RenderMode)0;
obj.sortingOrder = 32767;
GameObject val2 = new GameObject("Tint");
val2.transform.SetParent(val.transform, false);
Image obj2 = val2.AddComponent<Image>();
((Graphic)obj2).color = new Color(1f, 0.85f, 0.3f, 0.35f);
RectTransform rectTransform = ((Graphic)obj2).rectTransform;
rectTransform.anchorMin = Vector2.zero;
rectTransform.anchorMax = Vector2.one;
rectTransform.offsetMin = Vector2.zero;
rectTransform.offsetMax = Vector2.zero;
val.AddComponent<MuzzleFlashFader>();
}
private static void SpawnEnvironmentalLight(Camera cam)
{
//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_0016: 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)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: 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_008e: Expected O, but got Unknown
GameObject val = new GameObject("ShotgunMod_MuzzleFlash_Light");
val.transform.position = ((Component)cam).transform.position + ((Component)cam).transform.forward * 0.8f;
Light obj = val.AddComponent<Light>();
obj.type = (LightType)2;
obj.color = new Color(1f, 0.85f, 0.4f);
obj.intensity = 30f;
obj.range = 25f;
obj.shadows = (LightShadows)0;
obj.renderMode = (LightRenderMode)1;
Object.Destroy((Object)val, 0.2f);
}
private static void SpawnHitFx(Vector3 point, Vector3 normal)
{
//IL_003c: 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_0043: 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_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)
//IL_0079: 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_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: 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_0098: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Expected O, but got Unknown
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_unlitShader == (Object)null)
{
_unlitShader = Shader.Find("Unlit/Color");
}
int num = 5;
for (int i = 0; i < num; i++)
{
GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3);
Object.Destroy((Object)(object)obj.GetComponent<BoxCollider>());
obj.transform.position = point + normal * 0.02f;
obj.transform.localScale = Vector3.one * 0.05f;
Rigidbody obj2 = obj.AddComponent<Rigidbody>();
obj2.useGravity = true;
Vector3 val = normal + Random.insideUnitSphere * 0.8f;
Vector3 normalized = ((Vector3)(ref val)).normalized;
obj2.velocity = normalized * Random.Range(2.5f, 5.5f);
Renderer component = obj.GetComponent<Renderer>();
if ((Object)(object)component != (Object)null)
{
Color val2 = Color.Lerp(new Color(1f, 0.85f, 0.2f), new Color(1f, 0.55f, 0.1f), Random.value);
if ((Object)(object)_unlitShader != (Object)null)
{
Material val3 = new Material(_unlitShader);
val3.SetColor("_Color", val2);
component.material = val3;
}
else
{
component.material.color = val2;
component.material.EnableKeyword("_EMISSION");
component.material.SetColor("_EmissionColor", val2 * 2f);
}
}
Object.Destroy((Object)(object)obj, 0.5f);
}
}
}
public class MuzzleFlashFader : MonoBehaviour
{
private float _t;
private const float Duration = 0.12f;
private Image _img;
private void Start()
{
_img = ((Component)this).GetComponentInChildren<Image>();
}
private void Update()
{
//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_0056: Unknown result type (might be due to invalid IL or missing references)
_t += Time.deltaTime;
if ((Object)(object)_img != (Object)null)
{
float a = Mathf.Lerp(0.35f, 0f, _t / 0.12f);
Color color = ((Graphic)_img).color;
color.a = a;
((Graphic)_img).color = color;
}
if (_t >= 0.12f)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
}
[HarmonyPatch(typeof(UT_AudioClipHandler), "PlaySound", new Type[] { typeof(string) })]
public static class ShotgunSoundPatch
{
[HarmonyPrefix]
public static bool Prefix(UT_AudioClipHandler __instance, string sound)
{
if (sound != "item:use")
{
return true;
}
HandItem_Shoot component = ((Component)__instance).GetComponent<HandItem_Shoot>();
if ((Object)(object)component == (Object)null || ((HandItem)component).item == null || ((HandItem)component).item.itemTag != "shotgun")
{
return true;
}
if ((Object)(object)Plugin.ShotgunFireClip == (Object)null)
{
return true;
}
AudioSource component2 = ((Component)__instance).GetComponent<AudioSource>();
if ((Object)(object)component2 != (Object)null)
{
component2.PlayOneShot(Plugin.ShotgunFireClip);
return false;
}
return true;
}
}
public static class WavLoader
{
public static AudioClip LoadFromFile(string path)
{
byte[] array = File.ReadAllBytes(path);
if (array.Length < 44 || array[0] != 82 || array[1] != 73 || array[2] != 70 || array[3] != 70)
{
throw new Exception("Not a RIFF file");
}
if (array[8] != 87 || array[9] != 65 || array[10] != 86 || array[11] != 69)
{
throw new Exception("Not a WAVE file");
}
int i = 12;
int num = 0;
int num2 = 0;
int num3 = 0;
int num4 = -1;
int num5 = -1;
int num6;
for (; i < array.Length - 8; i += 8 + num6)
{
string @string = Encoding.ASCII.GetString(array, i, 4);
num6 = BitConverter.ToInt32(array, i + 4);
if (@string == "fmt ")
{
num = BitConverter.ToInt16(array, i + 10);
num2 = BitConverter.ToInt32(array, i + 12);
num3 = BitConverter.ToInt16(array, i + 22);
}
else if (@string == "data")
{
num4 = i + 8;
num5 = num6;
break;
}
}
if (num4 < 0)
{
throw new Exception("No data chunk found");
}
int num7 = num3 / 8;
int num8 = num5 / num7;
float[] array2 = new float[num8];
switch (num3)
{
case 16:
{
for (int m = 0; m < num8; m++)
{
short num12 = BitConverter.ToInt16(array, num4 + m * 2);
array2[m] = (float)num12 / 32768f;
}
break;
}
case 24:
{
for (int k = 0; k < num8; k++)
{
int num9 = array[num4 + k * 3];
int num10 = array[num4 + k * 3 + 1];
int num11 = ((sbyte)array[num4 + k * 3 + 2] << 16) | (num10 << 8) | num9;
array2[k] = (float)num11 / 8388608f;
}
break;
}
case 32:
{
for (int l = 0; l < num8; l++)
{
array2[l] = BitConverter.ToSingle(array, num4 + l * 4);
}
break;
}
case 8:
{
for (int j = 0; j < num8; j++)
{
array2[j] = (float)(array[num4 + j] - 128) / 128f;
}
break;
}
default:
throw new Exception($"Unsupported bit depth: {num3}");
}
AudioClip obj = AudioClip.Create("shotgun_fire_custom", num8 / num, num, num2, false);
obj.SetData(array2, 0);
return obj;
}
}
[HarmonyPatch(typeof(UT_EventController), "PlayEvent", new Type[] { typeof(string) })]
public static class ShotgunEventPatch
{
[HarmonyPrefix]
public static bool Prefix(UT_EventController __instance, string eventName)
{
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: 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)
HandItem_Shoot componentInParent = ((Component)__instance).GetComponentInParent<HandItem_Shoot>();
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogInfo((object)string.Format("[ShotgunEventPatch] PlayEvent('{0}') on '{1}' — handItem found: {2}, tag: {3}", eventName, ((Object)((Component)__instance).gameObject).name, (Object)(object)componentInParent != (Object)null, ((HandItem)(componentInParent?)).item?.itemTag ?? "null"));
}
if (((HandItem)(componentInParent?)).item?.itemTag != "shotgun")
{
return true;
}
if (eventName == "eject" && componentInParent.GetAmmo() > 0)
{
return false;
}
if (eventName == "shoot" && (Object)(object)Plugin.ShotgunFireClip != (Object)null)
{
Vector3 val = (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform.position : ((Component)componentInParent).transform.position);
AudioSource.PlayClipAtPoint(Plugin.ShotgunFireClip, val, 1f);
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogInfo((object)"[ShotgunEventPatch] played custom shotgun clip");
}
return false;
}
return true;
}
}
[HarmonyPatch(typeof(HandItem_Shoot), "FinishReload")]
public static class ShotgunReloadPatch
{
[HarmonyPrefix]
public static bool Prefix(HandItem_Shoot __instance)
{
if (((HandItem)(__instance?)).item?.itemTag != "shotgun")
{
return true;
}
int num = 1;
if ((Object)(object)Inventory.instance != (Object)null && !string.IsNullOrEmpty(__instance.ammoTag))
{
Item itemByTag = Inventory.instance.GetItemByTag(__instance.ammoTag);
if (itemByTag != null)
{
itemByTag.DestroyItem();
num = 2;
}
}
__instance.Recharge(num);
FieldInfo fieldInfo = AccessTools.Field(typeof(HandItem), "used");
if (fieldInfo != null)
{
fieldInfo.SetValue(__instance, false);
}
object? obj = AccessTools.Field(typeof(HandItem), "anim")?.GetValue(__instance);
Animator val = (Animator)((obj is Animator) ? obj : null);
if ((Object)(object)val != (Object)null && __instance.loadedAnimationState)
{
val.SetBool("Loaded", __instance.GetAmmo() > 0);
}
UnityEvent reloadEvent = __instance.reloadEvent;
if (reloadEvent != null)
{
reloadEvent.Invoke();
}
Plugin.Log.LogInfo((object)$"[ShotgunReloadPatch] Loaded {num} shells, ammo now {__instance.GetAmmo()}/{__instance.GetMaxAmmo()}");
return false;
}
}
[HarmonyPatch(typeof(HandItem_Shoot), "Initialize")]
public static class ShotgunMaxAmmoPatch
{
[HarmonyPrefix]
public static void Prefix(HandItem_Shoot __instance, Item i, Hand h)
{
if (i == null || i.itemTag != "shotgun")
{
return;
}
string value = null;
try
{
value = i.GetFirstDataStringByType("ammo", false);
}
catch
{
}
if (!string.IsNullOrEmpty(value))
{
return;
}
try
{
i.SetFirstDataStringsofType("ammo", "2");
}
catch
{
}
}
[HarmonyPostfix]
public static void Postfix(HandItem_Shoot __instance, Item i, Hand h)
{
if (i != null && !(i.itemTag != "shotgun"))
{
__instance.maxAmmo = 2;
}
}
}
public class ShotgunModHandler : MonoBehaviour
{
private float _lastHeartbeat;
private int _frameCount;
private float _startingItemsAddAt = -1f;
private static readonly List<(float time, HandItem_Shoot target)> _pendingSnapBacks = new List<(float, HandItem_Shoot)>();
private static readonly List<(float time, HandItem_Shoot target)> _pendingAudioRestores = new List<(float, HandItem_Shoot)>();
private static Dictionary<SpriteRenderer, Sprite> _cachedCockedByRenderer = new Dictionary<SpriteRenderer, Sprite>();
private static Sprite _shotgunFingerSprite;
private static Dictionary<HandItem_Shoot, float> _lastShotTime = new Dictionary<HandItem_Shoot, float>();
public static void QueueSnapBack(HandItem_Shoot instance, float delay)
{
_pendingSnapBacks.Add((Time.time + delay, instance));
}
public static void QueueAudioRestore(HandItem_Shoot instance, float delay)
{
_pendingAudioRestores.Add((Time.time + delay, instance));
}
private void OverrideShotgunSpriteIfLoaded()
{
ENT_Player playerObject = ENT_Player.playerObject;
if ((Object)(object)playerObject == (Object)null || playerObject.hands == null)
{
return;
}
Hand[] hands = playerObject.hands;
foreach (Hand val in hands)
{
if (val == null)
{
continue;
}
HandItem handItem = val.GetHandItem();
HandItem_Shoot val2 = (HandItem_Shoot)(object)((handItem is HandItem_Shoot) ? handItem : null);
if ((Object)(object)val2 == (Object)null || ((HandItem)val2).item == null || ((HandItem)val2).item.itemTag != "shotgun")
{
continue;
}
float value;
bool flag = (_lastShotTime.TryGetValue(val2, out value) ? (Time.time - value) : float.MaxValue) < 0.5f;
Sprite val3 = ((val2.GetAmmo() <= 0) ? Plugin.SpriteEmpty : ((!flag) ? Plugin.SpriteLoaded : Plugin.SpriteRecoil));
if ((Object)(object)val3 == (Object)null)
{
continue;
}
SpriteRenderer[] componentsInChildren = ((Component)val2).GetComponentsInChildren<SpriteRenderer>(true);
foreach (SpriteRenderer val4 in componentsInChildren)
{
if (!((Object)(object)val4 == (Object)null) && ((Object)((Component)val4).gameObject).name == "Item_Hands_Flaregun" && (Object)(object)((Component)val4).transform.parent != (Object)null && ((Object)((Component)val4).transform.parent).name == "Root_Placement" && (Object)(object)val4.sprite != (Object)(object)val3)
{
val4.sprite = val3;
}
}
}
}
private void OverrideShotgunSpriteIfLoadedOLD()
{
ENT_Player playerObject = ENT_Player.playerObject;
if ((Object)(object)playerObject == (Object)null || playerObject.hands == null)
{
return;
}
Hand[] hands = playerObject.hands;
foreach (Hand val in hands)
{
if (val == null)
{
continue;
}
HandItem handItem = val.GetHandItem();
HandItem_Shoot val2 = (HandItem_Shoot)(object)((handItem is HandItem_Shoot) ? handItem : null);
if ((Object)(object)val2 == (Object)null || ((HandItem)val2).item == null || ((HandItem)val2).item.itemTag != "shotgun" || val2.GetAmmo() <= 0)
{
continue;
}
float value;
float num = (_lastShotTime.TryGetValue(val2, out value) ? (Time.time - value) : float.MaxValue);
bool flag = num >= 0.067f && num <= 0.6f;
bool flag2 = num > 1f;
SpriteRenderer[] componentsInChildren = ((Component)val2).GetComponentsInChildren<SpriteRenderer>(true);
foreach (SpriteRenderer val3 in componentsInChildren)
{
if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.sprite == (Object)null))
{
Sprite value2;
if (flag2)
{
_cachedCockedByRenderer[val3] = val3.sprite;
}
else if (flag && _cachedCockedByRenderer.TryGetValue(val3, out value2) && (Object)(object)value2 != (Object)null && (Object)(object)val3.sprite != (Object)(object)value2)
{
val3.sprite = value2;
}
}
}
}
}
private void ProcessSnapBacks()
{
for (int num = _pendingSnapBacks.Count - 1; num >= 0; num--)
{
if (Time.time >= _pendingSnapBacks[num].time)
{
HandItem_Shoot item = _pendingSnapBacks[num].target;
_pendingSnapBacks.RemoveAt(num);
if (!((Object)(object)item == (Object)null))
{
try
{
object? obj = AccessTools.Field(typeof(HandItem), "anim")?.GetValue(item);
Animator val = (Animator)((obj is Animator) ? obj : null);
if ((Object)(object)val != (Object)null)
{
val.SetBool("Loaded", true);
val.Play("Item_Flaregun_Idle_loaded", 0, 0f);
val.Update(0f);
}
item.ResetUsedState();
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)("Snap-back failed: " + ex.Message));
}
}
}
}
}
for (int num2 = _pendingAudioRestores.Count - 1; num2 >= 0; num2--)
{
if (Time.time >= _pendingAudioRestores[num2].time)
{
HandItem_Shoot item2 = _pendingAudioRestores[num2].target;
_pendingAudioRestores.RemoveAt(num2);
if (!((Object)(object)item2 == (Object)null))
{
try
{
AudioSource[] componentsInChildren = ((Component)item2).GetComponentsInChildren<AudioSource>(true);
foreach (AudioSource val2 in componentsInChildren)
{
if ((Object)(object)val2 != (Object)null)
{
val2.volume = 1f;
}
}
}
catch
{
}
}
}
}
}
private static Sprite FindLoadedSpriteByName(string name)
{
Sprite[] array = Resources.FindObjectsOfTypeAll<Sprite>();
foreach (Sprite val in array)
{
if ((Object)(object)val != (Object)null && ((Object)val).name == name)
{
return val;
}
}
return null;
}
private static Texture2D FindLoadedTextureByName(string name)
{
Texture2D[] array = Resources.FindObjectsOfTypeAll<Texture2D>();
foreach (Texture2D val in array)
{
if ((Object)(object)val != (Object)null && ((Object)val).name == name)
{
return val;
}
}
return null;
}
private static Sprite CreateSpriteFromTexture(string textureName, int x, int y, int w, int h, Vector2 pivot)
{
//IL_003c: 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)
Texture2D val = FindLoadedTextureByName(textureName);
if ((Object)(object)val == (Object)null)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)("Texture '" + textureName + "' not found in loaded assets"));
}
return null;
}
return Sprite.Create(val, new Rect((float)x, (float)y, (float)w, (float)h), pivot, 100f);
}
public static void RecordShotTime(HandItem_Shoot instance)
{
_lastShotTime[instance] = Time.time;
}
private void Update()
{
_frameCount++;
if (Time.time - _lastHeartbeat > 30f)
{
_lastHeartbeat = Time.time;
Debug.Log((object)$"[ShotgunModHandler] alive, frames={_frameCount}");
}
ProcessSnapBacks();
if ((Object)(object)Camera.main != (Object)null && Mathf.Abs(Camera.main.fieldOfView - 100f) > 0.1f)
{
Camera.main.fieldOfView = 100f;
}
if (InventoryInitPatch.needsStartingItems && _startingItemsAddAt < 0f)
{
_startingItemsAddAt = Time.time + 1f;
}
if (_startingItemsAddAt > 0f && Time.time >= _startingItemsAddAt)
{
TryAddStartingItems();
_startingItemsAddAt = -2f;
InventoryInitPatch.needsStartingItems = false;
}
if (Input.GetKeyDown((KeyCode)290))
{
Debug.Log((object)"[ShotgunModHandler] F9 pressed - spawning test shotgun");
SpawnTestShotgun();
}
}
private void LateUpdate()
{
OverrideShotgunSpriteIfLoaded();
if (Time.frameCount % 15 == 0)
{
ReapplyOutlineToShotguns();
}
}
private void ReapplyOutlineToShotguns()
{
if ((Object)(object)Plugin.OutlineMaterial == (Object)null)
{
return;
}
Item_Object[] array = Object.FindObjectsOfType<Item_Object>();
foreach (Item_Object val in array)
{
if (val?.itemData?.itemTag != "shotgun")
{
continue;
}
MeshRenderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<MeshRenderer>(true);
foreach (MeshRenderer val2 in componentsInChildren)
{
if (((Object)val2).name.StartsWith("Outline_"))
{
continue;
}
Material[] sharedMaterials = ((Renderer)val2).sharedMaterials;
bool flag = false;
Material[] array2 = sharedMaterials;
for (int k = 0; k < array2.Length; k++)
{
if ((Object)(object)array2[k] == (Object)(object)Plugin.OutlineMaterial)
{
flag = true;
break;
}
}
if (!flag)
{
Material[] array3 = (Material[])(object)new Material[sharedMaterials.Length + 1];
for (int l = 0; l < sharedMaterials.Length; l++)
{
array3[l] = sharedMaterials[l];
}
array3[sharedMaterials.Length] = Plugin.OutlineMaterial;
((Renderer)val2).sharedMaterials = array3;
}
}
}
}
private void TryAddStartingItems()
{
//IL_010e: 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)
Inventory pendingInventory = InventoryInitPatch.pendingInventory;
if ((Object)(object)pendingInventory == (Object)null)
{
return;
}
int num = 0;
bool flag = false;
foreach (Item bagItem in pendingInventory.bagItems)
{
if (bagItem != null && bagItem.itemTag == "shotgun")
{
flag = true;
break;
}
}
if (!flag)
{
try
{
Item val = Plugin.CreateShotgunItem();
pendingInventory.AddItemToInventoryScreen(new Vector3(0f, 0.1f, 1f), val, true, false);
num++;
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"Failed to add shotgun: {arg}");
}
}
GameObject assetGameObject = CL_AssetManager.GetAssetGameObject("Item_Flaregun_Ammo", "");
if ((Object)(object)assetGameObject != (Object)null)
{
Item_Object component = assetGameObject.GetComponent<Item_Object>();
if ((Object)(object)component != (Object)null && component.itemData != null)
{
for (int i = 0; i < 2; i++)
{
try
{
Item clone = component.itemData.GetClone((Item)null);
pendingInventory.AddItemToInventoryScreen(new Vector3(0.15f * ((float)i - 0.5f), 0.2f, 1f), clone, true, false);
num++;
}
catch (Exception arg2)
{
Plugin.Log.LogError((object)$"Failed to add flare {i}: {arg2}");
}
}
}
}
Plugin.Log.LogInfo((object)$"[TryAddStartingItems] Added {num} starting items");
}
private void SpawnTestShotgun()
{
//IL_0043: 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)
//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)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: 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_007d: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Plugin.ShotgunPrefab == (Object)null)
{
Debug.LogError((object)"[ShotgunModHandler] Cannot spawn: prefab is null");
return;
}
Camera main = Camera.main;
if ((Object)(object)main == (Object)null)
{
Debug.LogWarning((object)"[ShotgunModHandler] No main camera, spawning at origin");
Object.Instantiate<GameObject>(Plugin.ShotgunPrefab);
}
else
{
Vector3 val = ((Component)main).transform.position + ((Component)main).transform.forward * 2f;
ConfigureAsPickup(Object.Instantiate<GameObject>(Plugin.ShotgunPrefab, val, Quaternion.identity));
Debug.Log((object)$"[ShotgunModHandler] Shotgun spawned at {val}");
}
}
public static void ConfigureAsPickup(GameObject shotgun)
{
//IL_0254: Unknown result type (might be due to invalid IL or missing references)
//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
//IL_02b4: Expected O, but got Unknown
//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
//IL_02bf: Expected O, but got Unknown
//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
//IL_02ca: Expected O, but got Unknown
//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
//IL_02d5: Expected O, but got Unknown
//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0222: Unknown result type (might be due to invalid IL or missing references)
//IL_0227: Unknown result type (might be due to invalid IL or missing references)
//IL_0233: Unknown result type (might be due to invalid IL or missing references)
shotgun.layer = 10;
Transform[] componentsInChildren = shotgun.GetComponentsInChildren<Transform>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
((Component)componentsInChildren[i]).gameObject.layer = 10;
}
try
{
shotgun.tag = "Pickupable";
}
catch
{
}
ObjectTagger val = shotgun.GetComponent<ObjectTagger>();
if ((Object)(object)val == (Object)null)
{
val = shotgun.AddComponent<ObjectTagger>();
}
if (val.tags == null)
{
val.tags = new List<string>();
}
if (!val.tags.Contains("Pickupable"))
{
val.tags.Add("Pickupable");
}
if (!val.tags.Contains("Item"))
{
val.tags.Add("Item");
}
if ((Object)(object)Plugin.OutlineMaterial != (Object)null)
{
int num = 0;
MeshRenderer[] componentsInChildren2 = shotgun.GetComponentsInChildren<MeshRenderer>(true);
foreach (MeshRenderer val2 in componentsInChildren2)
{
if (((Object)val2).name.StartsWith("Outline_"))
{
continue;
}
Material[] sharedMaterials = ((Renderer)val2).sharedMaterials;
bool flag = false;
Material[] array = sharedMaterials;
for (int j = 0; j < array.Length; j++)
{
if ((Object)(object)array[j] == (Object)(object)Plugin.OutlineMaterial)
{
flag = true;
break;
}
}
if (!flag)
{
Material[] array2 = (Material[])(object)new Material[sharedMaterials.Length + 1];
for (int k = 0; k < sharedMaterials.Length; k++)
{
array2[k] = sharedMaterials[k];
}
array2[sharedMaterials.Length] = Plugin.OutlineMaterial;
((Renderer)val2).sharedMaterials = array2;
num++;
}
}
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogInfo((object)$"[Outline] Added outline material to {num} renderers on {((Object)shotgun).name}");
}
}
else
{
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogWarning((object)"[Outline] OutlineMaterial is null");
}
}
if ((Object)(object)shotgun.GetComponentInChildren<Collider>() == (Object)null)
{
Renderer[] componentsInChildren3 = shotgun.GetComponentsInChildren<Renderer>();
if (componentsInChildren3.Length != 0)
{
Bounds bounds = componentsInChildren3[0].bounds;
for (int l = 1; l < componentsInChildren3.Length; l++)
{
((Bounds)(ref bounds)).Encapsulate(componentsInChildren3[l].bounds);
}
BoxCollider obj2 = shotgun.AddComponent<BoxCollider>();
obj2.center = shotgun.transform.InverseTransformPoint(((Bounds)(ref bounds)).center);
obj2.size = ((Bounds)(ref bounds)).size;
}
else
{
shotgun.AddComponent<BoxCollider>().size = new Vector3(1.5f, 0.3f, 0.3f);
}
}
Rigidbody val3 = shotgun.GetComponent<Rigidbody>();
if ((Object)(object)val3 == (Object)null)
{
val3 = shotgun.AddComponent<Rigidbody>();
}
val3.mass = 0.5f;
Item_Object val4 = shotgun.GetComponent<Item_Object>();
if ((Object)(object)val4 == (Object)null)
{
val4 = shotgun.AddComponent<Item_Object>();
}
val4.itemData = Plugin.CreateShotgunItem();
val4.canPickup = true;
val4.pickupEvent = new UnityEvent();
val4.onDrop = new UnityEvent();
val4.onPlaceInInventory = new UnityEvent();
val4.onPlaceInWorld = new UnityEvent();
CL_Prop val5 = shotgun.GetComponent<CL_Prop>();
if ((Object)(object)val5 == (Object)null)
{
val5 = shotgun.AddComponent<CL_Prop>();
}
if (val5.hitSounds == null)
{
val5.hitSounds = new List<PropAudioEffect>();
}
if (val5.dragSounds == null)
{
val5.dragSounds = new List<PropAudioEffect>();
}
if (val5.breakSounds == null)
{
val5.breakSounds = new List<PropAudioEffect>();
}
if (val5.unstickSounds == null)
{
val5.unstickSounds = new List<PropAudioEffect>();
}
if (val5.damageSounds == null)
{
val5.damageSounds = new List<PropAudioEffect>();
}
}
}
}