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 Lyreclaw v1.1.1
BepInEx/plugins/Lyreclaw/Lyreclaw.dll
Decompiled 2 years ago#define DEBUG using System; using System.Collections; using System.Collections.Generic; 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.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using LethalLib.Modules; using Lyreclaw.Configuration; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Lyreclaw")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Lyreclaw")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("049e486c-61cd-4528-9094-c172188305db")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace Lyreclaw { internal class LyreclawEnemyAI : EnemyAI { private enum State { SearchingForPlayer, StickingInFrontOfPlayer, HeadSwingAttackInProgress } public Transform turnCompass = null; public Transform attackArea = null; private float timeSinceHittingLocalPlayer; private float timeSinceNewRandPos; private Vector3 positionRandomness; private Vector3 StalkPos; private Random enemyRandom = null; private bool isDeadAnimationDone; public AudioClip[] luringSoundsSFX; public AudioClip[] alertSoundsSFX; public AudioClip[] attackSoundsSFX; [Conditional("DEBUG")] private void LogIfDebugBuild(string text) { Debug.Log((object)text); } public override void Start() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) ((EnemyAI)this).Start(); LogIfDebugBuild("Example Enemy Spawned"); timeSinceHittingLocalPlayer = 0f; base.creatureAnimator.SetTrigger("startWalk"); timeSinceNewRandPos = 0f; positionRandomness = new Vector3(0f, 0f, 0f); enemyRandom = new Random(StartOfRound.Instance.randomMapSeed + base.thisEnemyIndex); isDeadAnimationDone = false; base.currentBehaviourStateIndex = 0; ((EnemyAI)this).StartSearch(((Component)this).transform.position, (AISearchRoutine)null); } public override void Update() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) ((EnemyAI)this).Update(); if (base.isEnemyDead) { if (!isDeadAnimationDone) { LogIfDebugBuild("Stopping enemy voice with janky code."); isDeadAnimationDone = true; base.creatureVoice.Stop(); base.creatureVoice.PlayOneShot(base.dieSFX); } return; } timeSinceHittingLocalPlayer += Time.deltaTime; timeSinceNewRandPos += Time.deltaTime; int currentBehaviourStateIndex = base.currentBehaviourStateIndex; if ((Object)(object)base.targetPlayer != (Object)null && (currentBehaviourStateIndex == 1 || currentBehaviourStateIndex == 2)) { turnCompass.LookAt(((Component)base.targetPlayer.gameplayCamera).transform.position); ((Component)this).transform.rotation = Quaternion.Lerp(((Component)this).transform.rotation, Quaternion.Euler(new Vector3(0f, turnCompass.eulerAngles.y, 0f)), 4f * Time.deltaTime); } if (base.stunNormalizedTimer > 0f) { base.agent.speed = 0f; } } public override void DoAIInterval() { //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) ((EnemyAI)this).DoAIInterval(); if (base.isEnemyDead || StartOfRound.Instance.allPlayersDead) { return; } switch (base.currentBehaviourStateIndex) { case 0: base.agent.speed = 2f; if (FoundClosestPlayerInRange(25f, 3f)) { LogIfDebugBuild("Start Target Player"); ((EnemyAI)this).StopSearch(base.currentSearch, true); ((EnemyAI)this).SwitchToBehaviourClientRpc(1); } else if (!base.creatureSFX.isPlaying && enemyRandom.Next(0, 10) == 0) { base.creatureSFX.PlayOneShot(luringSoundsSFX[enemyRandom.Next(0, luringSoundsSFX.Length)]); } break; case 1: base.agent.speed = 5f; if (!TargetClosestPlayerInAnyCase() || (Vector3.Distance(((Component)this).transform.position, ((Component)base.targetPlayer).transform.position) > 15f && !((EnemyAI)this).CheckLineOfSightForPosition(((Component)base.targetPlayer).transform.position, 45f, 60, -1f, (Transform)null))) { LogIfDebugBuild("Stop Target Player"); ((EnemyAI)this).StartSearch(((Component)this).transform.position, (AISearchRoutine)null); ((EnemyAI)this).SwitchToBehaviourClientRpc(0); break; } if (!base.creatureSFX.isPlaying && enemyRandom.Next(0, 3) == 0) { DoAnimationClientRpc("getHit"); base.creatureSFX.PlayOneShot(alertSoundsSFX[enemyRandom.Next(0, alertSoundsSFX.Length)]); } StickingInFrontOfPlayer(); break; case 2: base.agent.speed = 14f; break; default: LogIfDebugBuild("This Behavior State doesn't exist!"); break; } } private bool FoundClosestPlayerInRange(float range, float senseRange) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) ((EnemyAI)this).TargetClosestPlayer(1.5f, true, 70f); if ((Object)(object)base.targetPlayer == (Object)null) { ((EnemyAI)this).TargetClosestPlayer(1.5f, false, 70f); range = senseRange; } return (Object)(object)base.targetPlayer != (Object)null && Vector3.Distance(((Component)this).transform.position, ((Component)base.targetPlayer).transform.position) < range; } private bool TargetClosestPlayerInAnyCase() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) base.mostOptimalDistance = 2000f; base.targetPlayer = null; for (int i = 0; i < StartOfRound.Instance.connectedPlayersAmount + 1; i++) { base.tempDist = Vector3.Distance(((Component)this).transform.position, ((Component)StartOfRound.Instance.allPlayerScripts[i]).transform.position); if (base.tempDist < base.mostOptimalDistance) { base.mostOptimalDistance = base.tempDist; base.targetPlayer = StartOfRound.Instance.allPlayerScripts[i]; } } if ((Object)(object)base.targetPlayer == (Object)null) { return false; } return true; } private void StickingInFrontOfPlayer() { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)base.targetPlayer == (Object)null || !((NetworkBehaviour)this).IsOwner || !(timeSinceNewRandPos > 1f)) { return; } timeSinceNewRandPos = 0f; if (enemyRandom.Next(0, 5) == 0) { if (timeSinceHittingLocalPlayer < 1f) { return; } DoAnimationClientRpc("prepareAttack"); base.creatureSFX.PlayOneShot(attackSoundsSFX[enemyRandom.Next(0, attackSoundsSFX.Length)]); ((MonoBehaviour)this).StartCoroutine(SwingAttack()); } else { positionRandomness = new Vector3((float)enemyRandom.Next(-1, 1), 0f, (float)enemyRandom.Next(-1, 1)); StalkPos = ((Component)base.targetPlayer).transform.position - Vector3.Scale(new Vector3(-5f, 0f, -5f), ((Component)base.targetPlayer).transform.forward) + positionRandomness; } ((EnemyAI)this).SetDestinationToPosition(StalkPos, false); } private IEnumerator SwingAttack() { ((EnemyAI)this).SwitchToBehaviourClientRpc(2); StalkPos = ((Component)base.targetPlayer).transform.position - Vector3.Scale(new Vector3(2f, 0f, 2f), ((Component)base.targetPlayer).transform.forward); ((EnemyAI)this).SetDestinationToPosition(StalkPos, false); yield return (object)new WaitForSeconds(1f); if (!base.isEnemyDead) { yield return (object)new WaitForSeconds(0.35f); if (base.currentBehaviourStateIndex != 2) { yield return (object)new WaitForSeconds(0.35f); } ((EnemyAI)this).SwitchToBehaviourClientRpc(1); } } public override void OnCollideWithPlayer(Collider other) { if (!(timeSinceHittingLocalPlayer < 1f) && !isDeadAnimationDone) { PlayerControllerB val = ((EnemyAI)this).MeetsStandardPlayerCollisionConditions(other, false, false); if ((Object)(object)val != (Object)null) { LogIfDebugBuild("Example Enemy Collision with Player!"); DoHitPlayer(val, 20); } ((EnemyAI)this).SwitchToBehaviourClientRpc(1); } } private void DoHitPlayer(PlayerControllerB playerControllerB, int damage) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) DoAnimationClientRpc("swingAttack"); timeSinceHittingLocalPlayer = 0f; playerControllerB.DamagePlayer(damage, true, true, (CauseOfDeath)6, 0, false, default(Vector3)); base.creatureSFX.Play(); ((EnemyAI)this).SwitchToBehaviourClientRpc(1); ((MonoBehaviour)this).StopCoroutine(SwingAttack()); } public override void HitEnemy(int force = 1, PlayerControllerB playerWhoHit = null, bool playHitSFX = false, int hitID = -1) { ((EnemyAI)this).HitEnemy(force, playerWhoHit, playHitSFX, hitID); if (!base.isEnemyDead) { DoAnimationClientRpc("getHit"); base.enemyHP -= force; if (((NetworkBehaviour)this).IsOwner && base.enemyHP <= 0 && !base.isEnemyDead) { ((MonoBehaviour)this).StopCoroutine(SwingAttack()); ((MonoBehaviour)this).StopCoroutine(base.searchCoroutine); ((EnemyAI)this).KillEnemyOnOwnerClient(false); } } } [ClientRpc] public void DoAnimationClientRpc(string animationName) { LogIfDebugBuild("Animation: " + animationName); base.creatureAnimator.SetTrigger(animationName); } [ClientRpc] public void SwingAttackHitClientRpc() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) LogIfDebugBuild("SwingAttackHitClientRPC"); int num = 8; Collider[] array = Physics.OverlapBox(attackArea.position, attackArea.localScale, Quaternion.identity, num); if (array.Length == 0) { return; } List<int> list = new List<int>(); foreach (Collider item in array.Distinct()) { if (timeSinceHittingLocalPlayer < 1f) { return; } PlayerControllerB val = ((EnemyAI)this).MeetsStandardPlayerCollisionConditions(item, false, false); if ((Object)(object)val != (Object)null) { LogIfDebugBuild("should attack player : " + ((Object)val).GetInstanceID()); if (!list.Contains(((Object)val).GetInstanceID())) { list.Add(((Object)item).GetInstanceID()); LogIfDebugBuild("Swing attack hit player!"); DoHitPlayer(val, 30); } } } list = null; } } [BepInPlugin("DawnDreamIsland.LethalMods.Lyreclaw", "Lyreclaw", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private const string modGUID = "DawnDreamIsland.LethalMods.Lyreclaw"; private const string modName = "Lyreclaw"; private const string modVersion = "1.1.0"; internal static ManualLogSource Logger; public static AssetBundle ModAssets; internal static PluginConfig BoundConfig { get; private set; } private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; BoundConfig = new PluginConfig(((BaseUnityPlugin)this).Config); InitializeNetworkBehaviours(); string path = "lyreclaw"; ModAssets = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), path)); if ((Object)(object)ModAssets == (Object)null) { Logger.LogError((object)"Failed to load custom assets."); return; } EnemyType val = ModAssets.LoadAsset<EnemyType>("Lyreclaw"); TerminalNode val2 = ModAssets.LoadAsset<TerminalNode>("LyreclawTN"); TerminalKeyword val3 = ModAssets.LoadAsset<TerminalKeyword>("LyreclawTK"); NetworkPrefabs.RegisterNetworkPrefab(val.enemyPrefab); Enemies.RegisterEnemy(val, BoundConfig.SpawnWeight.Value, (LevelTypes)(-1), val2, val3); Logger.LogInfo((object)"Plugin DawnDreamIsland.LethalMods.Lyreclaw is loaded!"); } private static void InitializeNetworkBehaviours() { Type[] types = Assembly.GetExecutingAssembly().GetTypes(); Type[] array = types; foreach (Type type in array) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array2 = methods; foreach (MethodInfo methodInfo in array2) { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { methodInfo.Invoke(null, null); } } } } } } namespace Lyreclaw.Configuration { public class PluginConfig { public ConfigEntry<int> SpawnWeight; public PluginConfig(ConfigFile cfg) { SpawnWeight = cfg.Bind<int>("General", "Spawn weight", 20, "The spawn chance weight for The Lyreclaws, relative to other existing enemies.\nGoes up from 0, lower is more rare, 100 and up is very common."); ClearUnusedEntries(cfg); } private void ClearUnusedEntries(ConfigFile cfg) { PropertyInfo property = ((object)cfg).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic); Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(cfg, null); dictionary.Clear(); cfg.Save(); } } }