diff --git a/S1API.Tests/Entities/NPCPanicApiCompatibilityTests.cs b/S1API.Tests/Entities/NPCPanicApiCompatibilityTests.cs
new file mode 100644
index 00000000..ec0592a5
--- /dev/null
+++ b/S1API.Tests/Entities/NPCPanicApiCompatibilityTests.cs
@@ -0,0 +1,43 @@
+#if IL2CPPMELON
+using NativeNpc = Il2CppScheduleOne.NPCs.NPC;
+#elif MONOMELON
+using NativeNpc = ScheduleOne.NPCs.NPC;
+#endif
+
+using System.Reflection;
+using S1API.Entities;
+
+namespace S1API.Tests.Entities;
+
+public sealed class NPCPanicApiCompatibilityTests
+{
+ [Fact]
+ public void PanicRetainsItsParameterlessManagedSurface()
+ {
+ MethodInfo? method = typeof(NPC).GetMethod(
+ nameof(NPC.Panic),
+ BindingFlags.Public | BindingFlags.Instance,
+ binder: null,
+ types: Type.EmptyTypes,
+ modifiers: null);
+
+ Assert.NotNull(method);
+ Assert.Equal(typeof(void), method!.ReturnType);
+ Assert.Empty(method.GetParameters());
+ }
+
+ [Fact]
+ public void NativePanicRpcRemainsParameterless()
+ {
+ MethodInfo? method = typeof(NativeNpc).GetMethod(
+ "SetPanicked_Server",
+ BindingFlags.Public | BindingFlags.Instance,
+ binder: null,
+ types: Type.EmptyTypes,
+ modifiers: null);
+
+ Assert.NotNull(method);
+ Assert.Equal(typeof(void), method!.ReturnType);
+ Assert.Empty(method.GetParameters());
+ }
+}
diff --git a/S1API/Entities/NPC.cs b/S1API/Entities/NPC.cs
index 256bfbfb..20e4eb52 100644
--- a/S1API/Entities/NPC.cs
+++ b/S1API/Entities/NPC.cs
@@ -2624,19 +2624,6 @@ private void EnsureMessageConversationInstance(ConversationCategoryList categori
}
}
- private static bool SafeIsServer()
- {
- try
- {
- var nm = InstanceFinder.NetworkManager;
- return nm != null && nm.IsServer;
- }
- catch
- {
- return false;
- }
- }
-
private static object? GetGameMember(object? target, string memberName)
{
return target == null
@@ -2907,19 +2894,10 @@ public void LerpScale(float scale, float lerpTime) =>
S1NPC.SetScale(scale, lerpTime);
///
- /// Causes the NPC to become panicked.
- /// Currently host/server-only: non-host clients hit the SafeIsServer guard below and this becomes a silent no-op,
- /// which is inconsistent with other server-RPC-style wrappers in the API and with the runtime docs.
+ /// Requests that the NPC become panicked.
///
- public void Panic()
- {
- // TODO: Revisit this guard. Unlike wrappers such as Cartel.SetStatus and CombatBehaviour.SetAndAttackTarget,
- // Panic() can no longer be invoked meaningfully from multiplayer clients because non-host callers return here.
- if (!SafeIsServer())
- return;
-
+ public void Panic() =>
S1NPC.SetPanicked_Server();
- }
///
/// Causes the NPC to stop panicking, if they are currently.