Decompiled source of AcolyteBetterEcho v0.1.0

AcolyteBetterEcho.dll

Decompiled 18 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using EntityStates.Acolyte.Backpack;
using EntityStates.Acolyte.Sacrifice;
using EntityStates.Acolyte.Weapon;
using On.EntityStates.Acolyte.Backpack;
using On.EntityStates.Acolyte.Sacrifice;
using On.EntityStates.Acolyte.Weapon;
using On.RoR2;
using RoR2;
using RoR2.Skills;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("AcolyteBetterEcho")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("AcolyteBetterEcho")]
[assembly: AssemblyTitle("AcolyteBetterEcho")]
[assembly: AssemblyVersion("0.1.0.0")]
namespace AcolyteBetterEcho;

[BepInPlugin("com.EviLord.AcolyteBetterEcho", "AcolyteBetterEcho", "0.1.0")]
public class AcolyteBetterEchoPlugin : BaseUnityPlugin
{
	public const string PluginAuthor = "EviLord";

	public const string PluginName = "AcolyteBetterEcho";

	public const string PluginGUID = "com.EviLord.AcolyteBetterEcho";

	public const string PluginVersion = "0.1.0";

	internal static ManualLogSource Log;

	internal static ConfigEntry<bool> Enabled;

	internal static ConfigEntry<int> EchoSacrificeConvictions;

	private void Awake()
	{
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable the Echo changes. Requires a restart.");
		EchoSacrificeConvictions = ((BaseUnityPlugin)this).Config.Bind<int>("General", "EchoSacrificeConvictions", 3, new ConfigDescription("Convictions granted by a Sacrifice hit when Anima Echo is selected (vanilla: 2). Kills still grant 1 extra. Gameplay uses the new value immediately; skill descriptions update after a restart.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 7), Array.Empty<object>()));
		if (Enabled.Value)
		{
			EchoChanges.Init();
			EchoDescriptions.Init();
		}
		Log.LogInfo((object)"AcolyteBetterEcho 0.1.0 loaded.");
	}
}
internal static class EchoChanges
{
	private class ControllerState
	{
		public int bufferedSouls;

		public bool pendingSpecialReset;
	}

	private const string AnimaEchoNameToken = "ACOLYTE_SPECIAL_ALT_TRANSFORM_NAME";

	private static readonly ConditionalWeakTable<AcolyteFormController, ControllerState> states = new ConditionalWeakTable<AcolyteFormController, ControllerState>();

	internal static void Init()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Expected O, but got Unknown
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Expected O, but got Unknown
		Sacrifice.OnEnter += new hook_OnEnter(Sacrifice_OnEnter);
		SacrificeIdle.FixedUpdate += new hook_FixedUpdate(SacrificeIdle_FixedUpdate);
		BaseBackpackState.OnEnter += new hook_OnEnter(BaseBackpackState_OnEnter);
		BaseBackpackState.OnExit += new hook_OnExit(BaseBackpackState_OnExit);
		AcolyteFormController.AddSouls += new hook_AddSouls(AcolyteFormController_AddSouls);
	}

	private static ControllerState GetState(AcolyteFormController controller)
	{
		return states.GetOrCreateValue(controller);
	}

	internal static bool IsEchoSelected(AcolyteFormController controller)
	{
		GenericSkill val = (Object.op_Implicit((Object)(object)controller) ? controller.transformSkillSlot : null);
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.skillDef))
		{
			return val.skillDef.skillNameToken == "ACOLYTE_SPECIAL_ALT_TRANSFORM_NAME";
		}
		return false;
	}

	private static void Sacrifice_OnEnter(orig_OnEnter orig, Sacrifice self)
	{
		if (IsEchoSelected(((Component)((EntityState)self).outer).GetComponent<AcolyteFormController>()))
		{
			self.soulValue = AcolyteBetterEchoPlugin.EchoSacrificeConvictions.Value;
		}
		orig.Invoke(self);
	}

	private static void SacrificeIdle_FixedUpdate(orig_FixedUpdate orig, SacrificeIdle self)
	{
		orig.Invoke(self);
		if (!Object.op_Implicit((Object)(object)((BaseSacrificeState)self).controller))
		{
			return;
		}
		ControllerState state = GetState(((BaseSacrificeState)self).controller);
		if (!state.pendingSpecialReset)
		{
			return;
		}
		GenericSkill val = ((Component)((EntityState)self).outer).GetComponent<SkillLocator>()?.special;
		if (!Object.op_Implicit((Object)(object)val))
		{
			state.pendingSpecialReset = false;
			return;
		}
		if ((Object)(object)val.skillDef == (Object)(object)val.baseSkill)
		{
			val.Reset();
			state.pendingSpecialReset = false;
			return;
		}
		SkillDef skillDef = val.skillDef;
		GenericSkill transformSkillSlot = ((BaseSacrificeState)self).controller.transformSkillSlot;
		if ((Object)(object)skillDef != (Object)(object)((transformSkillSlot != null) ? transformSkillSlot.skillDef : null))
		{
			state.pendingSpecialReset = false;
		}
	}

	private static void BaseBackpackState_OnEnter(orig_OnEnter orig, BaseBackpackState self)
	{
		AcolyteFormController component = ((Component)((EntityState)self).outer).GetComponent<AcolyteFormController>();
		if (Object.op_Implicit((Object)(object)component))
		{
			GetState(component).bufferedSouls = 0;
		}
		orig.Invoke(self);
		if (self is BackpackActivate && IsEchoSelected(component) && Util.HasEffectiveAuthority(((Component)((EntityState)self).outer).gameObject))
		{
			ResetSkills(((Component)((EntityState)self).outer).GetComponent<SkillLocator>());
			GetState(component).pendingSpecialReset = true;
		}
	}

	private static void ResetSkills(SkillLocator skillLocator)
	{
		if (Object.op_Implicit((Object)(object)skillLocator))
		{
			if (Object.op_Implicit((Object)(object)skillLocator.primary))
			{
				skillLocator.primary.Reset();
			}
			if (Object.op_Implicit((Object)(object)skillLocator.secondary))
			{
				skillLocator.secondary.Reset();
			}
			if (Object.op_Implicit((Object)(object)skillLocator.utility))
			{
				skillLocator.utility.Reset();
			}
		}
	}

	private static void BaseBackpackState_OnExit(orig_OnExit orig, BaseBackpackState self)
	{
		orig.Invoke(self);
		AcolyteFormController component = ((Component)((EntityState)self).outer).GetComponent<AcolyteFormController>();
		if (!Object.op_Implicit((Object)(object)component))
		{
			return;
		}
		ControllerState state = GetState(component);
		state.pendingSpecialReset = false;
		if (NetworkServer.active)
		{
			int bufferedSouls = state.bufferedSouls;
			state.bufferedSouls = 0;
			if (bufferedSouls > 0 && Object.op_Implicit((Object)(object)component.characterBody) && component.characterBody.healthComponent.alive)
			{
				component.AddSouls(bufferedSouls);
			}
		}
	}

	private static void AcolyteFormController_AddSouls(orig_AddSouls orig, AcolyteFormController self, int amount)
	{
		if (NetworkServer.active && self.isEchoForm && IsEchoSelected(self))
		{
			GetState(self).bufferedSouls += amount;
		}
		else
		{
			orig.Invoke(self, amount);
		}
	}
}
internal static class EchoDescriptions
{
	private struct Additions
	{
		public string echo;

		public string sacrifice;
	}

	private const string EchoDescriptionToken = "ACOLYTE_SPECIAL_ALT_TRANSFORM_DESCRIPTION";

	private const string SacrificeDescriptionToken = "ACOLYTE_SPECIAL_DESCRIPTION";

	private static readonly Dictionary<string, Additions> additions = new Dictionary<string, Additions>(StringComparer.OrdinalIgnoreCase)
	{
		["en"] = new Additions
		{
			echo = " Activating it <style=cIsUtility>resets all skill cooldowns</style>. Convictions earned during the Litany are <style=cIsUtility>stored</style> and granted when it ends.",
			sacrifice = " With Anima Echo, gain <style=cIsDamage>{0}</style> Convictions instead."
		},
		["FR"] = new Additions
		{
			echo = " L'activation <style=cIsUtility>réinitialise le temps de recharge de toutes vos compétences</style>. Les Convictions obtenues pendant la Litanie sont <style=cIsUtility>conservées</style> et accordées à la fin de celle-ci.",
			sacrifice = " Avec l'Écho d'anima, confère <style=cIsDamage>{0}</style> Convictions à la place."
		},
		["IT"] = new Additions
		{
			echo = " L'attivazione <style=cIsUtility>azzera la ricarica di tutte le tue abilità</style>. Le Convinzioni ottenute durante la Litania vengono <style=cIsUtility>conservate</style> e conferite al suo termine.",
			sacrifice = " Con l'Eco dell'Anima, ottieni invece <style=cIsDamage>{0}</style> Convinzioni."
		},
		["RU"] = new Additions
		{
			echo = " При активации <style=cIsUtility>сбрасывает время восстановления всех навыков</style>. Заряды убеждения, полученные во время Литании, <style=cIsUtility>накапливаются</style> и начисляются после её окончания.",
			sacrifice = " С Эхом Анимы даёт <style=cIsDamage>{0}</style> {1} убеждения."
		},
		["de"] = new Additions
		{
			echo = " Beim Aktivieren werden <style=cIsUtility>die Abklingzeiten aller deiner Fähigkeiten zurückgesetzt</style>. Während der Litanei erhaltene Überzeugungen werden <style=cIsUtility>gespeichert</style> und nach ihrem Ende gewährt.",
			sacrifice = " Mit Anima-Echo erhältst du stattdessen <style=cIsDamage>{0}</style> Überzeugungen."
		},
		["es-ES"] = new Additions
		{
			echo = " Al activarlo, <style=cIsUtility>se reinician los tiempos de reutilización de todas tus habilidades</style>. Las convicciones obtenidas durante la Letanía se <style=cIsUtility>acumulan</style> y se otorgan al terminar.",
			sacrifice = " Con Eco de almas, obtiene <style=cIsDamage>{0}</style> convicciones en su lugar."
		},
		["es-419"] = new Additions
		{
			echo = " Al activarlo, <style=cIsUtility>se reinician los tiempos de reutilización de todas tus habilidades</style>. Las convicciones obtenidas durante la Letanía se <style=cIsUtility>acumulan</style> y se otorgan al terminar.",
			sacrifice = " Con Eco de almas, obtiene <style=cIsDamage>{0}</style> convicciones en su lugar."
		},
		["pt-BR"] = new Additions
		{
			echo = " Ao ativar, <style=cIsUtility>reinicia a recarga de todas as suas habilidades</style>. Convicções obtidas durante a Litania são <style=cIsUtility>armazenadas</style> e concedidas quando ela termina.",
			sacrifice = " Com Eco de Anima, ganha <style=cIsDamage>{0}</style> Convicções em vez disso."
		},
		["tr"] = new Additions
		{
			echo = " Etkinleştirildiğinde <style=cIsUtility>tüm yeteneklerinin bekleme sürelerini sıfırlar</style>. Ayin sırasında kazanılan İnançlar <style=cIsUtility>saklanır</style> ve Ayin sona erdiğinde verilir.",
			sacrifice = " Anima Yankısı seçiliyken bunun yerine <style=cIsDamage>{0}</style> İnanç kazanırsın."
		},
		["ja"] = new Additions
		{
			echo = "発動すると<style=cIsUtility>すべてのスキルのクールダウンがリセットされる</style>。リタニー中に獲得したコンヴィクションは<style=cIsUtility>蓄積され</style>、リタニー終了時に付与される。",
			sacrifice = "アニマの残響を選択している場合、代わりに<style=cIsDamage>{0}</style> 個のコンヴィクションを獲得する。"
		},
		["ko"] = new Additions
		{
			echo = " 발동 시 <style=cIsUtility>모든 스킬의 재사용 대기시간이 초기화</style>됩니다. 호칭기도 중에 얻은 신념은 <style=cIsUtility>저장</style>되었다가 호칭기도가 끝나면 지급됩니다.",
			sacrifice = " 생령의 메아리 선택 시 대신 신념 <style=cIsDamage>{0}</style>중첩을 얻습니다."
		},
		["zh-CN"] = new Additions
		{
			echo = "发动时<style=cIsUtility>重置所有技能的冷却时间</style>。诵祷期间获得的信念会被<style=cIsUtility>储存</style>,并在诵祷结束后获得。",
			sacrifice = "选择灵魂回响时,改为获得<style=cIsDamage>{0}</style>层信念。"
		}
	};

	internal static void Init()
	{
		Language.onCurrentLanguageChanged += Apply;
		Apply();
	}

	private static void Apply()
	{
		Language currentLanguage = Language.currentLanguage;
		if (currentLanguage != null && additions.TryGetValue(Language.currentLanguageName ?? "", out var value))
		{
			Append(currentLanguage, "ACOLYTE_SPECIAL_ALT_TRANSFORM_DESCRIPTION", value.echo);
			int value2 = AcolyteBetterEchoPlugin.EchoSacrificeConvictions.Value;
			if (value2 != 2)
			{
				Append(currentLanguage, "ACOLYTE_SPECIAL_DESCRIPTION", string.Format(value.sacrifice, value2, RussianChargeWord(value2)));
			}
		}
	}

	private static void Append(Language language, string token, string addition)
	{
		string localizedStringByToken = language.GetLocalizedStringByToken(token);
		if (!localizedStringByToken.EndsWith(addition, StringComparison.Ordinal))
		{
			language.SetStringByToken(token, localizedStringByToken + addition);
		}
	}

	private static string RussianChargeWord(int count)
	{
		int num = count % 100;
		int num2 = count % 10;
		if (num >= 11 && num <= 14)
		{
			return "зарядов";
		}
		switch (num2)
		{
		case 1:
			return "заряд";
		case 2:
		case 3:
		case 4:
			return "заряда";
		default:
			return "зарядов";
		}
	}
}
internal static class BuildInfo
{
	public const string Version = "0.1.0";
}