proof of concept

This commit is contained in:
mikx
2026-02-12 23:38:28 -05:00
parent c724674b5a
commit 6a8a09e2f6
6 changed files with 683 additions and 15 deletions

View File

@@ -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<UnityEngine.Canvas>();
c.renderMode = RenderMode.ScreenSpaceOverlay;
c.sortingOrder = 9999; // Just behind killfeed
CanvasScaler scaler = _eventRoot.AddComponent<CanvasScaler>();
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
scaler.referenceResolution = new Vector2(1920, 1080);
_canvasGroup = _eventRoot.AddComponent<CanvasGroup>();
_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<Image>();
panelImage.color = new UnityEngine.Color(0, 0, 0, 0.7f);
// Find Valheim Sprite
foreach (Sprite s in Resources.FindObjectsOfTypeAll<Sprite>())
{
if (s.name == "item_background")
{
panelImage.sprite = s;
panelImage.type = Image.Type.Sliced;
break;
}
}
RectTransform pRect = panel.GetComponent<RectTransform>();
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<VerticalLayoutGroup>();
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<Image>().color = new UnityEngine.Color(0.2f, 0.2f, 0.2f, 0.8f);
barBg.GetComponent<RectTransform>().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<Image>();
_progressBar.color = UnityEngine.Color.red;
_progressBar.type = Image.Type.Filled;
_progressBar.fillMethod = Image.FillMethod.Horizontal;
RectTransform fRect = _progressBar.GetComponent<RectTransform>();
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<Text>();
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<UnityEngine.Font>())
if (f.name == "AveriaSerifLibre-Bold") return f;
return Resources.GetBuiltinResource<UnityEngine.Font>("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;
}
}

View File

@@ -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<SpawnSystem.SpawnData> { frostWraith };
// 3. Add to the game's master list
system.m_events.Add(myCustomRaid);
}
}
}

View File

@@ -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<Canvas>();
c.renderMode = RenderMode.ScreenSpaceOverlay;
c.sortingOrder = 9999;
CanvasScaler scaler = _eventRoot.AddComponent<CanvasScaler>();
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
scaler.referenceResolution = new Vector2(1920, 1080);
_canvasGroup = _eventRoot.AddComponent<CanvasGroup>();
_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<Image>();
panelImage.color = new Color(0, 0, 0, 0.7f);
// Styling with Valheim Assets
foreach (Sprite s in Resources.FindObjectsOfTypeAll<Sprite>())
{
if (s.name == "item_background")
{
panelImage.sprite = s;
panelImage.type = Image.Type.Sliced;
break;
}
}
RectTransform pRect = panel.GetComponent<RectTransform>();
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<VerticalLayoutGroup>();
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<Image>().color = new Color(0.1f, 0.1f, 0.1f, 0.9f);
barBg.GetComponent<RectTransform>().sizeDelta = new Vector2(350, 8);
GameObject fillObj = new GameObject("Fill", typeof(RectTransform), typeof(Image));
fillObj.transform.SetParent(barBg.transform, false);
_progressBar = fillObj.GetComponent<Image>();
_progressBar.color = Color.red;
_progressBar.type = Image.Type.Filled;
_progressBar.fillMethod = Image.FillMethod.Horizontal;
_progressBar.GetComponent<RectTransform>().anchorMin = Vector2.zero;
_progressBar.GetComponent<RectTransform>().anchorMax = Vector2.one;
_progressBar.GetComponent<RectTransform>().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<Text>();
t.text = content;
t.fontSize = size;
t.color = col;
t.alignment = TextAnchor.MiddleCenter;
Font valFont = null;
foreach (Font f in Resources.FindObjectsOfTypeAll<Font>())
if (f.name == "AveriaSerifLibre-Bold") valFont = f;
t.font = valFont ?? Resources.GetBuiltinResource<Font>("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<ZNetView>();
// 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<ZNetView>();
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<BaseAI>();
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.");
}
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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<bool> Config_Locked;
public static ConfigEntry<int> 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<TMP_SpriteAsset>().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<string, int, int>("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()

View File

@@ -44,7 +44,9 @@
<Reference Include="BepInEx">
<HintPath>E:\SteamLibrary\steamapps\common\Valheim\BepInEx\core\BepInEx.dll</HintPath>
</Reference>
<Reference Include="gui_framework, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Reference Include="gui_framework">
<HintPath>E:\SteamLibrary\steamapps\common\Valheim\Valheim_Data\Managed\gui_framework.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>E:\SteamLibrary\steamapps\common\Valheim\BepInEx\plugins\Newtonsoft.Json.dll</HintPath>
</Reference>
@@ -59,7 +61,9 @@
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="Unity.TextMeshPro, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Reference Include="Unity.TextMeshPro">
<HintPath>E:\SteamLibrary\steamapps\common\Valheim\Valheim_Data\Managed\Unity.TextMeshPro.dll</HintPath>
</Reference>
<Reference Include="UnityEngine">
<HintPath>E:\SteamLibrary\steamapps\common\Valheim\Valheim_Data\Managed\UnityEngine.dll</HintPath>
</Reference>
@@ -74,7 +78,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>E:\SteamLibrary\steamapps\common\Valheim\Valheim_Data\Managed\UnityEngine.PhysicsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.TextRenderingModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Reference Include="UnityEngine.TextRenderingModule">
<HintPath>E:\SteamLibrary\steamapps\common\Valheim\Valheim_Data\Managed\UnityEngine.TextRenderingModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UI, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>E:\SteamLibrary\steamapps\common\Valheim\Valheim_Data\Managed\UnityEngine.UI.dll</HintPath>
@@ -85,6 +91,10 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="EventSystem\EventHud.cs" />
<Compile Include="EventSystem\EventList.cs" />
<Compile Include="EventSystem\Patch.cs" />
<Compile Include="EventSystem\WaveManager.cs" />
<Compile Include="KillFeed\NPCIcon.cs" />
<Compile Include="KillFeed\Patch.cs" />
<Compile Include="MxValheim.cs" />