更新
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user