Code/ExpresionesInyector.cs

A GameObjectSystem that periodically scans skinned model renderers in the scene and injects an ExpresionesNextbot component into game objects tagged as sbh_nextbot that have bodygroups and do not already have the component. It skips accessory objects tagged sbh_accesorio.

Reflection
namespace SBH;

using Sandbox;

/// <summary>
/// [SBHBase] Inyecta ExpresionesNextbot (con defaults) a todo nextbot cuyo
/// modelo tenga bodygroups y no traiga ya el componente — mismo patrón de
/// escaneo que RitmoInyector. Cubre la fusión de carteles: un bot spawneado
/// como personaje sin bodygroups que se transforma en uno que sí tiene,
/// gana sus expresiones al próximo escaneo. Si el prefab ya trae el
/// componente (el addon lo emite con índices calibrados), se respeta.
/// </summary>
public sealed class ExpresionesInyector : GameObjectSystem
{
	TimeSince _desdeEscaneo;

	public ExpresionesInyector( Scene scene ) : base( scene )
	{
		Listen( Stage.StartUpdate, 25, Escanear, "ExpresionesInyector" );
	}

	void Escanear()
	{
		if ( _desdeEscaneo < 1f ) return;
		_desdeEscaneo = 0f;

		foreach ( var renderer in Scene.GetAllComponents<SkinnedModelRenderer>() )
		{
			var go = renderer.GameObject;
			if ( !go.IsValid() || !go.Tags.Has( "sbh_nextbot" ) ) continue;
			// Accesorios bonemerge: heredan el tag del bot vestido pero son
			// decoración — la cara la maneja el dueño, no el accesorio
			if ( go.Tags.Has( "sbh_accesorio" ) ) continue;
			if ( !renderer.HasBodyGroups ) continue;
			if ( go.Components.Get<ExpresionesNextbot>( true ) != null ) continue;

			go.Components.Create<ExpresionesNextbot>();
			Log.Info( $"🙂 ExpresionesNextbot inyectado a {go.Name} (bodygroups detectados)" );
		}
	}
}