using System;
using System.Collections.Generic;
using Cielonos.Core.Interaction;
using Cielonos.MainGame.Inventory;
using Cielonos.MainGame.Items;
using Cielonos.MainGame.UI;
using Lean.Pool;
using Sirenix.OdinInspector;
using SLSUtilities.General;
using UnityEngine;
namespace Cielonos.MainGame.Interactions
{
///
/// 机械台(Roguelite 宝箱房)场景交互对象。
/// 生成时根据配置的权重随机决定稀有度,并实例化对应的 table 模型。
/// 玩家交互后呼出 MechanicalTableUIPage,显示该稀有度下的随机装备供选择。
/// 选择后获得装备,标记为 Exhausted(单次使用),不可再次触发。
///
public class MechanicalTable : InteractableObjectBase
{
private const int OFFER_COUNT = 3;
[TitleGroup("稀有度配置")]
[Tooltip("每种稀有度对应的 table 模型。生成时,根据稀有度生成对应模型。")]
[SerializeField]
private Dictionary _tablePrefabs = new Dictionary();
[SerializeField]
[Tooltip("当机械台不可用时显示的模型(如已被使用)。")]
private GameObject _notAvailableTablePrefab;
private GameObject _currentTable;
[TitleGroup("运行时状态"), ReadOnly]
public ItemRarity rarity;
private Dictionary RarityWeights => MainGameManager.Config.mechanicalTableRarityWeights;
private List _currentOffers;
[ShowInInspector]
private bool _isAvailable;
private void Start()
{
if (!_isAvailable)
{
Setup(new System.Random());
}
}
protected override void InitializeChoices()
{
choices.Add(new InteractionChoice("Open Mechanical Table", OpenTable));
}
///
/// 由 RunManager 或场景加载逻辑调用,预先配置本机械台的稀有度和物品列表。
/// 使用节点坐标派生的 RNG 确保同 seed 可复现。
///
/// 本节点的随机数生成器。
public void Setup(System.Random rng)
{
rarity = RollRarity(rng);
if (_currentTable != null) Destroy(_currentTable);
if (_tablePrefabs.TryGetValue(rarity, out GameObject tablePrefab) && tablePrefab != null)
{
_currentTable = Instantiate(tablePrefab, transform);
}
else
{
Debug.LogWarning($"[MechanicalTable] 稀有度 {rarity} 没有对应的 table 预制体。");
}
_currentOffers = RollItems(rng, rarity);
_isAvailable = true;
}
private void OpenTable()
{
// 如果未通过 Setup() 预配置,自动配置(fallback)
if (!_isAvailable && (_currentOffers == null || _currentOffers.Count == 0))
{
System.Random fallbackRng = RunManager.Instance?.currentRun?.randomizer?.Next() ?? new System.Random();
Setup(fallbackRng);
}
if (!_isAvailable) return;
if (_currentOffers == null || _currentOffers.Count == 0)
{
Debug.LogWarning("[MechanicalTable] 候选池为空,没有符合条件的装备。");
return;
}
var uiPage = PlayerCanvas.MainGamePages.mechanicalTablePage;
uiPage.SetOffers(_currentOffers, HandleOfferSelected);
uiPage.Open();
}
private void HandleOfferSelected(int index)
{
if (index < 0 || index >= _currentOffers.Count) return;
GameObject selectedPrefab = _currentOffers[index];
// 通过 BackpackSubmodule 将物品加入背包
MainGameManager.Player.inventorySc.backpackSm.ObtainItem(selectedPrefab);
_isAvailable = false;
Destroy(_currentTable);
_currentTable = Instantiate(_notAvailableTablePrefab, transform);
// 禁用场景中的交互触发器
SetInteractable(false);
Debug.Log($"[MechanicalTable] 玩家选择了 '{selectedPrefab.name}'({rarity}),机械台已用完。");
}
// ================================================================
// 稀有度逻辑
// ================================================================
///
/// 根据权重表随机选取一个稀有度。
///
private ItemRarity RollRarity(System.Random rng)
{
float totalWeight = 0f;
foreach (var kvp in RarityWeights)
{
totalWeight += kvp.Value;
}
if (totalWeight <= 0f)
{
Debug.LogWarning("[MechanicalTable] 稀有度权重总和为 0,使用默认 Tera。");
return ItemRarity.Tera;
}
float roll = (float)(rng.NextDouble() * totalWeight);
float cumulative = 0f;
foreach (var kvp in RarityWeights)
{
cumulative += kvp.Value;
if (roll <= cumulative)
{
return kvp.Key;
}
}
// 安全回退
return ItemRarity.Tera;
}
///
/// 从 Resources/Items 中按稀有度筛选并加权随机抽取装备。
/// 机械台只出 Support 和 Passive 类型。
///
private List RollItems(System.Random rng, ItemRarity targetRarity)
{
ItemFilter filter = ItemFilter.ByRarity(targetRarity);
return ItemPoolHelper.Roll(OFFER_COUNT, rng, filter, "SupportEquipment", "PassiveEquipment");
}
}
}