107 lines
5.0 KiB
C#
107 lines
5.0 KiB
C#
using System;
|
||
using Cielonos.MainGame;
|
||
using Cielonos.MainGame.Inventory;
|
||
using Cielonos.MainGame.Narrative;
|
||
using UnityEngine;
|
||
using Yarn.Unity;
|
||
|
||
namespace Cielonos.Narrative
|
||
{
|
||
public static partial class CustomFunctions
|
||
{
|
||
/// <summary>
|
||
/// 提供给 Yarn Spinner 调用的自定义函数,用于在对话中给予玩家指定物品。
|
||
/// 物品在授予后,会自动写入 InfoTransistor 中的 StartInventory,以便跨场景保存。
|
||
/// </summary>
|
||
/// <param name="itemClass">物品的类名(需存在于 Inventory.Collections 命名空间下)</param>
|
||
/// <param name="stackAmount">物品的数量/层数,默认为 1</param>
|
||
[YarnCommand("obtain_item")]
|
||
public static void ObtainItem(string itemClass, int stackAmount = 1)
|
||
{
|
||
PlayerInventorySaveData startInventory = InfoTransistor.GetInfo<PlayerInventorySaveData>("StartInventory");
|
||
if (startInventory == null)
|
||
{
|
||
// 如果当前不存在过渡存档数据,说明这是本次场景内的第一次额外物品获取。
|
||
// 此时建立一个空的 SaveData 作为起始收集器。
|
||
InfoTransistor.SetInfo("StartInventory", new PlayerInventorySaveData());
|
||
startInventory = InfoTransistor.GetInfo<PlayerInventorySaveData>("StartInventory");
|
||
}
|
||
|
||
Type type = Type.GetType($"Cielonos.MainGame.Inventory.Collections.{itemClass}");
|
||
if (type == null)
|
||
{
|
||
Debug.LogError($"[YarnCommand] Cannot find item class type for name '{itemClass}'. Make sure it is in namespace Cielonos.MainGame.Inventory.Collections");
|
||
return;
|
||
}
|
||
|
||
ItemBase item = MainGameManager.Player.inventorySc.backpackSm.ObtainItem(type, stackAmount);
|
||
ItemSaveData itemSaveData = new ItemSaveData(itemClass);
|
||
if (item is MainWeaponBase mainWeapon)
|
||
{
|
||
MainGameManager.Player.inventorySc.equipmentSm.PrepareMainWeapon(mainWeapon);
|
||
MainGameManager.Player.inventorySc.equipmentSm.EquipMainWeapon(mainWeapon);
|
||
|
||
startInventory.mainWeapons.Add(itemSaveData);
|
||
startInventory.preparedMainWeapons.Add(itemSaveData);
|
||
startInventory.currentMainWeapon = itemSaveData;
|
||
}
|
||
else if (item is SupportEquipmentBase supportEquipment)
|
||
{
|
||
MainGameManager.Player.inventorySc.equipmentSm.EquipSupportEquipment(supportEquipment, 0);
|
||
|
||
startInventory.supportEquipments.Add(itemSaveData);
|
||
startInventory.currentSupportEquipments.Add(itemSaveData);
|
||
}
|
||
else if (item is PassiveEquipmentBase passiveEquipment)
|
||
{
|
||
MainGameManager.Player.inventorySc.backpackSm.ObtainItem(passiveEquipment);
|
||
startInventory.passiveEquipments.Add(itemSaveData);
|
||
}
|
||
else if (item is ConsumableBase consumable)
|
||
{
|
||
itemSaveData.stackAmount = stackAmount;
|
||
startInventory.consumables.Add(itemSaveData);
|
||
Debug.Log($"[obtain_item] Obtained consumable '{itemClass}' with stack amount {stackAmount}.");
|
||
}
|
||
}
|
||
|
||
[YarnFunction("check_have_item")]
|
||
public static bool CheckHaveItem(string itemClass)
|
||
{
|
||
return MainGameManager.Player.inventorySc.backpackSm.HaveItem(itemClass);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 结束当前的地图事件(Event)。
|
||
/// 调用后会通知 RunManager 将当前节点标记为已完成/已耗尽,并把系统状态恢复到 MapSelection 以便玩家继续前进。
|
||
/// </summary>
|
||
[YarnCommand("finish_event")]
|
||
public static void FinishEvent()
|
||
{
|
||
if (RunManager.Instance != null && RunManager.Instance.currentPhase == RunPhase.InEvent)
|
||
{
|
||
RunManager.Instance.CompleteCurrentNode();
|
||
Debug.Log("[CustomFunctions] finish_event: 当前地图事件已结束,系统状态已恢复到 MapSelection。");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 耗尽/禁用指定的 NPC 交互(在剧情结束后彻底移除它的对话选项)。
|
||
/// 适用于那些不能被反复对话的 NPC,或者需要等离开场景才重置交互逻辑的 NPC。
|
||
/// </summary>
|
||
/// <param name="npcID">NPC 的标识ID(例如 "SupportPersonnel")</param>
|
||
[YarnCommand("exhaust_npc")]
|
||
public static void ExhaustNpc(string npcID)
|
||
{
|
||
if (StoryDirector.ActiveNpcs.TryGetValue(npcID, out var npc))
|
||
{
|
||
npc.SetExhausted();
|
||
Debug.Log($"[CustomFunctions] NPC '{npcID}' 交互已耗尽。");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"[CustomFunctions] exhaust_npc 找不到处于激活状态的 NPC: '{npcID}'");
|
||
}
|
||
}
|
||
}
|
||
} |