Files
Cielonos/Assets/Scripts/MainGame/Interactions/LogisticsCenter.cs
SoulliesOfficial 39b43680a9 爆更
2026-07-18 03:16:20 -04:00

139 lines
4.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using Cielonos.Core.Interaction;
using Cielonos.MainGame.Characters;
using Cielonos.MainGame.Inventory;
using Cielonos.MainGame.Inventory.Collections;
using Cielonos.MainGame.Items;
using Cielonos.MainGame.Rewards;
using Cielonos.MainGame.UI;
using Sirenix.OdinInspector;
using UnityEngine;
namespace Cielonos.MainGame.Interactions
{
/// <summary>
/// 物流中心(商店)场景交互对象。
/// 玩家靠近按交互键后呼出 LogisticCenterUIPage显示可购买的随机装备。
/// 商店可反复打开(不像机械台单次使用),商品在首次进入时生成,买完即消失。
/// 货币通过消耗背包中的 RareMaterial 消耗品来支付。
/// </summary>
public class LogisticsCenter : InteractableObjectBase
{
[TitleGroup("Reward Profile")]
[SerializeField, Required]
private RewardProfile _profile;
private List<ShopOffer> currentOffers;
private bool isInitialized;
protected override void InitializeChoices()
{
choices.Add(new InteractionChoice("Open Logistic Center", OpenShop));
}
/// <summary>
/// 由 RunManager 或场景加载逻辑调用,预先生成本次商店的商品列表和价格。
/// 若未调用此方法,交互时会自动从 Resources/Items 中生成。
/// </summary>
/// <param name="rng">本局 Run 的随机数生成器。</param>
public void Setup(System.Random rng)
{
currentOffers = RollShopOffers(rng);
isInitialized = true;
}
private void OpenShop()
{
if (!isInitialized)
{
System.Random rng = RunManager.Instance?.currentRun?.randomizer?.Next() ?? new System.Random();
currentOffers = RollShopOffers(rng);
isInitialized = true;
}
if (currentOffers == null || currentOffers.Count == 0)
{
Debug.LogWarning("[LogisticCenter] 候选池为空,没有可售卖的装备。");
return;
}
var uiPage = PlayerCanvas.MainGamePages.logisticsCenterPage;
uiPage.SetOffers(currentOffers, HandlePurchase);
uiPage.Open();
}
private void HandlePurchase(int index)
{
if (index < 0 || index >= currentOffers.Count) return;
ShopOffer offer = currentOffers[index];
// 获取玩家背包中的 RareMaterial
PlayerInventorySubcontroller inventorySc = MainGameManager.Player.inventorySc;
RareMaterial rareMaterial = MainGameManager.Player.inventorySc.GetRareMaterial();
if (rareMaterial == null || rareMaterial.stackAmount < offer.price)
{
Debug.Log("[LogisticCenter] RareMaterial 不足,无法购买。");
return;
}
// 扣除 RareMaterial
rareMaterial.Use(offer.price);
int remaining = rareMaterial != null ? rareMaterial.stackAmount : 0;
// 将物品加入背包
inventorySc.backpackSm.ObtainItemPrefab(offer.item);
// 从商品列表中移除已购买的商品
currentOffers.RemoveAt(index);
Debug.Log($"[LogisticCenter] 玩家购买了 '{offer.item.name}',花费 {offer.price} RareMaterial剩余 {remaining}。");
}
/// <summary>
/// 从 RewardProfile 生成商店候选并生成包含价格的 ShopOffer。
/// Profile 可明确限制可用主武器,避免废弃武器自动进入商店池。
/// </summary>
private List<ShopOffer> RollShopOffers(System.Random rng)
{
if (_profile == null)
{
Debug.LogError("[LogisticsCenter] RewardProfile is not assigned.");
return new List<ShopOffer>();
}
List<ItemBase> rolledItems = RewardGenerator.GeneratePrefabOffers(_profile, rng,
RewardGenerationContext.FromPlayer().ExcludeOwnedNonConsumables());
List<ShopOffer> offers = new List<ShopOffer>(rolledItems.Count);
foreach (ItemBase item in rolledItems)
{
if (item == null || item.contentData == null) continue;
int price = MainGameManager.Config.RollPrice(item.contentData.itemRarity, rng);
offers.Add(new ShopOffer(item, price));
}
return offers;
}
}
/// <summary>
/// 商店中的单个商品条目:包含物品预制体引用和售价。
/// </summary>
[Serializable]
public class ShopOffer
{
public ItemBase item;
public int price;
public ShopOffer(ItemBase item, int price)
{
this.item = item;
this.price = price;
}
}
}