WeaponManager.cs

Component that manages available weapons and equips them. It defines weapon metadata, initializes a list of weapon prefabs on start, allows buying/unlocking via a MetaProgression component, and spawns/attaches a prefab instance to the player model or camera when equipping.

File Access
using Sandbox;
using System;
using System.Collections.Generic;
using System.Linq;

public sealed class WeaponManager : Component
{
	public static WeaponManager Instance { get; private set; }

	public class WeaponData
	{
		public string Id { get; set; }
		public string NameRu { get; set; }
		public string NameEn { get; set; }
		public int Cost { get; set; }
		public PrefabFile Prefab { get; set; }
		public bool IsUnlocked { get; set; } = false;
	}

	[Property] public PrefabFile UspPrefab { get; set; }
	[Property] public PrefabFile Mp5Prefab { get; set; }
	[Property] public PrefabFile M4A1Prefab { get; set; }
	[Property] public PrefabFile M700Prefab { get; set; }

	public List<WeaponData> Weapons { get; private set; } = new();
	public WeaponData CurrentWeapon { get; private set; }

	private GameObject _spawnedWeaponInstance;

	protected override void OnStart()
	{
		Instance = this;

		Weapons = new List<WeaponData>
		{
			new WeaponData { Id = "usp", NameRu = "🔫 USP", NameEn = "🔫 USP", Cost = 50, Prefab = UspPrefab },
			new WeaponData { Id = "mp5", NameRu = "💥 MP5", NameEn = "💥 MP5", Cost = 120, Prefab = Mp5Prefab },
			new WeaponData { Id = "m4a1", NameRu = "🔥 M4A1", NameEn = "🔥 M4A1", Cost = 250, Prefab = M4A1Prefab },
			new WeaponData { Id = "m700", NameRu = "🎯 M700", NameEn = "🎯 M700", Cost = 400, Prefab = M700Prefab }
		};
	}

	public bool TryBuyOrEquip( WeaponData weapon )
	{
		if ( weapon == null ) return false;

		var meta = Scene.GetAllComponents<MetaProgression>().FirstOrDefault();

		if ( weapon.IsUnlocked )
		{
			EquipWeapon( weapon );
			return true;
		}

		if ( meta != null && meta.Credits >= weapon.Cost )
		{
			meta.AddCredits( -weapon.Cost );
			weapon.IsUnlocked = true;
			EquipWeapon( weapon );
			return true;
		}

		return false;
	}

	public void EquipWeapon( WeaponData weapon )
	{
		if ( _spawnedWeaponInstance.IsValid() )
		{
			_spawnedWeaponInstance.Destroy();
		}

		CurrentWeapon = weapon;

		if ( weapon?.Prefab == null )
		{
			Log.Warning( $"[WeaponManager] Префаб для {weapon?.Id} не назначен в Инспекторе!" );
			return;
		}

		// 1. Ищем модели/персонажа
		var playerModel = Scene.GetAllComponents<SkinnedModelRenderer>()
			.FirstOrDefault( x => !x.IsProxy );

		GameObject attachParent = null;

		if ( playerModel.IsValid() )
		{
			attachParent = playerModel.GameObject;
		}
		else if ( Scene.Camera.IsValid() )
		{
			attachParent = Scene.Camera.GameObject;
		}

		if ( !attachParent.IsValid() ) return;

		// 2. Создаем объект из префаба
		_spawnedWeaponInstance = GameObject.Clone( weapon.Prefab );

		if ( _spawnedWeaponInstance.IsValid() )
		{
			// Привязываем родителя (второй аргумент keepWorldPosition = false)
			_spawnedWeaponInstance.SetParent( attachParent, false );

			// Подгоняем локальную позицию и поворот под руку персонажа
			_spawnedWeaponInstance.Transform.LocalPosition = new Vector3( 12, -8, 38 );
			_spawnedWeaponInstance.Transform.LocalRotation = Rotation.From( 0, 90, 0 );
			_spawnedWeaponInstance.Transform.LocalScale = Vector3.One;

			Log.Info( $"[WeaponManager] Оружие {weapon.Id} успешно экипировано!" );
		}
	}
}