From 6a8a09e2f689cdecc35319db4f333e94860f358a Mon Sep 17 00:00:00 2001 From: mikx Date: Thu, 12 Feb 2026 23:38:28 -0500 Subject: [PATCH] proof of concept --- MxValheim/EventSystem/EventHud.cs | 129 +++++++++ MxValheim/EventSystem/EventList.cs | 48 ++++ MxValheim/EventSystem/Patch.cs | 396 +++++++++++++++++++++++++++ MxValheim/EventSystem/WaveManager.cs | 66 +++++ MxValheim/MxValheim.cs | 43 ++- MxValheim/MxValheim.csproj | 16 +- 6 files changed, 683 insertions(+), 15 deletions(-) create mode 100644 MxValheim/EventSystem/EventHud.cs create mode 100644 MxValheim/EventSystem/EventList.cs create mode 100644 MxValheim/EventSystem/Patch.cs create mode 100644 MxValheim/EventSystem/WaveManager.cs diff --git a/MxValheim/EventSystem/EventHud.cs b/MxValheim/EventSystem/EventHud.cs new file mode 100644 index 0000000..4c1b2a9 --- /dev/null +++ b/MxValheim/EventSystem/EventHud.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Annotations; +using System.Windows.Controls; +using UnityEngine; +using UnityEngine.UI; +using Image = UnityEngine.UI.Image; + +namespace MxValheim.EventSystem +{ + internal class EventHud + { + private static GameObject _eventRoot; + private static Text _eventTitleText; + private static Text _eventProgressText; + private static Image _progressBar; + private static CanvasGroup _canvasGroup; + + public static void CreateEventHud() + { + // 1. Setup Root (Stacked under your KillFeed which is at -30) + _eventRoot = new GameObject("MxEventHUD_Root"); + UnityEngine.Object.DontDestroyOnLoad(_eventRoot); + + UnityEngine.Canvas c = _eventRoot.AddComponent(); + c.renderMode = RenderMode.ScreenSpaceOverlay; + c.sortingOrder = 9999; // Just behind killfeed + + CanvasScaler scaler = _eventRoot.AddComponent(); + scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; + scaler.referenceResolution = new Vector2(1920, 1080); + + _canvasGroup = _eventRoot.AddComponent(); + _canvasGroup.alpha = 0f; + + // 2. Main Panel (Positioned at -80 to sit below the KillFeed) + GameObject panel = new GameObject("Background", typeof(RectTransform), typeof(Image)); + panel.transform.SetParent(_eventRoot.transform, false); + Image panelImage = panel.GetComponent(); + panelImage.color = new UnityEngine.Color(0, 0, 0, 0.7f); + + // Find Valheim Sprite + foreach (Sprite s in Resources.FindObjectsOfTypeAll()) + { + if (s.name == "item_background") + { + panelImage.sprite = s; + panelImage.type = Image.Type.Sliced; + break; + } + } + + RectTransform pRect = panel.GetComponent(); + pRect.anchorMin = pRect.anchorMax = pRect.pivot = new Vector2(0.5f, 1f); + pRect.anchoredPosition = new Vector2(0, -80); // Lowered to avoid overlap + pRect.sizeDelta = new Vector2(450, 60); // Slightly taller for progress bar + + // 3. Vertical Layout for Title + Progress Bar + VerticalLayoutGroup layout = panel.AddComponent(); + layout.childAlignment = UnityEngine.TextAnchor.MiddleCenter; + layout.spacing = 5f; + layout.padding = new RectOffset(10, 10, 5, 5); + + // 4. Title Text + _eventTitleText = CreateText(panel.transform, "EVENT ACTIVE", 14, UnityEngine.Color.yellow); + + // 5. Progress Bar Background + GameObject barBg = new GameObject("BarBG", typeof(RectTransform), typeof(Image)); + barBg.transform.SetParent(panel.transform, false); + barBg.GetComponent().color = new UnityEngine.Color(0.2f, 0.2f, 0.2f, 0.8f); + barBg.GetComponent().sizeDelta = new Vector2(400, 10); + + // 6. Actual Progress Fill + GameObject fillObj = new GameObject("Fill", typeof(RectTransform), typeof(Image)); + fillObj.transform.SetParent(barBg.transform, false); + _progressBar = fillObj.GetComponent(); + _progressBar.color = UnityEngine.Color.red; + _progressBar.type = Image.Type.Filled; + _progressBar.fillMethod = Image.FillMethod.Horizontal; + + RectTransform fRect = _progressBar.GetComponent(); + fRect.anchorMin = Vector2.zero; + fRect.anchorMax = Vector2.one; + fRect.sizeDelta = Vector2.zero; + + // 7. Counter Text (e.g., 12/20) + _eventProgressText = CreateText(panel.transform, "0 / 0", 10, UnityEngine.Color.white); + + _eventRoot.SetActive(false); + } + + public static Text CreateText(Transform parent, string content, int size, UnityEngine.Color col) + { + GameObject txtObj = new GameObject("Text", typeof(RectTransform), typeof(Text)); + txtObj.transform.SetParent(parent, false); + Text t = txtObj.GetComponent(); + t.text = content; + t.fontSize = size; + t.color = col; + t.alignment = UnityEngine.TextAnchor.MiddleCenter; + t.font = GetValheimFont(); + return t; + } + + public static UnityEngine.Font GetValheimFont() + { + foreach (UnityEngine.Font f in Resources.FindObjectsOfTypeAll()) + if (f.name == "AveriaSerifLibre-Bold") return f; + return Resources.GetBuiltinResource("Arial.ttf"); + } + + public static void UpdateDisplay(string title, int current, int total, Color barColor) + { + if (_eventRoot == null) return; + _eventRoot.SetActive(true); + _canvasGroup.alpha = 1f; + + _eventTitleText.text = title.ToUpper(); + _eventProgressText.text = $"{current} / {total}"; + _progressBar.fillAmount = (float)current / total; + _progressBar.color = barColor; + } + + public static void Hide() => _canvasGroup.alpha = 0f; + } +} diff --git a/MxValheim/EventSystem/EventList.cs b/MxValheim/EventSystem/EventList.cs new file mode 100644 index 0000000..c87c91b --- /dev/null +++ b/MxValheim/EventSystem/EventList.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MxValheim.EventSystem +{ + internal class EventList + { + public static void SetupCustomRaid(RandEventSystem system) + { + // 1. Create the Event Data + RandomEvent myCustomRaid = new RandomEvent + { + m_name = "MxEvent_God1", + m_enabled = true, + m_duration = 600f, // 10 minutes + m_nearBaseOnly = true, // Must be near player structures + m_pauseIfNoPlayerInArea = true, + m_forceMusic = "Music_Boss_Moder", // Use specific music + m_startMessage = "The gods themselves challenge you...", + m_endMessage = "The gods are satisfied.", + m_forceEnvironment = "SnowStorm" // Force weather + }; + + // 2. Define what spawns during this event + SpawnSystem.SpawnData frostWraith = new SpawnSystem.SpawnData + { + m_name = "Frost Wraith", + m_prefab = ZNetScene.instance.GetPrefab("Wraith"), // Get the Wraith prefab + m_maxSpawned = 5, // Max alive at once + m_spawnInterval = 10f, // Try to spawn every 10s + m_spawnDistance = 30f, // Distance from player + m_spawnRadiusMax = 10f, + m_spawnRadiusMin = 5f, + m_groupSizeMin = 1, + m_groupSizeMax = 2, + m_enabled = true + }; + + myCustomRaid.m_spawn = new List { frostWraith }; + + // 3. Add to the game's master list + system.m_events.Add(myCustomRaid); + } + } +} diff --git a/MxValheim/EventSystem/Patch.cs b/MxValheim/EventSystem/Patch.cs new file mode 100644 index 0000000..159875e --- /dev/null +++ b/MxValheim/EventSystem/Patch.cs @@ -0,0 +1,396 @@ +using HarmonyLib; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Controls; +using UnityEngine; +using UnityEngine.UI; +using static MxValheimMod; +using Canvas = UnityEngine.Canvas; +using Image = UnityEngine.UI.Image; + +namespace MxValheim.EventSystem +{ + internal class EventSystem_Patch + { + public static GameObject _eventRoot; + public static Text _eventTitleText; + public static Text _eventProgressText; + public static Image _progressBar; + public static CanvasGroup _canvasGroup; + + // --- STATE DATA --- + public enum RaidPhase + { + None, + Scouts, + EliteGuard, + BossInbound, + Completed + } + public static RaidPhase CurrentPhase = RaidPhase.None; + public static int KillsInCurrentPhase = 0; + // --- 1. HUD CREATION (Your Style) --- + public static void CreateEventHud() + { + if (_eventRoot != null) return; + + _eventRoot = new GameObject("MxEventHUD_Root"); + UnityEngine.Object.DontDestroyOnLoad(_eventRoot); + + Canvas c = _eventRoot.AddComponent(); + c.renderMode = RenderMode.ScreenSpaceOverlay; + c.sortingOrder = 9999; + + CanvasScaler scaler = _eventRoot.AddComponent(); + scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; + scaler.referenceResolution = new Vector2(1920, 1080); + + _canvasGroup = _eventRoot.AddComponent(); + _canvasGroup.alpha = 0f; + + // Background Panel (Positioned -90 to sit below KillFeed at -30) + GameObject panel = new GameObject("Background", typeof(RectTransform), typeof(Image)); + panel.transform.SetParent(_eventRoot.transform, false); + Image panelImage = panel.GetComponent(); + panelImage.color = new Color(0, 0, 0, 0.7f); + + // Styling with Valheim Assets + foreach (Sprite s in Resources.FindObjectsOfTypeAll()) + { + if (s.name == "item_background") + { + panelImage.sprite = s; + panelImage.type = Image.Type.Sliced; + break; + } + } + + RectTransform pRect = panel.GetComponent(); + pRect.anchorMin = pRect.anchorMax = pRect.pivot = new Vector2(0.5f, 1f); + pRect.anchoredPosition = new Vector2(0, -90); // Stacks below your KillFeed + pRect.sizeDelta = new Vector2(400, 55); + + VerticalLayoutGroup layout = panel.AddComponent(); + layout.childAlignment = TextAnchor.MiddleCenter; + layout.spacing = 2f; + layout.padding = new RectOffset(10, 10, 5, 5); + + // Title + _eventTitleText = CreateText(panel.transform, "RAID STATUS", 14, Color.yellow); + + // Progress Bar + GameObject barBg = new GameObject("BarBG", typeof(RectTransform), typeof(Image)); + barBg.transform.SetParent(panel.transform, false); + barBg.GetComponent().color = new Color(0.1f, 0.1f, 0.1f, 0.9f); + barBg.GetComponent().sizeDelta = new Vector2(350, 8); + + GameObject fillObj = new GameObject("Fill", typeof(RectTransform), typeof(Image)); + fillObj.transform.SetParent(barBg.transform, false); + _progressBar = fillObj.GetComponent(); + _progressBar.color = Color.red; + _progressBar.type = Image.Type.Filled; + _progressBar.fillMethod = Image.FillMethod.Horizontal; + _progressBar.GetComponent().anchorMin = Vector2.zero; + _progressBar.GetComponent().anchorMax = Vector2.one; + _progressBar.GetComponent().sizeDelta = Vector2.zero; + + // Progress Text + _eventProgressText = CreateText(panel.transform, "0 / 0", 11, Color.white); + } + + private static Text CreateText(Transform parent, string content, int size, Color col) + { + GameObject txtObj = new GameObject("Text", typeof(Text)); + txtObj.transform.SetParent(parent, false); + Text t = txtObj.GetComponent(); + t.text = content; + t.fontSize = size; + t.color = col; + t.alignment = TextAnchor.MiddleCenter; + + Font valFont = null; + foreach (Font f in Resources.FindObjectsOfTypeAll()) + if (f.name == "AveriaSerifLibre-Bold") valFont = f; + t.font = valFont ?? Resources.GetBuiltinResource("Arial.ttf"); + + return t; + } + + // --- 2. WAVE LOGIC --- + public static void UpdateWave(bool reset = false) + { + Debug.Log($"MxEvent:UpdateWave Seen a wave start."); + if (reset) + { + CurrentPhase = RaidPhase.Scouts; + KillsInCurrentPhase = 0; + } + + int target = GetTargetForPhase(CurrentPhase); + + Color barColor = (CurrentPhase == RaidPhase.Scouts) ? Color.magenta : Color.red; + + UpdateDisplay($"PHASE: {CurrentPhase}", KillsInCurrentPhase, target, barColor); + } + + public static int GetTargetForPhase(RaidPhase phase) + { + switch (phase) + { + case RaidPhase.Scouts: return 5; // 5 kills to clear scouts + case RaidPhase.EliteGuard: return 10; // 10 kills for elite guard + case RaidPhase.BossInbound: return 1; // Just the boss + default: return 0; + } + } + + public static void AdvancePhase() + { + KillsInCurrentPhase = 0; // Reset counter for the new phase + + if (CurrentPhase == RaidPhase.Scouts) CurrentPhase = RaidPhase.EliteGuard; + else if (CurrentPhase == RaidPhase.EliteGuard) CurrentPhase = RaidPhase.BossInbound; + else CurrentPhase = RaidPhase.Completed; + + if (CurrentPhase == RaidPhase.Scouts) + { + // Spawn Eikthyr at the player's location + GameObject boarPrefab = ZNetScene.instance.GetPrefab("Boar"); + if (boarPrefab != null) + { + UnityEngine.Object.Instantiate(boarPrefab, Player.m_localPlayer.transform.position + Vector3.forward * 20f, Quaternion.identity); + } + } + + if (CurrentPhase == RaidPhase.BossInbound) + { + // Spawn Eikthyr at the player's location + GameObject bossPrefab = ZNetScene.instance.GetPrefab("Eikthyr"); + if (bossPrefab != null) + { + UnityEngine.Object.Instantiate(bossPrefab, Player.m_localPlayer.transform.position + Vector3.forward * 10f, Quaternion.identity); + } + } + + Debug.Log($"MxEvent: Advancing to {CurrentPhase}"); + + // Play a sound to notify the player (The 'Quest Update' sound) + Player.m_localPlayer?.Message(MessageHud.MessageType.Center, $"$inventory_newphase: {CurrentPhase}"); + + if (CurrentPhase == RaidPhase.Completed) + { + Debug.Log("MxEvent: All phases complete. Ending vanilla raid."); + EndRaidManually(); + } + } + + public static void UpdateDisplay(string title, int curr, int total, Color col) + { + Debug.Log($"MxEvent:UpdateDisplay Something reached my display update logic."); + if (_eventRoot == null) CreateEventHud(); + _eventRoot.SetActive(true); + _canvasGroup.alpha = 1f; + + _eventTitleText.text = title; + _eventProgressText.text = $"{curr} / {total}"; + _progressBar.fillAmount = (float)curr / total; + _progressBar.color = col; + } + + public static void EndRaidManually() + { + if (RandEventSystem.instance != null) + { + // This tells Valheim the time is up + RandomEvent activeEvent = RandEventSystem.instance.GetActiveEvent(); + if (activeEvent != null) + { + activeEvent.m_time = 0; + } + } + FadeOutHud(); // Start your fade out + } + + // --- 3. HARMONY PATCHES --- + + [HarmonyPatch(typeof(RandEventSystem), nameof(RandEventSystem.FixedUpdate))] + public static class DebugRaidFrequency + { + static void Prefix(RandEventSystem __instance) + { + // Use a small timer check so we don't spam the logic every single frame + // though for debugging, forcing these values is fine. + __instance.m_eventIntervalMin = 10f; + __instance.m_eventChance = 100f; + } + } + + [HarmonyPatch(typeof(RandEventSystem), nameof(RandEventSystem.FixedUpdate))] + public static class TimerFreezePatch + { + static void Prefix(RandEventSystem __instance) + { + RandomEvent activeEvent = __instance.GetActiveEvent(); + + // If we are in our custom phases and haven't reached "Completed" yet + if (activeEvent != null && CurrentPhase != RaidPhase.Completed) + { + // Valheim subtracts time in FixedUpdate. + // We add it back using the engine's global fixedDeltaTime. + activeEvent.m_time += Time.fixedDeltaTime; + } + } + } + + // Ensure HUD is ready when the game UI loads + [HarmonyPatch(typeof(Hud), nameof(Hud.Awake))] + [HarmonyPostfix] + static void InitHud() => CreateEventHud(); + + [HarmonyPatch(typeof(Hud), nameof(Hud.Update))] + [HarmonyPostfix] + static void CheckForExistingRaid() + { + // If the HUD isn't visible but a raid IS active, force it to show + if (CurrentPhase == RaidPhase.None && RandEventSystem.instance.GetActiveEvent() != null) + { + Debug.Log("MxEvent: Detected existing raid on HUD update. Synchronizing..."); + UpdateWave(true); + } + } + + [HarmonyPatch(typeof(Hud), nameof(Hud.Update))] + public static class Hud_MonitorPatch + { + private static RandomEvent _lastKnownEvent = null; + + static void Postfix() + { + // 1. Safety check: Ensure the system exists + if (RandEventSystem.instance == null) return; + + RandomEvent activeEvent = RandEventSystem.instance.GetActiveEvent(); + + // 2. Logic: Detection + if (activeEvent != null && _lastKnownEvent == null) + { + Debug.Log($"MxEvent: HUD Heartbeat detected Raid Start: {activeEvent.m_name}"); + _lastKnownEvent = activeEvent; + + // Force HUD Creation and Display + UpdateWave(true); + } + else if (activeEvent == null && _lastKnownEvent != null) + { + Debug.Log("MxEvent: HUD Heartbeat detected Raid End."); + _lastKnownEvent = null; + FadeOutHud(); + } + } + } + + [HarmonyPatch(typeof(Character), nameof(Character.ApplyDamage))] + public static class DeathNotifier + { + static void Postfix(Character __instance) + { + // Check if the character is dead or just died + if (__instance.GetHealth() <= 0f) + { + ZNetView nview = __instance.GetComponent(); + + // This check should now pass because ApplyDamage happens before the object is invalidated + if (nview == null || !nview.IsValid() || !nview.IsOwner()) return; + + // 2. Check if a raid is active + RandomEvent activeEvent = RandEventSystem.instance.GetActiveEvent(); + if (activeEvent == null) return; + Debug.Log("MxEvent: Confirmed Active Event!"); + + Vector3 playerPos = Player.m_localPlayer.transform.position; + float distance = Vector3.Distance(playerPos, activeEvent.m_pos); + Debug.Log($"MxEvent: Distance: {distance}"); + + if (distance <= 96f) + { + KillsInCurrentPhase++; + int target = GetTargetForPhase(CurrentPhase); + + if (KillsInCurrentPhase >= target && CurrentPhase != RaidPhase.Completed) + { + AdvancePhase(); + } + + // Send the update + ZRoutedRpc.instance.InvokeRoutedRPC( + ZRoutedRpc.Everybody, + "RPC_UpdateRaidHUD", + $"PHASE: {CurrentPhase}", + KillsInCurrentPhase, + GetTargetForPhase(CurrentPhase) + ); + } + } + } + } + + public static bool IsEventCreature(Character character) + { + ZNetView nview = character.GetComponent(); + if (nview == null || nview.GetZDO() == null) return false; + + // Layer 1: Check the networked boolean (The standard way) + if (nview.GetZDO().GetBool("eventcreature")) return true; + + // Layer 2: Check the BaseAI component (The local way) + BaseAI ai = character.GetComponent(); + if (ai != null) + { + bool isRaidMob = (bool)AccessTools.Field(typeof(BaseAI), "m_eventCreature").GetValue(ai); + if (isRaidMob) return true; + } + + return false; + } + + // Hide HUD when raid ends + [HarmonyPatch(typeof(RandEventSystem), nameof(RandEventSystem.ResetRandomEvent))] + [HarmonyPostfix] + static void OnRaidEnd() + { + FadeOutHud(); + CurrentPhase = RaidPhase.None; + } + + private static IEnumerator FadeOutHud() + { + Debug.Log("MxEvent: Starting Fade Out..."); + + // Safety check for the component + if (_canvasGroup == null) + { + _eventRoot.SetActive(false); + yield break; + } + + float startAlpha = _canvasGroup.alpha; + float rate = 1.0f / 1.5f; // Fade over 1.5 seconds + float progress = 0.0f; + + while (progress < 1.0f) + { + progress += Time.deltaTime * rate; + _canvasGroup.alpha = Mathf.Lerp(startAlpha, 0, progress); + yield return null; + } + + _canvasGroup.alpha = 0; + _eventRoot.SetActive(false); // Fully disable to ensure it's gone + Debug.Log("MxEvent: HUD Hidden and Deactivated."); + } + } +} diff --git a/MxValheim/EventSystem/WaveManager.cs b/MxValheim/EventSystem/WaveManager.cs new file mode 100644 index 0000000..ad12401 --- /dev/null +++ b/MxValheim/EventSystem/WaveManager.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace MxValheim.EventSystem +{ + public enum RaidPhase { None, Scouts, Siege, Boss, Victory } + + public static class WaveManager + { + public static RaidPhase CurrentPhase = RaidPhase.None; + public static int KillsInCurrentPhase = 0; + public static int TotalInPhase = 20; + + public static void AdvanceWave() + { + KillsInCurrentPhase = 0; + CurrentPhase++; + + switch (CurrentPhase) + { + case RaidPhase.Scouts: + // + break; + case RaidPhase.Siege: + // + break; + case RaidPhase.Boss: + // + //SpawnBoss(); + break; + case RaidPhase.Victory: + // + break; + } + } + + public static void UpdateWave(bool reset = false) + { + if (reset) + { + CurrentPhase = RaidPhase.Scouts; + KillsInCurrentPhase = 0; + } + + int target = GetTargetForWave(CurrentPhase); + Color barColor = (CurrentPhase == RaidPhase.Boss) ? Color.magenta : Color.red; + + EventHud.UpdateDisplay($"PHASE: {CurrentPhase}", KillsInCurrentPhase, target, barColor); + } + + private static int GetTargetForWave(RaidPhase phase) + { + switch (phase) + { + case RaidPhase.Scouts: return 5; + case RaidPhase.Siege: return 15; + case RaidPhase.Boss: return 1; + default: return 0; + } + } + } +} diff --git a/MxValheim/MxValheim.cs b/MxValheim/MxValheim.cs index 9cc55a6..0486fe7 100644 --- a/MxValheim/MxValheim.cs +++ b/MxValheim/MxValheim.cs @@ -1,6 +1,7 @@ using BepInEx; using BepInEx.Configuration; using HarmonyLib; +using MxValheim.EventSystem; using MxValheim.KillFeed; using Newtonsoft.Json; using System; @@ -22,7 +23,7 @@ public class MxValheimMod : BaseUnityPlugin private const string ModGUID = "ovh.mxdev.mxvalheim"; private const string ModName = "MxValheim"; - private const string ModVersion = "1.5.5"; + private const string ModVersion = "1.6.0"; public static ConfigEntry Config_Locked; public static ConfigEntry Config_OreMultiplier; @@ -83,6 +84,20 @@ public class MxValheimMod : BaseUnityPlugin harmony.PatchAll(); } + public static void RPC_UpdateRaidHUD(long sender, string phaseName, int current, int total) + { + Color phaseColor; + switch (phaseName) + { + case "SCOUTS": phaseColor = Color.green; break; + case "ELITEGUARD": phaseColor = Color.yellow; break; + case "BOSSINBOUND": phaseColor = Color.red; break; + default: phaseColor = Color.white; break; + } + + EventSystem_Patch.UpdateDisplay(phaseName, current, total, phaseColor); + } + [HarmonyPatch(typeof(Localization), nameof(Localization.SetupLanguage))] public static class Localization_SetupLanguage_Patch { @@ -101,17 +116,7 @@ public class MxValheimMod : BaseUnityPlugin string text = __instance.m_input.text; if (text.ToLower() == "listicons") { - var spriteAsset = Resources.FindObjectsOfTypeAll().FirstOrDefault(x => x.name == "icons"); ; - - if (spriteAsset != null) - { - Debug.Log($"--- Listing all sprites in {spriteAsset.name} ---"); - for (int i = 0; i < spriteAsset.spriteCharacterTable.Count; i++) - { - var sprite = spriteAsset.spriteCharacterTable[i]; - Debug.Log($"Index: {i} | Name: {sprite.name}"); - } - } + } } } @@ -129,6 +134,14 @@ public class MxValheimMod : BaseUnityPlugin Debug.Log("MxValheimMod: RPC Registered successfully with explicit delegate."); } + + if (ZRoutedRpc.instance != null) + { + ZRoutedRpc.instance.Register("RPC_UpdateRaidHUD", RPC_UpdateRaidHUD); + Debug.Log("MxRaid: RPC Registered successfully."); + } + + EventSystem_Patch.CreateEventHud(); } } @@ -174,6 +187,12 @@ public class MxValheimMod : BaseUnityPlugin if (_displayTimer <= 0 && _hudRoot != null) _hudRoot.SetActive(false); } + if (RandEventSystem.instance.GetActiveEvent() == null) + { + EventSystem_Patch._canvasGroup.alpha = 0; + EventSystem_Patch._eventRoot.SetActive(false); + } + } public static void LoadLocalization() diff --git a/MxValheim/MxValheim.csproj b/MxValheim/MxValheim.csproj index 9418bca..4cd05b8 100644 --- a/MxValheim/MxValheim.csproj +++ b/MxValheim/MxValheim.csproj @@ -44,7 +44,9 @@ E:\SteamLibrary\steamapps\common\Valheim\BepInEx\core\BepInEx.dll - + + E:\SteamLibrary\steamapps\common\Valheim\Valheim_Data\Managed\gui_framework.dll + E:\SteamLibrary\steamapps\common\Valheim\BepInEx\plugins\Newtonsoft.Json.dll @@ -59,7 +61,9 @@ - + + E:\SteamLibrary\steamapps\common\Valheim\Valheim_Data\Managed\Unity.TextMeshPro.dll + E:\SteamLibrary\steamapps\common\Valheim\Valheim_Data\Managed\UnityEngine.dll @@ -74,7 +78,9 @@ False E:\SteamLibrary\steamapps\common\Valheim\Valheim_Data\Managed\UnityEngine.PhysicsModule.dll - + + E:\SteamLibrary\steamapps\common\Valheim\Valheim_Data\Managed\UnityEngine.TextRenderingModule.dll + False E:\SteamLibrary\steamapps\common\Valheim\Valheim_Data\Managed\UnityEngine.UI.dll @@ -85,6 +91,10 @@ + + + +