using System;
using System.Collections.Generic;
using Cielonos.Core.Interaction;
using Cielonos.MainGame.Inventory;
using Cielonos.MainGame.Inventory.Collections;
using Cielonos.MainGame.Rewards;
using Cielonos.MainGame.UI;
using Sirenix.OdinInspector;
using UnityEngine;
namespace Cielonos.MainGame.Interactions
{
///
/// 战斗完成奖励用的一次性补给包。
/// 候选生成、领取和放弃补偿均由 RewardProfile 驱动。
///
public class SupplyPack : InteractableObjectBase, ICombatRewardInteractable
{
[TitleGroup("Presentation")]
[SerializeField]
private GameObject _availableViewPrefab;
[SerializeField]
private GameObject _notAvailableTablePrefab;
[TitleGroup("Reward Profile")]
[SerializeField]
private RewardProfile _profile;
[TitleGroup("Runtime State"), ReadOnly]
private List _currentOffers = new();
[ShowInInspector, ReadOnly]
private bool _isAvailable;
private GameObject _currentView;
private Transform _offerStagingRoot;
private void Start()
{
SetAvailable(_isAvailable);
}
private void OnDestroy()
{
ClearCurrentOffers();
}
protected override void InitializeChoices()
{
choices.Add(new InteractionChoice("打开补给包", OpenSupplyPack));
}
public void SetupCombatReward(CombatRewardInstruction instruction, System.Random rng)
{
Setup();
}
private void Setup()
{
if (_currentView != null)
{
Destroy(_currentView);
}
if (_availableViewPrefab != null)
{
_currentView = Instantiate(_availableViewPrefab, transform);
}
ClearCurrentOffers();
_isAvailable = GetProfile() != null;
if (!_isAvailable)
{
Debug.LogError("[SupplyPack] RewardProfile is not assigned.");
}
RefreshChoiceStates();
SetAvailable(_isAvailable);
}
private void OpenSupplyPack()
{
if (!_isAvailable)
{
Setup();
if (!_isAvailable)
{
return;
}
}
if (_currentOffers.Count == 0)
{
GenerateOffers();
}
RewardProfile profile = GetProfile();
if (_currentOffers.Count == 0)
{
Debug.LogWarning($"[SupplyPack] Profile '{profile?.name ?? "None"}' generated no valid offers.");
return;
}
var page = PlayerCanvas.MainGamePages.rewardChoicePage;
if (page == null)
{
Debug.LogError("[SupplyPack] RewardChoiceUIPage is not registered.");
return;
}
page.SetOffers(_currentOffers, HandleOfferSelected, HandleOfferSkipped);
page.Open();
}
private void GenerateOffers()
{
ClearCurrentOffers();
RewardProfile profile = GetProfile();
if (profile == null)
{
return;
}
System.Random rng = RunManager.Instance?.currentRun?.randomizer?.Next() ?? new System.Random();
_currentOffers = RewardGenerator.GenerateRuntimeOffers(profile, rng, GetOfferStagingRoot(),
RewardGenerationContext.FromPlayer());
}
private void HandleOfferSelected(int index)
{
if (index < 0 || index >= _currentOffers.Count)
{
return;
}
ItemBase selected = _currentOffers[index];
_currentOffers.RemoveAt(index);
int amount = selected is ConsumableBase consumable ? consumable.stackAmount : 1;
NotificationData notification = NotificationUIArea.CreateItemObtainedData(selected, amount);
MainGameManager.Player.inventorySc.backpackSm.ObtainRewardOffer(selected);
PlayerCanvas.NotificationUIArea?.Push(notification);
ClearCurrentOffers();
CompleteSupplyPack();
}
private void HandleOfferSkipped()
{
RewardProfile profile = GetProfile();
System.Random rng = RunManager.Instance?.currentRun?.randomizer?.Next() ?? new System.Random();
int compensation = profile?.RollSkipCompensation(rng) ?? 0;
if (compensation > 0)
{
MainGameManager.Player.inventorySc.backpackSm.ObtainItem(compensation);
}
PlayerCanvas.NotificationUIArea?.PushRareMaterial(compensation, "放弃补给");
ClearCurrentOffers();
CompleteSupplyPack();
}
private void CompleteSupplyPack()
{
_isAvailable = false;
RefreshChoiceStates();
if (_currentView != null)
{
Destroy(_currentView);
}
if (_notAvailableTablePrefab != null)
{
_currentView = Instantiate(_notAvailableTablePrefab, transform);
}
SetExhausted();
if (RunManager.Instance == null || !RunManager.Instance.TryCompletePendingCombatReward())
{
RunManager.Instance?.CompleteCurrentNode();
}
}
private RewardProfile GetProfile()
{
return _profile;
}
private void RefreshChoiceStates()
{
if (choices == null || choices.Count == 0)
{
return;
}
choices[0].isInteractable = _isAvailable;
}
private void SetAvailable(bool available)
{
_isAvailable = available;
RefreshChoiceStates();
SetInteractable(available);
if (_currentView != null)
{
_currentView.SetActive(available);
}
}
private Transform GetOfferStagingRoot()
{
if (_offerStagingRoot != null)
{
return _offerStagingRoot;
}
GameObject root = new("GeneratedOffers");
root.transform.SetParent(transform, false);
root.SetActive(false);
_offerStagingRoot = root.transform;
return _offerStagingRoot;
}
private void ClearCurrentOffers()
{
foreach (ItemBase item in _currentOffers)
{
if (item != null)
{
Destroy(item.gameObject);
}
}
_currentOffers.Clear();
}
}
}