├── AMERT.png ├── Advanced MER tools ├── DONT TOUCH │ └── TextEditor.cs ├── Convertor.cs ├── Rotator.cs ├── MirrorObject.cs ├── GroovyNoise.cs ├── AutoScaler.cs ├── Arrange.cs ├── Text.cs ├── InteractableObject.cs ├── CustomCollider.cs ├── InteractablePickup.cs ├── InteractableTeleporter.cs ├── HealthObject.cs ├── FunctionCollections.cs ├── CustomRGBA.cs ├── Serializables.cs ├── Modules.cs ├── FunctionExecutor.cs └── ValueCollections.cs ├── AdvancedMERTools (plugin) ├── AMEREventArgs.cs ├── AdvancedMERTools.sln ├── GroovyNoise.cs ├── Config.cs ├── CustomDoor.cs ├── Serializables.cs ├── Patches.cs ├── InteractableTeleporter.cs ├── AdvancedMERTools.csproj ├── InteractablePickup.cs ├── InteractableObject.cs ├── CustomCollider.cs ├── DummyDoor.cs ├── FunctionExecutor.cs └── HealthObject.cs └── README.md /AMERT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MujisongPlay/AdvancedMERtools/HEAD/AMERT.png -------------------------------------------------------------------------------- /Advanced MER tools/DONT TOUCH/TextEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | [CustomEditor(typeof(Text))] 5 | public class TextEditor : Editor 6 | { 7 | public override void OnInspectorGUI() 8 | { 9 | DrawDefaultInspector(); 10 | 11 | Text textScript = (Text)target; 12 | if (GUILayout.Button("Add Letters From Folder")) 13 | { 14 | textScript.AddLettersFromFolder(); 15 | } 16 | 17 | if (GUILayout.Button("Add Numbers From Folder")) 18 | { 19 | textScript.AddNumbersFromFolder(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/AMEREventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Exiled.API.Features; 7 | using Exiled.API.Enums; 8 | 9 | namespace AdvancedMERTools 10 | { 11 | public class HealthObjectDeadEventArgs : EventArgs, Exiled.Events.EventArgs.Interfaces.IExiledEvent 12 | { 13 | public HealthObjectDeadEventArgs(HODTO healthObject, Player Attacker) 14 | { 15 | HealthObject = healthObject; 16 | Killer = Attacker; 17 | } 18 | 19 | public HODTO HealthObject; 20 | public Player Killer; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/AdvancedMERTools.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.33027.164 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedMERTools", "AdvancedMERTools.csproj", "{93B7E3DC-BD0F-4777-8763-9482B996AC4A}" 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 | {93B7E3DC-BD0F-4777-8763-9482B996AC4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {93B7E3DC-BD0F-4777-8763-9482B996AC4A}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {93B7E3DC-BD0F-4777-8763-9482B996AC4A}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {93B7E3DC-BD0F-4777-8763-9482B996AC4A}.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 = {B2BF8DC2-9104-4EE9-A163-45C3E66F5514} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Advanced MER tools/Convertor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | using UnityEditorInternal; 6 | 7 | public class Convertor : MonoBehaviour 8 | { 9 | private void OnDrawGizmos() 10 | { 11 | if (Activate) 12 | { 13 | Activate = false; 14 | List tags = new List { }; 15 | tags.AddRange(InternalEditorUtility.tags); 16 | foreach (MeshFilter mesh in GetComponentsInChildren()) 17 | { 18 | if (!mesh.TryGetComponent(out _) && mesh.CompareTag("Untagged") && tags.Contains(mesh.sharedMesh.name)) 19 | { 20 | mesh.gameObject.tag = mesh.sharedMesh.name; 21 | MeshRenderer renderer = mesh.GetComponent(); 22 | Color color = renderer.sharedMaterial.color; 23 | Color _color = new Color(color.r, color.g, color.b, color.a); 24 | PrimitiveComponent primitive = mesh.gameObject.AddComponent(); 25 | primitive.Collidable = true; 26 | primitive.Color = _color; 27 | Material material = new Material((Material)Resources.Load(_color.a >= 1f ? "Materials/Regular" : "Materials/Transparent")); 28 | renderer.sharedMaterial = material; 29 | renderer.sharedMaterial.color = _color; 30 | } 31 | } 32 | } 33 | } 34 | 35 | public bool Activate = false; 36 | } 37 | -------------------------------------------------------------------------------- /Advanced MER tools/Rotator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class Rotator : MonoBehaviour 6 | { 7 | private void OnDrawGizmos() 8 | { 9 | if (Count <= 1 || Angle == Vector3.zero) return; 10 | rotators.AddRange(this.GetComponentsInChildren()); 11 | List Registed = new List { }; 12 | for (int i = 0; i < this.transform.childCount; i++) 13 | { 14 | GameObject game = this.transform.GetChild(i).gameObject; 15 | if (rotators.TrueForAll(x => !x.Duplicated.Contains(game))) 16 | { 17 | Registed.Add(game); 18 | } 19 | } 20 | Duplicated.ForEach(x => DestroyImmediate(x)); 21 | Duplicated.Clear(); 22 | Vector3 offset = Angle / Count; 23 | for (int i = 1; i < Count; i++) 24 | { 25 | GameObject copy = GameObject.Instantiate(this.gameObject); 26 | DestroyImmediate(copy.GetComponent()); 27 | if (this.transform.root != this.transform) copy.transform.parent = this.transform.parent; 28 | copy.transform.localPosition = this.transform.localPosition; 29 | copy.transform.localEulerAngles = this.transform.localEulerAngles + offset; 30 | copy.transform.localScale = this.transform.localScale; 31 | offset += Angle / Count; 32 | Duplicated.Add(copy); 33 | } 34 | } 35 | 36 | public Vector3 Angle; 37 | public int Count; 38 | 39 | List Duplicated = new List { }; 40 | List rotators = new List { }; 41 | } 42 | -------------------------------------------------------------------------------- /Advanced MER tools/MirrorObject.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | using System.ComponentModel; 6 | 7 | public class MirrorObject : MonoBehaviour 8 | { 9 | private void OnDrawGizmos() 10 | { 11 | if (ApplyMirror) 12 | { 13 | Duplicated.Clear(); 14 | x = false; 15 | y = false; 16 | z = false; 17 | ApplyMirror = false; 18 | } 19 | if (!x & !y & !z) return; 20 | mirrors.AddRange(this.GetComponentsInChildren()); 21 | List Registed = new List { }; 22 | for (int i = 0; i < this.transform.childCount; i++) 23 | { 24 | GameObject game = this.transform.GetChild(i).gameObject; 25 | if (mirrors.TrueForAll(x => !x.Duplicated.Contains(game))) 26 | { 27 | Registed.Add(game); 28 | } 29 | } 30 | Vector3 vector = Vector3.one; 31 | Duplicated.ForEach(x => DestroyImmediate(x)); 32 | Duplicated.Clear(); 33 | if (x) vector.x = -1; 34 | if (y) vector.y = -1; 35 | if (z) vector.z = -1; 36 | foreach (GameObject game in Registed) 37 | { 38 | GameObject copy = GameObject.Instantiate(game, this.transform); 39 | Vector3 v = copy.transform.localPosition; 40 | copy.transform.localPosition = new Vector3(v.x * vector.x, v.y * vector.y, v.z * vector.z); 41 | v = copy.transform.localEulerAngles; 42 | copy.transform.localEulerAngles = new Vector3(v.x * vector.z * vector.y, v.y * vector.z * vector.x, v.z * vector.x * vector.y); 43 | copy.transform.localScale = game.transform.localScale; 44 | Duplicated.Add(copy); 45 | } 46 | } 47 | 48 | public bool x; 49 | public bool y; 50 | public bool z; 51 | public bool ApplyMirror; 52 | 53 | List Duplicated = new List { }; 54 | List mirrors = new List { }; 55 | } 56 | -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/GroovyNoise.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnityEngine; 7 | using Exiled.API.Features; 8 | using Exiled.API.Features.Pickups; 9 | using Exiled.API.Features.Items; 10 | using MapEditorReborn.API.Features.Objects; 11 | using MapEditorReborn.API.Features; 12 | using Exiled.CustomItems; 13 | using CommandSystem; 14 | using Utf8Json.Formatters; 15 | using RemoteAdmin; 16 | using Exiled.CustomItems.API.Features; 17 | 18 | namespace AdvancedMERTools 19 | { 20 | public class GroovyNoise : AMERTInteractable 21 | { 22 | protected virtual void Start() 23 | { 24 | Base = base.Base as GNDTO; 25 | AdvancedMERTools.Singleton.groovyNoises.Add(this); 26 | //MEC.Timing.CallDelayed(0.1f, () => 27 | //{ 28 | // if (AdvancedMERTools.Singleton.groovyNoises.All(x => x.Base.GMDTOs.Select(y => y.codes).All(y => !y.Contains(Base.Code)))) 29 | // Active = true; 30 | //}); 31 | } 32 | 33 | protected virtual void Update() 34 | { 35 | if (Active) 36 | { 37 | //ServerConsole.AddLog("!!!"); 38 | GMDTO.Execute(Base.Settings, new ModuleGeneralArguments { schematic = OSchematic, transform = transform }); 39 | } 40 | Active = false; 41 | } 42 | 43 | public new GNDTO Base; 44 | } 45 | 46 | public class FGroovyNoise : GroovyNoise 47 | { 48 | protected override void Start() 49 | { 50 | Base = ((AMERTInteractable)this).Base as FGNDTO; 51 | AdvancedMERTools.Singleton.groovyNoises.Add(this); 52 | //MEC.Timing.CallDelayed(0.1f, () => 53 | //{ 54 | // if (AdvancedMERTools.Singleton.groovyNoises.All(x => x.Base.GMDTOs.Select(y => y.codes).All(y => !y.Contains(Base.Code)))) 55 | // Active = true; 56 | //}); 57 | } 58 | 59 | protected override void Update() 60 | { 61 | if (Active) 62 | { 63 | //ServerConsole.AddLog("!!!"); 64 | FGMDTO.Execute(Base.Settings, new FunctionArgument(this)); 65 | } 66 | Active = false; 67 | } 68 | 69 | public new FGNDTO Base; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # How to Install AdvancedMERtools (AMERT) 2 | 3 | ![image](https://github.com/Maciupek/AdvancedMERtools/blob/main/AMERT.png?raw=true) 4 | 5 | ## Installation Instructions 6 | 1. Download the necessary files from the specified folder above. 7 | 2. Drag and drop the files into the 'Project' tab in the Unity Editor. Preferably to `DONT TOUCH/Scripts` 8 | 3. In the release tab, you will find a plugin that facilitates the execution of functions and modeling for LCZ, HCZ, and EZ doors. 9 | 10 | Additionally, download the AudioPlayerApi from the following link: 11 | [AudioPlayerApi](https://github.com/Killers0992/AudioPlayerApi) 12 | Then, place the `AMERTAudioModule.dll` file in the `Roaming\SCPSL\PluginAPI\Global\Dependencies` directory. 13 | 14 | ## AdvancedMERtools Description 15 | AdvancedMERtools offers advanced tools for the SCP: SL plugin called MapEditorReborn (MER). Please download the tools from the folder mentioned above and integrate them into your project. We plan to add more features in the future. 16 | 17 | ### Features 18 | - **AutoScaler**: Scales grouped objects up or down automatically. 19 | - **Rotator**: Rotates objects akin to the behavior of a magnetic field or sphere. 20 | - **Mirror**: Creates a mirrored copy of objects. 21 | - **Arrange**: Duplicates and arranges objects. 22 | - **Health Object**: Adds a hitbox to your objects. **Requires additional plugin.** 23 | - **Interactable Pickup**: Functions similarly to the Health Object. **Requires additional plugin.** 24 | - **Custom Collider**: Adds custom collision properties to objects. 25 | - **Interactable Teleporters**: 26 | - **Text**: Adds text to set empty object. 27 | - **Custom RGBA**: Extends the minimum and maximum RGBA values beyond 0-255 to enhance object glow. 28 | - **Converter**: Converts Unity's primitives into MER's components if placed accidentally. Activating it will also automatically color your primitives based on the set material. 29 | 30 | ## Tutorials 31 | - Arrange Tutorial: [Watch Tutorial](https://youtu.be/adXuM0UINhE) 32 | - Text Tutorial: [Watch Tutorial](https://youtu.be/UmkEbiVhDTE) 33 | 34 | ![image](https://github.com/MujisongPlay/AdvancedMERtools/assets/96275409/3249ec64-4bfc-4071-98fb-51d1052cc8e6) 35 | 36 | ## DummyDoorSpawner 37 | The DummyDoorSpawner creates visible dummy doors to counteract the visibility issues caused by the culling system. 38 | 39 | - Showcase Video: [Watch Showcase](https://youtu.be/TLkXputvKFc) 40 | - Straightforward Installation Tutorial: [Watch Tutorial](https://youtu.be/-_IvE2kCHvU) 41 | -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/Config.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Exiled.API.Features; 9 | using Exiled.Loader; 10 | using Exiled.API.Interfaces; 11 | using System.IO; 12 | 13 | namespace AdvancedMERTools 14 | { 15 | public class Config : IConfig 16 | { 17 | public bool IsEnabled { get; set; } = true; 18 | public bool Debug { get; set; } = false; 19 | //public bool ReplacementMode { get; set; } = true; 20 | //public List DummyDoorInstallingMaps { get; set; } = new List 21 | //{ 22 | // "ExampleMap" 23 | //}; 24 | //[Description("Below index means the door numbering that do not require dummy door installing. Caution: It's double List. - (Above Map Index) - (Door Index)")] 25 | //public List> BlackListOfDummyDoor { get; set; } = new List> 26 | //{ 27 | // new List 28 | // { 29 | // 101 30 | // }, 31 | // new List 32 | // { 33 | // 15 34 | // } 35 | //}; 36 | public Dictionary> Gates { get; set; } = new Dictionary> 37 | { 38 | { "ExampleMapName", new List { new GateSerializable(), new GateSerializable() } } 39 | }; 40 | [Description("If turned on, it will autowork with every MER's door spawning event.")] 41 | public bool AutoRun { get; set; } = false; 42 | //[Description("Generated, Round, Decont, Warhead")] 43 | //public List AutoRunOnEventList { get; set; } = new List 44 | //{ 45 | // Config.EventList.Generated, 46 | //}; 47 | //[Description("If you load massive schematic, extend delay.")] 48 | //public float AutoRunDelay { get; set; } = 2f; 49 | //[Description("If you build doors with external-plugin not MER, use this option.")] 50 | //public bool AutoRunWithEveryDoor { get; set; } = false; 51 | public bool CustomSpawnPointEnable { get; set; } = true; 52 | //public bool UseExperimentalFeature { get; set; } = false; 53 | public string AudioFolderPath { get; set; } = Path.Combine(Paths.Configs, "Music"); 54 | 55 | [Serializable] 56 | public enum EventList 57 | { 58 | Generated, 59 | Round, 60 | Decont, 61 | Warhead 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Advanced MER tools/GroovyNoise.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnityEngine; 7 | using System.ComponentModel; 8 | using UnityEditor; 9 | using System.IO; 10 | using Newtonsoft.Json; 11 | 12 | public class GroovyNoise : FakeMono 13 | { 14 | public new GNDTO data = new(); 15 | public new FGNDTO ScriptValueData = new(); 16 | public override DTO _data { get => data; } 17 | public override DTO _ScriptValueData { get => ScriptValueData; } 18 | } 19 | 20 | [Serializable] 21 | public class GNDTO : DTO 22 | { 23 | public override void OnValidate() 24 | { 25 | } 26 | 27 | public List Settings; 28 | } 29 | 30 | [Serializable] 31 | public class FGNDTO : DTO 32 | { 33 | public override void OnValidate() 34 | { 35 | Settings.ForEach(x => x.OnValidate()); 36 | } 37 | 38 | public List Settings; 39 | } 40 | 41 | public class GroovyNoiseCompiler : MonoBehaviour 42 | { 43 | private static readonly Config Config = SchematicManager.Config; 44 | 45 | [MenuItem("SchematicManager/Compile Groovy Noise", priority = -11)] 46 | public static void OnCompile() 47 | { 48 | foreach (Schematic schematic in GameObject.FindObjectsOfType()) 49 | { 50 | Compile(schematic); 51 | } 52 | } 53 | 54 | public static void Compile(Schematic schematic) 55 | { 56 | string parentDirectoryPath = Directory.Exists(Config.ExportPath) 57 | ? Config.ExportPath 58 | : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), 59 | "MapEditorReborn_CompiledSchematics"); 60 | string schematicDirectoryPath = Path.Combine(parentDirectoryPath, schematic.gameObject.name); 61 | 62 | if (!Directory.Exists(parentDirectoryPath)) 63 | { 64 | Debug.LogError("Could Not find root object's compiled directory!"); 65 | return; 66 | } 67 | 68 | Directory.CreateDirectory(schematicDirectoryPath); 69 | 70 | File.WriteAllText(Path.Combine(schematicDirectoryPath, $"{schematic.gameObject.name}-GroovyNoises.json"), JsonConvert.SerializeObject(schematic.transform.GetComponentsInChildren().Where(x => !x.UseScriptValue).Select(x => x.data), Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore })); 71 | File.WriteAllText(Path.Combine(schematicDirectoryPath, $"{schematic.gameObject.name}-FGroovyNoises.json"), JsonConvert.SerializeObject(schematic.transform.GetComponentsInChildren().Where(x => x.UseScriptValue).Select(x => x.ScriptValueData), Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, TypeNameHandling = TypeNameHandling.Auto }).Replace("Assembly-CSharp", "AdvancedMERTools")); 72 | Debug.Log("Successfully Imported Groovy Noises!"); 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /Advanced MER tools/AutoScaler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using UnityEngine; 5 | 6 | public class AutoScaler : MonoBehaviour 7 | { 8 | private void OnDrawGizmos() 9 | { 10 | if (!Activate) return; 11 | Activate = false; 12 | pairs.Clear(); 13 | foreach (Transform game in this.transform.GetComponentsInChildren()) 14 | { 15 | Vector3 v1 = game.position; 16 | Vector3 v2 = game.eulerAngles; 17 | Vector3 v3 = game.lossyScale; 18 | pairs.Add(game, new Values(IsEmpty(game.gameObject) && ResetPos ? Vector3.zero : new Vector3(v1.x, v1.y, v1.z), 19 | IsEmpty(game.gameObject) && ResetRot ? Vector3.zero : new Vector3(v2.x, v2.y, v2.z), 20 | IsEmpty(game.gameObject) && ResetScl ? Vector3.one : new Vector3(v3.x, v3.y, v3.z))); 21 | } 22 | List list = new List { }; 23 | list.AddRange(this.transform.GetComponentsInChildren()); 24 | list.ForEach(x => 25 | { 26 | Values values = pairs[x]; 27 | x.position = values.pos; 28 | x.eulerAngles = values.rot; 29 | x.localScale = values.scl; 30 | //x.localScale = operatorDivide(x.lossyScale, values.scl); 31 | }); 32 | //wait(list); 33 | } 34 | 35 | //static async Task wait(List transforms) 36 | //{ 37 | // ForceStop = true; 38 | // await Task.Delay(1000); 39 | // transforms.ForEach(x => 40 | // { 41 | // Values values = pairs[x]; 42 | // x.position = values.pos; 43 | // x.eulerAngles = values.rot; 44 | // //x.localScale = operatorDivide(x.lossyScale, values.scl); 45 | // }); 46 | // ForceStop = false; 47 | //} 48 | 49 | bool IsEmpty(GameObject game) 50 | { 51 | if (game == gameObject || game.GetComponents().Length == 1) 52 | return true; 53 | if (!game.TryGetComponent(out _) && !game.TryGetComponent(out _) && !game.TryGetComponent(out _)) 54 | return true; 55 | return false; 56 | } 57 | 58 | private Vector3 operatorDivide(Vector3 vector, Vector3 vector1) 59 | { 60 | return new Vector3(vector.x / vector1.x, vector.y / vector1.y, vector.z / vector1.z); 61 | } 62 | 63 | //static bool ForceStop = false; 64 | 65 | public bool Activate; 66 | public bool ResetPos; 67 | public bool ResetRot; 68 | public bool ResetScl = true; 69 | 70 | public struct Values 71 | { 72 | public Values(Vector3 v1, Vector3 v2, Vector3 v3) 73 | { 74 | pos = v1; 75 | rot = v2; 76 | scl = v3; 77 | } 78 | 79 | public Vector3 pos; 80 | public Vector3 rot; 81 | public Vector3 scl; 82 | } 83 | 84 | Dictionary pairs = new Dictionary { }; 85 | } 86 | -------------------------------------------------------------------------------- /Advanced MER tools/Arrange.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | public class Arrange : MonoBehaviour 7 | { 8 | private void OnDrawGizmos() 9 | { 10 | if (Count <= 0 /*|| (UseCurve && BezierCurve == null)*/) return; 11 | arranges.AddRange(this.GetComponentsInChildren()); 12 | List Registed = new List { }; 13 | for (int i = 0; i < this.transform.childCount; i++) 14 | { 15 | GameObject game = this.transform.GetChild(i).gameObject; 16 | if (arranges.TrueForAll(x => !x.Duplicated.Contains(game))) 17 | { 18 | Registed.Add(game); 19 | } 20 | } 21 | Duplicated.ForEach(x => DestroyImmediate(x)); 22 | Duplicated.Clear(); 23 | Vector3 pos = Vector3.zero; 24 | Vector3 rot = Vector3.zero; 25 | Vector3 scl = Vector3.one; 26 | float Time = 0; 27 | for (int i = 0; i < Count; i++) 28 | { 29 | if (!UseCurve) 30 | { 31 | pos += ConstantOffset + Vector3.Scale(RelativeOffset, pos == Vector3.zero ? Vector3.one : pos); 32 | rot += ConstantRotation + Vector3.Scale(RelativeRotation, rot); 33 | } 34 | else 35 | { 36 | //Vector3 v1 = BezierCurve.GetPointAt(Time); 37 | //Vector3 v2 = BezierCurve.GetPointAt(Time + (Time > 0 ? -CurveIntegrationAccuracity : CurveIntegrationAccuracity)); 38 | //Quaternion q = Quaternion.LookRotation(v1 - v2, Vector3.up); 39 | //pos = BezierCurve.GetPointAt(Time) + ConstantOffset + q * RelativeOffset; 40 | //rot = q.eulerAngles + ConstantRotation + Vector3.Scale(q.eulerAngles, RelativeRotation); 41 | //Time += 1f / (float)Count; 42 | } 43 | scl += ConstantScale + Vector3.Scale(RelativeScale, scl); 44 | GameObject copy = GameObject.Instantiate(this.gameObject); 45 | DestroyImmediate(copy.GetComponent()); 46 | if (this.transform.root != this.transform) copy.transform.parent = this.transform.parent; 47 | copy.transform.localPosition = this.transform.localPosition + pos; 48 | copy.transform.localRotation = Quaternion.Euler(this.transform.localEulerAngles + rot); 49 | copy.transform.localScale = Vector3.Scale(this.transform.localScale, scl); 50 | Duplicated.Add(copy); 51 | } 52 | } 53 | 54 | public Vector3 RelativeOffset; 55 | public Vector3 ConstantOffset; 56 | public Vector3 RelativeRotation; 57 | public Vector3 ConstantRotation; 58 | public Vector3 RelativeScale; 59 | public Vector3 ConstantScale; 60 | public int Count; 61 | public bool UseCurve; 62 | //public BezierCurve BezierCurve; 63 | public float CurveIntegrationAccuracity = 0.01f; 64 | 65 | List Duplicated = new List { }; 66 | List arranges = new List { }; 67 | } 68 | -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/CustomDoor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using MapEditorReborn.API.Features; 8 | using UnityEngine; 9 | using Exiled.API.Features; 10 | using MapEditorReborn.API.Features.Serializable; 11 | using MapEditorReborn.API.Features.Objects; 12 | using Exiled.API.Features.Doors; 13 | using Exiled.Events.EventArgs.Player; 14 | using System.IO; 15 | using Utf8Json; 16 | using System.Reflection.Emit; 17 | using System.Reflection; 18 | using PlayerRoles.FirstPersonControl; 19 | using PlayerRoles.FirstPersonControl.NetworkMessages; 20 | using Mirror; 21 | using PlayerRoles; 22 | using RelativePositioning; 23 | using Exiled.API.Enums; 24 | 25 | namespace AdvancedMERTools 26 | { 27 | public class CustomDoor : AMERTInteractable 28 | { 29 | void Start() 30 | { 31 | Base = base.Base as CDDTO; 32 | AdvancedMERTools.Singleton.customDoors.Add(this); 33 | animator = EventManager.FindObjectWithPath(transform, Base.animator).GetComponent(); 34 | door = ObjectSpawner.SpawnDoor(new DoorSerializable 35 | { 36 | DoorHealth = Base.DoorHealth, 37 | DoorType = new DoorType[] { DoorType.LightContainmentDoor, DoorType.HeavyContainmentDoor, DoorType.EntranceDoor }[(int)Base.DoorType], 38 | IgnoredDamageSources = (Interactables.Interobjects.DoorUtils.DoorDamageType)(31 ^ (byte)Base.DoorDamageType), 39 | KeycardPermissions = (Interactables.Interobjects.DoorUtils.KeycardPermissions)(int)Base.DoorPermissions, 40 | RoomType = RoomType.Surface, 41 | Position = transform.position + transform.rotation * Base.DoorInstallPos, 42 | Rotation = Quaternion.LookRotation(transform.TransformDirection(Base.DoorInstallRot), Vector3.up).eulerAngles, 43 | Scale = Base.DoorInstallScl 44 | }).Door; 45 | door.Transform.parent = this.transform; 46 | Exiled.Events.Handlers.Player.InteractingDoor += OnInteract; 47 | Exiled.Events.Handlers.Player.DamagingDoor += OnDestroy; 48 | } 49 | 50 | void OnDestroy() 51 | { 52 | AdvancedMERTools.Singleton.customDoors.Remove(this); 53 | } 54 | 55 | void OnInteract(Exiled.Events.EventArgs.Player.InteractingDoorEventArgs ev) 56 | { 57 | if (ev.Door != door || !ev.IsAllowed) 58 | return; 59 | animator.Play(door.IsOpen ? Base.CloseAnimation : Base.OpenAnimation); 60 | } 61 | 62 | void OnDestroy(Exiled.Events.EventArgs.Player.DamagingDoorEventArgs ev) 63 | { 64 | if (ev.Door != door || !ev.IsAllowed) 65 | return; 66 | if (ev.Damage >= (door.Base as Interactables.Interobjects.BreakableDoor).RemainingHealth) 67 | animator.Play(Base.BrokenAnimation); 68 | } 69 | 70 | public void OnLockChange(ushort value) 71 | { 72 | if (value == 0) 73 | animator.Play(Base.UnlockAnimation); 74 | else 75 | animator.Play(Base.LockAnimation); 76 | } 77 | 78 | public Animator animator; 79 | 80 | public Door door; 81 | 82 | public new CDDTO Base; 83 | } 84 | } -------------------------------------------------------------------------------- /Advanced MER tools/Text.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | public class Text : MonoBehaviour 5 | { 6 | [Tooltip("The input string to display.")] 7 | public string input; 8 | 9 | [Tooltip("The distance between each character.")] 10 | public Vector3 distanceBetweenChars; 11 | 12 | [Tooltip("The length of the spacebar.")] 13 | public Vector3 spacebarLength; 14 | 15 | [Tooltip("Insert 26 letters to this. Ensure that the object name matches the character. For example, 'A' should match the GameObject named 'A'.")] 16 | public List chars = new List(); 17 | 18 | private List duplicatedChars = new List(); 19 | 20 | private string previousInput; 21 | private Vector3 previousDistanceBetweenChars; 22 | private Vector3 previousSpacebarLength; 23 | 24 | public void AddLettersFromFolder() 25 | { 26 | #if UNITY_EDITOR 27 | string path = "Assets/Blocks/Letters/European"; 28 | 29 | if (System.IO.Directory.Exists(path)) 30 | { 31 | foreach (string file in System.IO.Directory.GetFiles(path, "*.prefab")) 32 | { 33 | GameObject prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(file); 34 | if (prefab != null && !chars.Contains(prefab)) 35 | { 36 | chars.Add(prefab); 37 | } 38 | } 39 | 40 | Debug.Log("Letters added from Assets/Blocks/Letters/European"); 41 | } 42 | else 43 | { 44 | Debug.LogWarning("Folder Assets/Blocks/Letters/European not found. Please add letters manually to the chars list."); 45 | } 46 | #endif 47 | } 48 | 49 | public void AddNumbersFromFolder() 50 | { 51 | #if UNITY_EDITOR 52 | string path = "Assets/Blocks/Letters/Numbers"; 53 | 54 | if (System.IO.Directory.Exists(path)) 55 | { 56 | foreach (string file in System.IO.Directory.GetFiles(path, "*.prefab")) 57 | { 58 | GameObject prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(file); 59 | if (prefab != null && !chars.Contains(prefab)) 60 | { 61 | chars.Add(prefab); 62 | } 63 | } 64 | 65 | Debug.Log("Numbers added from Assets/Blocks/Letters/Numbers"); 66 | } 67 | else 68 | { 69 | Debug.LogWarning("Folder Assets/Blocks/Letters/Numbers not found. Please add numbers manually to the chars list."); 70 | } 71 | #endif 72 | } 73 | 74 | private void OnDrawGizmos() 75 | { 76 | if (string.IsNullOrEmpty(input) || (input == previousInput && distanceBetweenChars == previousDistanceBetweenChars && spacebarLength == previousSpacebarLength)) 77 | { 78 | return; 79 | } 80 | 81 | foreach (var charObject in duplicatedChars) 82 | { 83 | DestroyImmediate(charObject); 84 | } 85 | duplicatedChars.Clear(); 86 | 87 | Vector3 currentPosition = Vector3.zero; 88 | 89 | foreach (char character in input) 90 | { 91 | GameObject charPrefab = chars.Find(x => x.name.Equals(character.ToString(), System.StringComparison.OrdinalIgnoreCase)); 92 | 93 | if (charPrefab == null) 94 | { 95 | currentPosition += spacebarLength; 96 | continue; 97 | } 98 | 99 | GameObject instantiatedChar = Instantiate(charPrefab, this.transform); 100 | instantiatedChar.transform.localEulerAngles = Vector3.zero; 101 | instantiatedChar.transform.localScale = Vector3.one; 102 | instantiatedChar.transform.localPosition = currentPosition; 103 | 104 | currentPosition += distanceBetweenChars; 105 | duplicatedChars.Add(instantiatedChar); 106 | } 107 | 108 | previousInput = input; 109 | previousDistanceBetweenChars = distanceBetweenChars; 110 | previousSpacebarLength = spacebarLength; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /Advanced MER tools/InteractableObject.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.ComponentModel; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | using System.Linq; 6 | //using NaughtyAttributes; 7 | using System; 8 | using System.IO; 9 | using UnityEditor; 10 | using Newtonsoft.Json; 11 | 12 | public class InteractableObject : FakeMono 13 | { 14 | public new IODTO data = new(); 15 | public new FIODTO ScriptValueData = new(); 16 | public override DTO _data { get => data; } 17 | public override DTO _ScriptValueData { get => ScriptValueData; } 18 | } 19 | 20 | [Serializable] 21 | public class IODTO : DTO 22 | { 23 | public override void OnValidate() 24 | { 25 | AnimationModules.ForEach(x => x.AnimatorAdress = PublicFunctions.FindPath(x.Animator)); 26 | } 27 | 28 | public KeyCode InputKeyCode; 29 | public float InteractionMaxRange; 30 | public IPActionType ActionType; 31 | public List AnimationModules; 32 | public WarheadActionType warheadActionType; 33 | public List MessageModules; 34 | public List dropItems; 35 | public List commandings; 36 | public Scp914Mode Scp914Mode; 37 | public List ExplodeModules; 38 | public List effectGivingModules; 39 | public List AudioModules; 40 | public List GroovieNoiseToCall; 41 | public List FunctionToCall; 42 | } 43 | 44 | [Serializable] 45 | public class FIODTO : DTO 46 | { 47 | public override void OnValidate() 48 | { 49 | InteractionMaxRange.OnValidate(); 50 | Scp914Mode.OnValidate(); 51 | warheadActionType.OnValidate(); 52 | AnimationModules.ForEach(x => { x.parent = this; x.OnValidate(); x.AnimatorAdress = PublicFunctions.FindPath(x.Animator); }); 53 | MessageModules.ForEach(x => x.OnValidate()); 54 | dropItems.ForEach(x => x.OnValidate()); 55 | commandings.ForEach(x => x.OnValidate()); 56 | ExplodeModules.ForEach(x => x.OnValidate()); 57 | effectGivingModules.ForEach(x => x.OnValidate()); 58 | AudioModules.ForEach(x => x.OnValidate()); 59 | GroovieNoiseToCall.ForEach(x => x.OnValidate()); 60 | FunctionToCall.ForEach(x => x.OnValidate()); 61 | } 62 | 63 | public KeyCode InputKeyCode; 64 | public ScriptValue InteractionMaxRange; 65 | public IPActionType ActionType; 66 | public ScriptValue Scp914Mode; 67 | public List AnimationModules; 68 | public ScriptValue warheadActionType; 69 | public List MessageModules; 70 | public List dropItems; 71 | public List commandings; 72 | public List ExplodeModules; 73 | public List effectGivingModules; 74 | public List AudioModules; 75 | public List GroovieNoiseToCall; 76 | public List FunctionToCall; 77 | } 78 | 79 | public class InteractableObjectCompiler 80 | { 81 | private static readonly Config Config = SchematicManager.Config; 82 | 83 | [MenuItem("SchematicManager/Compile Interactable Objects", priority = -11)] 84 | public static void OnCompile() 85 | { 86 | foreach (Schematic schematic in GameObject.FindObjectsOfType()) 87 | { 88 | Compile(schematic); 89 | } 90 | } 91 | 92 | public static void Compile(Schematic schematic) 93 | { 94 | string parentDirectoryPath = Directory.Exists(Config.ExportPath) 95 | ? Config.ExportPath 96 | : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), 97 | "MapEditorReborn_CompiledSchematics"); 98 | string schematicDirectoryPath = Path.Combine(parentDirectoryPath, schematic.gameObject.name); 99 | 100 | if (!Directory.Exists(parentDirectoryPath)) 101 | { 102 | Debug.LogError("Could Not find root object's compiled directory!"); 103 | return; 104 | } 105 | 106 | Directory.CreateDirectory(schematicDirectoryPath); 107 | 108 | File.WriteAllText(Path.Combine(schematicDirectoryPath, $"{schematic.gameObject.name}-Objects.json"), JsonConvert.SerializeObject(schematic.transform.GetComponentsInChildren().Where(x => !x.UseScriptValue).Select(x => x.data), Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore })); 109 | File.WriteAllText(Path.Combine(schematicDirectoryPath, $"{schematic.gameObject.name}-FObjects.json"), JsonConvert.SerializeObject(schematic.transform.GetComponentsInChildren().Where(x => x.UseScriptValue).Select(x => x.ScriptValueData).ToList(), Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, TypeNameHandling = TypeNameHandling.Auto }).Replace("Assembly-CSharp", "AdvancedMERTools")); 110 | Debug.Log("Successfully Imported Interactable Objects."); 111 | } 112 | } -------------------------------------------------------------------------------- /Advanced MER tools/CustomCollider.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Collections; 6 | using System.ComponentModel; 7 | using System.IO; 8 | using UnityEditor; 9 | using UnityEngine; 10 | 11 | public class CustomCollider : FakeMono 12 | { 13 | public new CCDTO data = new CCDTO(); 14 | public new FCCDTO ScriptValueData = new FCCDTO(); 15 | public override DTO _data { get => data; } 16 | public override DTO _ScriptValueData { get => ScriptValueData; } 17 | } 18 | 19 | [Serializable] 20 | public class CCDTO : DTO 21 | { 22 | public override void OnValidate() 23 | { 24 | AnimationModules.ForEach(x => x.AnimatorAdress = PublicFunctions.FindPath(x.Animator)); 25 | } 26 | 27 | public ColliderActionType ColliderActionType; 28 | public CollisionType CollisionType; 29 | public DetectType DetectType; 30 | public float ModifyHealthAmount; 31 | public List AnimationModules; 32 | public WarheadActionType warheadActionType; 33 | public List MessageModules; 34 | public List dropItems; 35 | public List commandings; 36 | public List ExplodeModules; 37 | public List effectGivingModules; 38 | public List AudioModules; 39 | public List GroovieNoiseToCall; 40 | public List FunctionToCall; 41 | } 42 | 43 | [Serializable] 44 | public class FCCDTO : DTO 45 | { 46 | public override void OnValidate() 47 | { 48 | CollisionType.OnValidate(); 49 | DetectType.OnValidate(); 50 | ModifyHealthAmount.OnValidate(); 51 | warheadActionType.OnValidate(); 52 | AnimationModules.ForEach(x => { x.parent = this; x.OnValidate(); x.AnimatorAdress = PublicFunctions.FindPath(x.Animator); }); 53 | MessageModules.ForEach(x => x.OnValidate()); 54 | dropItems.ForEach(x => x.OnValidate()); 55 | commandings.ForEach(x => x.OnValidate()); 56 | ExplodeModules.ForEach(x => x.OnValidate()); 57 | effectGivingModules.ForEach(x => x.OnValidate()); 58 | AudioModules.ForEach(x => x.OnValidate()); 59 | GroovieNoiseToCall.ForEach(x => x.OnValidate()); 60 | FunctionToCall.ForEach(x => x.OnValidate()); 61 | } 62 | 63 | public ColliderActionType ColliderActionType; 64 | public ScriptValue CollisionType; 65 | public ScriptValue DetectType; 66 | public ScriptValue ModifyHealthAmount; 67 | public List AnimationModules; 68 | public ScriptValue warheadActionType; 69 | public List MessageModules; 70 | public List dropItems; 71 | public List commandings; 72 | public List ExplodeModules; 73 | public List effectGivingModules; 74 | public List AudioModules; 75 | public List GroovieNoiseToCall; 76 | public List FunctionToCall; 77 | } 78 | 79 | public class CustomColliderCompiler 80 | { 81 | private static readonly Config Config = SchematicManager.Config; 82 | 83 | [MenuItem("SchematicManager/Compile custom collider", priority = -11)] 84 | public static void OnCompile() 85 | { 86 | foreach (Schematic schematic in GameObject.FindObjectsOfType()) 87 | { 88 | Compile(schematic); 89 | } 90 | } 91 | 92 | public static void Compile(Schematic schematic) 93 | { 94 | string parentDirectoryPath = Directory.Exists(Config.ExportPath) 95 | ? Config.ExportPath 96 | : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), 97 | "MapEditorReborn_CompiledSchematics"); 98 | string schematicDirectoryPath = Path.Combine(parentDirectoryPath, schematic.gameObject.name); 99 | 100 | if (!Directory.Exists(parentDirectoryPath)) 101 | { 102 | Debug.LogError("Could Not find root object's compiled directory!"); 103 | return; 104 | } 105 | 106 | Directory.CreateDirectory(schematicDirectoryPath); 107 | 108 | File.WriteAllText(Path.Combine(schematicDirectoryPath, $"{schematic.gameObject.name}-Colliders.json"), JsonConvert.SerializeObject(schematic.transform.GetComponentsInChildren().Where(x => !x.UseScriptValue).Select(x => x.data), Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore })); 109 | File.WriteAllText(Path.Combine(schematicDirectoryPath, $"{schematic.gameObject.name}-FColliders.json"), JsonConvert.SerializeObject(schematic.transform.GetComponentsInChildren().Where(x => x.UseScriptValue).Select(x => x.ScriptValueData).ToList(), Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, TypeNameHandling = TypeNameHandling.Auto }).Replace("Assembly-CSharp", "AdvancedMERTools")); 110 | Debug.Log("Successfully Imported Custom Colliders."); 111 | } 112 | } -------------------------------------------------------------------------------- /Advanced MER tools/InteractablePickup.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.ComponentModel; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | //using NaughtyAttributes; 6 | using System; 7 | using System.IO; 8 | using UnityEditor; 9 | using Newtonsoft.Json; 10 | using System.Linq; 11 | 12 | public class InteractablePickup : FakeMono 13 | { 14 | public new IPDTO data = new IPDTO(); 15 | public new FIPDTO ScriptValueData = new FIPDTO(); 16 | public override DTO _data { get => data; } 17 | public override DTO _ScriptValueData { get => ScriptValueData; } 18 | } 19 | 20 | [Serializable] 21 | public class IPDTO : DTO 22 | { 23 | public override void OnValidate() 24 | { 25 | AnimationModules.ForEach(x => x.AnimatorAdress = PublicFunctions.FindPath(x.Animator)); 26 | } 27 | 28 | public InvokeType InvokeType; 29 | public IPActionType ActionType; 30 | public bool CancelActionWhenActive; 31 | public List AnimationModules; 32 | public WarheadActionType warheadActionType; 33 | public List MessageModules; 34 | public List dropItems; 35 | public List commandings; 36 | public Scp914Mode Scp914Mode; 37 | public List ExplodeModules; 38 | public List effectGivingModules; 39 | public List AudioModules; 40 | public List GroovieNoiseToCall; 41 | public List FunctionToCall; 42 | } 43 | 44 | [Serializable] 45 | public class FIPDTO : DTO 46 | { 47 | public override void OnValidate() 48 | { 49 | CancelActionWhenActive.OnValidate(); 50 | Scp914Mode.OnValidate(); 51 | warheadActionType.OnValidate(); 52 | AnimationModules.ForEach(x => { x.parent = this; x.OnValidate(); x.AnimatorAdress = PublicFunctions.FindPath(x.Animator); }); 53 | MessageModules.ForEach(x => x.OnValidate()); 54 | dropItems.ForEach(x => x.OnValidate()); 55 | commandings.ForEach(x => x.OnValidate()); 56 | ExplodeModules.ForEach(x => x.OnValidate()); 57 | effectGivingModules.ForEach(x => x.OnValidate()); 58 | AudioModules.ForEach(x => x.OnValidate()); 59 | GroovieNoiseToCall.ForEach(x => x.OnValidate()); 60 | FunctionToCall.ForEach(x => x.OnValidate()); 61 | } 62 | 63 | public InvokeType InvokeType; 64 | public IPActionType ActionType; 65 | public ScriptValue CancelActionWhenActive; 66 | public ScriptValue Scp914Mode; 67 | public List AnimationModules; 68 | public ScriptValue warheadActionType; 69 | public List MessageModules; 70 | public List dropItems; 71 | public List commandings; 72 | public List ExplodeModules; 73 | public List effectGivingModules; 74 | public List AudioModules; 75 | public List GroovieNoiseToCall; 76 | public List FunctionToCall; 77 | } 78 | 79 | public class InteractablePickupCompiler 80 | { 81 | private static readonly Config Config = SchematicManager.Config; 82 | 83 | [MenuItem("SchematicManager/Compile Interactable pickups", priority = -11)] 84 | public static void OnCompile() 85 | { 86 | foreach (Schematic schematic in GameObject.FindObjectsOfType()) 87 | { 88 | Compile(schematic); 89 | } 90 | } 91 | 92 | public static void Compile(Schematic schematic) 93 | { 94 | string parentDirectoryPath = Directory.Exists(Config.ExportPath) 95 | ? Config.ExportPath 96 | : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), 97 | "MapEditorReborn_CompiledSchematics"); 98 | string schematicDirectoryPath = Path.Combine(parentDirectoryPath, schematic.gameObject.name); 99 | 100 | if (!Directory.Exists(parentDirectoryPath)) 101 | { 102 | Debug.LogError("Could Not find root object's compiled directory!"); 103 | return; 104 | } 105 | 106 | Directory.CreateDirectory(schematicDirectoryPath); 107 | 108 | File.WriteAllText(Path.Combine(schematicDirectoryPath, $"{schematic.gameObject.name}-Pickups.json"), JsonConvert.SerializeObject(schematic.transform.GetComponentsInChildren().Where(x => !x.UseScriptValue).Select(x => x.data), Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore })); 109 | File.WriteAllText(Path.Combine(schematicDirectoryPath, $"{schematic.gameObject.name}-FPickups.json"), JsonConvert.SerializeObject(schematic.transform.GetComponentsInChildren().Where(x => x.UseScriptValue).Select(x => x.ScriptValueData).ToList(), Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, TypeNameHandling = TypeNameHandling.Auto }).Replace("Assembly-CSharp", "AdvancedMERTools")); 110 | Debug.Log("Successfully Imported Interactable Pickups."); 111 | } 112 | } -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/Serializables.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Exiled.API.Enums; 7 | using UnityEngine; 8 | using MapEditorReborn.API.Features.Objects; 9 | using Utils; 10 | using Footprinting; 11 | using Exiled.CustomItems.API.Features; 12 | using Exiled.API.Features; 13 | using Exiled.API.Features.Items; 14 | using Mirror; 15 | using InventorySystem; 16 | using InventorySystem.Items; 17 | using InventorySystem.Items.Pickups; 18 | using System.IO; 19 | 20 | namespace AdvancedMERTools 21 | { 22 | 23 | [Flags] 24 | [Serializable] 25 | public enum ColliderActionType 26 | { 27 | ModifyHealth = 1, 28 | GiveEffect = 2, 29 | SendMessage = 4, 30 | PlayAnimation = 8, 31 | SendCommand = 16, 32 | Warhead = 32, 33 | Explode = 64, 34 | PlayAudio = 128, 35 | CallGroovieNoise = 256, 36 | CallFunction = 512, 37 | } 38 | 39 | [Flags] 40 | [Serializable] 41 | public enum CollisionType 42 | { 43 | OnEnter = 1, 44 | OnStay = 2, 45 | OnExit = 4 46 | } 47 | 48 | [Flags] 49 | [Serializable] 50 | public enum DetectType 51 | { 52 | Pickup = 1, 53 | Player = 2, 54 | Projectile = 4 55 | } 56 | 57 | namespace AMERT 58 | { 59 | [Serializable] 60 | public enum DoorType : int 61 | { 62 | LCZ = 0, 63 | HCZ = 1, 64 | EZ = 2 65 | } 66 | } 67 | 68 | [Flags] 69 | [Serializable] 70 | public enum EffectFlagE 71 | { 72 | Disable = 1, 73 | Enable = 2, 74 | ModifyDuration = 4, 75 | ForceDuration = 8, 76 | ModifyIntensity = 16, 77 | ForceIntensity = 32 78 | } 79 | 80 | [Flags] 81 | [Serializable] 82 | public enum Scp914Mode 83 | { 84 | Rough = 0, 85 | Coarse = 1, 86 | OneToOne = 2, 87 | Fine = 3, 88 | VeryFine = 4 89 | } 90 | 91 | //[Flags] 92 | //[Serializable] 93 | //public enum TeleportInvokeType 94 | //{ 95 | // Enter = 1, 96 | // Exit = 2, 97 | // Collide = 4 98 | //} 99 | 100 | [Flags] 101 | [Serializable] 102 | public enum DeadType 103 | { 104 | Disappear = 1, 105 | GetRigidbody = 2, 106 | DynamicDisappearing = 4, 107 | Explode = 8, 108 | ResetHP = 16, 109 | PlayAnimation = 32, 110 | Warhead = 64, 111 | SendMessage = 128, 112 | DropItems = 256, 113 | SendCommand = 512, 114 | GiveEffect = 1024, 115 | PlayAudio = 2048, 116 | CallGroovieNoise = 4096, 117 | CallFunction = 8192 118 | } 119 | 120 | [Flags] 121 | [Serializable] 122 | public enum IPActionType 123 | { 124 | Disappear = 1, 125 | Explode = 2, 126 | PlayAnimation = 4, 127 | Warhead = 8, 128 | SendMessage = 16, 129 | DropItems = 32, 130 | SendCommand = 64, 131 | UpgradeItem = 128, 132 | GiveEffect = 256, 133 | PlayAudio = 512, 134 | CallGroovieNoise = 1024, 135 | CallFunction = 2048, 136 | } 137 | 138 | [Flags] 139 | [Serializable] 140 | public enum InvokeType 141 | { 142 | Searching = 1, 143 | Picked = 2 144 | } 145 | 146 | [Serializable] 147 | public enum AnimationTypeE 148 | { 149 | Start, 150 | Stop, 151 | ModifyParameter 152 | } 153 | 154 | [Serializable] 155 | public enum ParameterTypeE 156 | { 157 | Integer, 158 | Float, 159 | Bool, 160 | Trigger 161 | } 162 | 163 | [Flags] 164 | [Serializable] 165 | public enum WarheadActionType 166 | { 167 | Start = 1, 168 | Stop = 2, 169 | Lock = 4, 170 | UnLock = 8, 171 | Disable = 16, 172 | Enable = 32 173 | } 174 | 175 | [Serializable] 176 | public enum MessageTypeE 177 | { 178 | Cassie, 179 | BroadCast, 180 | Hint 181 | } 182 | 183 | [Flags] 184 | [Serializable] 185 | public enum SendType 186 | { 187 | Interactor = 1, 188 | AllExceptAboveOne = 2, 189 | Alive = 4, 190 | Spectators = 8 191 | } 192 | 193 | //[Serializable] 194 | //public enum CommandType 195 | //{ 196 | // RemoteAdmin, 197 | // ClientConsole 198 | //} 199 | 200 | //[Serializable] 201 | //public enum ExecutorType 202 | //{ 203 | // Attacker, 204 | // LocalAdmin 205 | //} 206 | 207 | //[Serializable] 208 | //public class DoorInstallingGuideDTO 209 | //{ 210 | // public float Health; 211 | // public DoorDamageType DamagableDamageType; 212 | // public KeycardPermissions KeycardPermissions; 213 | // public string ObjectId; 214 | //} 215 | } 216 | -------------------------------------------------------------------------------- /Advanced MER tools/InteractableTeleporter.cs: -------------------------------------------------------------------------------- 1 | //using System.Collections; 2 | //using System.Collections.Generic; 3 | //using UnityEngine; 4 | //using System.ComponentModel; 5 | ////using NaughtyAttributes; 6 | //using Newtonsoft.Json; 7 | //using System.IO; 8 | //using UnityEditor; 9 | //using System; 10 | //using System.Linq; 11 | 12 | //public class InteractableTeleporter : FakeMono 13 | //{ 14 | // public new ITDTO data = new ITDTO(); 15 | // public override DTO _data { get => data; } 16 | // public override DTO _ScriptValueData { get => ScriptValueData; } 17 | 18 | // private void OnValidate() 19 | // { 20 | // bool flag = false; 21 | // if (data.ActionType.HasFlag(IPActionType.UpgradeItem)) 22 | // { 23 | // flag = true; 24 | // data.ActionType -= IPActionType.UpgradeItem; 25 | // } 26 | // //if (ActionType.HasFlag(IPActionType.PlayAnimation)) 27 | // //{ 28 | // // flag = true; 29 | // // ActionType -= IPActionType.PlayAnimation; 30 | // //} 31 | // if (data.ActionType.HasFlag(IPActionType.DropItems)) 32 | // { 33 | // flag = true; 34 | // data.ActionType -= IPActionType.DropItems; 35 | // } 36 | // if (flag) 37 | // Debug.Log("You cannot use that option in InteractableTeleporters!"); 38 | // } 39 | //} 40 | 41 | //[Serializable] 42 | //public class ITDTO : DTO 43 | //{ 44 | // public override void OnValidate() 45 | // { 46 | // } 47 | 48 | // [Tooltip("Index means the index of teleporter that this script will be applied to, in loaded map. It starts from 1.")] 49 | // public int index; 50 | // public TeleportInvokeType InvokeType; 51 | // public IPActionType ActionType; 52 | // public List animationDTOs; 53 | // public WarheadActionType warheadActionType; 54 | // public List MessageModules; 55 | // public List commandings; 56 | // public List ExplodeModules; 57 | // public List effectGivingModules; 58 | // public List AudioModules; 59 | // public List GroovieNoiseToCall; 60 | // public List FunctionToCall; 61 | //} 62 | 63 | //[Serializable] 64 | //public class FITDTO : DTO 65 | //{ 66 | // public override void OnValidate() 67 | // { 68 | // index.OnValidate(); 69 | // InvokeType.OnValidate(); 70 | // warheadActionType.OnValidate(); 71 | // MessageModules.ForEach(x => x.OnValidate()); 72 | // commandings.ForEach(x => x.OnValidate()); 73 | // ExplodeModules.ForEach(x => x.OnValidate()); 74 | // effectGivingModules.ForEach(x => x.OnValidate()); 75 | // AudioModules.ForEach(x => x.OnValidate()); 76 | // GroovieNoiseToCall.ForEach(x => x.OnValidate()); 77 | // FunctionToCall.ForEach(x => x.OnValidate()); 78 | // } 79 | 80 | // [Tooltip("Index means the index of teleporter that this script will be applied to, in loaded map. It starts from 1.")] 81 | // public ScriptValue index; 82 | // public ScriptValue InvokeType; 83 | // public IPActionType ActionType; 84 | // public List animationDTOs; 85 | // public ScriptValue warheadActionType; 86 | // public List MessageModules; 87 | // public List commandings; 88 | // public List ExplodeModules; 89 | // public List effectGivingModules; 90 | // public List AudioModules; 91 | // public List GroovieNoiseToCall; 92 | // public List FunctionToCall; 93 | //} 94 | 95 | //public class InteractableTeleporterCompiler 96 | //{ 97 | // private static readonly Config Config = SchematicManager.Config; 98 | 99 | // [MenuItem("SchematicManager/Compile Interactable teleporter", priority = -11)] 100 | // public static void OnCompile() 101 | // { 102 | // string parentDirectoryPath = Directory.Exists(Config.ExportPath) 103 | // ? Config.ExportPath 104 | // : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), 105 | // "MapEditorReborn_CompiledSchematics"); 106 | // if (!Directory.Exists(parentDirectoryPath)) 107 | // { 108 | // Debug.LogError("Could not find schematic output!"); 109 | // return; 110 | // } 111 | 112 | // File.WriteAllText(Path.Combine(parentDirectoryPath, "{map name here}-ITeleporters.json"), JsonConvert.SerializeObject(GameObject.FindObjectsOfType().Where(x => !x.UseScriptValue).Select(x => x.data), Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore })); 113 | // File.WriteAllText(Path.Combine(parentDirectoryPath, "{map name here}-FITeleporters.json"), JsonConvert.SerializeObject(GameObject.FindObjectsOfType().Where(x => x.UseScriptValue).Select(x => x.ScriptValueData), Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore })); 114 | // Debug.Log("Successfully Imported Interactable Teleporters."); 115 | // } 116 | //} -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/Patches.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Exiled.API.Features; 7 | using Exiled.API.Enums; 8 | using Exiled.Loader; 9 | using UnityEngine; 10 | using CustomCulling; 11 | using Interactables.Interobjects; 12 | using Interactables; 13 | using Interactables.Interobjects.DoorUtils; 14 | using System.IO; 15 | using Utf8Json; 16 | using MapEditorReborn.API.Features; 17 | using MapEditorReborn.API.Features.Objects; 18 | using Exiled.Events.Features; 19 | using Exiled.Events; 20 | using PlayerRoles; 21 | using MapEditorReborn.API; 22 | using MapEditorReborn.API.Enums; 23 | using MapEditorReborn.API.Features.Serializable; 24 | using Exiled.API.Features.Doors; 25 | using HarmonyLib; 26 | using Mirror; 27 | using System.Reflection.Emit; 28 | using System.Reflection; 29 | using PlayerRoles.FirstPersonControl; 30 | using CommandSystem; 31 | using CommandSystem.Commands; 32 | using RemoteAdmin; 33 | using Utf8Json.Formatters; 34 | 35 | using Maps = MapEditorReborn.Events.Handlers.Map; 36 | 37 | namespace AdvancedMERTools 38 | { 39 | [HarmonyPatch(typeof(DoorObject), nameof(DoorObject.Init))] 40 | public class DoorSpawnPatcher 41 | { 42 | static void Prefix(DoorObject __instance) 43 | { 44 | if (AdvancedMERTools.Singleton.Config.AutoRun && __instance.gameObject.TryGetComponent(out Interactables.Interobjects.BasicDoor basicDoor) && basicDoor.Rooms.Length == 0) 45 | { 46 | string str = "DoorLCZ"; 47 | if (__instance.gameObject.name.Contains("HCZ")) str = "DoorHCZ"; 48 | if (__instance.gameObject.name.Contains("EZ")) str = "DoorEZ"; 49 | //SchematicObject @object = ObjectSpawner.SpawnSchematic(str, basicDoor.transform.position, basicDoor.transform.rotation, isStatic: false); 50 | SchematicObject @object = ObjectSpawner.SpawnSchematic(str, basicDoor.transform.position, basicDoor.transform.rotation, basicDoor.transform.localScale, null); 51 | DummyDoor dummy = @object.gameObject.AddComponent(); 52 | AdvancedMERTools.Singleton.dummyDoors.Add(dummy); 53 | dummy.RealDoor = Door.Get(basicDoor); 54 | } 55 | } 56 | } 57 | 58 | [HarmonyPatch(nameof(DoorVariant), nameof(DoorVariant.NetworkTargetState), MethodType.Setter)] 59 | public class DoorVariantPatcher 60 | { 61 | static void Prefix(DoorVariant __instance, bool value) 62 | { 63 | DummyDoor d = AdvancedMERTools.Singleton.dummyDoors.Find(x => x.RealDoor == Door.Get(__instance)); 64 | if (d != null) 65 | d.OnInteractDoor(value); 66 | } 67 | } 68 | 69 | [HarmonyPatch(nameof(DoorVariant), nameof(DoorVariant.NetworkActiveLocks), MethodType.Setter)] 70 | public class DoorVariantLockPatcher 71 | { 72 | static void Prefix(DoorVariant __instance, ushort value) 73 | { 74 | CustomDoor d = AdvancedMERTools.Singleton.customDoors.Find(x => x.door == Door.Get(__instance)); 75 | if (d != null) 76 | d.OnLockChange(value); 77 | } 78 | } 79 | 80 | //[HarmonyPatch(typeof(MapUtils), nameof(MapUtils.LoadMap), new Type[] { typeof(MapSchematic) })] 81 | //public class MapLoadingPatcher 82 | //{ 83 | // static void Postfix(MapSchematic map) 84 | // { 85 | // if (map == null || !map.IsValid) 86 | // return; 87 | // string path = Path.Combine(MapEditorReborn.MapEditorReborn.MapsDir, map.Name + "-ITeleporters.json"); 88 | // if (File.Exists(path)) 89 | // { 90 | // List iTDTOs = JsonSerializer.Deserialize>(File.ReadAllText(path)); 91 | // TeleportObject[] teleports = API.SpawnedObjects.Where(x => x is TeleportObject).Cast().ToArray(); 92 | // foreach (ITDTO to in iTDTOs) 93 | // { 94 | // int n = int.Parse(to.ObjectId); 95 | // if (n > 0 && n <= teleports.Length) 96 | // { 97 | // InteractableTeleporter interactable = teleports[n - 1].gameObject.AddComponent(); 98 | // interactable.Base = to; 99 | // } 100 | // } 101 | // } 102 | // } 103 | //} 104 | 105 | //[HarmonyPatch(typeof(ServerListFormatter), nameof(ServerListFormatter.Serialize))] 106 | //public class PlayerCountPatcher 107 | //{ 108 | // static void Prefix(ref JsonWriter writer, ServerListItem value, IJsonFormatterResolver formatterResolver) 109 | // { 110 | // if (AdvancedMERTools.Singleton.Config.UseExperimentalFeature) 111 | // { 112 | // if (int.TryParse(value.players, out int result)) 113 | // value = new ServerListItem(value.serverId, value.ip, value.port, (result + 1 - ReferenceHub.AllHubs.Count(x => x.Mode == CentralAuth.ClientInstanceMode.DedicatedServer)).ToString(), value.info, value.pastebin, value.version, value.friendlyFire, value.modded, value.whitelist, value.officialCode); 114 | // else 115 | // ServerConsole.AddLog("Send folloing message to me. - Mujishung: " + value.players); 116 | // } 117 | // } 118 | //} 119 | } -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/InteractableTeleporter.cs: -------------------------------------------------------------------------------- 1 | //using System; 2 | //using System.Collections.Generic; 3 | //using System.Linq; 4 | //using System.Text; 5 | //using System.Threading.Tasks; 6 | //using UnityEngine; 7 | //using Exiled.API.Features; 8 | //using Exiled.API.Features.Pickups; 9 | //using Exiled.API.Features.Items; 10 | //using MapEditorReborn.Events.EventArgs; 11 | //using MapEditorReborn.API.Features.Objects; 12 | //using MapEditorReborn.API.Features; 13 | //using Exiled.CustomItems; 14 | //using CommandSystem; 15 | //using Utf8Json.Formatters; 16 | //using RemoteAdmin; 17 | //using Exiled.CustomItems.API.Features; 18 | 19 | //namespace AMERT 20 | //{ 21 | // public class InteractableTeleporter : AMERTInteractable 22 | // { 23 | // void Start() 24 | // { 25 | // this.Base = base.Base as ITDTO; 26 | // if (transform.TryGetComponent(out TO)) 27 | // { 28 | // AdvancedMERTools.Singleton.InteractableTPs.Add(this); 29 | // } 30 | // else 31 | // { 32 | // Destroy(this); 33 | // } 34 | // } 35 | 36 | // void OnTriggerEnter(Collider collider) 37 | // { 38 | // if (Player.TryGet(collider, out Player player) && Base.InvokeType.HasFlag(TeleportInvokeType.Collide)) 39 | // { 40 | // RunProcess(player); 41 | // } 42 | // } 43 | 44 | // public void RunProcess(Player player) 45 | // { 46 | // if (!Active) 47 | // return; 48 | // foreach (IPActionType type in Enum.GetValues(typeof(IPActionType))) 49 | // { 50 | // if (Base.ActionType.HasFlag(type)) 51 | // { 52 | // switch (type) 53 | // { 54 | // case IPActionType.Disappear: 55 | // Destroy(gameObject, 0.1f); 56 | // break; 57 | // case IPActionType.Explode: 58 | // ExplodeModule.GetSingleton().Execute(ExplodeModule.SelectList(Base.ExplodeModules), this.transform, player.ReferenceHub); 59 | // break; 60 | // case IPActionType.PlayAnimation: 61 | // AnimationDTO.GetSingleton().Execute(AnimationDTO.SelectList(Base.animationDTOs), this.gameObject); 62 | // break; 63 | // case IPActionType.Warhead: 64 | // AlphaWarhead(Base.warheadActionType); 65 | // break; 66 | // case IPActionType.SendMessage: 67 | // MessageModule.GetSingleton().Execute(MessageModule.SelectList(Base.MessageModules), Formatter, player, TO); 68 | // break; 69 | // case IPActionType.SendCommand: 70 | // Commanding.GetSingleton().Execute(Commanding.SelectList(Base.commandings), Formatter, player, TO); 71 | // break; 72 | // case IPActionType.GiveEffect: 73 | // EffectGivingModule.GetSingleton().Execute(EffectGivingModule.SelectList(Base.effectGivingModules), player); 74 | // break; 75 | // case IPActionType.PlayAudio: 76 | // AudioModule.GetSingleton().Execute(AudioModule.SelectList(Base.AudioModules), this.transform); 77 | // break; 78 | // case IPActionType.CallGroovieNoise: 79 | // CGNModule.GetSingleton().Execute(CGNModule.SelectList(Base.GroovieNoiseToCall), OSchematic); 80 | // break; 81 | // } 82 | // } 83 | // } 84 | // } 85 | 86 | // void OnDestroy() 87 | // { 88 | // AdvancedMERTools.Singleton.InteractableTPs.Remove(this); 89 | // } 90 | 91 | // static readonly Dictionary> Formatter = new Dictionary> 92 | // { 93 | // { "{p_i}", vs => (vs[0] as Player).Id.ToString() }, 94 | // { "{p_name}", vs => (vs[0] as Player).Nickname.ToString() }, 95 | // { "{p_pos}", vs => { Vector3 pos = (vs[0] as Player).Transform.position; return string.Format("{0} {1} {2}", pos.x, pos.y, pos.z); } }, 96 | // { "{p_room}", vs => (vs[0] as Player).CurrentRoom.RoomName.ToString() }, 97 | // { "{p_zone}", vs => (vs[0] as Player).Zone.ToString() }, 98 | // { "{p_role}", vs => (vs[0] as Player).Role.Type.ToString() }, 99 | // { "{p_item}", vs => (vs[0] as Player).CurrentItem.Type.ToString() }, 100 | // { "{o_pos}", vs => { Vector3 pos = (vs[1] as TeleportObject).transform.position; return string.Format("{0} {1} {2}", pos.x, pos.y, pos.z); } }, 101 | // { "{o_room}", vs => (vs[1] as TeleportObject).CurrentRoom.RoomName.ToString() }, 102 | // { "{o_zone}", vs => (vs[1] as TeleportObject).CurrentRoom.Zone.ToString() } 103 | // }; 104 | 105 | // public new ITDTO Base; 106 | 107 | // public TeleportObject TO; 108 | // } 109 | //} 110 | -------------------------------------------------------------------------------- /Advanced MER tools/HealthObject.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections; 5 | using System.ComponentModel; 6 | using System.IO; 7 | using UnityEditor; 8 | using UnityEngine; 9 | using System.Linq; 10 | 11 | public class HealthObject : FakeMono 12 | { 13 | public new HODTO data = new(); 14 | public new FHODTO ScriptValueData = new(); 15 | public override DTO _data { get => data; } 16 | public override DTO _ScriptValueData { get => ScriptValueData; } 17 | public string[] formats = "DO NOT TOUCH THE VALUES.\n{attacker_i} = attacker's player id.\n{attacker_name}\n{a_pos} = attacker's position.\n{a_room} = attacker's room\n{a_zone} = attacker's zone\n{a_role} = attacker's role\n{s_pos} = schematic's exact position.\n{s_room} = schematic's exact room.\n{s_zone} = schematic's zone.\n{a_item} = attacker's current item.\n{damage}".Split('\n'); 18 | } 19 | 20 | [Serializable] 21 | public class HODTO : DTO 22 | { 23 | public override void OnValidate() 24 | { 25 | AnimationModules.ForEach(x => x.AnimatorAdress = PublicFunctions.FindPath(x.Animator)); 26 | } 27 | 28 | public float Health; 29 | [Range(0, 100)] 30 | public int ArmorEfficient; 31 | public DeadType DeadType; 32 | public float DeadActionDelay; 33 | public float ResetHPTo; 34 | public bool DoNotDestroyAfterDeath; 35 | public List whitelistWeapons; 36 | public List AnimationModules; 37 | public WarheadActionType warheadAction; 38 | public List MessageModules; 39 | public List DropItems; 40 | public List Commandings; 41 | public List ExplodeModules; 42 | public List effectGivingModules; 43 | public List AudioModules; 44 | public List GroovieNoiseToCall; 45 | public List FunctionToCall; 46 | } 47 | 48 | [Serializable] 49 | public class FHODTO : DTO 50 | { 51 | public override void OnValidate() 52 | { 53 | Health.OnValidate(); 54 | ArmorEfficient.OnValidate(); 55 | DeadActionDelay.OnValidate(); 56 | ResetHPTo.OnValidate(); 57 | DoNotDestroyAfterDeath.OnValidate(); 58 | warheadActionType.OnValidate(); 59 | AnimationModules.ForEach(x => { x.parent = this; x.OnValidate(); x.AnimatorAdress = PublicFunctions.FindPath(x.Animator); }); 60 | MessageModules.ForEach(x => x.OnValidate()); 61 | dropItems.ForEach(x => x.OnValidate()); 62 | commandings.ForEach(x => x.OnValidate()); 63 | ExplodeModules.ForEach(x => x.OnValidate()); 64 | effectGivingModules.ForEach(x => x.OnValidate()); 65 | AudioModules.ForEach(x => x.OnValidate()); 66 | GroovieNoiseToCall.ForEach(x => x.OnValidate()); 67 | FunctionToCall.ForEach(x => x.OnValidate()); 68 | } 69 | 70 | public ScriptValue Health; 71 | [Range(0, 100)] 72 | public ScriptValue ArmorEfficient; 73 | public DeadType DeadType; 74 | public ScriptValue DeadActionDelay; 75 | public ScriptValue ResetHPTo; 76 | public ScriptValue DoNotDestroyAfterDeath; 77 | public List whitelistWeapons; 78 | public List AnimationModules; 79 | public ScriptValue warheadActionType; 80 | public List MessageModules; 81 | public List dropItems; 82 | public List commandings; 83 | public List ExplodeModules; 84 | public List effectGivingModules; 85 | public List AudioModules; 86 | public List GroovieNoiseToCall; 87 | public List FunctionToCall; 88 | } 89 | 90 | public class HealthObjectCompiler : MonoBehaviour 91 | { 92 | private static readonly Config Config = SchematicManager.Config; 93 | 94 | [MenuItem("SchematicManager/Compile Health Schematics", priority = -11)] 95 | public static void OnCompile() 96 | { 97 | foreach (Schematic schematic in GameObject.FindObjectsOfType()) 98 | { 99 | Compile(schematic); 100 | } 101 | } 102 | 103 | public static void Compile(Schematic schematic) 104 | { 105 | string parentDirectoryPath = Directory.Exists(Config.ExportPath) 106 | ? Config.ExportPath 107 | : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), 108 | "MapEditorReborn_CompiledSchematics"); 109 | string schematicDirectoryPath = Path.Combine(parentDirectoryPath, schematic.gameObject.name); 110 | 111 | if (!Directory.Exists(parentDirectoryPath)) 112 | { 113 | Debug.LogError("Could Not find root object's compiled directory!"); 114 | return; 115 | } 116 | 117 | Directory.CreateDirectory(schematicDirectoryPath); 118 | 119 | File.WriteAllText(Path.Combine(schematicDirectoryPath, $"{schematic.gameObject.name}-HealthObjects.json"), JsonConvert.SerializeObject(schematic.transform.GetComponentsInChildren().Where(x => !x.UseScriptValue).Select(x => x.data), Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore })); 120 | File.WriteAllText(Path.Combine(schematicDirectoryPath, $"{schematic.gameObject.name}-FHealthObjects.json"), JsonConvert.SerializeObject(schematic.transform.GetComponentsInChildren().Where(x => x.UseScriptValue).Select(x => x.ScriptValueData), Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, TypeNameHandling = TypeNameHandling.Auto }).Replace("Assembly-CSharp", "AdvancedMERTools")); 121 | Debug.Log("Successfully Imported HealthObjects."); 122 | } 123 | } -------------------------------------------------------------------------------- /Advanced MER tools/FunctionCollections.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections; 5 | using System.ComponentModel; 6 | using System.IO; 7 | using UnityEditor; 8 | using UnityEngine; 9 | using System.Reflection; 10 | 11 | [Serializable] 12 | public class If : Function 13 | { 14 | public ScriptValue Statement; 15 | public List Actions; 16 | 17 | public override void OnValidate() 18 | { 19 | Statement.OnValidate(); 20 | Actions.ForEach(x => x.OnValidate()); 21 | } 22 | } 23 | 24 | [Serializable] 25 | public class ElseIf : Function 26 | { 27 | public ScriptValue Statement; 28 | public List Actions; 29 | 30 | public override void OnValidate() 31 | { 32 | Statement.OnValidate(); 33 | Actions.ForEach(x => x.OnValidate()); 34 | } 35 | } 36 | 37 | [Serializable] 38 | public class Else : Function 39 | { 40 | public List Actions; 41 | 42 | public override void OnValidate() 43 | { 44 | Actions.ForEach(x => x.OnValidate()); 45 | } 46 | } 47 | 48 | [Serializable] 49 | public class While : Function 50 | { 51 | public ScriptValue Condition; 52 | public List Actions; 53 | 54 | public override void OnValidate() 55 | { 56 | Condition.OnValidate(); 57 | Actions.ForEach(x => x.OnValidate()); 58 | } 59 | } 60 | 61 | [Serializable] 62 | public class For : Function 63 | { 64 | public ScriptValue RepeatCount; 65 | public List Actions; 66 | 67 | public override void OnValidate() 68 | { 69 | RepeatCount.OnValidate(); 70 | Actions.ForEach(x => x.OnValidate()); 71 | } 72 | } 73 | 74 | [Serializable] 75 | public class ForEach : Function 76 | { 77 | public ScriptValue Array; 78 | public string ControlVariable; 79 | public List Actions; 80 | 81 | public override void OnValidate() 82 | { 83 | Array.OnValidate(); 84 | Actions.ForEach(x => x.OnValidate()); 85 | } 86 | } 87 | 88 | [Serializable] 89 | public class SetVariable : Function 90 | { 91 | public ScriptValue VariableName; 92 | public ScriptValue ValueToAssign; 93 | [Header("0: Function, 1: Script, 2: Schematic, 3: Game")] 94 | public ScriptValue AccessLevel; 95 | 96 | public override void OnValidate() 97 | { 98 | VariableName.OnValidate(); 99 | ValueToAssign.OnValidate(); 100 | AccessLevel.OnValidate(); 101 | } 102 | } 103 | 104 | [Serializable] 105 | public class Return : Function 106 | { 107 | public ScriptValue ReturnValue; 108 | 109 | public override void OnValidate() 110 | { 111 | ReturnValue.OnValidate(); 112 | } 113 | } 114 | 115 | [Serializable] 116 | public class Wait : Function 117 | { 118 | public ScriptValue WaitSecond; 119 | 120 | public override void OnValidate() 121 | { 122 | WaitSecond.OnValidate(); 123 | } 124 | } 125 | 126 | [Serializable] 127 | public class CallFunction : Function 128 | { 129 | public List FunctionModules; 130 | 131 | public override void OnValidate() 132 | { 133 | FunctionModules.ForEach(x => x.OnValidate()); 134 | } 135 | } 136 | 137 | [Serializable] 138 | public class CallGroovyNoise : Function 139 | { 140 | [Header("Caution: IDs won't be updated automatically!!")] 141 | public List Modules; 142 | 143 | public override void OnValidate() 144 | { 145 | Modules.ForEach(x => x.OnValidate()); 146 | } 147 | } 148 | 149 | [Serializable] 150 | public class PlayAnimation : Function 151 | { 152 | public List AnimationModules; 153 | 154 | public override void OnValidate() 155 | { 156 | AnimationModules.ForEach(x => x.OnValidate()); 157 | } 158 | } 159 | 160 | [Serializable] 161 | public class SendMessage : Function 162 | { 163 | public List MessageModules; 164 | 165 | public override void OnValidate() 166 | { 167 | MessageModules.ForEach(x => x.OnValidate()); 168 | } 169 | } 170 | 171 | [Serializable] 172 | public class SendCommand : Function 173 | { 174 | public List CommandModules; 175 | 176 | public override void OnValidate() 177 | { 178 | CommandModules.ForEach(x => x.OnValidate()); 179 | } 180 | } 181 | 182 | [Serializable] 183 | public class DropItems : Function 184 | { 185 | public List DropItemsModules; 186 | 187 | public override void OnValidate() 188 | { 189 | DropItemsModules.ForEach(x => x.OnValidate()); 190 | } 191 | } 192 | 193 | [Serializable] 194 | public class Explode : Function 195 | { 196 | public List ExplodeModules; 197 | 198 | public override void OnValidate() 199 | { 200 | ExplodeModules.ForEach(x => x.OnValidate()); 201 | } 202 | } 203 | 204 | [Serializable] 205 | public class GiveEffect : Function 206 | { 207 | public List EffectModules; 208 | 209 | public override void OnValidate() 210 | { 211 | EffectModules.ForEach(x => x.OnValidate()); 212 | } 213 | } 214 | 215 | [Serializable] 216 | public class PlayAudio : Function 217 | { 218 | public List AudioModules; 219 | 220 | public override void OnValidate() 221 | { 222 | AudioModules.ForEach(x => x.OnValidate()); 223 | } 224 | } 225 | 226 | [Serializable] 227 | public class FWarhead : Function 228 | { 229 | public ScriptValue ActionType; 230 | 231 | public override void OnValidate() 232 | { 233 | ActionType.OnValidate(); 234 | } 235 | } 236 | 237 | [Serializable] 238 | public class ChangePlayerValue : Function 239 | { 240 | public ScriptValue player; 241 | public PlayerUnaryOp.PlayerUnaryOpType ValueType; 242 | public ScriptValue Value; 243 | 244 | public override void OnValidate() 245 | { 246 | player.OnValidate(); 247 | Value.OnValidate(); 248 | } 249 | } 250 | 251 | [Serializable] 252 | public class PlayerAction : Function 253 | { 254 | [Serializable] 255 | public enum PlayerActionType 256 | { 257 | GiveItem, 258 | DropItem, 259 | RemoveItem 260 | } 261 | 262 | public ScriptValue Player; 263 | public PlayerActionType ActionType; 264 | public ScriptValue Argument; 265 | 266 | public override void OnValidate() 267 | { 268 | Player.OnValidate(); 269 | Argument.OnValidate(); 270 | } 271 | } 272 | 273 | [Serializable] 274 | public class ChangeEntityValue : Function 275 | { 276 | public ScriptValue Entity; 277 | public EntityUnaryOp.EntityUnaryOpType ValueType; 278 | public ScriptValue Value; 279 | 280 | public override void OnValidate() 281 | { 282 | Entity.OnValidate(); 283 | Value.OnValidate(); 284 | } 285 | } -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/AdvancedMERTools.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {93B7E3DC-BD0F-4777-8763-9482B996AC4A} 8 | Library 9 | Properties 10 | AdvancedMERTools 11 | AdvancedMERTools 12 | v4.8 13 | 512 14 | true 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | true 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | true 36 | 37 | 38 | 39 | ..\..\..\AppData\Roaming\EXILED\Plugins\dependencies\0Harmony.dll 40 | 41 | 42 | F:\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\Assembly-CSharp.dll 43 | 44 | 45 | F:\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\Assembly-CSharp-firstpass.dll 46 | 47 | 48 | ..\..\..\AppData\Roaming\EXILED\Plugins\dependencies\AudioPlayerApi.dll 49 | 50 | 51 | 52 | False 53 | ..\..\..\AppData\Roaming\SCP Secret Laboratory\PluginAPI\plugins\global\dependencies\Exiled.API.dll 54 | 55 | 56 | ..\..\..\AppData\Roaming\EXILED\Plugins\Exiled.CustomItems.dll 57 | 58 | 59 | ..\..\..\AppData\Roaming\EXILED\Plugins\Exiled.Events.dll 60 | 61 | 62 | ..\..\..\AppData\Roaming\SCP Secret Laboratory\PluginAPI\plugins\global\Exiled.Loader.dll 63 | 64 | 65 | ..\..\..\AppData\Roaming\EXILED\Plugins\Exiled.Permissions.dll 66 | 67 | 68 | ..\..\..\AppData\Roaming\EXILED\Plugins\MapEditorReborn.dll 69 | 70 | 71 | F:\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\Mirror.dll 72 | 73 | 74 | False 75 | ..\..\..\AppData\Roaming\EXILED\Plugins\dependencies\Newtonsoft.Json.dll 76 | 77 | 78 | 79 | F:\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\Pooling.dll 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | F:\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\UnityEngine.dll 91 | 92 | 93 | F:\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\UnityEngine.AnimationModule.dll 94 | 95 | 96 | F:\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\UnityEngine.CoreModule.dll 97 | 98 | 99 | F:\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\UnityEngine.PhysicsModule.dll 100 | 101 | 102 | ..\..\..\AppData\Roaming\EXILED\Plugins\dependencies\YamlDotNet.dll 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /Advanced MER tools/CustomRGBA.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | using System.ComponentModel; 6 | using System.IO; 7 | using System; 8 | using System.Linq; 9 | using Newtonsoft.Json; 10 | using System.Globalization; 11 | 12 | public class CustomRGBA : MonoBehaviour 13 | { 14 | public int R; 15 | public int G; 16 | public int B; 17 | public float A; 18 | public int R_max = 255; 19 | public int G_max = 255; 20 | public int B_max = 255; 21 | public float A_max = 1; 22 | public int R_min = 0; 23 | public int G_min = 0; 24 | public int B_min = 0; 25 | public float A_min = 0; 26 | 27 | float[] vs; 28 | 29 | private void OnDrawGizmos() 30 | { 31 | if (vs == null) 32 | { 33 | vs = new float[] { R, G, B, A }; 34 | } 35 | else if (vs[0] != R || vs[1] != G || vs[2] != B || vs[3] != A) 36 | { 37 | foreach (PrimitiveComponent component in transform.GetComponentsInChildren()) 38 | { 39 | Apply(component); 40 | } 41 | vs = new float[] { R, G, B, A }; 42 | } 43 | } 44 | 45 | public void Apply(PrimitiveComponent component) 46 | { 47 | component.Color = new Color(R / 255f, G / 255f, B / 255f, A); 48 | MeshRenderer renderer = component.gameObject.GetComponent(); 49 | if (_sharedRegular == null) 50 | _sharedRegular = new Material((Material)Resources.Load("Materials/Regular")); 51 | 52 | if (_sharedTransparent == null) 53 | _sharedTransparent = new Material((Material)Resources.Load("Materials/Transparent")); 54 | 55 | renderer.sharedMaterial = component.Color.a >= 1f ? _sharedRegular : _sharedTransparent; 56 | renderer.sharedMaterial.color = component.Color; 57 | } 58 | 59 | private static readonly Config Config = SchematicManager.Config; 60 | 61 | [MenuItem("SchematicManager/Compile Custom RGBAs", priority = -12)] 62 | public static void Compile() 63 | { 64 | foreach (Schematic s in GameObject.FindObjectsOfType()) 65 | { 66 | CompileSchematic(s); 67 | } 68 | } 69 | 70 | public static void CompileSchematic(Schematic schematic) 71 | { 72 | string parentDirectoryPath = Directory.Exists(Config.ExportPath) 73 | ? Config.ExportPath 74 | : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), 75 | "MapEditorReborn_CompiledSchematics"); 76 | 77 | string schematicDirectoryPath = Path.Combine(parentDirectoryPath, schematic.gameObject.name, $"{schematic.gameObject.name}.json"); 78 | 79 | if (!Directory.Exists(parentDirectoryPath)) 80 | return; 81 | if (!File.Exists(schematicDirectoryPath)) 82 | { 83 | Debug.Log("You should first compile schematic then compile Custom RGBAs."); 84 | return; 85 | } 86 | 87 | SchematicObjectDataList list = JsonConvert.DeserializeObject(File.ReadAllText(schematicDirectoryPath)); 88 | 89 | foreach (PrimitiveComponent primitive in schematic.GetComponentsInChildren()) 90 | { 91 | CustomRGBA custom = primitive.gameObject.GetComponentInParent(); 92 | if (custom != null) 93 | { 94 | custom.Apply(primitive); 95 | SchematicBlockData data = list.Blocks.Find(x => x.ObjectId == primitive.transform.GetInstanceID()); 96 | if (data == null) 97 | { 98 | Debug.Log("Unregistered item found! " + primitive.gameObject.name); 99 | continue; 100 | } 101 | if (data.Properties.ContainsKey("Color")) 102 | { 103 | data.Properties["Color"] = string.Format("{0}:{1}:{2}:{3}", custom.R, custom.G, custom.B, custom.A.ToString(CultureInfo.InvariantCulture)); 104 | } 105 | } 106 | } 107 | SchematicObjectDataList list1 = new SchematicObjectDataList 108 | { 109 | Blocks = list.Blocks, 110 | RootObjectId = list.RootObjectId 111 | }; 112 | 113 | File.WriteAllText(schematicDirectoryPath, JsonConvert.SerializeObject(list1, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore })); 114 | Debug.Log("Successfully compiled Custom RGBAs"); 115 | } 116 | 117 | private Material _sharedRegular; 118 | private Material _sharedTransparent; 119 | } 120 | 121 | [CustomEditor(typeof(CustomRGBA))] 122 | public class SliderEditor : Editor 123 | { 124 | SerializedProperty R; 125 | SerializedProperty G; 126 | SerializedProperty B; 127 | SerializedProperty A; 128 | SerializedProperty R_M; 129 | SerializedProperty G_M; 130 | SerializedProperty B_M; 131 | SerializedProperty A_M; 132 | SerializedProperty R_m; 133 | SerializedProperty G_m; 134 | SerializedProperty B_m; 135 | SerializedProperty A_m; 136 | 137 | private void OnEnable() 138 | { 139 | R = serializedObject.FindProperty("R"); 140 | G = serializedObject.FindProperty("G"); 141 | B = serializedObject.FindProperty("B"); 142 | A = serializedObject.FindProperty("A"); 143 | R_M = serializedObject.FindProperty("R_max"); 144 | G_M = serializedObject.FindProperty("G_max"); 145 | B_M = serializedObject.FindProperty("B_max"); 146 | A_M = serializedObject.FindProperty("A_max"); 147 | R_m = serializedObject.FindProperty("R_min"); 148 | G_m = serializedObject.FindProperty("G_min"); 149 | B_m = serializedObject.FindProperty("B_min"); 150 | A_m = serializedObject.FindProperty("A_min"); 151 | } 152 | 153 | public override void OnInspectorGUI() 154 | { 155 | serializedObject.Update(); 156 | 157 | EditorGUILayout.PropertyField(R); 158 | EditorGUILayout.PropertyField(G); 159 | EditorGUILayout.PropertyField(B); 160 | EditorGUILayout.PropertyField(A); 161 | 162 | GUILayout.BeginHorizontal(); 163 | EditorGUILayout.PropertyField(R_M);EditorGUILayout.PropertyField(R_m); 164 | GUILayout.EndHorizontal(); 165 | 166 | GUILayout.BeginHorizontal(); 167 | EditorGUILayout.PropertyField(G_M);EditorGUILayout.PropertyField(G_m); 168 | GUILayout.EndHorizontal(); 169 | 170 | GUILayout.BeginHorizontal(); 171 | EditorGUILayout.PropertyField(B_M);EditorGUILayout.PropertyField(B_m); 172 | GUILayout.EndHorizontal(); 173 | 174 | GUILayout.BeginHorizontal(); 175 | EditorGUILayout.PropertyField(A_M);EditorGUILayout.PropertyField(A_m); 176 | GUILayout.EndHorizontal(); 177 | 178 | R.intValue = Mathf.RoundToInt(EditorGUILayout.Slider("R value", R.intValue, R_m.intValue, R_M.intValue)); 179 | G.intValue = Mathf.RoundToInt(EditorGUILayout.Slider("G value", G.intValue, G_m.intValue, G_M.intValue)); 180 | B.intValue = Mathf.RoundToInt(EditorGUILayout.Slider("B value", B.intValue, B_m.intValue, B_M.intValue)); 181 | A.floatValue = EditorGUILayout.Slider("A value", A.floatValue, A_m.floatValue, A_M.floatValue); 182 | 183 | serializedObject.ApplyModifiedProperties(); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/InteractablePickup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnityEngine; 7 | using Exiled.API.Features; 8 | using Exiled.API.Features.Pickups; 9 | using Exiled.API.Features.Items; 10 | using MapEditorReborn.API.Features.Objects; 11 | using MapEditorReborn.API.Features; 12 | using Exiled.CustomItems; 13 | using CommandSystem; 14 | using Utf8Json.Formatters; 15 | using RemoteAdmin; 16 | using Exiled.CustomItems.API.Features; 17 | 18 | namespace AdvancedMERTools 19 | { 20 | public class InteractablePickup : AMERTInteractable 21 | { 22 | protected virtual void Start() 23 | { 24 | this.Base = base.Base as IPDTO; 25 | Pickup = Pickup.Get(this.gameObject); 26 | if (Pickup != null) 27 | { 28 | AdvancedMERTools.Singleton.InteractablePickups.Add(this); 29 | } 30 | else 31 | { 32 | Destroy(this); 33 | } 34 | } 35 | 36 | public virtual void RunProcess(Player player, Pickup pickup, out bool Remove) 37 | { 38 | bool r = false; 39 | Remove = false; 40 | if (pickup != this.Pickup || !Active) 41 | { 42 | return; 43 | } 44 | ModuleGeneralArguments args = new ModuleGeneralArguments { interpolations = Formatter, interpolationsList = new object[] { player }, player = player, schematic = OSchematic, transform = this.transform, TargetCalculated = false }; 45 | var ipActionExecutors = new Dictionary 46 | { 47 | { IPActionType.Disappear, () => r = true }, 48 | { IPActionType.Explode, () => ExplodeModule.Execute(Base.ExplodeModules, args) }, 49 | { IPActionType.PlayAnimation, () => AnimationDTO.Execute(Base.AnimationModules, args) }, 50 | { IPActionType.Warhead, () => AlphaWarhead(Base.warheadActionType) }, 51 | { IPActionType.SendMessage, () => MessageModule.Execute(Base.MessageModules, args) }, 52 | { IPActionType.DropItems, () => DropItem.Execute(Base.dropItems, args) }, 53 | { IPActionType.SendCommand, () => Commanding.Execute(Base.commandings, args) }, 54 | { IPActionType.UpgradeItem, () => 55 | { 56 | if (player.GameObject.TryGetComponent(out Collider col)) 57 | { 58 | var vs = Enumerable.Range(0, 5) 59 | .Where(j => Base.Scp914Mode.HasFlag((Scp914Mode)j)) 60 | .ToList(); 61 | Scp914.Scp914Upgrader.Upgrade( 62 | new Collider[] { col }, 63 | Scp914.Scp914Mode.Held, 64 | (Scp914.Scp914KnobSetting)vs.RandomItem() 65 | ); 66 | } 67 | } 68 | }, 69 | { IPActionType.GiveEffect, () => EffectGivingModule.Execute(Base.effectGivingModules, args) }, 70 | { IPActionType.PlayAudio, () => AudioModule.Execute(Base.AudioModules, args) }, 71 | { IPActionType.CallGroovieNoise, () => CGNModule.Execute(Base.GroovieNoiseToCall, args) }, 72 | { IPActionType.CallFunction, () => CFEModule.Execute(Base.FunctionToCall, args) } 73 | }; 74 | foreach (IPActionType type in Enum.GetValues(typeof(IPActionType))) 75 | { 76 | if (Base.ActionType.HasFlag(type) && ipActionExecutors.TryGetValue(type, out var execute)) 77 | { 78 | execute(); 79 | } 80 | } 81 | Remove = r; 82 | } 83 | 84 | void OnDestroy() 85 | { 86 | AdvancedMERTools.Singleton.InteractablePickups.Remove(this); 87 | } 88 | 89 | static readonly Dictionary> Formatter = new Dictionary> 90 | { 91 | { "{p_i}", vs => (vs[0] as Player).Id.ToString() }, 92 | { "{p_name}", vs => (vs[0] as Player).Nickname.ToString() }, 93 | { "{p_pos}", vs => { Vector3 pos = (vs[0] as Player).Transform.position; return $"{pos.x} {pos.y} {pos.z}"; } }, 94 | { "{p_room}", vs => (vs[0] as Player).CurrentRoom.RoomName.ToString() }, 95 | { "{p_zone}", vs => (vs[0] as Player).Zone.ToString() }, 96 | { "{p_role}", vs => (vs[0] as Player).Role.Type.ToString() }, 97 | { "{p_item}", vs => (vs[0] as Player).CurrentItem.Type.ToString() }, 98 | { "{o_pos}", vs => { Vector3 pos = (vs[1] as Pickup).Transform.position; return $"{pos.x} {pos.y} {pos.z}"; } }, 99 | { "{o_room}", vs => (vs[1] as Pickup).Room.RoomName.ToString() }, 100 | { "{o_zone}", vs => (vs[1] as Pickup).Room.Zone.ToString() } 101 | }; 102 | 103 | public Pickup Pickup; 104 | 105 | public new IPDTO Base; 106 | } 107 | 108 | public class FInteractablePickup : InteractablePickup 109 | { 110 | protected override void Start() 111 | { 112 | this.Base = ((AMERTInteractable)this).Base as FIPDTO; 113 | Pickup = Pickup.Get(this.gameObject); 114 | if (Pickup != null) 115 | { 116 | AdvancedMERTools.Singleton.InteractablePickups.Add(this); 117 | } 118 | else 119 | { 120 | Destroy(this); 121 | } 122 | } 123 | 124 | public override void RunProcess(Player player, Pickup pickup, out bool Remove) 125 | { 126 | bool r = false; 127 | Remove = false; 128 | if (pickup != this.Pickup || !Active) 129 | { 130 | return; 131 | } 132 | FunctionArgument args = new FunctionArgument(this, player); 133 | var ipActionExecutors = new Dictionary 134 | { 135 | { IPActionType.Disappear, () => r = true }, 136 | { IPActionType.Explode, () => FExplodeModule.Execute(Base.ExplodeModules, args) }, 137 | { IPActionType.PlayAnimation, () => FAnimationDTO.Execute(Base.AnimationModules, args) }, 138 | { IPActionType.Warhead, () => AlphaWarhead(Base.warheadActionType.GetValue(args, 0)) }, 139 | { IPActionType.SendMessage, () => FMessageModule.Execute(Base.MessageModules, args) }, 140 | { IPActionType.DropItems, () => FDropItem.Execute(Base.dropItems, args) }, 141 | { IPActionType.SendCommand, () => FCommanding.Execute(Base.commandings, args) }, 142 | { IPActionType.UpgradeItem, () => 143 | { 144 | if (player.GameObject.TryGetComponent(out Collider col)) 145 | { 146 | Scp914Mode mode = Base.Scp914Mode.GetValue(args, 0); 147 | var vs = Enumerable.Range(0, 5) 148 | .Where(j => mode.HasFlag((Scp914Mode)j)) 149 | .ToList(); 150 | Scp914.Scp914Upgrader.Upgrade( 151 | new Collider[] { col }, 152 | Scp914.Scp914Mode.Held, 153 | (Scp914.Scp914KnobSetting)vs.RandomItem() 154 | ); 155 | } 156 | } 157 | }, 158 | { IPActionType.GiveEffect, () => FEffectGivingModule.Execute(Base.effectGivingModules, args) }, 159 | { IPActionType.PlayAudio, () => FAudioModule.Execute(Base.AudioModules, args) }, 160 | { IPActionType.CallGroovieNoise, () => FCGNModule.Execute(Base.GroovieNoiseToCall, args) }, 161 | { IPActionType.CallFunction, () => FCFEModule.Execute(Base.FunctionToCall, args) } 162 | }; 163 | foreach (IPActionType type in Enum.GetValues(typeof(IPActionType))) 164 | { 165 | if (Base.ActionType.HasFlag(type) && ipActionExecutors.TryGetValue(type, out var execute)) 166 | { 167 | execute(); 168 | } 169 | } 170 | Remove = r; 171 | } 172 | 173 | void OnDestroy() 174 | { 175 | AdvancedMERTools.Singleton.InteractablePickups.Remove(this); 176 | } 177 | 178 | public new FIPDTO Base; 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/InteractableObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnityEngine; 7 | using Exiled.API.Features; 8 | using Exiled.API.Features.Pickups; 9 | using Exiled.API.Features.Items; 10 | using MapEditorReborn.API.Features.Objects; 11 | using MapEditorReborn.API.Features; 12 | using Exiled.CustomItems; 13 | using CommandSystem; 14 | using Utf8Json.Formatters; 15 | using RemoteAdmin; 16 | using Exiled.CustomItems.API.Features; 17 | using UserSettings.ServerSpecific; 18 | 19 | namespace AdvancedMERTools 20 | { 21 | public class InteractableObject : AMERTInteractable 22 | { 23 | protected virtual void Start() 24 | { 25 | this.Base = base.Base as IODTO; 26 | AdvancedMERTools.Singleton.interactableObjects.Add(this); 27 | if (AdvancedMERTools.Singleton.IOkeys.ContainsKey(Base.InputKeyCode)) 28 | { 29 | AdvancedMERTools.Singleton.IOkeys[Base.InputKeyCode].Add(this); 30 | } 31 | else 32 | { 33 | ServerSpecificSettingsSync.DefinedSettings = ServerSpecificSettingsSync.DefinedSettings.Append(new SSKeybindSetting(null, $"AMERT - Interactable Object - {(KeyCode)Base.InputKeyCode}", (KeyCode)Base.InputKeyCode, true, "")).ToArray(); 34 | ServerSpecificSettingsSync.SendToAll(); 35 | AdvancedMERTools.Singleton.IOkeys.Add(Base.InputKeyCode, new List { this }); 36 | } 37 | } 38 | 39 | public virtual void RunProcess(Player player) 40 | { 41 | if (!Active) 42 | return; 43 | ModuleGeneralArguments args = new ModuleGeneralArguments { interpolations = Formatter, interpolationsList = new object[] { player }, player = player, schematic = OSchematic, transform = this.transform, TargetCalculated = false }; 44 | var actionExecutors = new Dictionary 45 | { 46 | { IPActionType.Disappear, () => Destroy(this.gameObject, 0.1f) }, 47 | { IPActionType.Explode, () => ExplodeModule.Execute(Base.ExplodeModules, args) }, 48 | { IPActionType.PlayAnimation, () => AnimationDTO.Execute(Base.AnimationModules, args) }, 49 | { IPActionType.Warhead, () => AlphaWarhead(Base.warheadActionType) }, 50 | { IPActionType.SendMessage, () => MessageModule.Execute(Base.MessageModules, args) }, 51 | { IPActionType.DropItems, () => DropItem.Execute(Base.dropItems, args) }, 52 | { IPActionType.SendCommand, () => Commanding.Execute(Base.commandings, args) }, 53 | { IPActionType.UpgradeItem, () => 54 | { 55 | if (player.GameObject.TryGetComponent(out Collider col)) 56 | { 57 | List vs = new List(); 58 | for (int j = 0; j < 5; j++) 59 | { 60 | if (Base.Scp914Mode.HasFlag((Scp914Mode)j)) 61 | { 62 | vs.Add(j); 63 | } 64 | } 65 | Scp914.Scp914Upgrader.Upgrade( 66 | new Collider[] { col }, 67 | Scp914.Scp914Mode.Held, 68 | (Scp914.Scp914KnobSetting)vs.RandomItem() 69 | ); 70 | } 71 | } 72 | }, 73 | { IPActionType.GiveEffect, () => EffectGivingModule.Execute(Base.effectGivingModules, args) }, 74 | { IPActionType.PlayAudio, () => AudioModule.Execute(Base.AudioModules, args) }, 75 | { IPActionType.CallGroovieNoise, () => CGNModule.Execute(Base.GroovieNoiseToCall, args) }, 76 | { IPActionType.CallFunction, () => CFEModule.Execute(Base.FunctionToCall, args) } 77 | }; 78 | foreach (IPActionType type in Enum.GetValues(typeof(IPActionType))) 79 | { 80 | if (Base.ActionType.HasFlag(type) && actionExecutors.TryGetValue(type, out var execute)) 81 | { 82 | execute(); 83 | } 84 | } 85 | } 86 | 87 | void OnDestroy() 88 | { 89 | AdvancedMERTools.Singleton.interactableObjects.Remove(this); 90 | } 91 | 92 | static readonly Dictionary> Formatter = new Dictionary> 93 | { 94 | { "{p_i}", vs => (vs[0] as Player).Id.ToString() }, 95 | { "{p_name}", vs => (vs[0] as Player).Nickname.ToString() }, 96 | { "{p_pos}", vs => { Vector3 pos = (vs[0] as Player).Transform.position; return $"{pos.x} {pos.y} {pos.z}"; } }, 97 | { "{p_room}", vs => (vs[0] as Player).CurrentRoom.RoomName.ToString() }, 98 | { "{p_zone}", vs => (vs[0] as Player).Zone.ToString() }, 99 | { "{p_role}", vs => (vs[0] as Player).Role.Type.ToString() }, 100 | { "{p_item}", vs => (vs[0] as Player).CurrentItem.Type.ToString() } 101 | }; 102 | 103 | public new IODTO Base; 104 | } 105 | 106 | public class FInteractableObject : InteractableObject 107 | { 108 | protected override void Start() 109 | { 110 | this.Base = ((AMERTInteractable)this).Base as FIODTO; 111 | AdvancedMERTools.Singleton.interactableObjects.Add(this); 112 | if (AdvancedMERTools.Singleton.IOkeys.ContainsKey(Base.InputKeyCode)) 113 | { 114 | AdvancedMERTools.Singleton.IOkeys[Base.InputKeyCode].Add(this); 115 | } 116 | else 117 | { 118 | List original = ServerSpecificSettingsSync.DefinedSettings.ToList(); 119 | int index = original.FindIndex(x => x is SSGroupHeader && x.Label.Equals("AMERT Keybinds")); 120 | bool flag = false; 121 | SSKeybindSetting key = new SSKeybindSetting(null, $"AMERT - Interactable Object - {(KeyCode)Base.InputKeyCode}", (KeyCode)Base.InputKeyCode, true, ""); 122 | if (index == -1) 123 | original.Add(new SSGroupHeader("AMERT Keybinds")); 124 | else 125 | { 126 | for (index++; index < original.Count; index++) 127 | { 128 | if (original[index].Label == null || !original[index].Label.StartsWith("AMERT")) 129 | { 130 | flag = true; 131 | original.Insert(index, key); 132 | break; 133 | } 134 | } 135 | } 136 | if (!flag) 137 | original.Add(key); 138 | ServerSpecificSettingsSync.DefinedSettings = original.ToArray(); 139 | ServerSpecificSettingsSync.SendToAll(); 140 | AdvancedMERTools.Singleton.IOkeys.Add(Base.InputKeyCode, new List { this }); 141 | } 142 | } 143 | 144 | public override void RunProcess(Player player) 145 | { 146 | if (!Active) 147 | return; 148 | FunctionArgument args = new FunctionArgument(this, player); 149 | var actionExecutors = new Dictionary 150 | { 151 | { IPActionType.Disappear, () => Destroy(this.gameObject, 0.1f) }, 152 | { IPActionType.Explode, () => FExplodeModule.Execute(Base.ExplodeModules, args) }, 153 | { IPActionType.PlayAnimation, () => FAnimationDTO.Execute(Base.AnimationModules, args) }, 154 | { IPActionType.Warhead, () => AlphaWarhead(Base.warheadActionType.GetValue(args, 0)) }, 155 | { IPActionType.SendMessage, () => FMessageModule.Execute(Base.MessageModules, args) }, 156 | { IPActionType.DropItems, () => FDropItem.Execute(Base.dropItems, args) }, 157 | { IPActionType.SendCommand, () => FCommanding.Execute(Base.commandings, args) }, 158 | { IPActionType.UpgradeItem, () => 159 | { 160 | if (player.GameObject.TryGetComponent(out Collider col)) 161 | { 162 | List vs = new List(); 163 | Scp914Mode mode = Base.Scp914Mode.GetValue(args, 0); 164 | for (int j = 0; j < 5; j++) 165 | { 166 | if (mode.HasFlag((Scp914Mode)j)) 167 | { 168 | vs.Add(j); 169 | } 170 | } 171 | Scp914.Scp914Upgrader.Upgrade( 172 | new Collider[] { col }, 173 | Scp914.Scp914Mode.Held, 174 | (Scp914.Scp914KnobSetting)vs.RandomItem() 175 | ); 176 | } 177 | } 178 | }, 179 | { IPActionType.GiveEffect, () => FEffectGivingModule.Execute(Base.effectGivingModules, args) }, 180 | { IPActionType.PlayAudio, () => FAudioModule.Execute(Base.AudioModules, args) }, 181 | { IPActionType.CallGroovieNoise, () => FCGNModule.Execute(Base.GroovieNoiseToCall, args) }, 182 | { IPActionType.CallFunction, () => FCFEModule.Execute(Base.FunctionToCall, args) } 183 | }; 184 | foreach (IPActionType type in Enum.GetValues(typeof(IPActionType))) 185 | { 186 | if (Base.ActionType.HasFlag(type) && actionExecutors.TryGetValue(type, out var execute)) 187 | { 188 | execute(); 189 | } 190 | } 191 | } 192 | 193 | void OnDestroy() 194 | { 195 | AdvancedMERTools.Singleton.interactableObjects.Remove(this); 196 | } 197 | 198 | public new FIODTO Base; 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /Advanced MER tools/Serializables.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections; 5 | using System.ComponentModel; 6 | using System.IO; 7 | using UnityEditor; 8 | using UnityEngine; 9 | using System.Reflection; 10 | //using NaughtyAttributes; 11 | 12 | [Flags] 13 | [Serializable] 14 | public enum ColliderActionType 15 | { 16 | ModifyHealth = 1, 17 | GiveEffect = 2, 18 | SendMessage = 4, 19 | PlayAnimation = 8, 20 | SendCommand = 16, 21 | Warhead = 32, 22 | Explode = 64, 23 | PlayAudio = 128, 24 | CallGroovieNoise = 256, 25 | CallFunction = 512, 26 | } 27 | 28 | [Flags] 29 | [Serializable] 30 | public enum CollisionType 31 | { 32 | OnEnter = 1, 33 | OnStay = 2, 34 | OnExit = 4, 35 | } 36 | 37 | [Flags] 38 | [Serializable] 39 | public enum DetectType 40 | { 41 | Pickup = 1, 42 | Player = 2, 43 | Projectile = 4 44 | } 45 | 46 | [Flags] 47 | [Serializable] 48 | public enum EffectFlag 49 | { 50 | Disable = 1, 51 | Enable = 2, 52 | ModifyDuration = 4, 53 | ForceDuration = 8, 54 | ModifyIntensity = 16, 55 | ForceIntensity = 32 56 | } 57 | 58 | [Serializable] 59 | public enum EffectType 60 | { 61 | None, 62 | // Token: 0x0400036B RID: 875 63 | AmnesiaItems, 64 | // Token: 0x0400036C RID: 876 65 | AmnesiaVision, 66 | // Token: 0x0400036D RID: 877 67 | Asphyxiated, 68 | // Token: 0x0400036E RID: 878 69 | Bleeding, 70 | // Token: 0x0400036F RID: 879 71 | Blinded, 72 | // Token: 0x04000370 RID: 880 73 | Burned, 74 | // Token: 0x04000371 RID: 881 75 | Concussed, 76 | // Token: 0x04000372 RID: 882 77 | Corroding, 78 | // Token: 0x04000373 RID: 883 79 | Deafened, 80 | // Token: 0x04000374 RID: 884 81 | Decontaminating, 82 | // Token: 0x04000375 RID: 885 83 | Disabled, 84 | // Token: 0x04000376 RID: 886 85 | Ensnared, 86 | // Token: 0x04000377 RID: 887 87 | Exhausted, 88 | // Token: 0x04000378 RID: 888 89 | Flashed, 90 | // Token: 0x04000379 RID: 889 91 | Hemorrhage, 92 | // Token: 0x0400037A RID: 890 93 | Invigorated, 94 | // Token: 0x0400037B RID: 891 95 | BodyshotReduction, 96 | // Token: 0x0400037C RID: 892 97 | Poisoned, 98 | // Token: 0x0400037D RID: 893 99 | Scp207, 100 | // Token: 0x0400037E RID: 894 101 | Invisible, 102 | // Token: 0x0400037F RID: 895 103 | SinkHole, 104 | // Token: 0x04000380 RID: 896 105 | DamageReduction, 106 | // Token: 0x04000381 RID: 897 107 | MovementBoost, 108 | // Token: 0x04000382 RID: 898 109 | RainbowTaste, 110 | // Token: 0x04000383 RID: 899 111 | SeveredHands, 112 | // Token: 0x04000384 RID: 900 113 | Stained, 114 | // Token: 0x04000385 RID: 901 115 | Vitality, 116 | // Token: 0x04000386 RID: 902 117 | Hypothermia, 118 | // Token: 0x04000387 RID: 903 119 | Scp1853, 120 | // Token: 0x04000388 RID: 904 121 | CardiacArrest, 122 | // Token: 0x04000389 RID: 905 123 | InsufficientLighting, 124 | // Token: 0x0400038A RID: 906 125 | SoundtrackMute, 126 | // Token: 0x0400038B RID: 907 127 | SpawnProtected, 128 | // Token: 0x0400038C RID: 908 129 | Traumatized, 130 | // Token: 0x0400038D RID: 909 131 | AntiScp207, 132 | // Token: 0x0400038E RID: 910 133 | Scanned, 134 | // Token: 0x0400038F RID: 911 135 | PocketCorroding, 136 | // Token: 0x04000390 RID: 912 137 | SilentWalk, 138 | // Token: 0x04000391 RID: 913 139 | [Obsolete("Not functional in-game")] 140 | Marshmallow, 141 | // Token: 0x04000392 RID: 914 142 | Strangled, 143 | // Token: 0x04000393 RID: 915 144 | Ghostly, 145 | // Token: 0x04000394 RID: 916 146 | FogControl, 147 | // Token: 0x04000395 RID: 917 148 | Slowness, 149 | // Token: 0x04000396 RID: 918 150 | Scp1344, 151 | // Token: 0x04000397 RID: 919 152 | SeveredEyes, 153 | // Token: 0x04000398 RID: 920 154 | PitDeath, 155 | // Token: 0x04000399 RID: 921 156 | Blurred, 157 | // Token: 0x0400039A RID: 922 158 | [Obsolete("Only availaible for Christmas and AprilFools.")] 159 | BecomingFlamingo, 160 | // Token: 0x0400039B RID: 923 161 | [Obsolete("Only availaible for Christmas and AprilFools.")] 162 | Scp559, 163 | // Token: 0x0400039C RID: 924 164 | [Obsolete("Only availaible for Christmas and AprilFools.")] 165 | Scp956Target, 166 | // Token: 0x0400039D RID: 925 167 | [Obsolete("Only availaible for Christmas and AprilFools.")] 168 | Snowed 169 | } 170 | 171 | [Flags] 172 | [Serializable] 173 | public enum TeleportInvokeType 174 | { 175 | Enter = 1, 176 | Exit = 2, 177 | Collide = 4 178 | } 179 | 180 | [Flags] 181 | [Serializable] 182 | public enum DeadType 183 | { 184 | Disappear = 1, 185 | GetRigidbody = 2, 186 | DynamicDisappearing = 4, 187 | Explode = 8, 188 | ResetHP = 16, 189 | PlayAnimation = 32, 190 | Warhead = 64, 191 | SendMessage = 128, 192 | DropItems = 256, 193 | SendCommand = 512, 194 | GiveEffect = 1024, 195 | PlayAudio = 2048, 196 | CallGroovieNoise = 4096, 197 | CallFunction = 8192 198 | } 199 | 200 | [Flags] 201 | [Serializable] 202 | public enum WarheadActionType 203 | { 204 | Start = 1, 205 | Stop = 2, 206 | Lock = 4, 207 | UnLock = 8, 208 | Disable = 16, 209 | Enable = 32 210 | } 211 | 212 | [Serializable] 213 | public enum AnimationType 214 | { 215 | Start, 216 | Stop, 217 | ModifyParameter 218 | } 219 | 220 | [Serializable] 221 | public enum ParameterType 222 | { 223 | Integer, 224 | Float, 225 | Bool, 226 | Trigger 227 | } 228 | 229 | [Serializable] 230 | public enum MessageType 231 | { 232 | Cassie, 233 | BroadCast, 234 | Hint 235 | } 236 | 237 | [Flags] 238 | [Serializable] 239 | public enum SendType 240 | { 241 | Interactor = 1, 242 | AllExceptAboveOne = 2, 243 | Alive = 4, 244 | Spectators = 8 245 | } 246 | 247 | [Flags] 248 | [Serializable] 249 | public enum Scp914Mode 250 | { 251 | Rough = 1, 252 | Coarse = 2, 253 | OneToOne = 4, 254 | Fine = 8, 255 | VeryFine = 16 256 | } 257 | 258 | [Flags] 259 | [Serializable] 260 | public enum IPActionType 261 | { 262 | Disappear = 1, 263 | Explode = 2, 264 | PlayAnimation = 4, 265 | Warhead = 8, 266 | SendMessage = 16, 267 | DropItems = 32, 268 | SendCommand = 64, 269 | UpgradeItem = 128, 270 | GiveEffect = 256, 271 | PlayAudio = 512, 272 | CallGroovieNoise = 1024, 273 | CallFunction = 2048, 274 | } 275 | 276 | [Flags] 277 | [Serializable] 278 | public enum InvokeType 279 | { 280 | Searching = 1, 281 | Picked = 2 282 | } 283 | 284 | [Serializable] 285 | public enum RoleTypeId : sbyte 286 | { 287 | // Token: 0x04000F02 RID: 3842 288 | None = -1, 289 | // Token: 0x04000F03 RID: 3843 290 | Scp173, 291 | // Token: 0x04000F04 RID: 3844 292 | ClassD, 293 | // Token: 0x04000F05 RID: 3845 294 | Spectator, 295 | // Token: 0x04000F06 RID: 3846 296 | Scp106, 297 | // Token: 0x04000F07 RID: 3847 298 | NtfSpecialist, 299 | // Token: 0x04000F08 RID: 3848 300 | Scp049, 301 | // Token: 0x04000F09 RID: 3849 302 | Scientist, 303 | // Token: 0x04000F0A RID: 3850 304 | Scp079, 305 | // Token: 0x04000F0B RID: 3851 306 | ChaosConscript, 307 | // Token: 0x04000F0C RID: 3852 308 | Scp096, 309 | // Token: 0x04000F0D RID: 3853 310 | Scp0492, 311 | // Token: 0x04000F0E RID: 3854 312 | NtfSergeant, 313 | // Token: 0x04000F0F RID: 3855 314 | NtfCaptain, 315 | // Token: 0x04000F10 RID: 3856 316 | NtfPrivate, 317 | // Token: 0x04000F11 RID: 3857 318 | Tutorial, 319 | // Token: 0x04000F12 RID: 3858 320 | FacilityGuard, 321 | // Token: 0x04000F13 RID: 3859 322 | Scp939, 323 | // Token: 0x04000F14 RID: 3860 324 | CustomRole, 325 | // Token: 0x04000F15 RID: 3861 326 | ChaosRifleman, 327 | // Token: 0x04000F16 RID: 3862 328 | ChaosMarauder, 329 | // Token: 0x04000F17 RID: 3863 330 | ChaosRepressor, 331 | // Token: 0x04000F18 RID: 3864 332 | Overwatch, 333 | // Token: 0x04000F19 RID: 3865 334 | Filmmaker, 335 | // Token: 0x04000F1A RID: 3866 336 | Scp3114, 337 | // Token: 0x04000F1B RID: 3867 338 | Destroyed, 339 | // Token: 0x04000F1C RID: 3868 340 | Flamingo, 341 | // Token: 0x04000F1D RID: 3869 342 | AlphaFlamingo, 343 | // Token: 0x04000F1E RID: 3870 344 | ZombieFlamingo 345 | } 346 | 347 | public class PublicFunctions 348 | { 349 | public static string FindPath(GameObject mono) 350 | { 351 | if (mono == null) 352 | return ""; 353 | return FindPath(mono.transform); 354 | } 355 | 356 | public static string FindPath(Transform transform) 357 | { 358 | string path = ""; 359 | if (transform.TryGetComponent(out _)) 360 | { 361 | return path; 362 | } 363 | while (transform.parent != null) 364 | { 365 | for (int i = 0; i < transform.parent.childCount; i++) 366 | { 367 | if (transform.parent.GetChild(i) == transform) 368 | { 369 | path += i.ToString(); 370 | } 371 | } 372 | transform = transform.parent; 373 | if (transform.TryGetComponent(out _)) break; 374 | path += " "; 375 | } 376 | return path; 377 | } 378 | 379 | public static void OnIDChange(int original, int New) 380 | { 381 | //Debug.Log("!!"); 382 | AMERTs.RemoveWhere(x => x == null); 383 | //Debug.Log(AMERTs.Count); 384 | foreach (FakeMono noise in AMERTs) 385 | { 386 | if (noise is GroovyNoise && (noise as GroovyNoise).data.Settings != null) 387 | { 388 | foreach (GMDTO id in (noise as GroovyNoise).data.Settings) 389 | { 390 | for (int i = 0; i < id.Targets.Count; i++) 391 | { 392 | if (id.Targets[i] == original) 393 | { 394 | id.Targets[i] = New; 395 | } 396 | } 397 | } 398 | } 399 | else 400 | { 401 | //Debug.Log(noise.GetType()); 402 | object arr; 403 | object obj; 404 | FieldInfo info = noise.GetType().GetField("data", BindingFlags.Instance | BindingFlags.Public); 405 | if (info != null && (obj = info.GetValue(noise)) != null) 406 | { 407 | FieldInfo info1 = obj.GetType().GetField("GroovieNoiseToCall", BindingFlags.Instance | BindingFlags.Public); 408 | if (info1 != null && (arr = info1.GetValue(obj)) != null) 409 | { 410 | foreach (CGNModule module in (List)arr) 411 | { 412 | if (module.GroovieNoiseId == original) 413 | module.GroovieNoiseId = New; 414 | } 415 | } 416 | } 417 | } 418 | } 419 | } 420 | 421 | public static HashSet AMERTs = new HashSet { }; 422 | } -------------------------------------------------------------------------------- /Advanced MER tools/Modules.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections; 5 | using System.ComponentModel; 6 | using System.IO; 7 | using UnityEditor; 8 | using UnityEngine; 9 | using System.Reflection; 10 | 11 | public class FakeMono : MonoBehaviour 12 | { 13 | [Header("Used for GroovyNoise")] 14 | [JsonIgnore] 15 | public int ScriptId; 16 | public string ScriptGroup; 17 | public bool UseScriptValue; 18 | public DTO data; 19 | public DTO ScriptValueData; 20 | public virtual DTO _data { get => data; } 21 | public virtual DTO _ScriptValueData { get => ScriptValueData; } 22 | private void OnValidate() 23 | { 24 | PublicFunctions.AMERTs.Add(this); 25 | int t = GetInstanceID(); 26 | if (ScriptId != t) 27 | { 28 | PublicFunctions.OnIDChange(ScriptId, t); 29 | ScriptId = t; 30 | } 31 | if (_data != null && _ScriptValueData != null) 32 | { 33 | _data.parent = this; 34 | _ScriptValueData.parent = this; 35 | _data.Code = _ScriptValueData.Code = ScriptId; 36 | _data.UseScriptValue = _ScriptValueData.UseScriptValue = UseScriptValue; 37 | _data.ScriptGroup = _ScriptValueData.ScriptGroup = ScriptGroup; 38 | _data.ObjectId = _ScriptValueData.ObjectId = PublicFunctions.FindPath(transform); 39 | try 40 | { 41 | _data.OnValidate(); 42 | } 43 | catch { } 44 | try 45 | { 46 | _ScriptValueData.OnValidate(); 47 | } 48 | catch { } 49 | } 50 | } 51 | } 52 | 53 | [Serializable] 54 | public abstract class DTO 55 | { 56 | public abstract void OnValidate(); 57 | 58 | public bool Active; 59 | [HideInInspector] 60 | public string ObjectId; 61 | [HideInInspector] 62 | public int Code; 63 | [HideInInspector] 64 | public string ScriptGroup; 65 | [HideInInspector] 66 | public bool UseScriptValue; 67 | [HideInInspector] 68 | [JsonIgnore] 69 | public FakeMono parent; 70 | } 71 | 72 | [Serializable] 73 | public class CGNModule : RandomExecutionModule 74 | { 75 | public int GroovieNoiseId; 76 | public string GroovieNoiseGroup; 77 | } 78 | 79 | [Serializable] 80 | public class FCGNModule : FRandomExecutionModule 81 | { 82 | public override void OnValidate() 83 | { 84 | base.OnValidate(); 85 | GroovieNoiseId.OnValidate(); 86 | GroovieNoiseGroup.OnValidate(); 87 | } 88 | 89 | public ScriptValue GroovieNoiseId; 90 | public ScriptValue GroovieNoiseGroup; 91 | } 92 | 93 | [Serializable] 94 | public class CFEModule : RandomExecutionModule 95 | { 96 | public string FunctionName; 97 | } 98 | 99 | [Serializable] 100 | public class FCFEModule : FRandomExecutionModule 101 | { 102 | public override void OnValidate() 103 | { 104 | base.OnValidate(); 105 | FunctionName.OnValidate(); 106 | FunctionArguments.ForEach(x => x.OnValidate()); 107 | } 108 | 109 | public ScriptValue FunctionName; 110 | public List FunctionArguments; 111 | } 112 | 113 | [Serializable] 114 | public class EffectGivingModule : RandomExecutionModule 115 | { 116 | public EffectFlag EffectFlag; 117 | public EffectType effectType; 118 | public SendType GivingTo; 119 | public byte Inensity; 120 | public float Duration; 121 | } 122 | 123 | [Serializable] 124 | public class FEffectGivingModule : FRandomExecutionModule 125 | { 126 | public override void OnValidate() 127 | { 128 | base.OnValidate(); 129 | EffectFlag.OnValidate(); 130 | effectType.OnValidate(); 131 | GivingTo.OnValidate(); 132 | Inensity.OnValidate(); 133 | Duration.OnValidate(); 134 | } 135 | 136 | public ScriptValue EffectFlag; 137 | public ScriptValue effectType; 138 | public ScriptValue GivingTo; 139 | public ScriptValue Inensity; 140 | public ScriptValue Duration; 141 | } 142 | 143 | [Serializable] 144 | public class ExplodeModule : RandomExecutionModule 145 | { 146 | public bool FFon; 147 | public bool EffectOnly; 148 | public SVector3 LocalPosition; 149 | } 150 | 151 | [Serializable] 152 | public class FExplodeModule : FRandomExecutionModule 153 | { 154 | public override void OnValidate() 155 | { 156 | base.OnValidate(); 157 | FFon.OnValidate(); 158 | EffectOnly.OnValidate(); 159 | LocalPosition.OnValidate(); 160 | } 161 | 162 | public ScriptValue FFon; 163 | public ScriptValue EffectOnly; 164 | public ScriptValue LocalPosition; 165 | } 166 | 167 | [Serializable] 168 | public class AnimationDTO : RandomExecutionModule 169 | { 170 | [JsonIgnore] 171 | public GameObject Animator; 172 | [HideInInspector] 173 | public string AnimatorAdress; 174 | public string AnimationName; 175 | public AnimationType AnimationType; 176 | public ParameterType ParameterType; 177 | public string ParameterName; 178 | [Header("If parameter type is bool or trigger, input 0 for false, and input 1 for true.")] 179 | public string ParameterValue; 180 | } 181 | 182 | [Serializable] 183 | public class FAnimationDTO : FRandomExecutionModule 184 | { 185 | public override void OnValidate() 186 | { 187 | base.OnValidate(); 188 | AnimationName.OnValidate(); 189 | AnimationType.OnValidate(); 190 | ParameterType.OnValidate(); 191 | ParameterName.OnValidate(); 192 | ParameterValue.OnValidate(); 193 | AnimatorAdress = PublicFunctions.FindPath(Animator); 194 | } 195 | 196 | [JsonIgnore] 197 | public GameObject Animator; 198 | [HideInInspector] 199 | public string AnimatorAdress; 200 | public ScriptValue AnimationName; 201 | public ScriptValue AnimationType; 202 | public ScriptValue ParameterType; 203 | public ScriptValue ParameterName; 204 | [Header("If parameter type is bool or trigger, input 0 for false, and input 1 for true.")] 205 | public ScriptValue ParameterValue; 206 | } 207 | 208 | [Serializable] 209 | public class GMDTO : RandomExecutionModule 210 | { 211 | public List Targets; 212 | public List TargetGroups; 213 | public bool Enable; 214 | } 215 | 216 | [Serializable] 217 | public class FGMDTO : FRandomExecutionModule 218 | { 219 | public override void OnValidate() 220 | { 221 | base.OnValidate(); 222 | Targets.OnValidate(); 223 | TargetGroups.OnValidate(); 224 | Enable.OnValidate(); 225 | } 226 | 227 | public ScriptValue Targets; 228 | public ScriptValue TargetGroups; 229 | public ScriptValue Enable; 230 | } 231 | 232 | [Serializable] 233 | public class MessageModule : RandomExecutionModule 234 | { 235 | public SendType SendType; 236 | [Tooltip("{p_i} = player id.\n{p_name}\n{p_pos}\n{p_room}\n{p_zone}\n{p_role}\n{o_pos} = object's exact position.\n{o_room}\n{o_zone}\n{p_item} = player's current item." + 237 | "\n{damage} (HealthObject only)")] 238 | public string MessageContent; 239 | public MessageType MessageType; 240 | public float Duration; 241 | } 242 | 243 | [Serializable] 244 | public class FMessageModule : FRandomExecutionModule 245 | { 246 | public override void OnValidate() 247 | { 248 | base.OnValidate(); 249 | SendType.OnValidate(); 250 | MessageContent.OnValidate(); 251 | MessageType.OnValidate(); 252 | Duration.OnValidate(); 253 | } 254 | 255 | public ScriptValue SendType; 256 | public ScriptValue MessageContent; 257 | public ScriptValue MessageType; 258 | public ScriptValue Duration; 259 | } 260 | 261 | [Serializable] 262 | public class AudioModule : RandomExecutionModule 263 | { 264 | public string AudioName; 265 | [Header("0: Loop")] 266 | public int PlayCount; 267 | public bool IsSpatial; 268 | public float MaxDistance; 269 | public float MinDistance; 270 | public float Volume; 271 | public SVector3 LocalPlayPosition; 272 | } 273 | 274 | [Serializable] 275 | public class FAudioModule : FRandomExecutionModule 276 | { 277 | public override void OnValidate() 278 | { 279 | base.OnValidate(); 280 | AudioName.OnValidate(); 281 | PlayCount.OnValidate(); 282 | IsSpatial.OnValidate(); 283 | MaxDistance.OnValidate(); 284 | MinDistance.OnValidate(); 285 | Volume.OnValidate(); 286 | LocalPlayPosition.OnValidate(); 287 | } 288 | 289 | public ScriptValue AudioName; 290 | [Header("0: Loop")] 291 | public ScriptValue PlayCount; 292 | public ScriptValue IsSpatial; 293 | public ScriptValue MaxDistance; 294 | public ScriptValue MinDistance; 295 | public ScriptValue Volume; 296 | public ScriptValue LocalPlayPosition; 297 | } 298 | 299 | [Serializable] 300 | public class RandomExecutionModule 301 | { 302 | public float ChanceWeight; 303 | public bool ForceExecute; 304 | public float ActionDelay; 305 | } 306 | 307 | [Serializable] 308 | public class FRandomExecutionModule : Value 309 | { 310 | public override void OnValidate() 311 | { 312 | ChanceWeight.OnValidate(); 313 | ForceExecute.OnValidate(); 314 | ActionDelay.OnValidate(); 315 | } 316 | 317 | [JsonIgnore] 318 | [HideInInspector] 319 | public DTO parent; 320 | public ScriptValue ChanceWeight; 321 | public ScriptValue ForceExecute; 322 | public ScriptValue ActionDelay; 323 | } 324 | 325 | [Serializable] 326 | public class DropItem : RandomExecutionModule 327 | { 328 | public ItemType ItemType; 329 | public uint CustomItemId; 330 | public int Count; 331 | public SVector3 DropLocalPosition; 332 | } 333 | 334 | [Serializable] 335 | public class FDropItem : FRandomExecutionModule 336 | { 337 | public override void OnValidate() 338 | { 339 | base.OnValidate(); 340 | ItemType.OnValidate(); 341 | CustomItemId.OnValidate(); 342 | Count.OnValidate(); 343 | DropLocalPosition.OnValidate(); 344 | } 345 | 346 | public ScriptValue ItemType; 347 | public ScriptValue CustomItemId; 348 | public ScriptValue Count; 349 | public ScriptValue DropLocalPosition; 350 | } 351 | 352 | [Serializable] 353 | public class Commanding : RandomExecutionModule 354 | { 355 | [Tooltip("{p_i} = player id.\n{p_name}\n{p_pos}\n{p_room}\n{p_zone}\n{p_role}\n{o_pos} = object's exact position.\n{o_room}\n{o_zone}\n{p_item} = attacker's current item." + 356 | "\n{damage} (HealthObject only)")] 357 | public string CommandContext; 358 | } 359 | 360 | [Serializable] 361 | public class FCommanding : FRandomExecutionModule 362 | { 363 | public ScriptValue CommandContext; 364 | 365 | public override void OnValidate() 366 | { 367 | CommandContext.OnValidate(); 368 | } 369 | } 370 | 371 | [Serializable] 372 | public class SVector3 373 | { 374 | public float x; 375 | public float y; 376 | public float z; 377 | } 378 | 379 | [Serializable] 380 | public class WhitelistWeapon 381 | { 382 | public ItemType ItemType; 383 | public uint CustomItemId; 384 | } 385 | 386 | [Serializable] 387 | public class FWhitelistWeapon : Value 388 | { 389 | public override void OnValidate() 390 | { 391 | ItemType.OnValidate(); 392 | CustomItemId.OnValidate(); 393 | } 394 | 395 | public ScriptValue ItemType; 396 | public ScriptValue CustomItemId; 397 | } -------------------------------------------------------------------------------- /Advanced MER tools/FunctionExecutor.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections; 5 | using System.ComponentModel; 6 | using System.IO; 7 | using UnityEditor; 8 | using UnityEngine; 9 | using System.Reflection; 10 | 11 | public class FunctionExecutor : MonoBehaviour 12 | { 13 | private void OnValidate() 14 | { 15 | try 16 | { 17 | data.OnValidate(); 18 | } 19 | catch { } 20 | } 21 | 22 | public FEDTO data; 23 | } 24 | 25 | [Serializable] 26 | public class FEDTO 27 | { 28 | public void OnValidate() 29 | { 30 | Conditions.ForEach(x => x.OnValidate()); 31 | Actions.ForEach(x => x.OnValidate()); 32 | } 33 | 34 | public string FunctionName; 35 | public string[] ArgumentsName; 36 | public List Conditions; 37 | public List Actions; 38 | } 39 | 40 | 41 | [Serializable] 42 | public class ScriptAction 43 | { 44 | public FunctionType ActionType; 45 | [SerializeReference] 46 | public Function function; 47 | 48 | public void OnValidate() 49 | { 50 | if (!IsFunctionTypeMatch(function, ActionType)) 51 | { 52 | function = (Function)CreateFunctionInstance(ActionType); 53 | } 54 | function.OnValidate(); 55 | } 56 | 57 | private bool IsFunctionTypeMatch(object functionInstance, FunctionType actionType) 58 | { 59 | if (functionInstance == null) 60 | return false; 61 | if (EnumToFunc.TryGetValue(actionType, out Type type)) 62 | return functionInstance.GetType() == type; 63 | else 64 | return false; 65 | } 66 | 67 | private object CreateFunctionInstance(FunctionType actionType) 68 | { 69 | if (EnumToFunc.TryGetValue(actionType, out Type type)) 70 | return Activator.CreateInstance(type); 71 | return Activator.CreateInstance(typeof(DFunction)); 72 | } 73 | 74 | public static readonly Dictionary EnumToFunc = new Dictionary 75 | { 76 | { FunctionType.If, typeof(If) }, 77 | { FunctionType.ElseIf, typeof(ElseIf) }, 78 | { FunctionType.Else, typeof(Else) }, 79 | { FunctionType.While, typeof(While) }, 80 | { FunctionType.For, typeof(For) }, 81 | { FunctionType.ForEach, typeof(ForEach) }, 82 | { FunctionType.SetVariable, typeof(SetVariable) }, 83 | { FunctionType.Return, typeof(Return) }, 84 | { FunctionType.Wait, typeof(Wait) }, 85 | { FunctionType.CallFunction, typeof(CallFunction) }, 86 | { FunctionType.CallGroovyNoise, typeof(CallGroovyNoise) }, 87 | { FunctionType.PlayAnimation, typeof(PlayAnimation) }, 88 | { FunctionType.SendMessage, typeof(SendMessage) }, 89 | { FunctionType.SendCommand, typeof(SendCommand) }, 90 | { FunctionType.DropItems, typeof(DropItems) }, 91 | { FunctionType.Explode, typeof(Explode) }, 92 | { FunctionType.GiveEffect, typeof(GiveEffect) }, 93 | { FunctionType.PlayAudio, typeof(PlayAudio) }, 94 | { FunctionType.Warhead, typeof(FWarhead) }, 95 | { FunctionType.ChangePlayerValue, typeof(ChangePlayerValue) }, 96 | { FunctionType.PlayerAction, typeof(PlayerAction) }, 97 | { FunctionType.ChangeEntityValue, typeof(ChangeEntityValue) } 98 | }; 99 | } 100 | 101 | [Serializable] 102 | public enum FunctionType 103 | { 104 | If, 105 | ElseIf, 106 | Else, 107 | While, 108 | For, 109 | ForEach, 110 | Break, 111 | Continue, 112 | SetVariable, 113 | Return, 114 | Wait, 115 | CallFunction, 116 | CallGroovyNoise, 117 | PlayAnimation, 118 | SendMessage, 119 | SendCommand, 120 | DropItems, 121 | Explode, 122 | GiveEffect, 123 | PlayAudio, 124 | Warhead, 125 | ChangePlayerValue, 126 | PlayerAction, 127 | ChangeEntityValue 128 | } 129 | 130 | [Serializable] 131 | public abstract class Function 132 | { 133 | public abstract void OnValidate(); 134 | } 135 | 136 | [Serializable] 137 | public class DFunction : Function 138 | { 139 | public override void OnValidate() 140 | { 141 | } 142 | } 143 | 144 | [Serializable] 145 | public class ScriptValue 146 | { 147 | public ValueType ValueType; 148 | [SerializeReference] 149 | public Value value; 150 | 151 | public void OnValidate() 152 | { 153 | if (!IsValueTypeMatch(value, ValueType)) 154 | { 155 | value = (Value)CreateValueInstance(ValueType); 156 | } 157 | value.OnValidate(); 158 | } 159 | 160 | private bool IsValueTypeMatch(object functionInstance, ValueType valueType) 161 | { 162 | if (functionInstance == null) 163 | return false; 164 | if (EnumToV.TryGetValue(valueType, out Type type)) 165 | return functionInstance.GetType() == type; 166 | else 167 | return false; 168 | } 169 | 170 | private object CreateValueInstance(ValueType valueType) 171 | { 172 | if (EnumToV.TryGetValue(valueType, out Type type)) 173 | return Activator.CreateInstance(type); 174 | return Activator.CreateInstance(typeof(DValue)); 175 | } 176 | 177 | public static readonly Dictionary EnumToV = new Dictionary 178 | { 179 | { ValueType.Integer, typeof(Integer) }, 180 | { ValueType.Real, typeof(Real) }, 181 | { ValueType.Bool, typeof(Bool) }, 182 | { ValueType.String, typeof(String) }, 183 | { ValueType.Compare, typeof(Compare) }, 184 | { ValueType.IfThenElse, typeof(IfThenElse) }, 185 | { ValueType.Array, typeof(Array) }, 186 | { ValueType.Variable, typeof(Variable) }, 187 | { ValueType.Argument, typeof(Argument) }, 188 | { ValueType.Function, typeof(VFunction) }, 189 | { ValueType.Vector, typeof(Vector) }, 190 | { ValueType.NumUnaryOp, typeof(NumUnaryOp) }, 191 | { ValueType.NumBinomialOp, typeof(NumBinomialOp) }, 192 | { ValueType.ArrUnaryOp, typeof(ArrUnaryOp) }, 193 | { ValueType.ArrBinomialOp, typeof(ArrBinomialOp) }, 194 | { ValueType.VecUnaryOp, typeof(VecUnaryOp) }, 195 | { ValueType.VecBinomialOp, typeof(VecBinomialOp) }, 196 | { ValueType.StrUnaryOp, typeof(StrUnaryOp) }, 197 | { ValueType.StrBinomialOp, typeof(StrBinomialOp) }, 198 | { ValueType.ArrayEvaluateHelper, typeof(ArrayEvaluateHelper) }, 199 | { ValueType.ConstValue, typeof(ConstValue) }, 200 | { ValueType.EvaluateOnce, typeof(EvaluateOnce) }, 201 | { ValueType.CollisionType, typeof(VCollisionType) }, 202 | { ValueType.CollisionDetectTarget, typeof(CollisionDetectTarget) }, 203 | { ValueType.EffectType, typeof(VEffectType) }, 204 | { ValueType.EffectActionType, typeof(EffectActionType) }, 205 | //{ ValueType.TeleportInvokeType, typeof(VTeleportInvokeType) }, 206 | { ValueType.WarheadActionType, typeof(VWarheadActionType) }, 207 | { ValueType.AnimationActionType, typeof(AnimationActionType) }, 208 | { ValueType.ParameterType, typeof(VParameterType) }, 209 | { ValueType.MessageType, typeof(VMessageType) }, 210 | { ValueType.PlayerArray, typeof(PlayerArray) }, 211 | { ValueType.Scp914Mode, typeof(VScp914Mode) }, 212 | { ValueType.ItemType, typeof(VItemType) }, 213 | { ValueType.RoleType, typeof(VRoleType) }, 214 | { ValueType.PlayerUnaryOp, typeof(PlayerUnaryOp) }, 215 | { ValueType.SingleTarget, typeof(SingleTarget) }, 216 | { ValueType.ItemUnaryOp, typeof(ItemUnaryOp) }, 217 | { ValueType.EntityUnaryOp, typeof(EntityUnaryOp) }, 218 | { ValueType.EntityBinomialOp, typeof(EntityBinomialOp) } 219 | }; 220 | } 221 | 222 | [Serializable] 223 | public enum ValueType 224 | { 225 | Integer, 226 | Real, 227 | Bool, 228 | String, 229 | Null, 230 | Compare, 231 | IfThenElse, 232 | EmptyArray, 233 | Array, 234 | Variable, 235 | Argument, 236 | Function, 237 | ZeroVector, 238 | Vector, 239 | NumUnaryOp, 240 | NumBinomialOp, 241 | ArrUnaryOp, 242 | ArrBinomialOp, 243 | VecUnaryOp, 244 | VecBinomialOp, 245 | StrUnaryOp, 246 | StrBinomialOp, 247 | ArrayEvaluateHelper, 248 | ConstValue, 249 | EvaluateOnce, 250 | CollisionType, 251 | CollisionDetectTarget, 252 | EffectType, 253 | EffectActionType, 254 | WarheadActionType, 255 | AnimationActionType, 256 | ParameterType, 257 | MessageType, 258 | PlayerArray, 259 | Scp914Mode, 260 | ItemType, 261 | RoleType, 262 | SingleTarget, 263 | ItemUnaryOp, 264 | PlayerUnaryOp, 265 | EntityUnaryOp, 266 | EntityBinomialOp 267 | } 268 | 269 | [Serializable] 270 | public abstract class Value 271 | { 272 | public abstract void OnValidate(); 273 | } 274 | 275 | [Serializable] 276 | public class DValue : Value 277 | { 278 | public override void OnValidate() 279 | { 280 | } 281 | } 282 | 283 | public class FunctionExecutorCompiler 284 | { 285 | private static readonly Config Config = SchematicManager.Config; 286 | 287 | [MenuItem("SchematicManager/Compile Function Executor", priority = -11)] 288 | public static void OnCompile() 289 | { 290 | foreach (Schematic schematic in GameObject.FindObjectsOfType()) 291 | { 292 | Compile(schematic); 293 | } 294 | } 295 | 296 | public static void Compile(Schematic schematic) 297 | { 298 | string parentDirectoryPath = Directory.Exists(Config.ExportPath) 299 | ? Config.ExportPath 300 | : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), 301 | "MapEditorReborn_CompiledSchematics"); 302 | string schematicDirectoryPath = Path.Combine(parentDirectoryPath, schematic.gameObject.name); 303 | 304 | if (!Directory.Exists(parentDirectoryPath)) 305 | { 306 | Debug.LogError("Could Not find root object's compiled directory!"); 307 | return; 308 | } 309 | 310 | Directory.CreateDirectory(schematicDirectoryPath); 311 | 312 | List interactables = new List { }; 313 | 314 | foreach (FunctionExecutor ip in schematic.transform.GetComponentsInChildren()) 315 | { 316 | interactables.Add(ip.data); 317 | } 318 | 319 | string serializedData = JsonConvert.SerializeObject(interactables, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, TypeNameHandling = TypeNameHandling.Auto }).Replace("Assembly-CSharp", "AdvancedMERTools"); 320 | 321 | File.WriteAllText(Path.Combine(schematicDirectoryPath, $"{schematic.gameObject.name}-Functions.json"), serializedData); 322 | Debug.Log("Successfully Imported Functions."); 323 | } 324 | } -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/CustomCollider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnityEngine; 7 | using Exiled.API.Features; 8 | using Exiled.API.Features.Pickups; 9 | using Exiled.API.Features.Items; 10 | using MapEditorReborn.Events.EventArgs; 11 | using MapEditorReborn.API.Features.Objects; 12 | using MapEditorReborn.API.Features; 13 | using Exiled.CustomItems; 14 | using CommandSystem; 15 | using Utf8Json.Formatters; 16 | using RemoteAdmin; 17 | using Exiled.CustomItems.API.Features; 18 | using InventorySystem.Items.ThrowableProjectiles; 19 | using MapGeneration; 20 | using Mirror; 21 | 22 | namespace AdvancedMERTools 23 | { 24 | public class CustomCollider : AMERTInteractable 25 | { 26 | protected virtual void Start() 27 | { 28 | this.Base = base.Base as CCDTO; 29 | Register(); 30 | } 31 | 32 | protected void Register() 33 | { 34 | AdvancedMERTools.Singleton.CustomColliders.Add(this); 35 | CustomCollider[] customColliders = gameObject.GetComponents(); 36 | if (customColliders.Length > 1 && customColliders[0] != this) 37 | { 38 | MEC.Timing.CallDelayed(0.1f, () => 39 | { 40 | meshCollider = customColliders[0].meshCollider; 41 | }); 42 | return; 43 | } 44 | Vector3[] vs = new Vector3[] { transform.position, transform.eulerAngles }; 45 | transform.position = Vector3.zero; 46 | transform.eulerAngles = Vector3.zero; 47 | 48 | MeshFilter[] meshFilters = transform.GetComponentsInChildren(); 49 | meshCollider = gameObject.AddComponent(); 50 | CombineInstance[] combineInstances = new CombineInstance[meshFilters.Length]; 51 | 52 | for (int i = 0; i < meshFilters.Length; i++) 53 | { 54 | combineInstances[i].mesh = meshFilters[i].sharedMesh; 55 | combineInstances[i].transform = meshFilters[i].transform.localToWorldMatrix; 56 | } 57 | 58 | Mesh mesh = new Mesh(); 59 | mesh.CombineMeshes(combineInstances); 60 | meshCollider.sharedMesh = mesh; 61 | meshCollider.convex = true; 62 | meshCollider.isTrigger = true; 63 | Rigidbody rigidbody = gameObject.AddComponent(); 64 | rigidbody.isKinematic = true; 65 | 66 | //if (Base.Invisible) 67 | //{ 68 | transform.GetComponentsInChildren().ForEach(x => 69 | { 70 | //ServerConsole.AddLog("!!!!"); 71 | Exiled.API.Features.Toys.Primitive.Get(x).Flags = AdminToys.PrimitiveFlags.None; 72 | //x.gameObject.SetActive(false); 73 | //NetworkServer.Destroy(x.gameObject); 74 | }); 75 | //} 76 | //meshCollider.contactOffset = Base.ContactOffSet; 77 | 78 | transform.position = vs[0]; 79 | transform.eulerAngles = vs[1]; 80 | 81 | } 82 | 83 | void OnTriggerEnter(Collider collider) 84 | { 85 | if (Base.CollisionType.HasFlag(CollisionType.OnEnter)) 86 | RunProcess(collider); 87 | } 88 | 89 | void OnTriggerExit(Collider collider) 90 | { 91 | if (Base.CollisionType.HasFlag(CollisionType.OnExit)) 92 | RunProcess(collider); 93 | } 94 | 95 | void OnTriggerStay(Collider collider) 96 | { 97 | if (Base.CollisionType.HasFlag(CollisionType.OnStay)) 98 | RunProcess(collider); 99 | } 100 | 101 | public virtual void RunProcess(Collider collider) 102 | { 103 | if (!Active) 104 | return; 105 | bool flag = false; 106 | Player target = null; 107 | Pickup pickup = Pickup.Get(collider.gameObject); 108 | if (Base.DetectType.HasFlag(DetectType.Pickup) && pickup != null) 109 | { 110 | target = pickup.PreviousOwner; 111 | flag = true; 112 | } 113 | if (Base.DetectType.HasFlag(DetectType.Player) && Player.TryGet(collider, out target)) 114 | { 115 | flag = target.Role.Base.ActiveTime > 0.25f; 116 | } 117 | ThrownProjectile projectile = collider.GetComponentInParent(); 118 | if (Base.DetectType.HasFlag(DetectType.Projectile) && projectile != null) 119 | { 120 | target = Player.Get(projectile.PreviousOwner); 121 | flag = true; 122 | } 123 | if (!flag) 124 | return; 125 | ModuleGeneralArguments args = new ModuleGeneralArguments { player = target, TargetCalculated = false, transform = this.transform, schematic = OSchematic, interpolations = Formatter, interpolationsList = new object[] { target, gameObject } }; 126 | var colliderActionExecutors = new Dictionary 127 | { 128 | { ColliderActionType.ModifyHealth, () => 129 | { 130 | if (target != null) 131 | { 132 | if (Base.ModifyHealthAmount > 0) 133 | target.Heal(Base.ModifyHealthAmount); 134 | else 135 | target.Hurt(-1 * Base.ModifyHealthAmount); 136 | } 137 | } 138 | }, 139 | { ColliderActionType.Explode, () => ExplodeModule.Execute(Base.ExplodeModules, args) }, 140 | { ColliderActionType.PlayAnimation, () => AnimationDTO.Execute(Base.AnimationModules, args) }, 141 | { ColliderActionType.Warhead, () => AlphaWarhead(Base.warheadActionType) }, 142 | { ColliderActionType.SendMessage, () => MessageModule.Execute(Base.MessageModules, args) }, 143 | { ColliderActionType.SendCommand, () => Commanding.Execute(Base.commandings, args) }, 144 | { ColliderActionType.GiveEffect, () => EffectGivingModule.Execute(Base.effectGivingModules, args) }, 145 | { ColliderActionType.PlayAudio, () => AudioModule.Execute(Base.AudioModules, args) }, 146 | { ColliderActionType.CallGroovieNoise, () => CGNModule.Execute(Base.GroovieNoiseToCall, args) }, 147 | { ColliderActionType.CallFunction, () => CFEModule.Execute(Base.FunctionToCall, args) } 148 | }; 149 | foreach (ColliderActionType type in Enum.GetValues(typeof(ColliderActionType))) 150 | { 151 | if (Base.ColliderActionType.HasFlag(type) && colliderActionExecutors.TryGetValue(type, out var execute)) 152 | { 153 | execute(); 154 | } 155 | } 156 | } 157 | 158 | static readonly Dictionary> Formatter = new Dictionary> 159 | { 160 | { "{p_i}", vs => (vs[0] as Player).Id.ToString() }, 161 | { "{p_name}", vs => (vs[0] as Player).Nickname.ToString() }, 162 | { "{p_pos}", vs => { Vector3 pos = (vs[0] as Player).Transform.position; return $"{pos.x} {pos.y} {pos.z}"; } }, 163 | { "{p_room}", vs => (vs[0] as Player).CurrentRoom.RoomName.ToString() }, 164 | { "{p_zone}", vs => (vs[0] as Player).Zone.ToString() }, 165 | { "{p_role}", vs => (vs[0] as Player).Role.Type.ToString() }, 166 | { "{p_item}", vs => (vs[0] as Player).CurrentItem.Type.ToString() }, 167 | { "{o_pos}", vs => { Vector3 pos = (vs[1] as GameObject).transform.position; return $"{pos.x} {pos.y} {pos.z}"; } }, 168 | { "{o_room}", vs => RoomIdUtils.RoomAtPosition((vs[1] as GameObject).transform.position).Name.ToString() }, 169 | { "{o_zone}", vs => RoomIdUtils.RoomAtPosition((vs[1] as GameObject).transform.position).Zone.ToString() } 170 | }; 171 | 172 | void OnDestroy() 173 | { 174 | AdvancedMERTools.Singleton.CustomColliders.Remove(this); 175 | } 176 | 177 | public MeshCollider meshCollider; 178 | 179 | public new CCDTO Base; 180 | 181 | public Transform originalT; 182 | } 183 | 184 | public class FCustomCollider : CustomCollider 185 | { 186 | protected override void Start() 187 | { 188 | Base = ((AMERTInteractable)this).Base as FCCDTO; 189 | Register(); 190 | } 191 | 192 | public override void RunProcess(Collider collider) 193 | { 194 | if (!Active) 195 | return; 196 | bool flag = false; 197 | Player target = null; 198 | Pickup pickup = Pickup.Get(collider.gameObject); 199 | CollisionType collision = Base.DetectType.GetValue(new FunctionArgument(this), 0); 200 | if (collision.HasFlag(DetectType.Pickup) && pickup != null) 201 | { 202 | target = pickup.PreviousOwner; 203 | flag = true; 204 | } 205 | if (collision.HasFlag(DetectType.Player) && Player.TryGet(collider, out target)) 206 | { 207 | flag = target.Role.Base.ActiveTime > 0.25f; 208 | } 209 | ThrownProjectile projectile = collider.GetComponentInParent(); 210 | if (collision.HasFlag(DetectType.Projectile) && projectile != null) 211 | { 212 | target = Player.Get(projectile.PreviousOwner); 213 | flag = true; 214 | } 215 | if (!flag) 216 | return; 217 | FunctionArgument args = new FunctionArgument(this, target); 218 | var colliderActionExecutors = new Dictionary 219 | { 220 | { ColliderActionType.ModifyHealth, () => 221 | { 222 | if (target != null) 223 | { 224 | float amount = Base.ModifyHealthAmount.GetValue(args, 0f); 225 | if (amount > 0) 226 | target.Heal(amount); 227 | else 228 | target.Hurt(-amount); 229 | } 230 | } 231 | }, 232 | { ColliderActionType.Explode, () => FExplodeModule.Execute(Base.ExplodeModules, args) }, 233 | { ColliderActionType.PlayAnimation, () => FAnimationDTO.Execute(Base.AnimationModules, args) }, 234 | { ColliderActionType.Warhead, () => AlphaWarhead(Base.warheadActionType.GetValue(args, 0)) }, 235 | { ColliderActionType.SendMessage, () => FMessageModule.Execute(Base.MessageModules, args) }, 236 | { ColliderActionType.SendCommand, () => FCommanding.Execute(Base.commandings, args) }, 237 | { ColliderActionType.GiveEffect, () => FEffectGivingModule.Execute(Base.effectGivingModules, args) }, 238 | { ColliderActionType.PlayAudio, () => FAudioModule.Execute(Base.AudioModules, args) }, 239 | { ColliderActionType.CallGroovieNoise, () => FCGNModule.Execute(Base.GroovieNoiseToCall, args) }, 240 | { ColliderActionType.CallFunction, () => FCFEModule.Execute(Base.FunctionToCall, args) }, 241 | }; 242 | foreach (ColliderActionType type in Enum.GetValues(typeof(ColliderActionType))) 243 | { 244 | if (Base.ColliderActionType.HasFlag(type) && colliderActionExecutors.TryGetValue(type, out var execute)) 245 | { 246 | execute(); 247 | } 248 | } 249 | } 250 | 251 | public new FCCDTO Base; 252 | } 253 | } -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/DummyDoor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using MapEditorReborn.API.Features; 8 | using UnityEngine; 9 | using Exiled.API.Features; 10 | using MapEditorReborn.API.Features.Serializable; 11 | using MapEditorReborn.API.Features.Objects; 12 | using Exiled.API.Features.Doors; 13 | using Exiled.Events.EventArgs.Player; 14 | using System.IO; 15 | using Utf8Json; 16 | using System.Reflection.Emit; 17 | using System.Reflection; 18 | using PlayerRoles.FirstPersonControl; 19 | using PlayerRoles.FirstPersonControl.NetworkMessages; 20 | using Mirror; 21 | using PlayerRoles; 22 | using RelativePositioning; 23 | 24 | namespace AdvancedMERTools 25 | { 26 | public class DummyDoor : MonoBehaviour 27 | { 28 | public DoorSerializable door; 29 | public Door RealDoor = null; 30 | 31 | public Animator animator; 32 | 33 | static readonly Config config = AdvancedMERTools.Singleton.Config; 34 | 35 | void Start() 36 | { 37 | MEC.Timing.CallDelayed(1f, () => 38 | { 39 | animator = this.transform.GetChild(0).GetComponent(); 40 | if (RealDoor == null) 41 | { 42 | foreach (DoorObject Door in GameObject.FindObjectsOfType()) 43 | { 44 | if (door == Door.Base) 45 | { 46 | RealDoor = Door.Door; 47 | break; 48 | } 49 | } 50 | if (RealDoor == null) 51 | { 52 | float distance = float.MaxValue; 53 | foreach (Door Door in Door.List) 54 | { 55 | if (distance > Vector3.Distance(Door.Position, this.transform.position)) 56 | { 57 | distance = Vector3.Distance(Door.Position, transform.position); 58 | RealDoor = Door; 59 | } 60 | } 61 | if (RealDoor == null) 62 | { 63 | ServerConsole.AddLog("Failed to find proper door!", ConsoleColor.Red); 64 | Destroy(this.gameObject); 65 | } 66 | } 67 | } 68 | this.transform.parent = RealDoor.Base.transform; 69 | this.transform.localEulerAngles = Vector3.zero; 70 | this.transform.localPosition = Vector3.zero; 71 | if (RealDoor.Base.Rooms.Length != 0) 72 | { 73 | AdvancedMERTools.Singleton.dummyDoors.Remove(this); 74 | Destroy(this.gameObject); 75 | return; 76 | } 77 | animator.Play("DoorClose"); 78 | }); 79 | } 80 | 81 | public void OnInteractDoor(bool trigger) 82 | { 83 | if (this.RealDoor == null || animator == null) 84 | return; 85 | animator.Play(trigger ? "DoorOpen" : "DoorClose"); 86 | } 87 | 88 | void Update() 89 | { 90 | if (RealDoor == null) return; 91 | if ((RealDoor as BreakableDoor).IsDestroyed) 92 | { 93 | AdvancedMERTools.Singleton.dummyDoors.Remove(this); 94 | Destroy(this.gameObject, 0.5f); 95 | } 96 | } 97 | } 98 | 99 | public class DummyGate : MonoBehaviour 100 | { 101 | void Start() 102 | { 103 | pickups = (from item in this.gameObject.GetComponentsInChildren() 104 | select Exiled.API.Features.Pickups.Pickup.Get(item)).ToArray(); 105 | if (MapEditorReborn.API.API.CurrentLoadedMap != null && AdvancedMERTools.Singleton.Config.Gates.TryGetValue(MapEditorReborn.API.API.CurrentLoadedMap.Name, out List ser)) 106 | { 107 | if (ser.Count > AdvancedMERTools.Singleton.dummyGates.Count) 108 | { 109 | GateSerializable = ser[AdvancedMERTools.Singleton.dummyGates.Count]; 110 | if (GateSerializable.IsOpened) 111 | { 112 | MEC.Timing.CallDelayed(3f, () => { IsOpened = true; }); 113 | } 114 | } 115 | } 116 | animator = this.transform.GetChild(1).GetComponent(); 117 | AdvancedMERTools.Singleton.dummyGates.Add(this); 118 | MEC.Timing.RunCoroutine(enumerator()); 119 | } 120 | 121 | IEnumerator enumerator() 122 | { 123 | yield return MEC.Timing.WaitUntilTrue(() => Round.IsStarted); 124 | MEC.Timing.CallDelayed(0.3f, Apply); 125 | yield break; 126 | } 127 | 128 | /*public void Apply() 129 | //{ 130 | //AudioSource = AdvancedMERTools.MakeAudio("Dummy Gate #" + AdvancedMERTools.Singleton.dummyGates.Count.ToString()); 131 | //audioPlayer = AudioPlayerBase.Get(AudioSource); 132 | //audioPlayer.BroadcastChannel = VoiceChat.VoiceChatChannel.Proximity; 133 | //MEC.Timing.CallDelayed(0.3f, () => 134 | //{ 135 | // AudioSource.roleManager.ServerSetRole(PlayerRoles.RoleTypeId.Tutorial, PlayerRoles.RoleChangeReason.None, PlayerRoles.RoleSpawnFlags.None); 136 | // audioPlayer.BroadcastChannel = VoiceChat.VoiceChatChannel.Proximity; 137 | //}); 138 | //MEC.Timing.CallDelayed(0.4f, () => 139 | //{ 140 | // FpcStandardRoleBase fpc = AudioSource.roleManager.CurrentRole as FpcStandardRoleBase; 141 | // if (fpc != null) 142 | // { 143 | // fpc.FpcModule.Noclip.IsActive = true; 144 | // AudioSource.transform.position = this.transform.position; 145 | // AudioSource.transform.localScale = Vector3.one * 0.1f; 146 | // } 147 | //}); 148 | 149 | //ServerConsole.AddLog(this.transform.position.ToString()); 150 | //npc = Npc.Spawn("Gate", PlayerRoles.RoleTypeId.Tutorial, position: this.transform.position); 151 | //PropertyInfo info = typeof(CentralAuth.PlayerAuthenticationManager).GetProperty("InstanceMode"); 152 | //info.SetValue(npc.ReferenceHub.authManager, CentralAuth.ClientInstanceMode.DedicatedServer); 153 | //audioPlayer = AudioPlayerBase.Get(npc.ReferenceHub); 154 | //MEC.Timing.CallDelayed(0.35f, () => 155 | //{ 156 | // info.SetValue(npc.ReferenceHub.authManager, CentralAuth.ClientInstanceMode.ReadyClient); 157 | //}); 158 | //MEC.Timing.CallDelayed(0.55f, () => 159 | //{ 160 | // npc.Scale = Vector3.one * -0.1f; 161 | // npc.Position = this.transform.position; 162 | // (npc.RoleManager.CurrentRole as FpcStandardRoleBase).FpcModule.Noclip.IsActive = true; 163 | 164 | //}); 165 | //MEC.Timing.CallDelayed(0.45f, () => 166 | //{ 167 | // info.SetValue(npc.ReferenceHub.authManager, CentralAuth.ClientInstanceMode.DedicatedServer); 168 | //}); 169 | //}*/ 170 | 171 | public void Apply() 172 | { 173 | //ReferenceHub hub = AdvancedMERTools.MakeAudio(out int id); 174 | //MEC.Timing.CallDelayed(0.35f, () => 175 | //{ 176 | // hub.authManager.UserId = "ID_Dedicated"; 177 | // //Central Core. 178 | // hub.authManager.NetworkSyncedUserId = "ID_Dedicated"; 179 | // hub.nicknameSync.DisplayName = $"{id}-Gate"; 180 | // hub.characterClassManager.GodMode = true; 181 | // hub.transform.localScale = Vector3.one * -0.01f; 182 | // foreach (Player player in Player.List) 183 | // { 184 | // Server.SendSpawnMessage.Invoke(null, new object[] 185 | // { 186 | // hub.netIdentity, 187 | // player.Connection 188 | // }); 189 | // } 190 | // FirstPersonMovementModule module = (hub.roleManager.CurrentRole as FpcStandardRoleBase).FpcModule; 191 | // //Preventer. 192 | // module.Position = this.transform.position - Vector3.up * 0.1f; 193 | // module.Motor.ReceivedPosition = new RelativePosition(this.transform.position - Vector3.up * 0.1f); 194 | // module.Noclip.IsActive = true; 195 | //}); 196 | //MEC.Timing.CallDelayed(0.45f, () => 197 | //{ 198 | // PropertyInfo info = typeof(CentralAuth.PlayerAuthenticationManager).GetProperty("InstanceMode"); 199 | // info.SetValue(hub.authManager, CentralAuth.ClientInstanceMode.DedicatedServer); 200 | // //hub.authManager.UserId = null; 201 | //}); 202 | //audioPlayer = AudioPlayerBase.Get(hub); 203 | } 204 | 205 | void Update() 206 | { 207 | if (Cooldown >= 0) 208 | Cooldown -= Time.deltaTime; 209 | } 210 | 211 | public void OnPickingUp(SearchingPickupEventArgs ev) 212 | { 213 | if (pickups.Contains(ev.Pickup)) 214 | { 215 | ev.IsAllowed = false; 216 | if (GateSerializable != null) 217 | { 218 | if (!GateSerializable.IsLocked && CheckPermission(ev.Player, GateSerializable.keycardPermissions)) 219 | { 220 | goto IL_01; 221 | } 222 | } 223 | else 224 | { 225 | goto IL_01; 226 | } 227 | } 228 | return; 229 | IL_01:; 230 | if (Cooldown <= 0) 231 | { 232 | IsOpened = !IsOpened; 233 | } 234 | } 235 | 236 | public bool CheckPermission(Exiled.API.Features.Player player, Interactables.Interobjects.DoorUtils.KeycardPermissions keycard) 237 | { 238 | if (keycard == Interactables.Interobjects.DoorUtils.KeycardPermissions.None) 239 | { 240 | return true; 241 | } 242 | if (player != null) 243 | { 244 | if (player.IsBypassModeEnabled) 245 | { 246 | return true; 247 | } 248 | if (player.IsScp) 249 | { 250 | return keycard.HasFlag(Interactables.Interobjects.DoorUtils.KeycardPermissions.ScpOverride); 251 | } 252 | if (player.CurrentItem == null) 253 | { 254 | return false; 255 | } 256 | InventorySystem.Items.Keycards.KeycardItem keycardItem = player.CurrentItem.Base as InventorySystem.Items.Keycards.KeycardItem; 257 | if (keycardItem != null) 258 | { 259 | if (GateSerializable != null && GateSerializable.RequireAllPermission) 260 | { 261 | return (keycardItem.Permissions & keycard) == keycard; 262 | } 263 | return (keycardItem.Permissions & keycard) > Interactables.Interobjects.DoorUtils.KeycardPermissions.None; 264 | } 265 | } 266 | return false; 267 | } 268 | 269 | public bool IsOpened 270 | { 271 | get 272 | { 273 | return _IsOpened; 274 | } 275 | set 276 | { 277 | if (animator != null) 278 | { 279 | //audioPlayer.CurrentPlay = Path.Combine(Path.Combine(Paths.Configs, "Music"), value ? "GateOpen.ogg" : "GateClose.ogg"); 280 | //audioPlayer.Loop = false; 281 | //audioPlayer.Play(-1); 282 | animator.Play(value ? "GateOpen" : "GateClose"); 283 | } 284 | Cooldown = 3f; 285 | _IsOpened = value; 286 | } 287 | } 288 | 289 | GateSerializable GateSerializable; 290 | public float Cooldown = 0f; 291 | bool _IsOpened = false; 292 | public Animator animator; 293 | public Exiled.API.Features.Pickups.Pickup[] pickups; 294 | //AudioPlayerBase audioPlayer; 295 | } 296 | } 297 | -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/FunctionExecutor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections; 4 | using System.ComponentModel; 5 | using System.IO; 6 | using UnityEditor; 7 | using UnityEngine; 8 | using System.Reflection; 9 | using Exiled.API.Features; 10 | using MapEditorReborn.API.Features.Objects; 11 | using System.Threading.Tasks; 12 | 13 | namespace AdvancedMERTools 14 | { 15 | 16 | public class FunctionExecutor : AMERTInteractable 17 | { 18 | void Start() 19 | { 20 | //if (!AdvancedMERTools.Singleton.FunctionExecutors.ContainsKey(OSchematic)) 21 | // AdvancedMERTools.Singleton.FunctionExecutors.Add(OSchematic, new Dictionary { }); 22 | if (AdvancedMERTools.Singleton.FunctionExecutors[OSchematic].ContainsKey(data.FunctionName)) 23 | { 24 | ServerConsole.AddLog($"WARNING! There's another function named: {data.FunctionName}. Overlapped Function Name is not allowed!", ConsoleColor.Red); 25 | Destroy(this); 26 | return; 27 | } 28 | AdvancedMERTools.Singleton.FunctionExecutors[OSchematic].Add(data.FunctionName, this); 29 | //data.OSchematic = OSchematic; 30 | } 31 | 32 | public FEDTO data; 33 | } 34 | 35 | public class FunctionArgument 36 | { 37 | public FunctionArgument() 38 | { 39 | } 40 | 41 | public FunctionArgument(AMERTInteractable interactable, Player player = null) 42 | { 43 | schematic = interactable.OSchematic; 44 | transform = interactable.transform; 45 | this.player = player; 46 | } 47 | 48 | public List Arguments = new List { }; 49 | public FEDTO Function; 50 | public Player player; 51 | public SchematicObject schematic; 52 | public Transform transform; 53 | public List<(object, int)> Levels = new List<(object, int)> { }; 54 | public Dictionary FunctionVariables = new Dictionary { }; 55 | } 56 | 57 | public class FunctionReturn 58 | { 59 | public object value; 60 | public FunctionResult result; 61 | 62 | public static implicit operator FunctionReturn(Task t) => t.Result; 63 | } 64 | 65 | public enum FunctionResult 66 | { 67 | Default, 68 | FunctionCheck, 69 | Return, 70 | Continue, 71 | Break, 72 | Wait 73 | } 74 | 75 | [Serializable] 76 | public class FEDTO : ActionsFunctioner 77 | { 78 | public override FunctionReturn Execute(FunctionArgument args) 79 | { 80 | args.Function = this; 81 | if (!ConditionCheck(args, Conditions)) 82 | return new FunctionReturn(); 83 | return ExecuteActions(args, FunctionResult.Return); 84 | } 85 | 86 | public string FunctionName; 87 | public string[] ArgumentsName; 88 | public SchematicObject OSchematic; 89 | public List Conditions; 90 | public Dictionary ScriptVariables = new Dictionary { }; 91 | } 92 | 93 | [Serializable] 94 | public class ScriptAction 95 | { 96 | public FunctionType ActionType; 97 | public Function function; 98 | 99 | public FunctionReturn Execute(FunctionArgument args) 100 | { 101 | if (function == null) 102 | return null; 103 | if (!EnumToFunc.TryGetValue(ActionType, out _)) 104 | { 105 | switch (ActionType) 106 | { 107 | case FunctionType.Break: 108 | return new FunctionReturn { result = FunctionResult.Break }; 109 | case FunctionType.Continue: 110 | return new FunctionReturn { result = FunctionResult.Continue }; 111 | 112 | } 113 | return new FunctionReturn { result = FunctionResult.FunctionCheck }; 114 | } 115 | return function.Execute(args); 116 | } 117 | 118 | public void OnValidate() 119 | { 120 | } 121 | 122 | public static readonly Dictionary EnumToFunc = new Dictionary 123 | { 124 | { FunctionType.If, typeof(If) }, 125 | { FunctionType.ElseIf, typeof(ElseIf) }, 126 | { FunctionType.Else, typeof(Else) }, 127 | { FunctionType.While, typeof(While) }, 128 | { FunctionType.For, typeof(For) }, 129 | { FunctionType.ForEach, typeof(ForEach) }, 130 | { FunctionType.SetVariable, typeof(SetVariable) }, 131 | { FunctionType.Return, typeof(Return) }, 132 | { FunctionType.Wait, typeof(Wait) }, 133 | { FunctionType.CallFunction, typeof(CallFunction) }, 134 | { FunctionType.CallGroovyNoise, typeof(CallGroovyNoise) }, 135 | { FunctionType.PlayAnimation, typeof(PlayAnimation) }, 136 | { FunctionType.SendMessage, typeof(SendMessage) }, 137 | { FunctionType.SendCommand, typeof(SendCommand) }, 138 | { FunctionType.DropItems, typeof(DropItems) }, 139 | { FunctionType.Explode, typeof(Explode) }, 140 | { FunctionType.GiveEffect, typeof(GiveEffect) }, 141 | { FunctionType.PlayAudio, typeof(PlayAudio) }, 142 | { FunctionType.Warhead, typeof(FWarhead) }, 143 | { FunctionType.ChangePlayerValue, typeof(ChangePlayerValue) }, 144 | { FunctionType.PlayerAction, typeof(PlayerAction) }, 145 | { FunctionType.ChangeEntityValue, typeof(ChangeEntityValue) } 146 | }; 147 | } 148 | 149 | [Serializable] 150 | public enum FunctionType 151 | { 152 | If, 153 | ElseIf, 154 | Else, 155 | While, 156 | For, 157 | ForEach, 158 | Break, 159 | Continue, 160 | SetVariable, 161 | Return, 162 | Wait, 163 | CallFunction, 164 | CallGroovyNoise, 165 | PlayAnimation, 166 | SendMessage, 167 | SendCommand, 168 | DropItems, 169 | Explode, 170 | GiveEffect, 171 | PlayAudio, 172 | Warhead, 173 | ChangePlayerValue, 174 | PlayerAction, 175 | ChangeEntityValue 176 | } 177 | 178 | [Serializable] 179 | public class Function 180 | { 181 | public virtual void OnValidate() { } 182 | public virtual FunctionReturn Execute(FunctionArgument args) 183 | { 184 | return new FunctionReturn(); 185 | } 186 | } 187 | 188 | [Serializable] 189 | public class DFunction : Function 190 | { 191 | public override void OnValidate() 192 | { 193 | } 194 | } 195 | 196 | [Serializable] 197 | public class ActionsFunctioner : Function 198 | { 199 | public List Actions; 200 | 201 | public override void OnValidate() 202 | { 203 | Actions.ForEach(x => x.OnValidate()); 204 | } 205 | 206 | protected bool ConditionCheck(FunctionArgument args, object obj) 207 | { 208 | if (obj is ScriptValue) 209 | { 210 | object obj2 = ((ScriptValue)obj).GetValue(args); 211 | return obj2 != null && obj2 is bool && Convert.ToBoolean(obj2); 212 | } 213 | else if (obj is List) 214 | { 215 | return ((List)obj).TrueForAll(x => 216 | { 217 | object obj2 = x.GetValue(args); 218 | if (obj2 == null || !(obj2 is bool)) 219 | return false; 220 | return Convert.ToBoolean(obj2); 221 | }); 222 | } 223 | return false; 224 | } 225 | 226 | protected async Task ExecuteActions(FunctionArgument args, FunctionResult result = FunctionResult.Default) 227 | { 228 | bool IfActed = false; 229 | for (int i = 0; i < Actions.Count; i++) 230 | { 231 | if (Actions[i].ActionType == FunctionType.ElseIf || Actions[i].ActionType == FunctionType.Else) 232 | { 233 | if (IfActed) 234 | continue; 235 | } 236 | else 237 | IfActed = false; 238 | FunctionReturn v = Actions[i].Execute(args); 239 | switch (v.result) 240 | { 241 | case FunctionResult.Break: 242 | case FunctionResult.Continue: 243 | case FunctionResult.Return: 244 | return v; 245 | case FunctionResult.Wait: 246 | //await Task.Delay(Mathf.RoundToInt(Convert.ToSingle(v.value) * 1000f)); 247 | break; 248 | } 249 | if (v.result == FunctionResult.FunctionCheck) 250 | { 251 | switch (Actions[i].ActionType) 252 | { 253 | case FunctionType.If: 254 | case FunctionType.ElseIf: 255 | IfActed = Convert.ToBoolean(v.value); 256 | break; 257 | } 258 | } 259 | } 260 | return new FunctionReturn { result = result, value = true }; 261 | } 262 | } 263 | 264 | [Serializable] 265 | public class ScriptValue 266 | { 267 | public ValueType ValueType; 268 | public Value value; 269 | 270 | public object GetValue(FunctionArgument args) 271 | { 272 | if (value == null) 273 | return null; 274 | if (!EnumToV.TryGetValue(ValueType, out _)) 275 | { 276 | switch (ValueType) 277 | { 278 | case ValueType.ZeroVector: 279 | return Vector3.zero; 280 | case ValueType.EmptyArray: 281 | return new object[] { }; 282 | } 283 | } 284 | return value.GetValue(args); 285 | } 286 | public T GetValue(FunctionArgument args, T def) 287 | { 288 | object obj = GetValue(args); 289 | if (obj == null) 290 | return def; 291 | //ServerConsole.AddLog("!"); 292 | if ((typeof(int) == typeof(T) || typeof(float) == typeof(T)) && (obj is int || obj is float)) 293 | { 294 | if (typeof(int) == typeof(T)) 295 | return (T)(object)(obj is int ? Convert.ToInt32(obj) : Mathf.RoundToInt(Convert.ToSingle(obj))); 296 | else 297 | return (T)(object)Convert.ToSingle(obj); 298 | } 299 | if (obj is T) 300 | return (T)obj; 301 | return def; 302 | } 303 | 304 | public void OnValidate() 305 | { 306 | } 307 | 308 | public static readonly Dictionary EnumToV = new Dictionary 309 | { 310 | { ValueType.Integer, typeof(Integer) }, 311 | { ValueType.Real, typeof(Real) }, 312 | { ValueType.Bool, typeof(Bool) }, 313 | { ValueType.String, typeof(String) }, 314 | { ValueType.Compare, typeof(Compare) }, 315 | { ValueType.IfThenElse, typeof(IfThenElse) }, 316 | { ValueType.Array, typeof(Array) }, 317 | { ValueType.Variable, typeof(Variable) }, 318 | { ValueType.Argument, typeof(Argument) }, 319 | { ValueType.Function, typeof(VFunction) }, 320 | { ValueType.Vector, typeof(Vector) }, 321 | { ValueType.NumUnaryOp, typeof(NumUnaryOp) }, 322 | { ValueType.NumBinomialOp, typeof(NumBinomialOp) }, 323 | { ValueType.ArrUnaryOp, typeof(ArrUnaryOp) }, 324 | { ValueType.ArrBinomialOp, typeof(ArrBinomialOp) }, 325 | { ValueType.VecUnaryOp, typeof(VecUnaryOp) }, 326 | { ValueType.VecBinomialOp, typeof(VecBinomialOp) }, 327 | { ValueType.StrUnaryOp, typeof(StrUnaryOp) }, 328 | { ValueType.StrBinomialOp, typeof(StrBinomialOp) }, 329 | { ValueType.ArrayEvaluateHelper, typeof(ArrayEvaluateHelper) }, 330 | { ValueType.ConstValue, typeof(ConstValue) }, 331 | { ValueType.EvaluateOnce, typeof(EvaluateOnce) }, 332 | { ValueType.CollisionType, typeof(VCollisionType) }, 333 | { ValueType.CollisionDetectTarget, typeof(CollisionDetectTarget) }, 334 | { ValueType.EffectType, typeof(VEffectType) }, 335 | { ValueType.EffectActionType, typeof(EffectActionType) }, 336 | //{ ValueType.TeleportInvokeType, typeof(VTeleportInvokeType) }, 337 | { ValueType.WarheadActionType, typeof(VWarheadActionType) }, 338 | { ValueType.AnimationActionType, typeof(AnimationActionType) }, 339 | { ValueType.ParameterType, typeof(VParameterType) }, 340 | { ValueType.MessageType, typeof(VMessageType) }, 341 | { ValueType.PlayerArray, typeof(PlayerArray) }, 342 | { ValueType.Scp914Mode, typeof(VScp914Mode) }, 343 | { ValueType.ItemType, typeof(VItemType) }, 344 | { ValueType.RoleType, typeof(VRoleType) }, 345 | { ValueType.PlayerUnaryOp, typeof(PlayerUnaryOp) }, 346 | { ValueType.SingleTarget, typeof(SingleTarget) }, 347 | { ValueType.ItemUnaryOp, typeof(ItemUnaryOp) }, 348 | { ValueType.EntityUnaryOp, typeof(EntityUnaryOp) }, 349 | { ValueType.EntityBinomialOp, typeof(EntityBinomialOp) } 350 | }; 351 | } 352 | 353 | [Serializable] 354 | public enum ValueType 355 | { 356 | Integer, 357 | Real, 358 | Bool, 359 | String, 360 | Null, 361 | Compare, 362 | IfThenElse, 363 | EmptyArray, 364 | Array, 365 | Variable, 366 | Argument, 367 | Function, 368 | ZeroVector, 369 | Vector, 370 | NumUnaryOp, 371 | NumBinomialOp, 372 | ArrUnaryOp, 373 | ArrBinomialOp, 374 | VecUnaryOp, 375 | VecBinomialOp, 376 | StrUnaryOp, 377 | StrBinomialOp, 378 | ArrayEvaluateHelper, 379 | ConstValue, 380 | EvaluateOnce, 381 | CollisionType, 382 | CollisionDetectTarget, 383 | EffectType, 384 | EffectActionType, 385 | WarheadActionType, 386 | AnimationActionType, 387 | ParameterType, 388 | MessageType, 389 | PlayerArray, 390 | Scp914Mode, 391 | ItemType, 392 | RoleType, 393 | SingleTarget, 394 | ItemUnaryOp, 395 | PlayerUnaryOp, 396 | EntityUnaryOp, 397 | EntityBinomialOp 398 | } 399 | 400 | [Serializable] 401 | public class Value 402 | { 403 | public virtual void OnValidate() { } 404 | public virtual object GetValue(FunctionArgument args) 405 | { 406 | //ServerConsole.AddLog("!!!!"); 407 | return null; 408 | } 409 | } 410 | 411 | [Serializable] 412 | public class DValue : Value 413 | { 414 | public override void OnValidate() 415 | { 416 | } 417 | } 418 | } 419 | -------------------------------------------------------------------------------- /Advanced MER tools/ValueCollections.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections; 5 | using System.ComponentModel; 6 | using System.IO; 7 | using UnityEditor; 8 | using UnityEngine; 9 | using System.Reflection; 10 | 11 | [Serializable] 12 | public class Integer : Value 13 | { 14 | public int Value; 15 | public override void OnValidate() { } 16 | } 17 | 18 | [Serializable] 19 | public class Real : Value 20 | { 21 | public float Value; 22 | public override void OnValidate() { } 23 | } 24 | 25 | [Serializable] 26 | public class Bool : Value 27 | { 28 | public bool Value; 29 | public override void OnValidate() { } 30 | } 31 | 32 | [Serializable] 33 | public class String : Value 34 | { 35 | public string Value; 36 | [Header("Replace {0}, {1}, ... to assgined values.")] 37 | public List StringInterpolations = new List { }; 38 | public override void OnValidate() 39 | { 40 | StringInterpolations.ForEach(x => x.OnValidate()); 41 | } 42 | } 43 | 44 | [Serializable] 45 | public class Compare : Value 46 | { 47 | [Serializable] 48 | public enum CompareType 49 | { 50 | Equal, 51 | NotEqual, 52 | Bigger, 53 | BigOrEqual, 54 | Less, 55 | LessOrEqual, 56 | TypeEqual, 57 | And, 58 | Or, 59 | Xor, 60 | Not 61 | } 62 | 63 | public ScriptValue Value1; 64 | public CompareType Operator; 65 | public ScriptValue Value2; 66 | 67 | public override void OnValidate() 68 | { 69 | Value1.OnValidate(); 70 | Value2.OnValidate(); 71 | } 72 | } 73 | 74 | [Serializable] 75 | public class IfThenElse : Value 76 | { 77 | public ScriptValue Statement; 78 | public ScriptValue Then; 79 | public ScriptValue Else; 80 | public override void OnValidate() 81 | { 82 | Statement.OnValidate(); 83 | Then.OnValidate(); 84 | Else.OnValidate(); 85 | } 86 | } 87 | 88 | [Serializable] 89 | public class Array : Value 90 | { 91 | public ScriptValue[] Values; 92 | public override void OnValidate() 93 | { 94 | for (int i = 0; Values != null && i < Values.Length; i++) 95 | Values[i].OnValidate(); 96 | } 97 | } 98 | 99 | [Serializable] 100 | public class Variable : Value 101 | { 102 | public ScriptValue VariableName; 103 | public ScriptValue AccessLevel; 104 | public override void OnValidate() 105 | { 106 | VariableName.OnValidate(); 107 | AccessLevel.OnValidate(); 108 | } 109 | } 110 | 111 | [Serializable] 112 | public class Argument : Value 113 | { 114 | public ScriptValue ArgumentName; 115 | public override void OnValidate() 116 | { 117 | ArgumentName.OnValidate(); 118 | } 119 | } 120 | 121 | [Serializable] 122 | public class VFunction : Value 123 | { 124 | public ScriptValue FunctionName; 125 | public List Arguments; 126 | public override void OnValidate() 127 | { 128 | FunctionName.OnValidate(); 129 | Arguments.ForEach(x => x.OnValidate()); 130 | } 131 | } 132 | 133 | [Serializable] 134 | public class Vector : Value 135 | { 136 | public ScriptValue X; 137 | public ScriptValue Y; 138 | public ScriptValue Z; 139 | public override void OnValidate() 140 | { 141 | X.OnValidate(); 142 | Y.OnValidate(); 143 | Z.OnValidate(); 144 | } 145 | } 146 | 147 | [Serializable] 148 | public class NumUnaryOp : Value 149 | { 150 | [Serializable] 151 | public enum NumUnaryOpType 152 | { 153 | Inverse, 154 | Reciprocal, 155 | Absolute, 156 | Factorial, 157 | Ceiling, 158 | Floor, 159 | Round, 160 | CommonLog, 161 | NaturalLog, 162 | BinaryLog, 163 | Exponential, 164 | Sine, 165 | Cosine, 166 | Tangent, 167 | Arcsine, 168 | Arccosine, 169 | Arctangent, 170 | Sigmoid, 171 | IsPrimeNumber 172 | } 173 | 174 | public NumUnaryOpType Operator; 175 | public ScriptValue Value; 176 | 177 | public override void OnValidate() 178 | { 179 | Value.OnValidate(); 180 | } 181 | } 182 | 183 | [Serializable] 184 | public class NumBinomialOp : Value 185 | { 186 | [Serializable] 187 | public enum NumBiOpType 188 | { 189 | Add, 190 | Subtract, 191 | Multiply, 192 | Divide, 193 | Modulo, 194 | RaiseToPower, 195 | Log, 196 | Max, 197 | Min, 198 | Permutation, 199 | Combination, 200 | Random, 201 | GCD, 202 | LCM, 203 | } 204 | 205 | public NumBiOpType Operator; 206 | public ScriptValue Value1; 207 | public ScriptValue Value2; 208 | 209 | public override void OnValidate() 210 | { 211 | Value1.OnValidate(); 212 | Value2.OnValidate(); 213 | } 214 | 215 | } 216 | 217 | [Serializable] 218 | public class ArrUnaryOp : Value 219 | { 220 | [Serializable] 221 | public enum ArrUnaryOpType 222 | { 223 | Length, 224 | Reverse, 225 | GetRandomValue, 226 | Shuffled, 227 | RemovedNull, 228 | IsEmpty, 229 | } 230 | 231 | public ArrUnaryOpType Operator; 232 | public ScriptValue Array; 233 | 234 | public override void OnValidate() 235 | { 236 | Array.OnValidate(); 237 | } 238 | } 239 | 240 | [Serializable] 241 | public class ArrBinomialOp : Value 242 | { 243 | [Serializable] 244 | public enum ArrBiOpType 245 | { 246 | AppendToArray, 247 | RemoveFromArray, 248 | Skip, 249 | SkipLast, 250 | FilteredArray, 251 | MappedArray, 252 | SortedArray, 253 | TrueForAll, 254 | TrueForAny, 255 | Contains, 256 | ElementAt, 257 | IndexOfElement, 258 | Count, 259 | Max, 260 | Min, 261 | Sum, 262 | Product, 263 | Distinct, 264 | Union, 265 | Intersect, 266 | DifferenceOfSets, 267 | Disjoint, 268 | Repeat, 269 | } 270 | 271 | public ArrBiOpType Operator; 272 | public ScriptValue Array; 273 | public ScriptValue EvaluationRule; 274 | 275 | public override void OnValidate() 276 | { 277 | Array.OnValidate(); 278 | EvaluationRule.OnValidate(); 279 | } 280 | } 281 | 282 | [Serializable] 283 | public class VecUnaryOp : Value 284 | { 285 | [Serializable] 286 | public enum VecUnaryOpType 287 | { 288 | X, 289 | Y, 290 | Z, 291 | Normalized, 292 | Magnitude, 293 | Inverse, 294 | DirectionFromAngles, 295 | AnglesFromDirection 296 | } 297 | 298 | public VecUnaryOpType Operator; 299 | public ScriptValue Vector; 300 | 301 | public override void OnValidate() 302 | { 303 | Vector.OnValidate(); 304 | } 305 | } 306 | 307 | [Serializable] 308 | public class VecBinomialOp : Value 309 | { 310 | [Serializable] 311 | public enum VecBiOpType 312 | { 313 | Add, 314 | Subtract, 315 | Multiply, 316 | Divide, 317 | Distance, 318 | AngleBetweenVectors, 319 | AngleDifference, 320 | DotProduct, 321 | CrossProduct, 322 | DirectionTowards 323 | } 324 | 325 | public VecBiOpType Operator; 326 | public ScriptValue Value1; 327 | public ScriptValue Value2; 328 | 329 | public override void OnValidate() 330 | { 331 | Value1.OnValidate(); 332 | Value2.OnValidate(); 333 | } 334 | } 335 | 336 | [Serializable] 337 | public class StrUnaryOp : Value 338 | { 339 | [Serializable] 340 | public enum StrUnaryOpType 341 | { 342 | Length, 343 | Upper, 344 | Lower, 345 | UpperLowerSwitch, 346 | Strip, 347 | Trim, 348 | ToInteger, 349 | ToReal, 350 | ToCharArray, 351 | ToPlayerAsName, 352 | ToItemAsName 353 | } 354 | 355 | public StrUnaryOpType Operator; 356 | public ScriptValue String; 357 | 358 | public override void OnValidate() 359 | { 360 | String.OnValidate(); 361 | } 362 | } 363 | 364 | [Serializable] 365 | public class StrBinomialOp : Value 366 | { 367 | [Serializable] 368 | public enum StrBinomialOpType 369 | { 370 | Add, 371 | Repeat, 372 | Contains, 373 | Split, 374 | Skip, 375 | SkipLast, 376 | } 377 | 378 | public StrBinomialOpType Operator; 379 | public ScriptValue String; 380 | public ScriptValue EvaluationRule; 381 | 382 | public override void OnValidate() 383 | { 384 | String.OnValidate(); 385 | EvaluationRule.OnValidate(); 386 | } 387 | } 388 | 389 | [Serializable] 390 | public class ArrayEvaluateHelper : Value 391 | { 392 | [Serializable] 393 | public enum AEVHelperType 394 | { 395 | CurrentEvaluateElement, 396 | CurrentEvaluateIndex 397 | } 398 | 399 | public AEVHelperType Value; 400 | [Header("Increase with its nested level from 0.")] 401 | public ScriptValue AccessLevel; 402 | 403 | public override void OnValidate() 404 | { 405 | AccessLevel.OnValidate(); 406 | } 407 | } 408 | 409 | [Serializable] 410 | public class ConstValue : Value 411 | { 412 | [Serializable] 413 | public enum ConstValueType 414 | { 415 | PI, 416 | E, 417 | GoldenRatio, 418 | C, 419 | TheAnswerToLifeTheUniverseAndEverything 420 | } 421 | 422 | public ConstValueType Value; 423 | 424 | public override void OnValidate() 425 | { 426 | } 427 | } 428 | 429 | [Serializable] 430 | public class EvaluateOnce : Value 431 | { 432 | public ScriptValue Value; 433 | 434 | public override void OnValidate() 435 | { 436 | Value.OnValidate(); 437 | } 438 | } 439 | 440 | [Serializable] 441 | public class VCollisionType : Value 442 | { 443 | public CollisionType Value; 444 | 445 | public override void OnValidate() 446 | { 447 | } 448 | } 449 | 450 | [Serializable] 451 | public class CollisionDetectTarget : Value 452 | { 453 | public DetectType Value; 454 | 455 | public override void OnValidate() 456 | { 457 | } 458 | } 459 | 460 | [Serializable] 461 | public class EffectActionType : Value 462 | { 463 | public EffectFlag Value; 464 | 465 | public override void OnValidate() 466 | { 467 | } 468 | } 469 | 470 | [Serializable] 471 | public class VEffectType : Value 472 | { 473 | public EffectType Value; 474 | 475 | public override void OnValidate() 476 | { 477 | } 478 | } 479 | 480 | //[Serializable] 481 | //public class VTeleportInvokeType : Value 482 | //{ 483 | // public TeleportInvokeType Value; 484 | 485 | // public override void OnValidate() 486 | // { 487 | // } 488 | //} 489 | 490 | [Serializable] 491 | public class VWarheadActionType : Value 492 | { 493 | public WarheadActionType Value; 494 | 495 | public override void OnValidate() 496 | { 497 | } 498 | } 499 | 500 | [Serializable] 501 | public class AnimationActionType : Value 502 | { 503 | public AnimationType Value; 504 | 505 | public override void OnValidate() 506 | { 507 | } 508 | } 509 | 510 | [Serializable] 511 | public class VParameterType : Value 512 | { 513 | public ParameterType Value; 514 | 515 | public override void OnValidate() 516 | { 517 | } 518 | } 519 | 520 | [Serializable] 521 | public class VMessageType : Value 522 | { 523 | public MessageType Value; 524 | 525 | public override void OnValidate() 526 | { 527 | } 528 | } 529 | 530 | [Serializable] 531 | public class PlayerArray : Value 532 | { 533 | public enum PlayerArrayType 534 | { 535 | AllPlayers, 536 | AlivePlayers, 537 | Scps, 538 | ScpsExcludeScp0492, 539 | Mtfs, 540 | Chaos, 541 | Dclass, 542 | Scientist, 543 | Spectators, 544 | Guards, 545 | FoundationSide, 546 | AntiFoundationSide, 547 | Humans, 548 | } 549 | 550 | public PlayerArrayType ArrayType; 551 | 552 | public override void OnValidate() 553 | { 554 | } 555 | } 556 | 557 | [Serializable] 558 | public class SingleTarget : Value 559 | { 560 | public enum SingleTargetType 561 | { 562 | EventPlayer, 563 | SchematicEntity, 564 | ScriptEntity, 565 | }; 566 | 567 | public SingleTargetType TargetType; 568 | 569 | public override void OnValidate() 570 | { 571 | } 572 | } 573 | 574 | [Serializable] 575 | public class VScp914Mode : Value 576 | { 577 | public Scp914Mode Value; 578 | 579 | public override void OnValidate() 580 | { 581 | } 582 | } 583 | 584 | [Serializable] 585 | public class VItemType : Value 586 | { 587 | public ItemType Value; 588 | 589 | public override void OnValidate() 590 | { 591 | } 592 | } 593 | 594 | [Serializable] 595 | public class VRoleType : Value 596 | { 597 | public RoleTypeId Value; 598 | 599 | public override void OnValidate() 600 | { 601 | } 602 | } 603 | 604 | [Serializable] 605 | public class ItemUnaryOp : Value 606 | { 607 | [Serializable] 608 | public enum ItemUnaryOpType 609 | { 610 | ItemType, 611 | Entity, 612 | Owner, 613 | PrevOwner 614 | } 615 | 616 | public ScriptValue ItemOrPickup; 617 | public ItemUnaryOpType Operator; 618 | 619 | public override void OnValidate() 620 | { 621 | ItemOrPickup.OnValidate(); 622 | } 623 | } 624 | 625 | [Serializable] 626 | public class PlayerUnaryOp : Value 627 | { 628 | [Serializable] 629 | public enum PlayerUnaryOpType 630 | { 631 | AHP, 632 | Cuffer, 633 | CurrentItem, 634 | CurrentSpectatingPlayers, 635 | CustomInfo, 636 | CustomName, 637 | DisplayNickname, 638 | GroupName, 639 | HP, 640 | HumeShield, 641 | Id, 642 | IsAlive, 643 | IsCHI, 644 | IsCuffed, 645 | IsDead, 646 | IsFoundationSide, 647 | IsFFon, 648 | IsHuman, 649 | IsInPocketDimension, 650 | IsInventoryEmpty, 651 | IsInventoryFull, 652 | IsJumping, 653 | IsNPC, 654 | IsNTF, 655 | IsReloading, 656 | IsScp, 657 | IsSpeaking, 658 | IsTutorial, 659 | IsUsingStamina, 660 | Items, 661 | MaxAHP, 662 | MaxHP, 663 | MaxHumeShield, 664 | Position, 665 | Role, 666 | FacingDirection, 667 | Scale, 668 | Stamina, 669 | EntityObject, 670 | UniqueRole, 671 | Velocity, 672 | } 673 | 674 | public PlayerUnaryOpType Operator; 675 | public ScriptValue Player; 676 | 677 | public override void OnValidate() 678 | { 679 | Player.OnValidate(); 680 | } 681 | } 682 | 683 | [Serializable] 684 | public class EntityUnaryOp : Value 685 | { 686 | [Serializable] 687 | public enum EntityUnaryOpType 688 | { 689 | Name, 690 | Position, 691 | Rotation, 692 | Scale, 693 | Parent, 694 | IsActive, 695 | ChildCount, 696 | ToPlayer, 697 | ToItem, 698 | } 699 | 700 | public EntityUnaryOpType Operator; 701 | public ScriptValue Entity; 702 | 703 | public override void OnValidate() 704 | { 705 | Entity.OnValidate(); 706 | } 707 | } 708 | 709 | [Serializable] 710 | public class EntityBinomialOp : Value 711 | { 712 | [Serializable] 713 | public enum EntityBinomialOpType 714 | { 715 | GetChildAt, 716 | WorldToLocal, 717 | LocalToWorld 718 | } 719 | 720 | public EntityBinomialOpType Operator; 721 | public ScriptValue Entity; 722 | public ScriptValue Value; 723 | 724 | public override void OnValidate() 725 | { 726 | Entity.OnValidate(); 727 | Value.OnValidate(); 728 | } 729 | } -------------------------------------------------------------------------------- /AdvancedMERTools (plugin)/HealthObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using UnityEngine; 8 | using Exiled.API.Features.Items; 9 | using InventorySystem.Items.Armor; 10 | using Exiled.API.Features; 11 | using Exiled.CustomItems.API.Features; 12 | using RemoteAdmin; 13 | using CommandSystem.Commands; 14 | using CommandSystem; 15 | using MapEditorReborn.API.Features.Objects; 16 | using InventorySystem.Items.Firearms.Modules; 17 | using InventorySystem.Items.ThrowableProjectiles; 18 | using AdminToys; 19 | using PlayerStatsSystem; 20 | using Mirror; 21 | 22 | namespace AdvancedMERTools 23 | { 24 | public class Healther : NetworkBehaviour, IDestructible 25 | { 26 | public uint NetworkId 27 | { 28 | get 29 | { 30 | return base.netId; 31 | } 32 | } 33 | 34 | public Vector3 CenterOfMass 35 | { 36 | get 37 | { 38 | return Vector3.zero; 39 | } 40 | } 41 | 42 | public bool Damage(float damage, DamageHandlerBase handler, Vector3 exactHitPos) 43 | { 44 | bool hit = false; 45 | parents.ForEach(x => hit |= x.Damage(damage, handler, exactHitPos)); 46 | return hit; 47 | } 48 | 49 | public List parents = new List { }; 50 | } 51 | 52 | public class HealthObject : AMERTInteractable, IDestructible 53 | { 54 | protected virtual void Start() 55 | { 56 | this.Base = base.Base as HODTO; 57 | Health = Base.Health; 58 | Register(); 59 | } 60 | 61 | protected void Register() 62 | { 63 | this.transform.GetComponentsInChildren().ForEach(x => 64 | { 65 | if (x.gameObject.TryGetComponent(out Healther healther)) 66 | { 67 | healther.parents.Add(this); 68 | } 69 | else 70 | { 71 | healther = x.gameObject.AddComponent(); 72 | healther.parents.Add(this); 73 | } 74 | }); 75 | AdvancedMERTools.Singleton.healthObjects.Add(this); 76 | } 77 | 78 | protected static Dictionary ExplosionDic = new Dictionary 79 | { 80 | { ExplosionType.Grenade, ItemType.GrenadeHE }, 81 | { ExplosionType.Disruptor, ItemType.ParticleDisruptor }, 82 | { ExplosionType.Jailbird, ItemType.Jailbird }, 83 | { ExplosionType.Cola, ItemType.SCP207 }, 84 | { ExplosionType.PinkCandy, ItemType.SCP330 }, 85 | { ExplosionType.SCP018, ItemType.SCP018 } 86 | }; 87 | 88 | public virtual bool Damage(float damage, DamageHandlerBase handler, Vector3 pos) 89 | { 90 | if (!IsAlive || !Active) 91 | return false; 92 | //ServerConsole.AddLog("1"); 93 | Player attacker = null; 94 | AttackerDamageHandler damageHandler = handler as AttackerDamageHandler; 95 | if (damageHandler != null) 96 | { 97 | //ServerConsole.AddLog("2"); 98 | attacker = Player.Get(damageHandler.Attacker); 99 | FirearmDamageHandler firearm = handler as FirearmDamageHandler; 100 | ExplosionDamageHandler explosion = handler as ExplosionDamageHandler; 101 | if (firearm != null) 102 | { 103 | //ServerConsole.AddLog("3"); 104 | if (Base.whitelistWeapons.Count == 0 || Base.whitelistWeapons.Any(x => 105 | { 106 | if (CustomItem.TryGet(attacker.CurrentItem, out CustomItem custom)) 107 | { 108 | return custom.Id == x.CustomItemId; 109 | } 110 | else 111 | { 112 | return attacker.CurrentItem.Type == x.ItemType; 113 | } 114 | })) 115 | { 116 | //ServerConsole.AddLog("4"); 117 | FieldInfo info = typeof(FirearmDamageHandler).GetField("_penetration", BindingFlags.NonPublic | BindingFlags.Instance); 118 | damage = BodyArmorUtils.ProcessDamage(Base.ArmorEfficient, damage, Mathf.RoundToInt((float)info.GetValue(firearm) * 100f)); 119 | } 120 | else 121 | return false; 122 | } 123 | //ServerConsole.AddLog("5"); 124 | if (explosion != null) 125 | { 126 | if (Base.whitelistWeapons.Count != 0 && !Base.whitelistWeapons.Any(x => 127 | { 128 | if (ExplosionDic.TryGetValue(explosion.ExplosionType, out ItemType item)) 129 | { 130 | return item == x.ItemType; 131 | } 132 | return false; 133 | })) 134 | { 135 | return false; 136 | } 137 | } 138 | //ServerConsole.AddLog("6"); 139 | } 140 | //ServerConsole.AddLog("7"); 141 | CheckDead(attacker, damage); 142 | return true; 143 | } 144 | 145 | public virtual void OnGrenadeExplode(Exiled.Events.EventArgs.Map.ExplodingGrenadeEventArgs ev) 146 | { 147 | if (!ev.IsAllowed || !IsAlive || !Active) return; 148 | if (Base.whitelistWeapons.Count != 0 && Base.whitelistWeapons.Find(x => x.CustomItemId == 0 && x.ItemType == ItemType.GrenadeHE) == null) return; 149 | if (ev.Projectile.Type == ItemType.GrenadeHE) 150 | { 151 | float Dis = Vector3.Distance(this.transform.position, ev.Position); 152 | FieldInfo info = typeof(ExplosionGrenade).GetField("_playerDamageOverDistance", BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.Instance); 153 | float damage = ((AnimationCurve)info.GetValue(ev.Projectile.Base as ExplosionGrenade)).Evaluate(Dis); 154 | damage = BodyArmorUtils.ProcessDamage(Base.ArmorEfficient, damage, 50); 155 | CheckDead(ev.Player, damage); 156 | } 157 | } 158 | 159 | public virtual void CheckDead(Player player, float damage) 160 | { 161 | Health -= damage; 162 | Hitmarker.SendHitmarkerDirectly(player.ReferenceHub, damage / 10f); 163 | if (Health <= 0) 164 | { 165 | HODTO clone = new HODTO 166 | { 167 | Health = this.Base.Health, 168 | ArmorEfficient = this.Base.ArmorEfficient, 169 | DeadType = this.Base.DeadType, 170 | ObjectId = this.Base.ObjectId 171 | }; 172 | IsAlive = false; 173 | ModuleGeneralArguments args = new ModuleGeneralArguments { interpolations = Formatter, interpolationsList = new object[] { player, transform }, player = player, schematic = OSchematic, transform = transform, TargetCalculated = false }; 174 | EventHandler.OnHealthObjectDead(new HealthObjectDeadEventArgs(clone, player)); 175 | MEC.Timing.CallDelayed(Base.DeadActionDelay, () => 176 | { 177 | var deadTypeExecutors = new Dictionary 178 | { 179 | { DeadType.Disappear, () => Destroy(this.gameObject, 0.1f) }, 180 | { DeadType.GetRigidbody, () => 181 | { 182 | MakeNonStatic(gameObject); 183 | this.gameObject.AddComponent(); 184 | } 185 | }, 186 | { DeadType.DynamicDisappearing, () => MakeNonStatic(gameObject) }, 187 | { DeadType.Explode, () => ExplodeModule.Execute(Base.ExplodeModules, args) }, 188 | { DeadType.ResetHP, () => 189 | { 190 | Health = Base.ResetHPTo == 0 ? Base.Health : Base.ResetHPTo; 191 | IsAlive = true; 192 | } 193 | }, 194 | { DeadType.PlayAnimation, () => AnimationDTO.Execute(Base.AnimationModules, args) }, 195 | { DeadType.Warhead, () => AlphaWarhead(Base.warheadAction) }, 196 | { DeadType.SendMessage, () => MessageModule.Execute(Base.MessageModules, args) }, 197 | { DeadType.DropItems, () => DropItem.Execute(Base.DropItems, args) }, 198 | { DeadType.SendCommand, () => Commanding.Execute(Base.Commandings, args) }, 199 | { DeadType.GiveEffect, () => EffectGivingModule.Execute(Base.effectGivingModules, args) }, 200 | { DeadType.PlayAudio, () => AudioModule.Execute(Base.AudioModules, args) }, 201 | { DeadType.CallGroovieNoise, () => CGNModule.Execute(Base.GroovieNoiseToCall, args) }, 202 | { DeadType.CallFunction, () => CFEModule.Execute(Base.FunctionToCall, args) } 203 | }; 204 | foreach (DeadType type in Enum.GetValues(typeof(DeadType))) 205 | { 206 | if (Base.DeadType.HasFlag(type) && deadTypeExecutors.TryGetValue(type, out var execute)) 207 | { 208 | execute(); 209 | } 210 | } 211 | }); 212 | } 213 | } 214 | 215 | void MakeNonStatic(GameObject game) 216 | { 217 | foreach (AdminToyBase adminToyBase in game.transform.GetComponentsInChildren()) 218 | { 219 | adminToyBase.enabled = true; 220 | } 221 | } 222 | 223 | static readonly Dictionary> Formatter = new Dictionary> 224 | { 225 | { "{p_i}", vs => (vs[0] as Player).Id.ToString() }, 226 | { "{p_name}", vs => (vs[0] as Player).Nickname.ToString() }, 227 | { "{p_pos}", vs => { Vector3 pos = (vs[0] as Player).Transform.position; return $"{pos.x} {pos.y} {pos.z}"; } }, 228 | { "{p_room}", vs => (vs[0] as Player).CurrentRoom.RoomName.ToString() }, 229 | { "{p_zone}", vs => (vs[0] as Player).Zone.ToString() }, 230 | { "{p_role}", vs => (vs[0] as Player).Role.Type.ToString() }, 231 | { "{p_item}", vs => (vs[0] as Player).CurrentItem.Type.ToString() }, 232 | { "{o_pos}", vs => { Vector3 pos = (vs[1] as Transform).position; return $"{pos.x} {pos.y} {pos.z}"; } }, 233 | { "{o_room}", vs => Room.Get((vs[1] as Transform).position).RoomName.ToString() }, 234 | { "{o_zone}", vs => Room.Get((vs[1] as Transform).position).Zone.ToString() }, 235 | { "{damage}", vs => (vs[2] as float?).ToString() } 236 | }; 237 | 238 | void Update() 239 | { 240 | if (Health <= 0 && this.Base.DeadType.HasFlag(DeadType.DynamicDisappearing) && !AnimationEnded) 241 | { 242 | this.transform.localScale = Vector3.Lerp(this.transform.localScale, Vector3.zero, Time.deltaTime); 243 | if (this.transform.localScale.magnitude <= 0.1f) 244 | { 245 | Destroy(); 246 | } 247 | } 248 | } 249 | 250 | protected virtual void Destroy() 251 | { 252 | AnimationEnded = true; 253 | if (Base.DoNotDestroyAfterDeath) return; 254 | Destroy(this.gameObject); 255 | } 256 | 257 | bool AnimationEnded = false; 258 | 259 | public float Health; 260 | 261 | public bool IsAlive = true; 262 | 263 | public new HODTO Base; 264 | 265 | public uint NetworkId 266 | { 267 | get 268 | { 269 | return base.netId; 270 | } 271 | } 272 | 273 | public Vector3 CenterOfMass 274 | { 275 | get 276 | { 277 | return Vector3.zero; 278 | } 279 | } 280 | } 281 | 282 | public class FHealthObject : HealthObject 283 | { 284 | protected override void Start() 285 | { 286 | this.Base = ((AMERTInteractable)this).Base as FHODTO; 287 | Health = Base.Health.GetValue(new FunctionArgument(this), 100f); 288 | Register(); 289 | } 290 | 291 | public override bool Damage(float damage, DamageHandlerBase handler, Vector3 pos) 292 | { 293 | if (!IsAlive || !Active) 294 | return false; 295 | //ServerConsole.AddLog("1"); 296 | Player attacker = null; 297 | AttackerDamageHandler damageHandler = handler as AttackerDamageHandler; 298 | if (damageHandler != null) 299 | { 300 | //ServerConsole.AddLog("2"); 301 | attacker = Player.Get(damageHandler.Attacker); 302 | FunctionArgument args = new FunctionArgument(this, attacker); 303 | FirearmDamageHandler firearm = handler as FirearmDamageHandler; 304 | ExplosionDamageHandler explosion = handler as ExplosionDamageHandler; 305 | if (firearm != null) 306 | { 307 | //ServerConsole.AddLog("3"); 308 | if (Base.whitelistWeapons.Count == 0 || Base.whitelistWeapons.Any(x => 309 | { 310 | if (CustomItem.TryGet(attacker.CurrentItem, out CustomItem custom)) 311 | { 312 | return custom.Id == x.CustomItemId.GetValue(args, 0); 313 | } 314 | else 315 | { 316 | return attacker.CurrentItem.Type == x.ItemType.GetValue(args, ItemType.None); 317 | } 318 | })) 319 | { 320 | //ServerConsole.AddLog("4"); 321 | FieldInfo info = typeof(FirearmDamageHandler).GetField("_penetration", BindingFlags.NonPublic | BindingFlags.Instance); 322 | damage = BodyArmorUtils.ProcessDamage(Base.ArmorEfficient.GetValue(args, 0), damage, Mathf.RoundToInt((float)info.GetValue(firearm) * 100f)); 323 | } 324 | else 325 | return false; 326 | } 327 | //ServerConsole.AddLog("5"); 328 | if (explosion != null) 329 | { 330 | if (Base.whitelistWeapons.Count != 0 && !Base.whitelistWeapons.Any(x => 331 | { 332 | if (ExplosionDic.TryGetValue(explosion.ExplosionType, out ItemType item)) 333 | { 334 | return item == x.ItemType.GetValue(args, ItemType.None); 335 | } 336 | return false; 337 | })) 338 | { 339 | return false; 340 | } 341 | } 342 | //ServerConsole.AddLog("6"); 343 | } 344 | //ServerConsole.AddLog("7"); 345 | CheckDead(attacker, damage); 346 | return true; 347 | } 348 | 349 | public override void OnGrenadeExplode(Exiled.Events.EventArgs.Map.ExplodingGrenadeEventArgs ev) 350 | { 351 | if (!ev.IsAllowed || !IsAlive || !Active) return; 352 | FunctionArgument args = new FunctionArgument(this, ev.Player); 353 | if (Base.whitelistWeapons.Count != 0 && Base.whitelistWeapons.Find(x => x.CustomItemId.GetValue(args, 0) == 0 && x.ItemType.GetValue(args, ItemType.None) == ItemType.GrenadeHE) == null) return; 354 | if (ev.Projectile.Type == ItemType.GrenadeHE) 355 | { 356 | float Dis = Vector3.Distance(this.transform.position, ev.Position); 357 | FieldInfo info = typeof(ExplosionGrenade).GetField("_playerDamageOverDistance", BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.Instance); 358 | float damage = ((AnimationCurve)info.GetValue(ev.Projectile.Base as ExplosionGrenade)).Evaluate(Dis); 359 | damage = BodyArmorUtils.ProcessDamage(Base.ArmorEfficient.GetValue(args, 0), damage, 50); 360 | CheckDead(ev.Player, damage); 361 | } 362 | } 363 | 364 | public override void CheckDead(Player player, float damage) 365 | { 366 | Health -= damage; 367 | Hitmarker.SendHitmarkerDirectly(player.ReferenceHub, damage / 10f); 368 | if (Health <= 0) 369 | { 370 | IsAlive = false; 371 | FunctionArgument args = new FunctionArgument(this, player); 372 | MEC.Timing.CallDelayed(Base.DeadActionDelay.GetValue(args, 0f), () => 373 | { 374 | var deadTypeExecutors = new Dictionary 375 | { 376 | { DeadType.Disappear, () => Destroy(this.gameObject, 0.1f) }, 377 | { DeadType.GetRigidbody, () => 378 | { 379 | MakeNonStatic(gameObject); 380 | this.gameObject.AddComponent(); 381 | } 382 | }, 383 | { DeadType.DynamicDisappearing, () => MakeNonStatic(gameObject) }, 384 | { DeadType.Explode, () => FExplodeModule.Execute(Base.ExplodeModules, args) }, 385 | { DeadType.ResetHP, () => 386 | { 387 | float RH = Base.ResetHPTo.GetValue(args, 0f); 388 | Health = RH == 0 ? Base.Health.GetValue(args, 100f) : RH; 389 | IsAlive = true; 390 | } 391 | }, 392 | { DeadType.PlayAnimation, () => FAnimationDTO.Execute(Base.AnimationModules, args) }, 393 | { DeadType.Warhead, () => AlphaWarhead(Base.warheadActionType.GetValue(args, 0)) }, 394 | { DeadType.SendMessage, () => FMessageModule.Execute(Base.MessageModules, args) }, 395 | { DeadType.DropItems, () => FDropItem.Execute(Base.dropItems, args) }, 396 | { DeadType.SendCommand, () => FCommanding.Execute(Base.commandings, args) }, 397 | { DeadType.GiveEffect, () => FEffectGivingModule.Execute(Base.effectGivingModules, args) }, 398 | { DeadType.PlayAudio, () => FAudioModule.Execute(Base.AudioModules, args) }, 399 | { DeadType.CallGroovieNoise, () => FCGNModule.Execute(Base.GroovieNoiseToCall, args) }, 400 | { DeadType.CallFunction, () => FCFEModule.Execute(Base.FunctionToCall, args) }, 401 | }; 402 | foreach (DeadType type in Enum.GetValues(typeof(DeadType))) 403 | { 404 | if (Base.DeadType.HasFlag(type) && deadTypeExecutors.TryGetValue(type, out var execute)) 405 | { 406 | execute(); 407 | } 408 | } 409 | }); 410 | } 411 | } 412 | 413 | void MakeNonStatic(GameObject game) 414 | { 415 | foreach (AdminToyBase adminToyBase in game.transform.GetComponentsInChildren()) 416 | { 417 | adminToyBase.enabled = true; 418 | } 419 | } 420 | 421 | protected override void Destroy() 422 | { 423 | AnimationEnded = true; 424 | if (Base.DoNotDestroyAfterDeath.GetValue(new FunctionArgument(this), false)) return; 425 | Destroy(this.gameObject); 426 | } 427 | 428 | bool AnimationEnded = false; 429 | 430 | public new FHODTO Base; 431 | } 432 | } 433 | --------------------------------------------------------------------------------