using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using MaskedModelReplacement.Patches;
using ModelReplacement;
using ModelReplacement.Monobehaviors.Enemies;
using ModelReplacement.Scripts.Enemies;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Rendering;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("MaskedModelReplacement")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MaskedModelReplacement")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e8c0087e-4258-4043-a787-7ded3d04acd6")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.1.0")]
namespace MaskedModelReplacement
{
[BepInPlugin("CubeMath.MaskedModelReplacementMod", "Masked Model Replacement", "1.2.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class MaskedModelReplacementBase : BaseUnityPlugin
{
private const string modGUID = "CubeMath.MaskedModelReplacementMod";
private const string modName = "Masked Model Replacement";
private const string modVersion = "1.2.0.0";
private readonly Harmony harmony = new Harmony("CubeMath.MaskedModelReplacementMod");
public static MaskedModelReplacementBase Instance;
public ManualLogSource Logger;
public static bool LogAvailableSuits;
public static bool ModelReplacementsOnly;
public static List<string> MaskedIgnoreSuits;
public static List<List<string>> preferredSuits;
public static List<string> RackHideSuits;
public static bool modelReplacementPresent;
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
Logger = Logger.CreateLogSource("CubeMath.MaskedModelReplacementMod");
Logger.LogInfo((object)"Init Masked Model Replacement");
modelReplacementPresent = Chainloader.PluginInfos.ContainsKey("meow.ModelReplacementAPI");
LogAvailableSuits = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Log Available Suits", false, "Log the unlockable names of the available suits into the console when you spawn in the ship.\nNames will be written in lowercase and spaces will be removed.").Value;
ModelReplacementsOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Model Replacements Only", false, "Masked enemies should only pick model replacements and ignore all suits that does not have a model replacement.").Value;
MaskedIgnoreSuits = (from s in ((BaseUnityPlugin)this).Config.Bind<string>("General", "Masked Ignore Suits", "", "Comma separated list of suits that the masked enemy should be excluded.\nExample: \"default, greensuit, hazardsuit, pajamasuit, purplesuit, beesuit\"").Value.ToLower().Replace(" ", "").Split(new char[1] { ',' })
select s.Trim()).ToList();
List<string> list = (from s in ((BaseUnityPlugin)this).Config.Bind<string>("General", "Preferred Suits per Moon", "", "Comma separated list of suits that the masked enemy should wear for specific moons.\nThis setting will overwrite the \"Masked Ignore Suits\" configuration if entries matches for the current moon.\nExample: \"assurance: greensuit hazardsuit pajamasuit,offense: purplesuit beesuit bunnysuit\"").Value.ToLower().Split(new char[1] { ',' })
select s.Trim()).ToList();
preferredSuits = new List<List<string>>();
list.ForEach(delegate(string suit_str)
{
int num = suit_str.IndexOf(":");
if (num != -1)
{
List<string> list2 = new List<string> { suit_str.Substring(0, num) };
suit_str = suit_str.Substring(num + 1);
list2.AddRange((from s in suit_str.Split(new char[1] { ' ' })
select s.Trim()).ToList());
preferredSuits.Add(list2);
}
});
harmony.PatchAll(typeof(MaskedModelReplacementBase));
harmony.PatchAll(typeof(MaskedPlayerEnemyPatch));
harmony.PatchAll(typeof(StartOfRoundPatch));
if (modelReplacementPresent)
{
harmony.PatchAll(typeof(ModelReplacementPatch));
}
}
}
}
namespace MaskedModelReplacement.Patches
{
internal class MaskedPlayerEnemyPatch
{
public static int NumSpawnedThisLevel;
public static int MaxHealth { get; private set; }
public static int Get_moon_id()
{
string str = StartOfRound.Instance.currentLevel.PlanetName.ToLower();
int num = str.IndexOf(" ");
string str2 = null;
if (num > -1)
{
str2 = str.Substring(num + 1);
}
int found_idx = -1;
int i = 0;
MaskedModelReplacementBase.preferredSuits.ForEach(delegate(List<string> pSuit)
{
if (found_idx == -1)
{
if (pSuit[0] == str || pSuit[0] == str2)
{
found_idx = i;
}
else
{
i++;
}
}
});
return found_idx;
}
[HarmonyPatch(typeof(MaskedPlayerEnemy), "Start")]
[HarmonyPostfix]
private static void Start(MaskedPlayerEnemy __instance)
{
if (!MaskedModelReplacementBase.modelReplacementPresent)
{
Random random = new Random(StartOfRound.Instance.randomMapSeed + NumSpawnedThisLevel);
List<UnlockableItem> suitList = StartOfRound.Instance.unlockablesList.unlockables;
UnlockableSuit[] array = null;
IEnumerable<UnlockableSuit> source = from suit in Resources.FindObjectsOfTypeAll<UnlockableSuit>()
where ((NetworkBehaviour)suit).IsSpawned
select suit;
int moon_id = Get_moon_id();
if (moon_id > -1)
{
array = (from suit in source
where MaskedModelReplacementBase.preferredSuits[moon_id].Contains(suitList[suit.suitID].unlockableName.ToLower().Replace(" ", ""))
where MaskedModelReplacementBase.preferredSuits[moon_id][0] != suitList[suit.suitID].unlockableName.ToLower().Replace(" ", "")
select suit).ToArray();
if (array.Length == 0)
{
array = source.Where((UnlockableSuit suit) => !MaskedModelReplacementBase.MaskedIgnoreSuits.Contains(suitList[suit.suitID].unlockableName.ToLower().Replace(" ", ""))).ToArray();
}
}
else
{
array = source.Where((UnlockableSuit suit) => !MaskedModelReplacementBase.MaskedIgnoreSuits.Contains(suitList[suit.suitID].unlockableName.ToLower().Replace(" ", ""))).ToArray();
}
UnlockableSuit val = array[random.Next(array.ToArray().Length)];
MaskedModelReplacementBase.Instance.Logger.LogInfo((object)("target_suit " + suitList[val.suitID].unlockableName.ToLower().Replace(" ", "")));
__instance.SetSuit(val.suitID);
}
MaxHealth = ((EnemyAI)__instance).enemyHP;
NumSpawnedThisLevel++;
}
}
internal class ModelReplacementPatch
{
public static int NumSpawnedThisLevel;
[HarmonyPatch(typeof(MaskedReplacementBase), "Awake")]
[HarmonyPrefix]
private static bool Awake(MaskedReplacementBase __instance, ref MaskedPlayerEnemy ___enemyAI)
{
//IL_026c: Unknown result type (might be due to invalid IL or missing references)
//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
//IL_02d6: Expected O, but got Unknown
___enemyAI = ((Component)__instance).GetComponent<MaskedPlayerEnemy>();
if (ModelReplacementAPI.MRAPI_NetworkingPresent)
{
return false;
}
PlayerControllerB mimickingPlayer = ___enemyAI.mimickingPlayer;
bool flag = false;
BodyReplacementBase val = null;
BodyReplacementBase val2 = null;
if ((Object)(object)mimickingPlayer != (Object)null)
{
BodyReplacementBase val3 = default(BodyReplacementBase);
flag = ModelReplacementAPI.GetPlayerModelReplacement(mimickingPlayer, ref val3);
val = val3;
}
else
{
Random random = new Random(StartOfRound.Instance.randomMapSeed + NumSpawnedThisLevel);
List<UnlockableItem> suitList = StartOfRound.Instance.unlockablesList.unlockables;
UnlockableSuit[] array = null;
IEnumerable<UnlockableSuit> source = from suit in Resources.FindObjectsOfTypeAll<UnlockableSuit>()
where ((NetworkBehaviour)suit).IsSpawned
select suit;
int moon_id = MaskedPlayerEnemyPatch.Get_moon_id();
if (moon_id > -1)
{
array = (from suit in source
where MaskedModelReplacementBase.preferredSuits[moon_id].Contains(suitList[suit.suitID].unlockableName.ToLower().Replace(" ", ""))
where MaskedModelReplacementBase.preferredSuits[moon_id][0] != suitList[suit.suitID].unlockableName.ToLower().Replace(" ", "")
select suit).ToArray();
if (array.Length == 0)
{
array = source.Where((UnlockableSuit suit) => !MaskedModelReplacementBase.MaskedIgnoreSuits.Contains(suitList[suit.suitID].unlockableName.ToLower().Replace(" ", ""))).ToArray();
}
}
else
{
array = source.Where((UnlockableSuit suit) => !MaskedModelReplacementBase.MaskedIgnoreSuits.Contains(suitList[suit.suitID].unlockableName.ToLower().Replace(" ", ""))).ToArray();
}
Dictionary<string, Type> regModelRepl = Traverse.Create(typeof(ModelReplacementAPI)).Field("RegisteredModelReplacements").GetValue() as Dictionary<string, Type>;
if (MaskedModelReplacementBase.ModelReplacementsOnly)
{
array = array.Where((UnlockableSuit suit) => regModelRepl.ContainsKey(suitList[suit.suitID].unlockableName.ToLower().Replace(" ", ""))).ToArray();
}
if (array.Length != 0)
{
int num = random.Next(array.Length);
string unlockableName = suitList[array[num].suitID].unlockableName;
unlockableName = unlockableName.ToLower().Replace(" ", "");
if (regModelRepl.ContainsKey(unlockableName))
{
flag = true;
Component obj = ((Component)StartOfRound.Instance.allPlayerScripts[0]).gameObject.AddComponent(regModelRepl[unlockableName]);
val2 = (BodyReplacementBase)(object)((obj is BodyReplacementBase) ? obj : null);
val2.suitName = unlockableName;
val = val2;
}
else
{
UnlockableSuit val4 = array[num];
___enemyAI.SetSuit(val4.suitID);
}
}
NumSpawnedThisLevel++;
}
if (!flag)
{
return false;
}
__instance.IsActive = true;
__instance.replacementModel = Object.Instantiate<GameObject>(val.replacementModel);
GameObject replacementModel = __instance.replacementModel;
((Object)replacementModel).name = ((Object)replacementModel).name + "(Masked)";
__instance.replacementModel.transform.localPosition = new Vector3(0f, 0f, 0f);
__instance.replacementModel.SetActive(true);
Renderer[] componentsInChildren = __instance.replacementModel.GetComponentsInChildren<Renderer>();
foreach (Renderer obj2 in componentsInChildren)
{
obj2.shadowCastingMode = (ShadowCastingMode)1;
((Component)obj2).gameObject.layer = val.viewState.VisibleLayer;
obj2.enabled = ((Behaviour)__instance).enabled;
}
MaskedAvatarUpdater val5 = new MaskedAvatarUpdater();
val5.AssignModelReplacement(((Component)___enemyAI).gameObject, __instance.replacementModel);
Traverse.Create((object)__instance).Field("<avatar>k__BackingField").SetValue((object)val5);
((Renderer)___enemyAI.rendererLOD0).enabled = false;
((Renderer)___enemyAI.rendererLOD1).enabled = false;
((Renderer)___enemyAI.rendererLOD2).enabled = false;
((Renderer)___enemyAI.rendererLOD0).shadowCastingMode = (ShadowCastingMode)0;
((Renderer)___enemyAI.rendererLOD1).shadowCastingMode = (ShadowCastingMode)0;
((Renderer)___enemyAI.rendererLOD2).shadowCastingMode = (ShadowCastingMode)0;
MeshRenderer[] componentsInChildren2 = ((Component)___enemyAI).gameObject.GetComponentsInChildren<MeshRenderer>();
((Renderer)componentsInChildren2.Where((MeshRenderer x) => ((Object)((Component)x).gameObject).name == "LevelSticker").First()).enabled = false;
((Renderer)componentsInChildren2.Where((MeshRenderer x) => ((Object)((Component)x).gameObject).name == "BetaBadge").First()).enabled = false;
if ((Object)(object)val2 != (Object)null)
{
val2.IsActive = false;
Object.Destroy((Object)(object)val2);
}
return false;
}
}
internal class StartOfRoundPatch
{
[HarmonyPatch(typeof(StartOfRound), "Start")]
[HarmonyPostfix]
[HarmonyPriority(200)]
public static void StartOfRoundSuitPatch(StartOfRound __instance)
{
if (!MaskedModelReplacementBase.LogAvailableSuits)
{
return;
}
StringBuilder stringBuilder = new StringBuilder("Available suits:\n");
int num = 1;
foreach (UnlockableItem unlockable in StartOfRound.Instance.unlockablesList.unlockables)
{
if (unlockable.unlockableType == 0)
{
stringBuilder.Append(string.Format("{0}. {1}\n", num, unlockable.unlockableName.ToLower().Replace(" ", "")));
num++;
}
}
MaskedModelReplacementBase.Instance.Logger.LogInfo((object)stringBuilder);
}
}
}