using System.Collections.Generic; using System.Collections.ObjectModel; using HG; using RoR2.Navigation; using UnityEngine; using UnityEngine.ResourceManagement.AsyncOperations; namespace RoR2; public class SpawnPoint : MonoBehaviour { private static List instancesList = new List(); private static ReadOnlyCollection _readOnlyInstancesList = new ReadOnlyCollection(instancesList); [Tooltip("Flagged when a player spawns on this position, to stop overlapping spawn positions")] public bool consumed; private static GameObject prefab; private static Mesh commandoMesh; private static bool attemptedCommandoMeshLoad = false; public static ReadOnlyCollection readOnlyInstancesList => _readOnlyInstancesList; private void OnEnable() { instancesList.Add(this); } public static SpawnPoint ConsumeSpawnPoint() { if (instancesList.Count == 0) { return null; } SpawnPoint spawnPoint = null; for (int i = 0; i < readOnlyInstancesList.Count; i++) { if (!readOnlyInstancesList[i].consumed) { spawnPoint = readOnlyInstancesList[i]; readOnlyInstancesList[i].consumed = true; break; } } if (!spawnPoint) { for (int j = 0; j < readOnlyInstancesList.Count; j++) { readOnlyInstancesList[j].consumed = false; } spawnPoint = readOnlyInstancesList[0]; } return spawnPoint; } private void OnDisable() { instancesList.Remove(this); } private static Mesh GetCommandoMesh() { if (!commandoMesh) { LoadCommandoMesh(); } return commandoMesh; } private static void LoadCommandoMesh() { if (attemptedCommandoMeshLoad) { return; } attemptedCommandoMeshLoad = true; GameObject gameObject = null; gameObject = LegacyResourcesAPI.Load("Prefabs/CharacterBodies/CommandoBody"); if (!gameObject) { return; } CharacterModel component = gameObject.GetComponent().modelTransform.GetComponent(); SkinnedMeshRenderer skinnedMeshRenderer = null; for (int i = 0; i < component.baseRendererInfos.Length; i++) { skinnedMeshRenderer = component.baseRendererInfos[i].renderer as SkinnedMeshRenderer; if ((bool)skinnedMeshRenderer) { break; } } commandoMesh = skinnedMeshRenderer.sharedMesh; } [InitDuringStartup] private static void Init() { AsyncOperationHandle asyncOperationHandle = LegacyResourcesAPI.LoadAsync("Prefabs/SpawnPoint"); asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) { prefab = x.Result; }; } public static void AddSpawnPoint(NodeGraph nodeGraph, NodeGraph.NodeIndex nodeIndex, Xoroshiro128Plus rng) { nodeGraph.GetNodePosition(nodeIndex, out var position); List list = CollectionPool>.RentCollection(); nodeGraph.GetActiveNodeLinks(nodeIndex, list); Quaternion rotation; if (list.Count > 0) { NodeGraph.LinkIndex linkIndex = rng.NextElementUniform(list); nodeGraph.GetNodePosition(nodeGraph.GetLinkEndNode(linkIndex), out var position2); rotation = Util.QuaternionSafeLookRotation(position2 - position); } else { rotation = Quaternion.Euler(0f, rng.nextNormalizedFloat * 360f, 0f); } AddSpawnPoint(position, rotation); list = CollectionPool>.ReturnCollection(list); } public static void AddSpawnPoint(Vector3 position, Quaternion rotation) { Object.Instantiate(prefab, position, rotation); } public void OnDrawGizmos() { Gizmos.matrix = base.transform.localToWorldMatrix; Gizmos.color = Color.green; Gizmos.DrawWireMesh(GetCommandoMesh()); } }