Commit initial BossHealth, DamageNumbers, Horde, ThirdPerson mods

This commit is contained in:
Andrej Stojkovikj committed 2026-10-17 23:55:15 +02:00
1 parent 7bd44d1d99
commit 9c123865bc
176 files changed
+10367

No files matched your search

+16
View File
@@ -0,0 +1,16 @@
# Sample BepInEx plugin
Minimal BepInEx **6 IL2CPP** plugin that logs `Skopje.Modding.ModAPI` events and shows a commented ScriptableObject override pattern.
Full guide: [`Docs/Modding.md`](../../Docs/Modding.md).
## Setup
1. Install BepInEx 6 IL2CPP for the game build.
2. Generate or copy Il2CppInterop assemblies from a run of that build (BepInEx `interop` / unhollowed output — folder names vary by pack).
3. Edit [`SamplePlugin.csproj`](SamplePlugin.csproj):
- Set `GameInteropDir` to that assemblies folder (must contain `SkopjeAssembly.dll` and BepInEx / Il2Cpp references as needed).
4. `dotnet build -c Release`
5. Copy `bin/Release/net6.0/Skopje.SamplePlugin.dll` to `BepInEx/plugins/`.
Gameplay mods that change stats must be installed on the dedicated server and every client. Shared JSON/CFG override files belong next to the DLL under `plugins/`, not in `BepInEx/config/`.
+67
View File
@@ -0,0 +1,67 @@
using System;
using BepInEx;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Skopje.Modding;
namespace Skopje.SamplePlugin
{
[BepInPlugin(PluginGuid, PluginName, PluginVersion)]
public class SamplePlugin : BasePlugin
{
public const string PluginGuid = "com.skopje.sampleplugin";
public const string PluginName = "Skopje Sample Plugin";
public const string PluginVersion = "1.0.0";
static ManualLogSource LogSource;
public override void Load()
{
LogSource = Log;
LogSource.LogInfo($"{PluginName} {PluginVersion} loaded. Subscribe to ModAPI from Load().");
ModAPI.OnServerStarted += () => LogSource.LogInfo("[ModAPI] OnServerStarted");
ModAPI.OnServerStopped += () => LogSource.LogInfo("[ModAPI] OnServerStopped");
ModAPI.OnClientStarted += () => LogSource.LogInfo("[ModAPI] OnClientStarted");
ModAPI.OnClientStopped += () => LogSource.LogInfo("[ModAPI] OnClientStopped");
ModAPI.OnPlayerStartedServer += player =>
LogSource.LogInfo($"[ModAPI] OnPlayerStartedServer idx={player?.PlayerIdx}");
ModAPI.OnPlayerStoppedServer += player =>
LogSource.LogInfo($"[ModAPI] OnPlayerStoppedServer idx={player?.PlayerIdx}");
ModAPI.OnPlayerStartedClient += player =>
LogSource.LogInfo($"[ModAPI] OnPlayerStartedClient idx={player?.PlayerIdx}");
ModAPI.OnPlayerStoppedClient += player =>
LogSource.LogInfo($"[ModAPI] OnPlayerStoppedClient idx={player?.PlayerIdx}");
ModAPI.OnGameModeStartedServer += OnGameModeStartedServer;
ModAPI.OnGameModeStartedClient += gm =>
LogSource.LogInfo($"[ModAPI] OnGameModeStartedClient scene={gm?.ActiveSceneName}");
ModAPI.OnGameStatusChanged += status =>
LogSource.LogInfo($"[ModAPI] OnGameStatusChanged {status}");
ModAPI.OnGameOver += () => LogSource.LogInfo("[ModAPI] OnGameOver");
ModAPI.OnNewDay += () => LogSource.LogInfo("[ModAPI] OnNewDay");
ModAPI.OnDay += () => LogSource.LogInfo("[ModAPI] OnDay");
ModAPI.OnNight += () => LogSource.LogInfo("[ModAPI] OnNight");
ModAPI.OnModCheckFailed += message =>
LogSource.LogError($"[ModAPI] OnModCheckFailed\n{message}");
}
static void OnGameModeStartedServer(SkopjeGameMode gameMode)
{
LogSource.LogInfo($"[ModAPI] OnGameModeStartedServer scene={gameMode?.ActiveSceneName}");
// Example: mutate an existing baked ScriptableObject after the GUID DB is ready.
// Replace YOUR_ITEM_GUID with a real Guid from the game’s ScriptableObject assets.
// Gameplay overrides must run on the dedicated server and every client.
//
// const int YourItemGuid = 0;
// if (ModAPI.TryGetGuidObject<ItemData>(YourItemGuid, out ItemData item))
// {
// item.ItemStackSize = 99;
// LogSource.LogInfo($"Overrode stack size for {item.name}");
// }
}
}
}
+37
View File
@@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>disable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AssemblyName>Skopje.SamplePlugin</AssemblyName>
<RootNamespace>Skopje.SamplePlugin</RootNamespace>
<AppendTargetFrameworkToOutputPath>true</AppendTargetFrameworkToOutputPath>
<!-- Point this at the game's BepInEx interop / unhollowed assembly folder after a run. -->
<GameInteropDir Condition="'$(GameInteropDir)' == ''">$(MSBuildThisFileDirectory)..\..\GameInterop</GameInteropDir>
</PropertyGroup>
<ItemGroup>
<Reference Include="BepInEx.Core">
<HintPath>$(GameInteropDir)\BepInEx.Core.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="BepInEx.Unity.IL2CPP">
<HintPath>$(GameInteropDir)\BepInEx.Unity.IL2CPP.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Il2CppInterop.Runtime">
<HintPath>$(GameInteropDir)\Il2CppInterop.Runtime.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="SkopjeAssembly">
<HintPath>$(GameInteropDir)\SkopjeAssembly.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>$(GameInteropDir)\UnityEngine.CoreModule.dll</HintPath>
<Private>false</Private>
</Reference>
</ItemGroup>
</Project>