ArenaMap.cs
using Sandbox;
using System;
namespace PaintballBaddies;
/// <summary>Map author settings. Reuses native SpawnPoint components for all six seats.</summary>
public sealed class ArenaMap : Component
{
[Property] public string Title { get; set; } = "Community Arena";
[Property] public bool ShowPracticeTargets { get; set; }
public static ArenaMap Find(Scene scene) => scene.GetAllComponents<ArenaMap>().FirstOrDefault();
public static string DisplayTitle(Scene scene) => Find(scene)?.Title ?? "Neon Foundry";
// Use the same ordered six native markers for solo opponents and network seats.
// Partial sets are rejected as a whole so a map never mixes two coordinate systems.
public static SpawnPoint[] Spawns(Scene scene) => scene.GetAllComponents<SpawnPoint>()
.Where(x => x.GameObject.Active).OrderBy(x => x.GameObject.Name, StringComparer.Ordinal).ToArray();
public static Vector3 PlayerSpawn(Scene scene, int seat, Vector3 legacyPosition)
{
var points = Spawns(scene);
return points.Length == 6 && seat >= 0 && seat < 6 ? points[seat].WorldPosition : legacyPosition;
}
public static ShieldSpawnPoint[] ShieldSpawns(Scene scene) => scene.GetAllComponents<ShieldSpawnPoint>()
.Where(x => x.GameObject.Active).ToArray();
protected override void OnStart()
{
if(Spawns(Scene).Length != 6)
Log.Warning("Paintball map requires six native SpawnPoint objects named 01 through 06. Using legacy arena positions until corrected.");
}
}
/// <summary>Place on walkable ground to choose a possible random shield pickup location.</summary>
public sealed class ShieldSpawnPoint : Component { }