Skip to content
This repository was archived by the owner on Jan 7, 2025. It is now read-only.

Commit a9b73aa

Browse files
committed
OwO
1 parent a045125 commit a9b73aa

File tree

9 files changed

+391
-0
lines changed

9 files changed

+391
-0
lines changed

TestingDummies.sln

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.33328.57
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestingDummies", "TestingDummies\TestingDummies.csproj", "{5BE42AB1-43D0-44B7-A2E8-6112ACA0E8B8}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{5BE42AB1-43D0-44B7-A2E8-6112ACA0E8B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{5BE42AB1-43D0-44B7-A2E8-6112ACA0E8B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{5BE42AB1-43D0-44B7-A2E8-6112ACA0E8B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{5BE42AB1-43D0-44B7-A2E8-6112ACA0E8B8}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {9D773D8A-4966-4FDC-9A74-2859F29DBEFA}
24+
EndGlobalSection
25+
EndGlobal
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using CommandSystem;
2+
using Exiled.API.Features;
3+
using Mirror;
4+
using System;
5+
6+
namespace TestingDummies.Commands
7+
{
8+
[CommandHandler(typeof(RemoteAdminCommandHandler))]
9+
public class RemoveDummy : ICommand
10+
{
11+
public string Command => "RemoveDevDummy";
12+
13+
public string[] Aliases => new string[] { "removedummy", "removedevdummy", "removedev" };
14+
15+
public string Description => "Removes a spawned dev dummy";
16+
17+
public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out string response)
18+
{
19+
if (arguments.Count > 1 || arguments.Count < 1)
20+
{
21+
response = "Insufficient arguments. Usage: removedummy [dummyID]";
22+
return false;
23+
}
24+
string dummyID = arguments.At(0);
25+
26+
if(Player.Get(dummyID) == null)
27+
{
28+
response = $"The player ID, '{dummyID}', dosent exist!";
29+
return false;
30+
}
31+
if(Plugin.Instance.DumRef.Contains(Player.Get(dummyID).ReferenceHub))
32+
{
33+
Player.Dictionary.Remove(Plugin.Instance.spawning.PlayerPrefabs[Player.Get(dummyID)]);
34+
Plugin.Instance.DumRef.Remove(Player.Get(dummyID).ReferenceHub);
35+
NetworkServer.DestroyPlayerForConnection(Plugin.Instance.spawning.PlayerConnIDs[Player.Get(dummyID)]);
36+
NetworkServer.Destroy(Player.Get(dummyID).GameObject);
37+
response = $"Removed {Player.Get(dummyID).Nickname}!";
38+
return true;
39+
}
40+
else
41+
{
42+
response = $"ID : '{Player.Get(dummyID).Id}', Nickname : '{Player.Get(dummyID).Nickname}' is not a dummy or you entered a incorrect ID!";
43+
return false;
44+
}
45+
}
46+
47+
}
48+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using CommandSystem;
2+
using Exiled.API.Features;
3+
using Exiled.Permissions.Extensions;
4+
using PlayerRoles;
5+
using System;
6+
7+
8+
namespace TestingDummies.Commands
9+
{
10+
[CommandHandler(typeof(RemoteAdminCommandHandler))]
11+
public class SpawnDummy : ICommand
12+
{
13+
public string Command => "SpawnDevDummy";
14+
15+
public string[] Aliases => new string[] { "spawndummy", "spawndevdummy", "spawndev" };
16+
17+
public string Description => "Spawns a dummy for development or testing purposes, it has 0 logic";
18+
19+
public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out string response)
20+
{
21+
if (arguments.Count < 3)
22+
{
23+
response = "Insufficient arguments. Usage: spawndummy [name] [role] [playerID]";
24+
return false;
25+
}
26+
string name = arguments.At(0);
27+
string roleString = arguments.At(1);
28+
string playerID = arguments.At(2);
29+
if (!Enum.TryParse(roleString, out RoleTypeId role))
30+
{
31+
response = $"Invalid role: {roleString}";
32+
return false;
33+
}
34+
if (Player.Get(playerID) == null)
35+
{
36+
response = $"Invalid player: {playerID}";
37+
return false;
38+
}
39+
MEC.MECExtensionMethods1.RunCoroutine(Plugin.Instance.spawning.SpawnDum(name, role, Player.Get(playerID)));
40+
response = $"Spawned dummy with name '{name}', role '{role}', for player '{Player.Get(playerID).Nickname}'";
41+
return true;
42+
}
43+
44+
}
45+
}

TestingDummies/Config.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using Exiled.API.Interfaces;
2+
using System.ComponentModel;
3+
4+
namespace TestingDummies
5+
{
6+
public class Config : IConfig
7+
{
8+
public bool IsEnabled { get; set; } = true;
9+
public bool Debug { get; set; } = false;
10+
11+
12+
[Description("Gives and shows a badge on the AI")]
13+
public bool NPCBadgeEnabled { get; set; } = true;
14+
15+
[Description("If NPCBadge is enabled, sets the color")]
16+
public string NPCBadgeColor { get; set; } = "aqua";
17+
18+
[Description("If NPCBadge is enabled, sets the name")]
19+
public string NPCBadgeName { get; set; } = "NPC";
20+
}
21+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using HarmonyLib;
2+
using NorthwoodLib.Pools;
3+
using PlayerRoles.FirstPersonControl;
4+
using System.Collections.Generic;
5+
using System.Reflection.Emit;
6+
7+
namespace TestingDummies.Patches
8+
{
9+
//Thank you to the SCP-575 Plugin that I st- borrowed this code from :3
10+
[HarmonyPatch(typeof(FpcMouseLook), nameof(FpcMouseLook.UpdateRotation))]
11+
public class AIRotation
12+
{
13+
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
14+
{
15+
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Shared.Rent(instructions);
16+
17+
Label skip = generator.DefineLabel();
18+
19+
newInstructions[newInstructions.Count - 1].labels.Add(skip);
20+
21+
newInstructions.InsertRange(0, new List<CodeInstruction>()
22+
{
23+
new(OpCodes.Ldarg_0),
24+
new(OpCodes.Ldfld, AccessTools.Field(typeof(FpcMouseLook), nameof(FpcMouseLook._hub))),
25+
new(OpCodes.Call, AccessTools.Method(typeof(Plugin), nameof(Plugin.IsAI))),
26+
new(OpCodes.Brtrue_S, skip)
27+
});
28+
29+
foreach (CodeInstruction instruction in newInstructions)
30+
yield return instruction;
31+
32+
ListPool<CodeInstruction>.Shared.Return(newInstructions);
33+
}
34+
}
35+
}

TestingDummies/Plugin.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using Exiled.API.Enums;
2+
using Exiled.API.Features;
3+
using System;
4+
using System.Collections.Generic;
5+
using TestingDummies.SpawningHandler;
6+
7+
namespace TestingDummies
8+
{
9+
public class Plugin : Plugin<Config>
10+
{
11+
public static Plugin Instance;
12+
public List<ReferenceHub> DumRef = new List<ReferenceHub>();
13+
public Spawn spawning;
14+
public override string Name => "Dev Dummies";
15+
public override string Prefix => "Dev Dum";
16+
public override string Author => "NotIntense";
17+
public override PluginPriority Priority => PluginPriority.Medium;
18+
public override Version Version => new(2, 0, 2);
19+
public override Version RequiredExiledVersion => new(7, 0, 0);
20+
21+
public override void OnEnabled()
22+
{
23+
Instance = this;
24+
spawning = new Spawn();
25+
base.OnEnabled();
26+
}
27+
28+
public override void OnDisabled()
29+
{
30+
Instance = null;
31+
spawning = null;
32+
base.OnDisabled();
33+
}
34+
35+
public static bool IsAI(ReferenceHub hub)
36+
{
37+
bool isDummy = Instance.DumRef.Contains(hub);
38+
return isDummy;
39+
}
40+
}
41+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
5+
// General Information about an assembly is controlled through the following
6+
// set of attributes. Change these attribute values to modify the information
7+
// associated with an assembly.
8+
[assembly: AssemblyTitle("TestingDummies")]
9+
[assembly: AssemblyDescription("")]
10+
[assembly: AssemblyConfiguration("")]
11+
[assembly: AssemblyCompany("")]
12+
[assembly: AssemblyProduct("TestingDummies")]
13+
[assembly: AssemblyCopyright("Copyright © 2023")]
14+
[assembly: AssemblyTrademark("")]
15+
[assembly: AssemblyCulture("")]
16+
17+
// Setting ComVisible to false makes the types in this assembly not visible
18+
// to COM components. If you need to access a type in this assembly from
19+
// COM, set the ComVisible attribute to true on that type.
20+
[assembly: ComVisible(false)]
21+
22+
// The following GUID is for the ID of the typelib if this project is exposed to COM
23+
[assembly: Guid("5be42ab1-43d0-44b7-a2e8-6112aca0e8b8")]
24+
25+
// Version information for an assembly consists of the following four values:
26+
//
27+
// Major Version
28+
// Minor Version
29+
// Build Number
30+
// Revision
31+
//
32+
// You can specify all the values or you can default the Build and Revision Numbers
33+
// by using the '*' as shown below:
34+
// [assembly: AssemblyVersion("1.0.*")]
35+
[assembly: AssemblyVersion("1.0.0.0")]
36+
[assembly: AssemblyFileVersion("1.0.0.0")]
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using CedMod.Addons.Audio;
2+
using Exiled.API.Features;
3+
using Mirror;
4+
using PlayerRoles;
5+
using System;
6+
using System.Collections.Generic;
7+
using UnityEngine;
8+
using MEC;
9+
using PlayerRoles.FirstPersonControl;
10+
11+
namespace TestingDummies.SpawningHandler
12+
{
13+
public class Spawn : MonoBehaviour
14+
{
15+
readonly int IDs = 1000;
16+
public Dictionary<Player, GameObject> PlayerPrefabs = new();
17+
public Dictionary<Player, FakeConnection> PlayerConnIDs = new();
18+
public IEnumerator<float> SpawnDum(string Name, RoleTypeId Role, Player targert)
19+
{
20+
GameObject newPlayer = Instantiate(NetworkManager.singleton.playerPrefab);
21+
Player NewPlayer = new(newPlayer);
22+
PlayerPrefabs.Add(NewPlayer, newPlayer);
23+
var fakeConnection = new FakeConnection(IDs + Plugin.Instance.DumRef.Count);
24+
ReferenceHub hubPlayer = newPlayer.GetComponent<ReferenceHub>();
25+
Plugin.Instance.DumRef.Add(hubPlayer);
26+
NetworkServer.AddPlayerForConnection(fakeConnection, newPlayer);
27+
PlayerConnIDs.Add(NewPlayer, fakeConnection);
28+
try
29+
{
30+
hubPlayer.characterClassManager.UserId = $"DevDummy@server";
31+
}
32+
catch (Exception e)
33+
{
34+
Log.Debug(e);
35+
}
36+
hubPlayer.enabled = true;
37+
hubPlayer.nicknameSync.Network_myNickSync = $"{Name}-{Plugin.Instance.DumRef.Count}";
38+
Player.Dictionary.Add(newPlayer, NewPlayer);
39+
if (Plugin.Instance.Config.NPCBadgeEnabled)
40+
{
41+
NewPlayer.RankName = Plugin.Instance.Config.NPCBadgeName;
42+
NewPlayer.RankColor = Plugin.Instance.Config.NPCBadgeColor;
43+
}
44+
hubPlayer.characterClassManager.GodMode = false;
45+
NewPlayer.RemoteAdminPermissions = PlayerPermissions.AFKImmunity;
46+
yield return Timing.WaitForSeconds(0.3f);
47+
NewPlayer.Role.Set(Role, Exiled.API.Enums.SpawnReason.ForceClass);
48+
NewPlayer.Position = targert.Position;
49+
Quaternion quat = Quaternion.LookRotation(targert.Rotation, Vector3.up);
50+
var mouseLookInsameroom = ((IFpcRole)NewPlayer.ReferenceHub.roleManager.CurrentRole).FpcModule.MouseLook;
51+
mouseLookInsameroom.CurrentHorizontal = Quaternion.Slerp(Quaternion.Euler(0f, mouseLookInsameroom.CurrentHorizontal, 0f), quat, Time.deltaTime).eulerAngles.y;
52+
mouseLookInsameroom.CurrentVertical = 0;
53+
54+
yield break;
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)