You are viewing a potentially older version of this package. View all versions.
4902-Blahaj-1.2.0 icon

Blahaj

Adds Blahaj as client sided scrap, percentage based retexture of axle

By 4902
Date uploaded 2 months ago
Version 1.2.0
Download link 4902-Blahaj-1.2.0.zip
Downloads 4122
Dependency string 4902-Blahaj-1.2.0

This mod requires the following mods to function

BepInEx-BepInExPack-5.4.2100 icon
BepInEx-BepInExPack

BepInEx pack for Mono Unity games. Preconfigured and ready to use.

Preferred version: 5.4.2100

README

Randomly replaces a certain percentage of Large axle items with Blahaj (also a chance for a pink version), with different item names and sound effects

Percentages are changable by config, defaults are 50% for blahaj, 10% for pink

Item types are synced between players if config percentages are the same

cs in zip. assetbundle from https://thunderstore.io/c/lethal-company/p/ArticFox_Monix/Blahaj/

CHANGELOG

1.2.0
-fixed error with getting lobbyid
-replaced system.random with custom random
-added section text to config
-added source code to the changelog

1.1.0
-added item type syncing by adding a seed to random based on lobbyid + networkobjectid

1.0.0
Source code

1.2.0

using UInt32 = System.UInt32; using UInt64 = System.UInt64; using System.IO; using System.Reflection; using BepInEx; using BepInEx.Logging; using BepInEx.Configuration; using HarmonyLib; using Blahaj.Patches; using GameNetcodeStuff; using UnityEngine; using UnityEngine.InputSystem; using Unity.Netcode; namespace Blahaj { [BepInPlugin("4902.Shark", "Shark", "1.0.0")] public class gura : BaseUnityPlugin { private readonly Harmony harmony = new Harmony("4902.Shark"); public static ManualLogSource mls; public static ConfigEntry<int> blue_percentage; public static ConfigEntry<int> pink_percentage; private void Awake() { blue_percentage = Config.Bind("#", "blahaj_percent", 50, "percentage that blahaj will replace axle\ninput = percentage, 50 is 50% etc"); pink_percentage = Config.Bind("#", "pink_variant_percent", 10, "percentage that blahaj will be pink\ninput = percentage"); mls = BepInEx.Logging.Logger.CreateLogSource("Shark"); mls.LogInfo("Blahaj is in your walls"); harmony.PatchAll(typeof(go)); harmony.PatchAll(typeof(pcb)); harmony.PatchAll(typeof(hm)); harmony.PatchAll(typeof(sor)); harmony.PatchAll(typeof(gnm)); } } } namespace Blahaj.Patches { [HarmonyPatch(typeof(GrabbableObject))] internal class go { public static string[] item = new string[2]; public static Mesh[] fish = new Mesh[2]; public static Material[][] cats = new Material[3][]; public static AudioClip[] take = new AudioClip[2]; public static AudioClip[] give = new AudioClip[2]; private static bool dots = false; [HarmonyPatch("Start")] private static void Postfix(GrabbableObject __instance) { if (((Object)__instance.itemProperties).name == "Cog1") { if (item[0] == null) { string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "4902-shark").Replace("\\", "/"); gura.mls.LogMessage("Searching this filepath:" + text); AssetBundle asset = AssetBundle.LoadFromFileAsync(text).assetBundle; //axle item[0] = "Large axle"; fish[0] = __instance.GetComponent<MeshFilter>().mesh; cats[0] = __instance.GetComponent<MeshRenderer>().materials; take[0] = __instance.itemProperties.grabSFX; give[0] = __instance.itemProperties.dropSFX; //shark item[1] = "Shark plushie"; fish[1] = asset.LoadAsset<Mesh>("blahaj.fbx"); cats[1] = new Material[1] {asset.LoadAsset<Material>("blahaj.mat")}; //blue cats[2] = new Material[1] {asset.LoadAsset<Material>("beyoublahaj.mat")}; //pink take[1] = asset.LoadAsset<AudioClip>("blahajgrab.mp3"); give[1] = asset.LoadAsset<AudioClip>("blahajdrop.mp3"); } if (item[0] != null) { Shion cr = (GameNetworkManager.Instance.disableSteam == false && sor.lobbyid != 0 && __instance.GetComponent<NetworkObject>() != null ? new Shion((int)((sor.lobbyid + __instance.GetComponent<NetworkObject>().NetworkObjectId) % 1000000000)) : new Shion()); //System.Random sr = (GameNetworkManager.Instance.disableSteam == false ? new System.Random((int)((GameNetworkManager.Instance.currentLobby.Value.Id + __instance.GetComponent<NetworkObject>().NetworkObjectId) % 1000000000)) : new System.Random()); int num = (cr.next32mm(0, 100) < gura.blue_percentage.Value ? 1 : 0); if (num == 1) { if (dots == false) { Vector3[] vertices = fish[1].vertices; Vector3[] normals = fish[1].normals; Vector3 center = fish[1].bounds.center; for (int n = 0; n < vertices.Length; n = n + 1) { vertices[n] = vertices[n] - center; vertices[n] = vertices[n] * 48f; float x = vertices[n].x; float z = vertices[n].z; float nx = normals[n].x; float nz = normals[n].z; vertices[n].x = z; vertices[n].z = -x; normals[n].x = nz; normals[n].z = -nx; vertices[n] = vertices[n] + center; } fish[1].vertices = vertices; fish[1].normals = normals; fish[1].RecalculateBounds(); fish[1].RecalculateNormals(); dots = true; } __instance.GetComponent<MeshRenderer>().materials = (cr.next32mm(0, 100) < gura.pink_percentage.Value ? cats[2] : cats[1]); } else { __instance.GetComponent<MeshRenderer>().materials = cats[0]; } __instance.itemProperties.itemName = item[num]; __instance.GetComponentInChildren<ScanNodeProperties>().headerText = item[num]; __instance.GetComponent<MeshFilter>().mesh = fish[num]; __instance.itemProperties.grabSFX = take[num]; __instance.itemProperties.dropSFX = give[num]; } } } [HarmonyPatch("PlayDropSFX")] private static void Prefix(ref GrabbableObject __instance) { if (item[0] != null && __instance != null && ((Object)__instance.itemProperties).name == "Cog1" && __instance.GetComponentInChildren<ScanNodeProperties>() != null) { __instance.itemProperties.dropSFX = (__instance.GetComponentInChildren<ScanNodeProperties>().headerText == item[1] ? give[1] : give[0]); } } } [HarmonyPatch(typeof(PlayerControllerB))] internal class pcb { [HarmonyPatch("BeginGrabObject")] private static void Postfix(ref GrabbableObject ___currentlyGrabbingObject) { if (go.item[0] != null && ___currentlyGrabbingObject != null && ((Object)___currentlyGrabbingObject.itemProperties).name == "Cog1" && ___currentlyGrabbingObject.GetComponentInChildren<ScanNodeProperties>() != null) { ___currentlyGrabbingObject.itemProperties.grabSFX = (___currentlyGrabbingObject.GetComponentInChildren<ScanNodeProperties>().headerText == go.item[1] ? go.take[1] : go.take[0]); ___currentlyGrabbingObject.itemProperties.itemName = ___currentlyGrabbingObject.GetComponentInChildren<ScanNodeProperties>().headerText; } } [HarmonyPatch("ScrollMouse_performed")] private static void Prefix(ref InputAction.CallbackContext context, ref int ___currentItemSlot, ref GrabbableObject[] ___ItemSlots) { if (go.item[0] != null) { bool foward = false; if (context.ReadValue<float>() > 0f) foward = true; int next = ___currentItemSlot - 1; if (foward == true) next = (___currentItemSlot + 1) % ___ItemSlots.Length; else if (___currentItemSlot == 0) next = ___ItemSlots.Length - 1; if (next >= 0 && next < ___ItemSlots.Length && ___ItemSlots[next] != null && ((Object)___ItemSlots[next].itemProperties).name == "Cog1" && ___ItemSlots[next].GetComponentInChildren<ScanNodeProperties>() != null) { ___ItemSlots[next].itemProperties.grabSFX = (___ItemSlots[next].GetComponentInChildren<ScanNodeProperties>().headerText == go.item[1] ? go.take[1] : go.take[0]); ___ItemSlots[next].itemProperties.itemName = ___ItemSlots[next].GetComponentInChildren<ScanNodeProperties>().headerText; } } } } [HarmonyPatch(typeof(HUDManager))] internal class hm { [HarmonyPatch("DisplayNewScrapFound")] [HarmonyPrefix] private static void Prefix1(ref System.Collections.Generic.List<GrabbableObject> ___itemsToBeDisplayed) { if (go.item[0] != null && ___itemsToBeDisplayed[0] != null && ((Object)___itemsToBeDisplayed[0].itemProperties).name == "Cog1" && ___itemsToBeDisplayed[0].GetComponentInChildren<ScanNodeProperties>() != null) { ___itemsToBeDisplayed[0].itemProperties.itemName = ___itemsToBeDisplayed[0].itemProperties.spawnPrefab.GetComponentInChildren<ScanNodeProperties>().headerText = ___itemsToBeDisplayed[0].GetComponentInChildren<ScanNodeProperties>().headerText; } } [HarmonyPatch("displayScrapTimer")] [HarmonyPrefix] private static void Prefix2(ref GameObject displayingObject) { if (go.item[0] != null && displayingObject.name == "Cog(Clone)" && displayingObject.GetComponentInChildren<ScanNodeProperties>() != null) { displayingObject.GetComponent<MeshFilter>().mesh = (displayingObject.GetComponentInChildren<ScanNodeProperties>().headerText == go.item[1] ? go.fish[1] : go.fish[0]); } } } [HarmonyPatch(typeof(StartOfRound))] internal class sor { public static uint lobbyid = 0; [HarmonyPatch("Start")] private static void Postfix() { if (GameNetworkManager.Instance.disableSteam == false) { if (GameNetworkManager.Instance.currentLobby.HasValue == true) { lobbyid = (uint)GameNetworkManager.Instance.currentLobby.Value.Id; gura.mls.LogInfo(lobbyid); } else { gura.mls.LogError("current lobby id is null"); } } } } [HarmonyPatch(typeof(GameNetworkManager))] internal class gnm { [HarmonyPatch("Disconnect")] private static void Postfix() { sor.lobbyid = 0; } } public class Shion { private UInt64[] state; public Shion() { System.Security.Cryptography.RandomNumberGenerator rand = System.Security.Cryptography.RandomNumberGenerator.Create(); byte[] randBytes = new byte[8]; rand.GetBytes(randBytes, 0, 8); UInt64 seed = System.BitConverter.ToUInt64(randBytes, 0); xorshift256_init(seed); } public Shion(int seed) { xorshift256_init((ulong)seed); } //next public int next32mm(int min, int max) { uint value = next32(); double scale = ((double)(max - min)) / UInt32.MaxValue; return (int)(min + (value * scale)); } public byte[] next8() { UInt64 nextInt64 = xoshiro256ss(); return System.BitConverter.GetBytes(nextInt64); } public UInt32 next32() { byte[] randBytes = next8(); return System.BitConverter.ToUInt32(randBytes, 0); } public UInt64 next64() { return xoshiro256ss(); } public double next01() { UInt64 nextInt64 = xoshiro256ss(); //0 inclusive, 1 exclusive return (double)nextInt64 / (double)(UInt64.MaxValue); } //misc private UInt64 splitmix64(UInt64 partialstate) { partialstate = partialstate + 0x9E3779B97f4A7C15; partialstate = (partialstate ^ (partialstate >> 30)) * 0xBF58476D1CE4E5B9; partialstate = (partialstate ^ (partialstate >> 27)) * 0x94D049BB133111EB; return partialstate ^ (partialstate >> 31); } private void xorshift256_init(UInt64 seed) { UInt64[] result = new UInt64[4]; result[0] = splitmix64(seed); result[1] = splitmix64(result[0]); result[2] = splitmix64(result[1]); result[3] = splitmix64(result[2]); state = result; } private UInt64 rotl64(UInt64 x, int k) { return (x << k) | (x >> (64 - k)); } private UInt64 xoshiro256ss() { UInt64 result = rotl64(state[1] * 5, 7) * 9; UInt64 t = state[1] << 17; state[2] ^= state[0]; state[3] ^= state[1]; state[1] ^= state[2]; state[0] ^= state[3]; state[2] ^= t; state[3] = rotl64(state[3], 45); return result; } } } /*previous version of this mods code. i remade it for uploading, mostly to add percentages for axle and configs //this was my first mod for lethal company, most of the code i referenced from https://thunderstore.io/c/lethal-company/p/Mellowdy/Maxwell/ using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Blahaj.Patches; using UnityEngine; namespace Blahaj { [BepInPlugin("4902.SharkReplacer", "SharkReplacer", "1.0.0")] public class SharkReplacerMod : BaseUnityPlugin { private readonly Harmony harmony = new Harmony("SharkReplacer"); public static ManualLogSource mls; private static SharkReplacerMod instance; private void Awake() { if ((Object)(object)instance == (Object)null) { instance = this; } mls = BepInEx.Logging.Logger.CreateLogSource("SharkReplacer"); mls.LogInfo("Blahaj is in your walls"); harmony.PatchAll(typeof(SharkReplacerMod)); harmony.PatchAll(typeof(ItemReplacerPatch)); } } } namespace Blahaj.Patches { [HarmonyPatch(typeof(GrabbableObject))] internal class ItemReplacerPatch { private static string assetName = "shark.plushie"; private static string name = "Shark plushie"; private static Mesh model = null; private static Material blue; private static Material pink; private static AudioClip grab; private static AudioClip drop; private static float size = 48f; [HarmonyPatch("Start")] [HarmonyPostfix] private static void ReplaceModel(GrabbableObject __instance, ref MeshRenderer ___mainObjectRenderer) { try { if (model == null) { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = Path.Combine(directoryName, assetName).Replace("\\", "/"); SharkReplacerMod.mls.LogMessage("Searching this filepath:" + text); AssetBundleCreateRequest val = AssetBundle.LoadFromFileAsync(text); AssetBundle assetBundle = val.assetBundle; model = assetBundle.LoadAsset<Mesh>("blahaj.fbx"); blue = assetBundle.LoadAsset<Material>("blahaj.mat"); pink = assetBundle.LoadAsset<Material>("beyoublahaj.mat"); grab = assetBundle.LoadAsset<AudioClip>("blahajgrab.mp3"); drop = assetBundle.LoadAsset<AudioClip>("blahajdrop.mp3"); } } catch { SharkReplacerMod.mls.LogError("Assets did not load"); } //int random = new Random().Next(0, 10); if (model != null && ((Object)__instance.itemProperties).name == "Cog1") { MeshFilter component = ___mainObjectRenderer.GetComponent<MeshFilter>(); component.mesh = Object.Instantiate<Mesh>(model); Mesh mesh = component.mesh; Vector3[] vertices = mesh.vertices; Vector3[] normals = mesh.normals; Bounds bounds = mesh.bounds; Vector3 center = bounds.center; for (int n = 0; n < vertices.Length; n++) { //vertices[n] = center + ((vertices[n] - center) * size); vertices[n] = vertices[n] - center; vertices[n] = vertices[n] * size; float x = vertices[n].x; float z = vertices[n].z; float nx = normals[n].x; float nz = normals[n].z; vertices[n].x = z; vertices[n].z = -x; normals[n].x = nz; normals[n].z = -nx; vertices[n] = vertices[n] + center; } mesh.vertices = vertices; mesh.normals = normals; mesh.RecalculateBounds(); mesh.RecalculateNormals(); if (Random.Range(0, 10) == 0) { ___mainObjectRenderer.materials = new Material[1] {pink}; } else { ___mainObjectRenderer.materials = new Material[1] {blue}; } __instance.itemProperties.itemName = name; ___mainObjectRenderer.GetComponentInChildren<ScanNodeProperties>().headerText = name; __instance.itemProperties.spawnPrefab.GetComponent<MeshFilter>().mesh = mesh; __instance.itemProperties.grabSFX = grab; __instance.itemProperties.dropSFX = drop; } } } }*/