SimonTendo-LCMaskedInfestationMod icon

LCMaskedInfestationMod

Add the possibility for infestations to spawn Maskeds!

Last updated 2 hours ago
Total downloads 10
Total rating 1 
Categories Mods Misc BepInEx Client-side
Dependency string SimonTendo-LCMaskedInfestationMod-1.0.0
Dependants 1 other package depends on this package

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

COMPANY-MANDATED MESSAGE:

Wait, when did we hire THIS many...? Ohhhhhh! Oh. Oh no...

Uhhh- Dear employees, we advice you to proceed with caution on your travels throughout the various facilities, as there appears to be a sudden spike in the amount of possessed masked ex-employees wandering their halls. We suspect this phenomenon finds its roots in, and functions similarly to, the same rare event that can cause an outburst of Linepithema-crassus (the so-called 'Hoarding Bugs'), and fear it can be just as dangerous, if not more.

And not only that, but these possessed souls have lost their will to collect scrap for the Company, so clearly having them goof off en masse is unforgivable. So get to it, real employees, chop-chop!

That is all for this message. We hope you stay a great asset to the Company.

The Mod

Introduction:

Get ready for facilities filled with fakers...

This mod adds the possibility for infestations to not only spawn the default enemies, but also Maskeds! Just like with regular infestations, there will already be a few waiting for you at the start of the day, and the moon's interior (and exterior too, don't forget) will quickly fill up to their max amount.

Have fun!

Creation:

  • I wanted to learn HarmonyLib Transpilers
    • Conclusion: scary stuff
  • In terms of how this specific Transpiler works (if it works at all, I hope):
    • The Transpiler itself just uses a Transpilers.EmitDelegate<Action>(delegate () { });
      • I don't actually know what this means, so far I just understand this lets me inject whatever is between the curly brackets at the moment I later specify
    • It checks the RoundManager's RefreshEnemiesList(), since this is where the enemyRushIndex is assigned
    • It then checks for where it asks the date from DateTime, as this is right before any checks for starting an infestation in the vanilla game happen
    • If it finds that, it saves that as the index to remove code from and insert my own
    • Then, if it's saved an index, it will jump back one iteration in the List of CodeInstructions (as I believe nothing is loaded into the callstack at that moment) and remove the following 152 CodeInstructions
      • This encapsulates the checking of the current date, creating a new random number generator, and the entire if-statement about infestations, right up until the moment it sets the currentMaxOutsidePowerCount
    • It removes all of this, and then inserts the above function from EmitDelegate, which is a carbon-copy of the original method with an extra else-if-statement between the Nutcracker's check and the default Hoarding bug infestation assignment
      • This is not the prettiest way, nor how I had hoped to do this, but I had trouble finding a satisfying way to insert a C# else-if without the context of the original method around it
      • On top of that, I wanted to keep the method as intact as possible, and therefore also had to include the check to DateTime and the new System.Random it would draw Next() random numbers from. So, I chose to jump in at a clean moment, remove everything up until the entire body with checks would finish, and replace it with a new yet identical version of the body, albeit with... complete control over every line of code now
      • So the chances of infestations are not altered, and Maskeds have the exact same odds of being picked as Nutcrackers, and set the currentMaxInsidePower to the same value of 20
    • I also added some debug lines throughout the Transpiler's inserted code, just as a way to check for myself if inserting code worked at all, and what the specific states of the method were while moving through it
    • And to try to catch errors, I also check 152 iterations ahead of the DateTime function, and see if it is the same CodeInstruction.ToString() as from the vanilla game. If not, it will return RefreshEnemiesList() in the exact way as it is in the original code, to hopefully prevent conflicts and gamebreaking bugs
  • For clarity's sake: This is a client-side mod using the host's data.
    • As far as I know, the host has always determined what enemies will spawn, and randomly rolls for an infestation to influence said spawn.
    • So the host can play with this mod without clients needing this mod, or mods at all. The only thing clients are concerned about is what enemies will spawn when and where, not how the host determined that.
  • And as to why I chosed Maskeds:
    • Their stats for spawning seem to be closest to that of Hoarding Bugs and Nutcrackers, the other enemies that infestations can spawn, with a Power Level of 1 and a Max Spawn count of around 10. They just weren't possible infestation-monsters yet, and I thought it would fit.
    • And besides, these things are terrifying :)

Credits:

  • Two main sources of information:
    • The Patching - Transpiler tutorial on the HarmonyLib API Documentation, for the initial understanding of Transpilers and reading IL code
    • And, again, the decompiled code of the MoskauNutcracker mod, as this was the first codebase I saw this used in myself
  • And thank you for checking out or even downloading this mod!