Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Soulbound v0.3.0
BepInEx/plugins/Soulbound/Soulbound.dll
Decompiled 2 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using On.RoR2; using R2API; using RoR2; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; [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("Soulbound")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Soulbound")] [assembly: AssemblyTitle("Soulbound")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 Soulbound { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.comic.soulbound", "Soulbound", "0.3.0")] public sealed class Plugin : BaseUnityPlugin { private sealed class CatalystState { public float TrackedHealing; public int DamageBoosts; } [CompilerGenerated] private static class <>O { public static StatHookEventHandler <0>__RecalculateStatsAPI_GetStatCoefficients; } public const string PluginGuid = "com.comic.soulbound"; public const string PluginAuthor = "comic"; public const string PluginName = "Soulbound"; public const string PluginVersion = "0.3.0"; private const string SoulseekerNameToken = "ROR2STARTERMOD_ITEM_SOULSEEKER_CATALYST_NAME"; private const string SoulseekerPickupToken = "ROR2STARTERMOD_ITEM_SOULSEEKER_CATALYST_PICKUP"; private const string SoulseekerDescriptionToken = "ROR2STARTERMOD_ITEM_SOULSEEKER_CATALYST_DESC"; private const string SoulseekerLoreToken = "ROR2STARTERMOD_ITEM_SOULSEEKER_CATALYST_LORE"; private const float LifestealFraction = 0.25f; private const float HealRequiredPerBoost = 100f; private const float BaseDamageBonus = 1f; private const float StackDamageBonus = 1.5f; private static readonly Dictionary<CharacterBody, CatalystState> CatalystStates = new Dictionary<CharacterBody, CatalystState>(); private static ItemDef _soulseekerCatalystItemDef = null; private static GameObject _soulseekerBoostEffectPrefab = null; private ConfigEntry<bool> _logRunStart; private ConfigEntry<bool> _enableSoulseekerCatalyst; internal static ManualLogSource Log { get; private set; } = null; private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; _soulseekerBoostEffectPrefab = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/WarCryOnMultiKill/WarCryEffect.prefab").WaitForCompletion(); _logRunStart = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "LogRunStart", true, "Write a message to the BepInEx console whenever a run starts."); _enableSoulseekerCatalyst = ((BaseUnityPlugin)this).Config.Bind<bool>("Items.SoulseekerCatalyst", "EnableEffect", true, "Allow Soulseeker Catalyst to heal attackers and grant damage boosts."); RegisterSoulseekerCatalystItem(); Run.Start += new hook_Start(Run_Start); GlobalEventManager.onServerDamageDealt += GlobalEventManager_onServerDamageDealt; object obj = <>O.<0>__RecalculateStatsAPI_GetStatCoefficients; if (obj == null) { StatHookEventHandler val = RecalculateStatsAPI_GetStatCoefficients; <>O.<0>__RecalculateStatsAPI_GetStatCoefficients = val; obj = (object)val; } RecalculateStatsAPI.GetStatCoefficients += (StatHookEventHandler)obj; Log.LogInfo((object)"Soulbound 0.3.0 loaded."); } private void OnDestroy() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown Run.Start -= new hook_Start(Run_Start); GlobalEventManager.onServerDamageDealt -= GlobalEventManager_onServerDamageDealt; object obj = <>O.<0>__RecalculateStatsAPI_GetStatCoefficients; if (obj == null) { StatHookEventHandler val = RecalculateStatsAPI_GetStatCoefficients; <>O.<0>__RecalculateStatsAPI_GetStatCoefficients = val; obj = (object)val; } RecalculateStatsAPI.GetStatCoefficients -= (StatHookEventHandler)obj; } private void Run_Start(orig_Start orig, Run self) { CatalystStates.Clear(); orig.Invoke(self); if (_logRunStart.Value) { Log.LogInfo((object)"A run started. Soulseeker Catalyst state has been reset."); } } private static void RegisterSoulseekerCatalystItem() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown _soulseekerCatalystItemDef = ScriptableObject.CreateInstance<ItemDef>(); ((Object)_soulseekerCatalystItemDef).name = "ROR2STARTERMOD_ITEM_SOULSEEKER_CATALYST"; _soulseekerCatalystItemDef.nameToken = "ROR2STARTERMOD_ITEM_SOULSEEKER_CATALYST_NAME"; _soulseekerCatalystItemDef.pickupToken = "ROR2STARTERMOD_ITEM_SOULSEEKER_CATALYST_PICKUP"; _soulseekerCatalystItemDef.descriptionToken = "ROR2STARTERMOD_ITEM_SOULSEEKER_CATALYST_DESC"; _soulseekerCatalystItemDef.loreToken = "ROR2STARTERMOD_ITEM_SOULSEEKER_CATALYST_LORE"; _soulseekerCatalystItemDef._itemTierDef = Addressables.LoadAssetAsync<ItemTierDef>((object)"RoR2/Base/Common/Tier3Def.asset").WaitForCompletion(); _soulseekerCatalystItemDef.pickupIconSprite = Addressables.LoadAssetAsync<Sprite>((object)"RoR2/Base/Common/MiscIcons/texMysteryIcon.png").WaitForCompletion(); _soulseekerCatalystItemDef.pickupModelPrefab = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Mystery/PickupMystery.prefab").WaitForCompletion(); _soulseekerCatalystItemDef.canRemove = true; _soulseekerCatalystItemDef.hidden = false; _soulseekerCatalystItemDef.tags = (ItemTag[])(object)new ItemTag[2] { (ItemTag)1, (ItemTag)2 }; LanguageAPI.Add("ROR2STARTERMOD_ITEM_SOULSEEKER_CATALYST_NAME", "Soulseeker Catalyst"); LanguageAPI.Add("ROR2STARTERMOD_ITEM_SOULSEEKER_CATALYST_PICKUP", "Your attacks heal you. Healing enough through the Catalyst increases your damage."); LanguageAPI.Add("ROR2STARTERMOD_ITEM_SOULSEEKER_CATALYST_DESC", "Your attacks <style=cIsHealing>heal</style> you for <style=cIsHealing>25%</style> of the total damage dealt. Every <style=cIsHealing>100 HP</style> healed through the Catalyst grants <style=cIsDamage>+100% damage</style> <style=cStack>(+150% per stack)</style>."); LanguageAPI.Add("ROR2STARTERMOD_ITEM_SOULSEEKER_CATALYST_LORE", "It does not drink blood. It listens for the moment a wound decides to close, and turns that answer into hunger."); ItemDisplayRuleDict val = new ItemDisplayRuleDict((ItemDisplayRule[])null); if (!ItemAPI.Add(new CustomItem(_soulseekerCatalystItemDef, val))) { Log.LogError((object)"Failed to register Soulseeker Catalyst."); } else { Log.LogInfo((object)"Registered custom item: Soulseeker Catalyst."); } } private void GlobalEventManager_onServerDamageDealt(DamageReport damageReport) { //IL_0078: 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) if (!_enableSoulseekerCatalyst.Value || !NetworkServer.active || (Object)(object)damageReport.attackerBody == (Object)null) { return; } CharacterBody attackerBody = damageReport.attackerBody; Inventory inventory = attackerBody.inventory; HealthComponent healthComponent = attackerBody.healthComponent; if ((Object)(object)inventory == (Object)null || (Object)(object)healthComponent == (Object)null || inventory.GetItemCount(_soulseekerCatalystItemDef) <= 0 || damageReport.damageDealt <= 0f) { return; } float num = damageReport.damageDealt * 0.25f; float num2 = healthComponent.Heal(num, default(ProcChainMask), true); if (!(num2 <= 0f)) { CatalystState catalystState = GetCatalystState(attackerBody); catalystState.TrackedHealing += num2; int num3 = 0; while (catalystState.TrackedHealing >= 100f) { catalystState.TrackedHealing -= 100f; catalystState.DamageBoosts++; num3++; } if (num3 > 0) { attackerBody.RecalculateStats(); SpawnSoulseekerBoostEffect(attackerBody); Log.LogInfo((object)$"{attackerBody.GetUserName()} earned {num3} Soulseeker Catalyst damage boost(s). Total boosts: {catalystState.DamageBoosts}."); } } } private static void RecalculateStatsAPI_GetStatCoefficients(CharacterBody sender, StatHookEventArgs args) { if (!((Object)(object)sender.inventory == (Object)null) && CatalystStates.TryGetValue(sender, out CatalystState value) && value.DamageBoosts > 0) { int itemCount = sender.inventory.GetItemCount(_soulseekerCatalystItemDef); if (itemCount > 0) { float num = 1f + 1.5f * (float)(itemCount - 1); args.damageMultAdd += (float)value.DamageBoosts * num; } } } private static CatalystState GetCatalystState(CharacterBody body) { if (!CatalystStates.TryGetValue(body, out CatalystState value)) { value = new CatalystState(); CatalystStates[body] = value; } return value; } private static void SpawnSoulseekerBoostEffect(CharacterBody body) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (!((Object)(object)_soulseekerBoostEffectPrefab == (Object)null)) { EffectData val = new EffectData { origin = body.corePosition, scale = body.radius }; val.SetNetworkedObjectReference(((Component)body).gameObject); EffectManager.SpawnEffect(_soulseekerBoostEffectPrefab, val, true); } } } }