using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
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("BossSummonsAllies")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BossSummonsAllies")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("578e601e-68c5-4110-ba4a-5b788cde8309")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BossTriggersRaid;
[BepInPlugin("Severon.BossSummonsAllies", "Boss Summons Allies", "0.6.0")]
[BepInProcess("Valheim.exe")]
public class BossSummonAllies : BaseUnityPlugin
{
[HarmonyPatch(typeof(Character), "OnEnable")]
private class CaptureBossOnAwake
{
private static void Postfix(Character __instance)
{
if (__instance.m_boss)
{
Controller.RegisterBoss(__instance);
}
}
}
[HarmonyPatch(typeof(RandEventSystem), "GetCurrentSpawners")]
public static class RaidSpawnerPatch
{
private static void Postfix(ref List<SpawnData> __result)
{
if (Controller != null && Controller.HasActiveRaids)
{
List<SpawnData> spawners = Controller.GetSpawners();
if (spawners != null && spawners.Count > 0)
{
__result = spawners;
}
}
}
}
public static BossRaidController Controller;
private readonly Harmony harmony = new Harmony("Severon.BossSummonsAllies");
public static ConfigEntry<float> WaveInterval;
private void Awake()
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
WaveInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "WaveIntervalSeconds", 120f, new ConfigDescription("Time between boss raid waves in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 600f), Array.Empty<object>()));
Controller = new BossRaidController();
WaveInterval.SettingChanged += delegate
{
Debug.Log((object)"Wave interval changed. Updating active raids...");
Controller?.OnConfigChanged();
};
harmony.PatchAll();
((BaseUnityPlugin)this).Logger.LogInfo((object)"[BossRaid] Loaded");
}
private void Update()
{
Controller?.Update(Time.deltaTime);
}
}
public class RaidInstance
{
public Character Boss;
public RandomEvent Event;
public bool Active;
public float WaveTimer;
}
public class BossRaidController
{
private Dictionary<Character, RaidInstance> _raids = new Dictionary<Character, RaidInstance>();
private Dictionary<string, string> _bossRaidMap = new Dictionary<string, string>
{
{ "$enemy_eikthyr", "army_eikthyr" },
{ "$enemy_gdking", "army_theelder" },
{ "$enemy_bonemass", "army_bonemass" },
{ "$enemy_dragon", "army_moder" },
{ "$enemy_goblinking", "army_goblin" },
{ "$enemy_seekerqueen", "army_seekers" },
{ "$enemy_fader", "army_charred" }
};
public bool HasActiveRaids => _raids.Count > 0;
public void OnConfigChanged()
{
foreach (RaidInstance value in _raids.Values)
{
Debug.Log((object)"Raid config updated for active raid.");
}
}
public void RegisterBoss(Character boss)
{
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer())
{
return;
}
string name = boss.m_name;
if (_bossRaidMap.TryGetValue(name, out var raidName))
{
RandomEvent val = RandEventSystem.instance.m_events.Find((RandomEvent e) => e.m_name == raidName);
if (val == null)
{
Debug.LogWarning((object)("Raid template not found for " + raidName));
return;
}
RaidInstance raidInstance = new RaidInstance();
raidInstance.Boss = boss;
raidInstance.Event = val.Clone();
raidInstance.Event.m_pos = ((Component)boss).transform.position;
raidInstance.Event.m_time = 0f;
raidInstance.Event.m_duration = 0f;
raidInstance.Event.OnStart();
raidInstance.Active = true;
raidInstance.WaveTimer = BossSummonAllies.WaveInterval.Value - 5f;
_raids.Add(boss, raidInstance);
Debug.Log((object)"Raid created for boss instance.");
}
}
public void Update(float dt)
{
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
if (_raids.Count == 0)
{
return;
}
List<RaidInstance> list = _raids.Values.ToList();
foreach (RaidInstance item in list)
{
if (item.Active)
{
if ((Object)(object)item.Boss == (Object)null || item.Boss.IsDead())
{
StopRaid(item);
continue;
}
bool flag = ArePlayersInRaidArea(item);
item.Event.m_pos = ((Component)item.Boss).transform.position;
item.Event.Update(true, false, flag, dt);
item.WaveTimer += dt;
}
}
}
private void StopRaid(RaidInstance raid)
{
if (raid.Active)
{
raid.Event.OnStop();
_raids.Remove(raid.Boss);
raid.Active = false;
Debug.Log((object)"Raid stopped for boss.");
}
}
public List<SpawnData> GetSpawners()
{
if (_raids.Count == 0)
{
return null;
}
List<SpawnData> list = new List<SpawnData>();
foreach (RaidInstance value2 in _raids.Values)
{
if (value2.Active && value2.Event != null)
{
float value = BossSummonAllies.WaveInterval.Value;
int num = CountPlayersInRaidArea(value2);
float num2 = 1f - 0.05f * (float)num;
num2 = Mathf.Clamp(num2, 0.5f, 1f);
float num3 = value * num2;
if (value2.WaveTimer >= num3)
{
MessageHud.instance.ShowMessage((MessageType)2, value2.Boss.m_name + " summons their allies!", 0, (Sprite)null, false);
list.AddRange(value2.Event.m_spawn);
value2.WaveTimer = 0f;
}
}
}
return (list.Count > 0) ? list : null;
}
private int CountPlayersInRaidArea(RaidInstance raid)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
int num = 0;
foreach (Player allPlayer in Player.GetAllPlayers())
{
float num2 = Vector3.Distance(((Component)allPlayer).transform.position, raid.Event.m_pos);
if (num2 < raid.Event.m_eventRange)
{
num++;
}
}
return num;
}
private bool ArePlayersInRaidArea(RaidInstance raid)
{
return CountPlayersInRaidArea(raid) > 0;
}
}