using UnityEngine;
using System.Collections.Generic;
using Vampirefall.DecisionSystem;
using System.Linq;
public class PerkDraftingSystem : MonoBehaviour
{
[Header("配置")]
public int draftOptionCount = 3; // 每次提供多少个Perk供选择
private DecisionEngine<PerkData> _decisionEngine;
private PerkBanFilter _perkBanFilter;
private List<PerkData> _allAvailablePerks; // 所有Perk的Master List
private List<PerkData> _playerOwnedPerks = new List<PerkData>();
private List<string> _playerSynergyTags = new List<string> { "Fire", "Melee" }; // 模拟玩家当前Build的标签
void Start()
{
InitializePerkPool();
InitializeDecisionEngine();
}
void InitializePerkPool()
{
// 模拟加载所有Perk
_allAvailablePerks = new List<PerkData>
{
new PerkData("P_FireDmg", "火焰强化", Rarity.Common, new List<string> { "Fire", "Damage" }),
new PerkData("P_IceDmg", "冰霜强化", Rarity.Common, new List<string> { "Ice", "Damage" }),
new PerkData("P_MeleeCrit", "近战暴击", Rarity.Rare, new List<string> { "Melee", "Crit" }),
new PerkData("P_RangedSpeed", "远程攻速", Rarity.Rare, new List<string> { "Ranged", "AttackSpeed" }),
new PerkData("P_BloodMagic", "血魔法", Rarity.Legendary, new List<string> { "Life", "Skill" }) { ConflictingPerkIDs = new List<string>{"P_ManaShield"} },
new PerkData("P_ManaShield", "法力护盾", Rarity.Epic, new List<string> { "Mana", "Defense" }) { ConflictingPerkIDs = new List<string>{"P_BloodMagic"} },
new PerkData("P_Fireball", "火球术", Rarity.Rare, new List<string> { "Fire", "Skill" }),
new PerkData("P_HealthBoost", "生命增幅", Rarity.Common, new List<string> { "Defense" }),
new PerkData("P_QuickFeet", "疾速步伐", Rarity.Common, new List<string> { "Movement" }),
new PerkData("P_Phoenix", "凤凰涅槃", Rarity.Epic, new List<string> { "Fire", "Life" }),
new PerkData("P_AuraOfMight", "力量光环", Rarity.Legendary, new List<string> { "Aura", "Damage" })
};
}
void InitializeDecisionEngine()
{
_decisionEngine = new DecisionEngine<PerkData>();
// 过滤器:排除已拥有或冲突的Perk
_perkBanFilter = new PerkBanFilter(_playerOwnedPerks.Select(p => p.ID).ToList());
_decisionEngine.AddFilter(_perkBanFilter);
// 评分器:
// 1. 稀有度评分 (权重高) - 基础权重,传说Perk得分最高
var rarityWeights = new Dictionary<Rarity, float>()
{
{ Rarity.Common, 1f },
{ Rarity.Rare, 2f },
{ Rarity.Epic, 4f },
{ Rarity.Legendary, 8f }
};
_decisionEngine.AddScorer(new RarityScorer<PerkData>(1f, p => p, rarityWeights));
// 2. 标签协同评分 (权重中等) - 偏好与玩家现有Build标签匹配的Perk
_decisionEngine.AddScorer(new TagSynergyScorer<PerkData>(2f, p => p)); // PlayerSynergyTags会从Context传入
// TODO: 其他评分器,如:同类Perk数量过多时降低权重,或PityTimerScorer等
}
/// <summary>
/// 触发一次Perk抽取,返回指定数量的Perk选项
/// </summary>
public List<PerkData> DraftPerks()
{
List<PerkData> draftedPerks = new List<PerkData>();
HashSet<string> selectedThisDraft = new HashSet<string>(); // 避免本次抽取中重复出现
DecisionContext ctx = new DecisionContext();
ctx.Set("PlayerSynergyTags", _playerSynergyTags); // 将玩家Build标签放入Context
// 为了避免在一次抽取中重复拿到同一个Perk,每次抽取后从池中临时移除
List<PerkData> currentPool = new List<PerkData>(_allAvailablePerks);
for (int i = 0; i < draftOptionCount; i++)
{
PerkData selectedPerk = _decisionEngine.SelectRandom(currentPool, ctx);
if (selectedPerk != null)
{
draftedPerks.Add(selectedPerk);
// 从当前抽取池中移除,避免本次Draft重复
currentPool.Remove(selectedPerk);
selectedThisDraft.Add(selectedPerk.ID);
}
}
Debug.Log($"Drafted Perks (Player Tags: {string.Join(", ", _playerSynergyTags)}):");
foreach(var perk in draftedPerks)
{
Debug.Log($"- {perk}");
}
return draftedPerks;
}
/// <summary>
/// 模拟玩家选择了一个Perk
/// </summary>
public void PlayerChosePerk(PerkData chosenPerk)
{
if (chosenPerk == null) return;
Debug.Log($"Player chose: {chosenPerk.Name}");
_playerOwnedPerks.Add(chosenPerk);
// 更新过滤器黑名单,以便下次抽取时排除已选择和冲突的Perk
List<string> newBlacklist = _playerOwnedPerks.SelectMany(p => p.ConflictingPerkIDs).ToList();
_perkBanFilter.UpdateBlacklist(_playerOwnedPerkIDs.Select(p=>p.ID).ToList().Concat(newBlacklist).ToList());
// 模拟更新玩家的协同标签 (例如,选择了火系Perk后,玩家Build标签中加入"Fire")
if (chosenPerk.Tags.Any(tag => tag == "Fire")) {
if (!_playerSynergyTags.Contains("Fire")) _playerSynergyTags.Add("Fire");
}
}
// 简单触发器
void Update() {
if (Input.GetKeyDown(KeyCode.Space)) {
Debug.Log("--- Drafting New Perks ---");
List<PerkData> options = DraftPerks();
if (options.Count > 0) {
// 模拟玩家选择第一个Perk
PlayerChosePerk(options[0]);
}
}
}
}