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

@@ -6,6 +6,7 @@ using Continentis.MainGame.UI;
using SLSFramework.General;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
namespace Continentis.MainGame.Card
{
@@ -17,6 +18,32 @@ namespace Continentis.MainGame.Card
public List<CharacterBase> conditionNotMetTargets = new List<CharacterBase>();
public List<CharacterBase> invalidTargets = new List<CharacterBase>();
#region Multi-Target Selection State
/// <summary>是否正处于多目标逐次点击选择模式。</summary>
private bool isMultiTargetSelecting;
/// <summary>多目标模式下已选中的目标列表(可含重复)。</summary>
private readonly List<CharacterBase> multiTargetSelectedList = new List<CharacterBase>();
/// <summary>多目标模式需要的总选择次数。</summary>
private int multiTargetRequired;
/// <summary>多目标模式下卡牌固定显示的位置(箭头起点)。</summary>
private Vector3 multiTargetCardAnchor;
#endregion
protected override void Update()
{
base.Update();
if (isMultiTargetSelecting)
{
HandleMultiTargetInput();
}
}
public override void OnPointerEnter(PointerEventData eventData)
{
base.OnPointerEnter(eventData);
@@ -78,11 +105,23 @@ namespace Continentis.MainGame.Card
card.user = CombatMainManager.Instance.currentCharacter;
card.DetectTargetsValidity(out validTargets, out conditionNotMetTargets, out invalidTargets);
if (card.attributeSubmodule.targetCount == 1)
int targetCount = card.attributeSubmodule.targetCount;
if (targetCount > 1)
{
// 多目标模式:先执行通用的可打出校验
if (!CheckCanStartPlay())
{
ResetSelectionState();
return;
}
EnterMultiTargetMode(targetCount);
}
else if (targetCount == 1)
{
CombatUIManager.Instance.arrowsPage.GeneratePointerArrow(cardTransform.position, cardTransform.position, true);
}
else if (card.attributeSubmodule.targetCount == -1)
else if (targetCount == -1)
{
CombatUIManager.Instance.arrowsPage.GeneratePointerArrow(cardTransform.position, cardTransform.position, true);
@@ -95,6 +134,9 @@ namespace Continentis.MainGame.Card
public void OnDrag(PointerEventData eventData)
{
// 多目标模式下拖拽无效,交互由 Update 中的点击处理
if (isMultiTargetSelecting) return;
RectTransform arrowCanvasRect = CombatUIManager.Instance.arrowsPage.rectTransform;
Camera uiCamera = CombatUIManager.Instance.uiCamera;
Camera worldCamera = CombatUIManager.Instance.combatCamera;
@@ -117,7 +159,7 @@ namespace Continentis.MainGame.Card
card.contentSubmodule.dirtyMark = true;
}
Vector3 startPosition = cardTransform.position; //+ new Vector3(0, cardTransform.rect.height * cardTransform.lossyScale.y / 2, 0);
Vector3 startPosition = cardTransform.position;
Vector3 endPosition = SpaceConverter.ScreenPointToUIPoint(arrowCanvasRect, eventData.position, uiCamera);
PointerArrow mainPointerArrow = CombatUIManager.Instance.arrowsPage.mainPointerArrow;
@@ -222,6 +264,9 @@ namespace Continentis.MainGame.Card
public void OnEndDrag(PointerEventData eventData)
{
// 多目标模式下,拖拽结束只是从拖拽过渡到点击模式,不做打出判定
if (isMultiTargetSelecting) return;
CombatCharacterViewBase hoveringCharacterView = CombatUIManager.Instance.hoveringCharacterView;
CharacterBase hoveringCharacter = hoveringCharacterView != null ? hoveringCharacterView.character : null;
Camera uiCamera = CombatUIManager.Instance.uiCamera;
@@ -242,11 +287,7 @@ namespace Continentis.MainGame.Card
return;
}
if (card.HasKeyword("Unplayable")) // 如果有“不能打出”关键词,直接返回
{
return;
}
if (!CheckCanStartPlay()) return;
if (!card.HasKeyword("TargetSelf"))
{
@@ -290,5 +331,211 @@ namespace Continentis.MainGame.Card
}
}
}
#region Play Validation
/// <summary>
/// 检查卡牌是否可以被打出Unplayable / Prerequisite 校验)。
/// 校验失败时会生成提示文本。
/// </summary>
private bool CheckCanStartPlay()
{
if (card.HasKeyword("Unplayable"))
{
return false;
}
if (!card.HasKeyword("Prerequisite"))
{
CharacterBase currentCharacter = CombatMainManager.Instance.currentCharacter;
List<CardInstance> handPile = currentCharacter.deckSubmodule.HandPile;
for (int i = 0; i < handPile.Count; i++)
{
if (handPile[i].HasKeyword("Prerequisite"))
{
MainGameManager.Instance.basePrefabs.GenerateInfoText(
"Keyword_Prerequisite_Warning".Localize(), currentCharacter.characterView);
return false;
}
}
}
return true;
}
/// <summary>重置选择状态(不触发 Untargeting 事件)。</summary>
private void ResetSelectionState()
{
isSelecting = false;
isHovering = false;
CombatUIManager.Instance.selectingCardView = null;
canvas.overrideSorting = false;
canvas.sortingOrder = 0;
}
#endregion
#region Multi-Target Selection
/// <summary>进入多目标逐次选择模式。</summary>
private void EnterMultiTargetMode(int required)
{
isMultiTargetSelecting = true;
multiTargetRequired = required;
multiTargetSelectedList.Clear();
// 记录卡牌当前位置作为箭头起点锚点
multiTargetCardAnchor = cardTransform.position;
UpdateMultiTargetHint();
}
/// <summary>多目标模式下的输入处理,在 Update 中调用。</summary>
private void HandleMultiTargetInput()
{
// Escape 取消全部
if (Keyboard.current.escapeKey.wasPressedThisFrame)
{
ExitMultiTargetMode();
return;
}
// 右键撤销上一步
if (Mouse.current.rightButton.wasPressedThisFrame)
{
UndoLastMultiTarget();
return;
}
// 左键选择目标
if (Mouse.current.leftButton.wasPressedThisFrame)
{
CombatCharacterViewBase hoveringView = CombatUIManager.Instance.hoveringCharacterView;
if (hoveringView == null) return;
CharacterBase hoveringCharacter = hoveringView.character;
// 判断是否为有效目标
if (!validTargets.Contains(hoveringCharacter)) return;
// 判断是否允许重复选择
if (!card.HasKeyword(CardKeywords.AllowDuplicateTargets)
&& multiTargetSelectedList.Contains(hoveringCharacter))
{
return;
}
// 选中目标
multiTargetSelectedList.Add(hoveringCharacter);
// 生成固定箭头指向该目标
RectTransform arrowCanvasRect = CombatUIManager.Instance.arrowsPage.rectTransform;
Camera worldCamera = CombatUIManager.Instance.combatCamera;
Camera uiCamera = CombatUIManager.Instance.uiCamera;
Vector3 targetWorldPos = hoveringView.transform.position;
Vector3 targetUIPos = SpaceConverter.WorldPointToUIPoint(
arrowCanvasRect, targetWorldPos, worldCamera, uiCamera);
// 第一支箭头为 main后续为 other
bool isMain = multiTargetSelectedList.Count == 1;
CombatUIManager.Instance.arrowsPage.GeneratePointerArrow(
multiTargetCardAnchor, targetUIPos, isMain);
// 触发 TargetingEffect 更新伤害预览
card.Targeting(hoveringCharacter);
card.contentSubmodule.dirtyMark = true;
UpdateMultiTargetHint();
// 检查是否选满
if (multiTargetSelectedList.Count >= multiTargetRequired)
{
ConfirmMultiTargetPlay();
}
}
}
/// <summary>撤销多目标模式下的上一步选择。</summary>
private void UndoLastMultiTarget()
{
if (multiTargetSelectedList.Count > 0)
{
multiTargetSelectedList.RemoveAt(multiTargetSelectedList.Count - 1);
CombatUIManager.Instance.arrowsPage.RemoveLastPointerArrow();
// 如果还有已选目标,触发最后一个目标的 TargetingEffect
if (multiTargetSelectedList.Count > 0)
{
card.Targeting(multiTargetSelectedList[^1]);
}
else
{
card.Untargeting();
}
card.contentSubmodule.dirtyMark = true;
UpdateMultiTargetHint();
}
// 已选归零 → 取消选择,卡牌归位
if (multiTargetSelectedList.Count == 0)
{
ExitMultiTargetMode();
}
}
/// <summary>选满后自动打出。</summary>
private void ConfirmMultiTargetPlay()
{
List<CharacterBase> targets = new List<CharacterBase>(multiTargetSelectedList);
// 清理多目标状态
isMultiTargetSelecting = false;
multiTargetSelectedList.Clear();
multiTargetRequired = 0;
CombatUIManager.Instance.arrowsPage.ClearPointerArrows();
isSelecting = false;
isHovering = false;
CombatUIManager.Instance.selectingCardView = null;
canvas.overrideSorting = false;
canvas.sortingOrder = 0;
// 打出卡牌
if (!card.Play(targets))
{
card.eventSubmodule.onUntargeting();
card.contentSubmodule.dirtyMark = true;
}
}
/// <summary>退出多目标选择模式(取消操作),清理所有状态,卡牌归位。</summary>
private void ExitMultiTargetMode()
{
isMultiTargetSelecting = false;
multiTargetSelectedList.Clear();
multiTargetRequired = 0;
CombatUIManager.Instance.arrowsPage.ClearPointerArrows();
isSelecting = false;
isHovering = false;
CombatUIManager.Instance.selectingCardView = null;
canvas.overrideSorting = false;
canvas.sortingOrder = 0;
card.eventSubmodule.onUntargeting();
card.contentSubmodule.dirtyMark = true;
}
/// <summary>更新多目标选择的计数提示。</summary>
private void UpdateMultiTargetHint()
{
string hint = $"{multiTargetSelectedList.Count} / {multiTargetRequired}";
MainGameManager.Instance.basePrefabs.GenerateInfoText(
hint, card.user.characterView, Color.cyan);
}
#endregion
}
}