BaddieWardrobeCatalog.cs
using Sandbox;
using System;
using System.Collections.Generic;
using System.Linq;

namespace PaintballBaddies;

/// <summary>Creator-owned seasonal wardrobe, editable with the native asset inspector.</summary>
[AssetType(Name="Baddies Wardrobe Catalogue",Extension="bvsward",Category="Baddies")]
public sealed class BaddieWardrobeCatalog : GameResource
{
    public const string CatalogPath="wardrobe/catalog.bvsward";
    public string ActiveSetId {get;set;}="diner";
    public List<BaddieWardrobeSet> Sets {get;set;}=new();

    public BaddieWardrobeLook FindLook(int index)
    {
        if(index<0 || index>=RosterSelection.Names.Length)return null;
        var set=Sets?.FirstOrDefault(s=>s is not null && s.Enabled && string.Equals(s.Id,ActiveSetId,StringComparison.OrdinalIgnoreCase));
        return set?.Looks?.FirstOrDefault(l=>l is not null && string.Equals(l.Character,RosterSelection.Names[index],StringComparison.OrdinalIgnoreCase));
    }

    public static string DefaultModel(int index,bool opponent)
        =>$"models/baddies_hi3d/{RosterSelection.Names[index].ToLowerInvariant()}/character_{(opponent ? "opponent" : "graph")}_contactfit.vmdl";

    public static string ModelPath(int index,bool opponent)
    {
        var look=ResourceLibrary.Get<BaddieWardrobeCatalog>(CatalogPath)?.FindLook(index);
        var path=opponent ? look?.OpponentModel : look?.PlayerModel;
        return string.IsNullOrWhiteSpace(path) ? DefaultModel(index,opponent) : path;
    }

    public static BaddieWardrobeLook ActiveLook(int index)
        =>ResourceLibrary.Get<BaddieWardrobeCatalog>(CatalogPath)?.FindLook(index);
}

public sealed class BaddieWardrobeSet
{
    // Stable identifiers can later be used by an inventory/gifting service.
    // This catalogue grants no entitlements and never accepts client model paths.
    public string Id {get;set;}="new-set";
    public string Title {get;set;}="New wardrobe";
    public string Theme {get;set;}="Everyday";
    public bool Enabled {get;set;}
    public List<BaddieWardrobeLook> Looks {get;set;}=new();
}

public sealed class BaddieWardrobeLook
{
    public string Character {get;set;}="Viper";
    [ResourceType("vmdl")] public string PlayerModel {get;set;}
    [ResourceType("vmdl")] public string OpponentModel {get;set;}
    [Description("Optional native .clothing assets, fitted to this character's base models. Empty keeps the complete model outfit.")]
    public List<BaddieWardrobeGarment> ClothingItems {get;set;}=new();
}

public sealed class BaddieWardrobeGarment
{
    [ResourceType("clothing")] public string Asset {get;set;}
}