From 37e3d6e9b1e2cdff9d7a67848f47e2fa93076ac4 Mon Sep 17 00:00:00 2001 From: LadyAliceMargatroid Date: Mon, 6 May 2024 02:13:04 -0700 Subject: [PATCH] Added spooky dark souls enemies Added potential fix for items spawning near doorways (and enemies potentially using them) --- .../DunGenPatch/Doorways/DoorwayCleanup.cs | 6 +++ .../GamePatch/Components/ScarletBedroom.cs | 9 +++- .../ScarletMansion/GamePatch/JesterAIPatch.cs | 2 +- .../GamePatch/Managers/DoorwayManager.cs | 48 +++++++++++++++++++ .../Managers/ScarletNetworkManager.cs | 40 ++++++++++++++++ .../NetworkObjectListScriptableObject.cs | 3 ++ ScarletMansion/ScarletMansion/Plugin.cs | 2 +- ScarletMansion/ScarletMansion/PluginConfig.cs | 11 ++++- 8 files changed, 116 insertions(+), 5 deletions(-) diff --git a/ScarletMansion/ScarletMansion/DunGenPatch/Doorways/DoorwayCleanup.cs b/ScarletMansion/ScarletMansion/DunGenPatch/Doorways/DoorwayCleanup.cs index de92e04..e53b253 100644 --- a/ScarletMansion/ScarletMansion/DunGenPatch/Doorways/DoorwayCleanup.cs +++ b/ScarletMansion/ScarletMansion/DunGenPatch/Doorways/DoorwayCleanup.cs @@ -33,6 +33,8 @@ namespace ScarletMansion.DunGenPatch.Doorways { } public void OnDungeonComplete(Dungeon dungeon) { + // fix for items spawning on doorways + SetBlockers(true); DoorwayManager.Instance.AddDoorwayCleanup(this); } @@ -55,6 +57,10 @@ namespace ScarletMansion.DunGenPatch.Doorways { } } + public void SetBlockers(bool state){ + foreach(var b in blockers) b.SetActive(state); + } + public void SwitchConnectorBlocker(bool isConnector){ if (overrideConnector) isConnector = true; foreach(var c in connectors) c.SetActive(isConnector); diff --git a/ScarletMansion/ScarletMansion/GamePatch/Components/ScarletBedroom.cs b/ScarletMansion/ScarletMansion/GamePatch/Components/ScarletBedroom.cs index f0732f0..26517c6 100644 --- a/ScarletMansion/ScarletMansion/GamePatch/Components/ScarletBedroom.cs +++ b/ScarletMansion/ScarletMansion/GamePatch/Components/ScarletBedroom.cs @@ -14,6 +14,9 @@ using GameNetcodeStuff; namespace ScarletMansion.GamePatch.Components { public class ScarletBedroom : MonoBehaviour, IDungeonCompleteReceiver { + public const string ENEMY_SPAWN_LIST_DEFAULT = "knight@s1,crawler,nutcracker,springman,maskedplayerenemy,jester@s1,butler"; + public static readonly string[] ENEMY_EVIL_LIST = new string[] { "knight", "crawler", "nutcracker", "springman" ,"maskedplayerenemy" ,"jester", "butler" }; + public static ActionList onBedroomEndEvent = new ActionList("onBedroomEnd"); [Header("References")] @@ -133,7 +136,7 @@ namespace ScarletMansion.GamePatch.Components { public static void CreateRandomEnemyList(List enemies){ var lower = PluginConfig.Instance.paintingEnemyListValue.ToLowerInvariant(); if (lower == "default"){ - lower = "knight@s1,crawler,nutcracker,springman,maskedplayerenemy,jester@s1"; + lower = ENEMY_SPAWN_LIST_DEFAULT; } spawnableEnemiesTrueList = new List(); @@ -193,7 +196,9 @@ namespace ScarletMansion.GamePatch.Components { bonusEnemy.ApplySpawnLogic(); roundmanager.currentEnemyPower += enemy.PowerLevel; - roundmanager.SpawnEnemyServerRpc(vent.transform.position, y, enemyIndex); + var spawnedEnemy = roundmanager.SpawnEnemyGameObject(vent.transform.position, y, enemyIndex); + + ScarletNetworkManager.Instance.RequestEvilSkinApply(spawnedEnemy, enemy.name.ToLowerInvariant()); } } catch (Exception e) { var enemyString = bonusEnemy != null ? bonusEnemy.ToString() : "NULL"; diff --git a/ScarletMansion/ScarletMansion/GamePatch/JesterAIPatch.cs b/ScarletMansion/ScarletMansion/GamePatch/JesterAIPatch.cs index 45e47f0..89ee650 100644 --- a/ScarletMansion/ScarletMansion/GamePatch/JesterAIPatch.cs +++ b/ScarletMansion/ScarletMansion/GamePatch/JesterAIPatch.cs @@ -18,8 +18,8 @@ namespace ScarletMansion.GamePatch { if (DunGenPatch.Patch.active && active && __instance.IsOwner) { Plugin.logger.LogInfo("Activing kill order for Jester"); __instance.SwitchToBehaviourState(1); - active = false; } + active = false; } } diff --git a/ScarletMansion/ScarletMansion/GamePatch/Managers/DoorwayManager.cs b/ScarletMansion/ScarletMansion/GamePatch/Managers/DoorwayManager.cs index e2b65c8..ba8f908 100644 --- a/ScarletMansion/ScarletMansion/GamePatch/Managers/DoorwayManager.cs +++ b/ScarletMansion/ScarletMansion/GamePatch/Managers/DoorwayManager.cs @@ -6,6 +6,9 @@ using System.Threading.Tasks; using UnityEngine; using DunGen; using ScarletMansion.DunGenPatch.Doorways; +using Unity.AI.Navigation; +using UnityEngine.AI; +using DunGen.Adapters; namespace ScarletMansion.GamePatch.Managers { public class DoorwayManager : MonoBehaviour { @@ -20,6 +23,39 @@ namespace ScarletMansion.GamePatch.Managers { doorwayCleanup = new List(); } + /* + + private NavMeshSurface surface; + private GameObject meshGameObject; + private MeshFilter meshFilter; + + void Update(){ + if (surface == null){ + surface = FindObjectOfType(); + } + + if (surface != null){ + if (meshFilter == null){ + meshGameObject = new GameObject("Nav Mesh V"); + meshFilter = meshGameObject.AddComponent(); + + var renderer = meshGameObject.AddComponent(); + renderer.materials = new Material[1]; + renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + } + + var mesh = new Mesh(); + var triangulation = NavMesh.CalculateTriangulation(); + mesh.SetVertices(triangulation.vertices); + mesh.SetIndices(triangulation.indices, MeshTopology.Triangles, 0); + + meshGameObject.transform.position = new Vector3(0f, 0.05f, 0f); + meshFilter.mesh = mesh; + } + } + */ + + public void AddDoorwayCleanup(DoorwayCleanup dw){ doorwayCleanup.Add(dw); } @@ -28,8 +64,20 @@ namespace ScarletMansion.GamePatch.Managers { if (Instance && DunGenPatch.Patch.active) { var doorwayCleanups = Instance.doorwayCleanup; foreach(var d in doorwayCleanups){ + d.SetBlockers(false); d.Cleanup(); } + + try{ + var dungeonGen = RoundManager.Instance.dungeonGenerator; + var navmesh = dungeonGen.transform.parent.GetComponentInChildren(); + navmesh.Run(dungeonGen.Generator); + Plugin.logger.LogInfo("Rebuild nav mesh"); + } catch (Exception e){ + Plugin.logger.LogError("Failed to rebuild nav mesh"); + Plugin.logger.LogError(e.ToString()); + } + } } diff --git a/ScarletMansion/ScarletMansion/GamePatch/Managers/ScarletNetworkManager.cs b/ScarletMansion/ScarletMansion/GamePatch/Managers/ScarletNetworkManager.cs index 2a8ff3b..50418ab 100644 --- a/ScarletMansion/ScarletMansion/GamePatch/Managers/ScarletNetworkManager.cs +++ b/ScarletMansion/ScarletMansion/GamePatch/Managers/ScarletNetworkManager.cs @@ -9,6 +9,7 @@ using Unity.Netcode; using GameNetcodeStuff; using ScarletMansion.GamePatch.Items; using ScarletMansion.GamePatch; +using ScarletMansion.GamePatch.Components; namespace ScarletMansion { @@ -261,6 +262,45 @@ namespace ScarletMansion { } } + + public void RequestEvilSkinApply(NetworkObjectReference reference, string enemyName) { + if (PluginConfig.Instance.paintingEnemyEvilSkinValue && ScarletBedroom.ENEMY_EVIL_LIST.Contains(enemyName)) { + RequestEvilSkinApplyClientRpc(reference); + } + } + + [ClientRpc] + public void RequestEvilSkinApplyClientRpc(NetworkObjectReference reference){ + + void ApplyMaterialToRenderers(T[] renderers) where T: Renderer{ + foreach(var render in renderers) { + var mats = render.materials; + for(var i = 0; i < mats.Length; i++) { + var material = new Material(Assets.networkObjectList.ghostMaterial); + material.mainTexture = mats[i].mainTexture; + mats[i] = material; + } + render.materials = mats; + } + } + + if (reference.TryGet(out var obj)){ + var enemy = obj.GetComponentInParent(); + if (enemy == null) return; + + var enemyName = enemy.name; + try { + Plugin.logger.LogInfo($"Applying evil material to {enemyName}"); + ApplyMaterialToRenderers(enemy.GetComponentsInChildren()); + ApplyMaterialToRenderers(enemy.GetComponentsInChildren()); + } catch (Exception e){ + Plugin.logger.LogWarning($"Failed to apply evil material to {enemyName}"); + Plugin.logger.LogWarning(e.ToString()); + } + } + + } + } public static class ScarletNetworkManagerUtility { diff --git a/ScarletMansion/ScarletMansion/LoadingPatch/NetworkObjectListScriptableObject.cs b/ScarletMansion/ScarletMansion/LoadingPatch/NetworkObjectListScriptableObject.cs index b85f2bd..24fd309 100644 --- a/ScarletMansion/ScarletMansion/LoadingPatch/NetworkObjectListScriptableObject.cs +++ b/ScarletMansion/ScarletMansion/LoadingPatch/NetworkObjectListScriptableObject.cs @@ -32,6 +32,9 @@ namespace ScarletMansion { [Header("Main Prefabs")] public GameObject scarletNetworkManager; + + [Header("Mis References")] + public Material ghostMaterial; public AudioClip sinkingAudioClip; } } diff --git a/ScarletMansion/ScarletMansion/Plugin.cs b/ScarletMansion/ScarletMansion/Plugin.cs index 012ddc9..712dce1 100644 --- a/ScarletMansion/ScarletMansion/Plugin.cs +++ b/ScarletMansion/ScarletMansion/Plugin.cs @@ -33,7 +33,7 @@ namespace ScarletMansion { public class Plugin : BaseUnityPlugin { public const string modGUID = "ImoutoSama.ScarletMansion"; private const string modName = "Scarlet Mansion"; - private const string modVersion = "1.3.13"; + private const string modVersion = "1.3.15"; public readonly Harmony harmony = new Harmony(modGUID); diff --git a/ScarletMansion/ScarletMansion/PluginConfig.cs b/ScarletMansion/ScarletMansion/PluginConfig.cs index b34eb09..96a4fc4 100644 --- a/ScarletMansion/ScarletMansion/PluginConfig.cs +++ b/ScarletMansion/ScarletMansion/PluginConfig.cs @@ -12,6 +12,7 @@ using BepInEx.Configuration; using BepInEx.Logging; using UnityEngine; using System.Reflection; +using ScarletMansion.GamePatch.Components; namespace ScarletMansion { @@ -368,7 +369,14 @@ namespace ScarletMansion { dungeonPaintingEventPrefix, "Enemy List", "default", - "The enemies that can spawn when the bedroom's painting event ends, in the form of a comma separated list of enemy names along with optional parameters separated or '@'.It can accept either the enemy's internal or display name.\n\nThe available parameters are:\nSpawn Logic: 's#' where '#' is either '0' for normal spawn logic or '1' for special spawn logic. Only the knight and jester have special spawn logic. When their special spawn logic is enabled, the knight will spawn properly in the bedroom and the jester will spawn already cranking.\n\nThe following string \"default\" is a preset that uses the following string \"knight@s1,crawler,nutcracker,springman,maskedplayerenemy,jester@s1\"." + $"The enemies that can spawn when the bedroom's painting event ends, in the form of a comma separated list of enemy names along with optional parameters separated or '@'.It can accept either the enemy's internal or display name.\n\nThe available parameters are:\nSpawn Logic: 's#' where '#' is either '0' for normal spawn logic or '1' for special spawn logic. Only the knight and jester have special spawn logic. When their special spawn logic is enabled, the knight will spawn properly in the bedroom and the jester will spawn already cranking.\n\nThe following string \"default\" is a preset that uses the following string \"{ScarletBedroom.ENEMY_SPAWN_LIST_DEFAULT}\"." + ); + + public static ConfigEntryBundle paintingEnemyEvilSkin = new ConfigEntryBundle( + dungeonPaintingEventPrefix, + "Invader Apperance", + true, + "Enemies spawned from the bedroom's painting event has a pitch black and red appearance. Only valid for the default enemy list." ); public static ConfigEntryBundle facilityMeltdownActive = new ConfigEntryBundle( @@ -383,6 +391,7 @@ namespace ScarletMansion { public IntRange paintingExtraLootValue = new IntRange("painting extra loot"); public bool paintingSpawnEnemyValue; public string paintingEnemyListValue; + public bool paintingEnemyEvilSkinValue; public bool facilityMeltdownActiveValue; // lighting