This commit is contained in:
SoulliesOfficial
2026-04-01 12:23:27 -04:00
parent aff7ac0e03
commit c3b1561375
933 changed files with 114333 additions and 119360 deletions

View File

@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using Continentis.MainGame.Card;
using SLSFramework.General;
using SoftCircuits.Collections;
using UnityEngine;
using UnityEngine.Events;
namespace Continentis.MainGame.Character
{
public partial class IntentionSubmodule : SubmoduleBase<CharacterBase>
{
public List<IntentionBase> allIntentions;
public IntentionBase currentIntention;
public UnityAction getIntendedCards;
public List<IntendedCard> intendedCards;
/// <summary>意图卡被移除后触发,参数为被移除的 IntendedCard 和它原来所在的索引。</summary>
public OrderedDictionary<string, PrioritizedAction<IntendedCard, int>> onIntendedCardRemoved;
/// <summary>意图卡被替换后触发,参数为旧 IntendedCard、新 IntendedCard 和所在的索引。</summary>
public OrderedDictionary<string, PrioritizedAction<IntendedCard, IntendedCard, int>> onIntendedCardReplaced;
/// <summary>意图卡被插入后触发,参数为新 IntendedCard 和插入的索引。</summary>
public OrderedDictionary<string, PrioritizedAction<IntendedCard, int>> onIntendedCardInserted;
public IntentionSubmodule(CharacterBase owner) : base(owner)
{
allIntentions = new List<IntentionBase>();
currentIntention = new IntentionBase(this);
getIntendedCards = owner.GetIntendedCards;
intendedCards = new List<IntendedCard>();
onIntendedCardRemoved = new OrderedDictionary<string, PrioritizedAction<IntendedCard, int>>();
onIntendedCardReplaced = new OrderedDictionary<string, PrioritizedAction<IntendedCard, IntendedCard, int>>();
onIntendedCardInserted = new OrderedDictionary<string, PrioritizedAction<IntendedCard, int>>();
}
}
public class IntendedCard
{
public CardInstance cardInstance;
public List<CharacterBase> targets;
public IntendedCard(CardInstance cardInstance, List<CharacterBase> targets)
{
this.cardInstance = cardInstance;
this.targets = targets;
}
}
public class IntentionBase : IPrioritized
{
public IntentionSubmodule intentionSubmodule;
public CharacterBase character => intentionSubmodule.owner;
public DeckSubmodule characterDeck => character.deckSubmodule;
public RecordSubmodule characterRecord => character.recordSubmodule;
public int Priority { get; protected set; }
public int guaranteedStamina;
public int guaranteedMana;
public int maxCardCount;
public IntentionBase(IntentionSubmodule intentionSubmodule)
{
this.intentionSubmodule = intentionSubmodule;
this.Priority = 0;
this.guaranteedStamina = 0;
this.guaranteedMana = 0;
this.maxCardCount = 999;
}
public virtual bool Condition()
{
return true;
}
public virtual void RefreshCardWeights()
{
}
public virtual void RefreshTargets()
{
}
/// <summary>NPC 本回合出牌前调用,可用于播放蓄力台词、切换动画状态等。</summary>
public virtual void PreAction() { }
/// <summary>NPC 本回合全部卡牌出完后调用,可用于播放结束台词、重置状态等。</summary>
public virtual void PostAction() { }
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 434edd20e1100e8489b175dab3fac8e0

View File

@@ -0,0 +1,238 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Continentis.MainGame.Card;
using SLSFramework.General;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Continentis.MainGame.Character
{
public partial class IntentionSubmodule
{
// ──────────────────────────────────────────────────────────────
// 原子操作层
// ──────────────────────────────────────────────────────────────
/// <summary>移除指定位置的意图卡并销毁其视图。</summary>
/// <returns>被移除的 IntendedCard索引越界时返回 null。</returns>
public IntendedCard RemoveIntendedCardAt(int index)
{
if (!IsValidIndex(index)) return null;
IntendedCard removed = intendedCards[index];
removed.cardInstance.DestroyIntentionCardView();
intendedCards.RemoveAt(index);
onIntendedCardRemoved.Invoke(removed, index);
return removed;
}
/// <summary>替换指定位置的意图卡,销毁旧视图并生成新视图。</summary>
/// <returns>被替换掉的旧 IntendedCard索引越界时返回 null。</returns>
public IntendedCard ReplaceIntendedCardAt(int index, IntendedCard newCard)
{
if (!IsValidIndex(index)) return null;
if (newCard == null)
{
Debug.LogWarning("[IntentionSubmodule] ReplaceIntendedCardAt: newCard is null, performing remove instead.");
return RemoveIntendedCardAt(index);
}
IntendedCard oldCard = intendedCards[index];
oldCard.cardInstance.DestroyIntentionCardView();
intendedCards[index] = newCard;
newCard.cardInstance.GenerateIntentionCardView();
// 设置文本解析目标
if (newCard.targets.Count > 0)
{
newCard.cardInstance.Targeting(newCard.targets[0]);
newCard.cardInstance.contentSubmodule.dirtyMark = true;
}
onIntendedCardReplaced.Invoke(oldCard, newCard, index);
return oldCard;
}
/// <summary>在指定位置插入一张新意图卡并生成视图。</summary>
public void InsertIntendedCard(int index, IntendedCard newCard)
{
if (newCard == null)
{
Debug.LogWarning("[IntentionSubmodule] InsertIntendedCard: newCard is null, insertion skipped.");
return;
}
int clampedIndex = Mathf.Clamp(index, 0, intendedCards.Count);
intendedCards.Insert(clampedIndex, newCard);
newCard.cardInstance.GenerateIntentionCardView();
// 设置文本解析目标
if (newCard.targets.Count > 0)
{
newCard.cardInstance.Targeting(newCard.targets[0]);
newCard.cardInstance.contentSubmodule.dirtyMark = true;
}
onIntendedCardInserted.Invoke(newCard, clampedIndex);
}
/// <summary>在末尾追加一张新意图卡并生成视图。</summary>
public void AddIntendedCard(IntendedCard newCard)
{
InsertIntendedCard(intendedCards.Count, newCard);
}
// ──────────────────────────────────────────────────────────────
// 查询 / 工具层
// ──────────────────────────────────────────────────────────────
/// <summary>返回 intendedCards 中的随机索引,列表为空时返回 -1。</summary>
public int GetRandomIntendedCardIndex()
{
return intendedCards.Count == 0 ? -1 : Random.Range(0, intendedCards.Count);
}
/// <summary>
/// 使用过滤器从 intendedCards 中筛选出符合条件的意图卡索引列表。
/// </summary>
/// <param name="filter">返回 true 表示该意图卡通过筛选。</param>
public List<int> GetFilteredIntendedCardIndices(Func<IntendedCard, bool> filter)
{
List<int> result = new List<int>();
for (int i = 0; i < intendedCards.Count; i++)
{
if (filter(intendedCards[i]))
result.Add(i);
}
return result;
}
/// <summary>
/// 使用过滤器从 intendedCards 中随机选取一个符合条件的意图卡索引。
/// </summary>
/// <returns>随机索引,无符合条件的意图卡时返回 -1。</returns>
public int GetRandomFilteredIntendedCardIndex(Func<IntendedCard, bool> filter)
{
List<int> filtered = GetFilteredIntendedCardIndices(filter);
return filtered.Count == 0 ? -1 : filtered[Random.Range(0, filtered.Count)];
}
/// <summary>
/// 尝试从 PoolPile 中获取一张可替换的随机卡牌(排除当前已在 intendedCards 中的卡牌)。
/// </summary>
/// <param name="result">生成的 IntendedCard失败时为 null。</param>
/// <param name="checkAffordability">是否检查体力/法力消耗。</param>
/// <returns>是否成功找到可替换的卡牌。</returns>
public bool TryGetRandomReplacementCard(out IntendedCard result, bool checkAffordability = false)
{
result = null;
HashSet<CardInstance> currentCards = new HashSet<CardInstance>(
intendedCards.Select(ic => ic.cardInstance));
List<CardInstance> candidates = owner.deckSubmodule.PoolPile
.Where(card => !currentCards.Contains(card) && !card.weightSubmodule.forceIgnore)
.ToList();
if (checkAffordability)
{
int stamina = owner.GetAttribute(CharacterAttributes.Stamina);
int mana = owner.GetAttribute(CharacterAttributes.Mana);
candidates = candidates.Where(card =>
card.GetAttribute(CardAttributes.StaminaCost) <= stamina &&
card.GetAttribute(CardAttributes.ManaCost) <= mana).ToList();
}
if (candidates.Count == 0) return false;
CardInstance chosen = candidates[Random.Range(0, candidates.Count)];
if (!owner.CheckAvailabilityAndSetTargets(chosen, out List<CharacterBase> targets))
return false;
result = new IntendedCard(chosen, targets);
return true;
}
// ──────────────────────────────────────────────────────────────
// 组合操作层
// ──────────────────────────────────────────────────────────────
/// <summary>随机移除一张意图卡。</summary>
/// <returns>被移除的 IntendedCard列表为空时返回 null。</returns>
public IntendedCard RemoveRandomIntendedCard()
{
int index = GetRandomIntendedCardIndex();
return index < 0 ? null : RemoveIntendedCardAt(index);
}
/// <summary>
/// 随机移除一张符合过滤条件的意图卡。
/// </summary>
/// <param name="filter">返回 true 表示该意图卡可被移除。</param>
/// <returns>被移除的 IntendedCard无符合条件的意图卡时返回 null。</returns>
public IntendedCard RemoveRandomIntendedCard(Func<IntendedCard, bool> filter)
{
int index = GetRandomFilteredIntendedCardIndex(filter);
return index < 0 ? null : RemoveIntendedCardAt(index);
}
/// <summary>
/// 随机将一张意图卡替换为 PoolPile 中的另一张卡牌。
/// 若无可替换卡牌则降级为移除。
/// </summary>
/// <param name="checkAffordability">是否检查体力/法力消耗。</param>
/// <returns>操作是否成功执行(移除或替换均算成功)。</returns>
public bool ChangeRandomIntendedCard(bool checkAffordability = false)
{
int index = GetRandomIntendedCardIndex();
if (index < 0) return false;
if (TryGetRandomReplacementCard(out IntendedCard replacement, checkAffordability))
{
ReplaceIntendedCardAt(index, replacement);
}
else
{
RemoveIntendedCardAt(index);
}
return true;
}
/// <summary>
/// 随机将一张符合过滤条件的意图卡替换为 PoolPile 中的另一张卡牌。
/// 若无可替换卡牌则降级为移除。
/// </summary>
/// <param name="filter">返回 true 表示该意图卡可被替换。</param>
/// <param name="checkAffordability">是否检查体力/法力消耗。</param>
/// <returns>操作是否成功执行。</returns>
public bool ChangeRandomIntendedCard(Func<IntendedCard, bool> filter, bool checkAffordability = false)
{
int index = GetRandomFilteredIntendedCardIndex(filter);
if (index < 0) return false;
if (TryGetRandomReplacementCard(out IntendedCard replacement, checkAffordability))
{
ReplaceIntendedCardAt(index, replacement);
}
else
{
RemoveIntendedCardAt(index);
}
return true;
}
// ──────────────────────────────────────────────────────────────
// 内部工具
// ──────────────────────────────────────────────────────────────
private bool IsValidIndex(int index)
{
if (index >= 0 && index < intendedCards.Count) return true;
Debug.LogWarning($"[IntentionSubmodule] Index {index} out of range (count: {intendedCards.Count}).");
return false;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 41e6e47005c77fb4994040c6b9763669