RosterSelection.cs
using Sandbox;
namespace PaintballBaddies;
/// <summary>Training roster selection; match rules will restrict swaps to the lobby.</summary>
public sealed class RosterSelection : Component
{
public static readonly string[] Names = { "Viper", "Roxie", "Imani", "Mei", "Freya", "Leilani" };
public int Selected { get; private set; }
[Property] public bool UseCitizenCharacters { get; set; }
private CitizenPlayerPresentation ownedPresentation;
public string CharacterName => Names[Selected];
public int AvailableCharacters => Names.Length;
// Retargeted hip proportions relative to the motion source; keeps gait speed tied to stride length.
private static readonly float[] MotionScales = { .933228f, .944392f, 1.031877f, .912818f, 1.038501f, .997422f };
public float MotionScale => MotionScales[Selected];
public static float GetMotionScale(int index) => MotionScales[index];
public static string GetModelPath(int index)
{
var slug = Names[index].ToLowerInvariant();
return $"models/characters/{slug}_protected_morph/{slug}_protected.vmdl";
}
private PlayerController player;
protected override void OnStart()
{
player = Components.Get<PlayerController>();
if (Components.Get<RosterHelmet>() is null) Components.Create<RosterHelmet>();
SelectNetwork(Components.Get<NetworkPawn>()?.Seat ?? 0);
}
protected override void OnUpdate()
{
if (UseCitizenCharacters && !ownedPresentation.IsValid() && Components.Get<CitizenPlayerPresentation>() is null)
ownedPresentation=Components.Create<CitizenPlayerPresentation>();
else if (!UseCitizenCharacters && ownedPresentation.IsValid())
{
ownedPresentation.Destroy();
ownedPresentation=null;
}
if(IsProxy || MultiplayerSession.Online)return;
if ( player is null || (!player.UseInputControls && Components.Get<ArenaMatch>()?.Status == "TRAINING") ) return;
for ( int i = 0; i < AvailableCharacters; i++ )
if ( Input.Pressed( $"slot{i + 1}" ) ) Select( i );
}
protected override void OnDestroy()
{
if (ownedPresentation.IsValid()) ownedPresentation.Destroy();
}
public bool Select( int index )
{
if(MultiplayerSession.Online || Components.Get<ArenaMatch>()?.InRound==true)return false;
return SelectNetwork(index);
}
internal bool SelectNetwork(int index)
{
if ( player?.Renderer is not { } renderer || index < 0 || index >= AvailableCharacters ) return false;
renderer.Model = Model.Load( GetModelPath(index) );
renderer.UseAnimGraph = false;
renderer.Sequence.Name = "idle";
renderer.Sequence.Looping = true;
renderer.Sequence.Blending = true;
Selected = index;
return true;
}
}