文本显示和Command大修

This commit is contained in:
SoulliesOfficial
2025-11-08 09:50:55 -05:00
parent 3f1e04dee7
commit b2e9e84c52
78 changed files with 293 additions and 244 deletions

View File

@@ -131,6 +131,65 @@ namespace Continentis.MainGame.Card
return GetFinalDamage(target, elementalTags, out _, out _, out _, out _);
}
/// <summary>
/// 获取最终伤害
/// </summary>
/// <param name="elementalTags">元素标签若为null则使用卡牌的元素标签</param>
public virtual int GetUserDamage(List<string> elementalTags = null)
{
return GetUserDamage(elementalTags, out _, out _, out _, out _);
}
/// <summary>
/// 获取在没有指定目标时的最终伤害值
/// </summary>
protected virtual int GetUserDamage(List<string> elementalTags,
out float baseDamageAfterOffset, out float elementalMultiplier, out float magicMultiplier, out float finalMultiplier)
{
elementalTags ??= GetElementalKeywords();
//----计算基础伤害增量----
int physicsOffset = 0;
if (HasKeyword("Physics") || HasKeyword("Slash") || HasKeyword("Prick") || HasKeyword("Strike"))
{
physicsOffset = user.GetAttribute("PhysicsDamageDealtOffset"); //物理伤害基础增量
}
int magicOffset = 0;
if (HasKeyword("Magic") || HasKeyword("Arcane") || HasKeyword("Sorcery"))
{
magicOffset = user.GetAttribute("MagicDamageDealtOffset"); //魔法伤害基础增量
}
Debug.Log("Magic Offset: " + magicOffset);
//----计算伤害因数----
//计算元素伤害加成注意“物理Physics”也是一种元素因此下方没有“通用物理伤害加成”的计算
elementalMultiplier = 1;
foreach (string element in elementalTags)
{
elementalMultiplier *= user.GetRawAttribute(element + "DamageDealtMultiplier", 1);
}
//计算通用的魔法伤害加成
magicMultiplier = 1;
if (HasKeyword("Magic") || HasKeyword("Arcane") || HasKeyword("Sorcery"))
{
magicMultiplier = user.GetRawAttribute("MagicDamageDealtMultiplier", 1);
}
//计算最终伤害加成
finalMultiplier = user.GetRawAttribute("FinalDamageDealtMultiplier", 1);
//----计算最终伤害----
baseDamageAfterOffset = attributeSubmodule.GetCurrentAttribute("Damage") + physicsOffset + magicOffset;
float finalDamage = baseDamageAfterOffset * elementalMultiplier * magicMultiplier * finalMultiplier;
return Mathf.RoundToInt(finalDamage);
}
protected virtual int GetFinalDamage(CharacterBase target, List<string> elementalTags,
out float baseDamageAfterOffset, out float elementalMultiplier, out float magicMultiplier, out float finalMultiplier)
{

View File

@@ -86,10 +86,8 @@ namespace Continentis.MainGame.Card
}
attributeSubmodule?.RefreshAllModifiedAttributes();
Debug.Log(base.attachedCard.GetAttribute("Damage"));
CardTextInterpreter.InterpretText(attachedCard);
attachedCard.handCardView?.Setup();
attachedCard.intentionCardView?.Setup();
attachedCard.contentSubmodule.dirtyMark = true;
Debug.Log(base.attachedCard.contentSubmodule.interpretedFunctionText);
}

View File

@@ -5,6 +5,7 @@ using Continentis.MainGame.Character;
using Continentis.MainGame.Equipment;
using SLSFramework.General;
using SLSFramework.UModAssistance;
using UniRx;
using UnityEngine;
namespace Continentis.MainGame.Card
@@ -14,6 +15,7 @@ namespace Continentis.MainGame.Card
[Header("Reference")]
public CardData cardData;
public CardInstance cardInstance;
public CompositeDisposable disposables = new CompositeDisposable();
public ICardOwner owner => cardInstance.owner;
public CharacterBase user => cardInstance.user;
@@ -82,8 +84,7 @@ namespace Continentis.MainGame.Card
public virtual void Initialize()
{
RefreshCardAttributes();
CardTextInterpreter.InterpretText(this);
if (HasKeyword("Instant")) //如果是“瞬发”牌,添加抽牌后立刻打出的事件
{
eventSubmodule.onDraw.InsertByPriority("Instant", new PrioritizedAction(() =>

View File

@@ -47,6 +47,8 @@ namespace Continentis.MainGame.Card
{
eventSubmodule.onUntargeting();
}
contentSubmodule.dirtyMark = true;
}
/// <summary>
@@ -198,7 +200,7 @@ namespace Continentis.MainGame.Card
});
}));
CommandQueueManager.Instance.AddCommand(PlayEffect(targetList));
CommandQueueManager.Instance.AddCommands(PlayEffect(targetList));
CommandQueueManager.Instance.AddCommand(new Cmd_Function(() =>
{
eventSubmodule.onAfterPlay.Invoke(targetList);
@@ -225,7 +227,7 @@ namespace Continentis.MainGame.Card
}
}
protected virtual CommandBase PlayEffect(List<CharacterBase> targetList)
protected virtual List<CommandBase> PlayEffect(List<CharacterBase> targetList)
{
return null;
}

View File

@@ -58,8 +58,12 @@ namespace Continentis.MainGame.Card
{
attributeGroup.ResetAttribute(attributeName);
owner.ApplyAttributeChangesByCard();
owner.combatBuffSubmodule.GetAttributeChange(attributeName, out float numeric, out float pAccumulation, out float pMultiplication);
attributeGroup.ModifyAttribute(attributeName, numeric, pAccumulation, pMultiplication);
owner.user.combatBuffSubmodule.GetGeneralAttributeChange(attributeName, out float cha_numeric, out float cha_pAccumulation, out float cha_pMultiplication);
owner.combatBuffSubmodule.GetAttributeChange(attributeName, out float card_numeric, out float card_pAccumulation, out float card_pMultiplication);
float final_numeric = cha_numeric + card_numeric;
float final_pAccumulation = cha_pAccumulation + card_pAccumulation;
float final_pMultiplication = cha_pMultiplication * card_pMultiplication;
attributeGroup.ModifyAttribute(attributeName, final_numeric, final_pAccumulation, final_pMultiplication);
string displayAttributeName = "Display" + attributeName;
if(attributeGroup.current.ContainsKey(displayAttributeName))
{

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using SLSFramework.General;
using UniRx;
using UnityEngine;
namespace Continentis.MainGame.Card
@@ -16,6 +17,11 @@ namespace Continentis.MainGame.Card
public string originalFunctionText;
public string interpretedFunctionText;
/// <summary>
/// 标记:内容已更改,需要刷新
/// </summary>
public bool dirtyMark;
public ContentSubmodule(CardLogicBase card) : base(card)
{
keywords = card.cardData.keywords;
@@ -24,9 +30,27 @@ namespace Continentis.MainGame.Card
originalFunctionText = card.cardData.functionText.Localize();
cardRarity = card.cardData.cardRarity;
cardType = card.cardData.cardType;
dirtyMark = false;
Observable.EveryLateUpdate().Subscribe(_ =>
{
if (dirtyMark)
{
RefreshContent();
dirtyMark = false;
}
}).AddTo(card.disposables);
//CardDescriptionInterpreter.InterpretDescription(card);
//keywords = CardDescriptionInterpreter.GetKeywords(card.cardData.cardDescription);
//Debug.Log($"Extracted Keywords: {string.Join(", ", keywords)}");
}
public void RefreshContent()
{
CardTextInterpreter.InterpretText(owner);
owner.handCardView?.Setup();
owner.intentionCardView?.Setup();
}
}
}

View File

@@ -76,13 +76,12 @@ namespace Continentis.MainGame.Card
if (card != null)
{
cardInstance = card;
isOccupied = false;
isHovering = false;
isSelecting = false;
isDuringPlaying = false;
}
isOccupied = false;
isHovering = false;
isSelecting = false;
isDuringPlaying = false;
cardNameText.text = cardLogic.contentSubmodule.cardName;
cardDescriptionText.text = cardLogic.contentSubmodule.interpretedFunctionText;
cardImage.sprite = cardLogic.contentSubmodule.cardSprite;

View File

@@ -19,8 +19,7 @@ namespace Continentis.MainGame.Card
public override void OnPointerEnter(PointerEventData eventData)
{
base.OnPointerEnter(eventData);
CardTextInterpreter.InterpretText(cardLogic);
cardDescriptionText.text = cardLogic.contentSubmodule.interpretedFunctionText;
cardLogic.contentSubmodule.dirtyMark = true;
if (CombatUIManager.Instance.selectingCardView == null)
{
canvas.overrideSorting = true;
@@ -114,9 +113,7 @@ namespace Continentis.MainGame.Card
currentTargetingCharacterView = null;
}
// 因为目标发生了变化(无论是选中了新的还是取消了),所以统一在这里更新描述
CardTextInterpreter.InterpretText(cardLogic);
cardDescriptionText.text = cardLogic.contentSubmodule.interpretedFunctionText;
cardLogic.contentSubmodule.dirtyMark = true;
}
Vector3 startPosition = cardTransform.position + new Vector3(0, cardTransform.rect.height * cardTransform.lossyScale.y / 2, 0);
@@ -237,8 +234,7 @@ namespace Continentis.MainGame.Card
canvas.overrideSorting = false;
canvas.sortingOrder = 0;
cardLogic.eventSubmodule.onUntargeting();
CardTextInterpreter.InterpretText(cardLogic);
cardDescriptionText.text = cardLogic.contentSubmodule.interpretedFunctionText;
cardLogic.contentSubmodule.dirtyMark = true;
}
else
{
@@ -267,8 +263,7 @@ namespace Continentis.MainGame.Card
if (!cardLogic.Play(new List<CharacterBase>() { CombatUIManager.Instance.hoveringCharacterView.character }))
{
cardLogic.eventSubmodule.onUntargeting();
CardTextInterpreter.InterpretText(cardLogic);
cardDescriptionText.text = cardLogic.contentSubmodule.interpretedFunctionText;
cardLogic.contentSubmodule.dirtyMark = true;
}
}
}

View File

@@ -13,7 +13,7 @@ namespace Continentis.MainGame.Card
protected override void UntargetingEffect()
{
card.SetAttribute("DisplayDamage", card.GetAttribute("Damage"));
card.SetAttribute("DisplayDamage", card.GetUserDamage());
}
/// <summary>

View File

@@ -50,12 +50,12 @@ namespace Continentis.MainGame.Character
{
if (attributeSubmodule.coreAttributeGroup.current.ContainsKey(attributeName))
{
return attributeSubmodule.GetRoundCurrentCoreAttribute(attributeName);
return attributeSubmodule.GetCurrentCoreAttribute(attributeName);
}
if (attributeSubmodule.generalAttributeGroup.current.ContainsKey(attributeName))
{
return attributeSubmodule.GetRoundCurrentGeneralAttribute(attributeName);
return attributeSubmodule.GetGeneralAttribute(attributeName);
}
Debug.LogWarning($"Attribute {attributeName} not found in any attribute group.");

View File

@@ -93,17 +93,20 @@ namespace Continentis.MainGame.Character
RefreshAttributes();
iconSubmodule?.Update();
attachedCharacter.deckSubmodule.GetAllCards().ForEach(card => card.cardLogic.RefreshCardAttributes());
}
public override void Remove()
{
OnBuffRemove();
this.attachedCharacter.combatBuffSubmodule.buffList.Remove(this);
attachedCharacter.deckSubmodule.GetAllCards().ForEach(card => card.cardLogic.RefreshCardAttributes());
}
public override void UntriggerRemove()
{
this.attachedCharacter.combatBuffSubmodule.buffList.Remove(this);
attachedCharacter.deckSubmodule.GetAllCards().ForEach(card => card.cardLogic.RefreshCardAttributes());
}
/// <summary>

View File

@@ -121,7 +121,7 @@ namespace Continentis.MainGame.Character
/// <returns>是否闪避成功</returns>
public bool CheckDodge(int damage)
{
int dodge = attributeSubmodule.GetRoundCurrentGeneralAttribute("Dodge");
int dodge = attributeSubmodule.GetGeneralAttribute("Dodge");
if (dodge > 0)
{
@@ -145,7 +145,7 @@ namespace Continentis.MainGame.Character
/// <returns>格挡之后的剩余伤害</returns>
public int CheckBlock(int damage)
{
int block = attributeSubmodule.GetRoundCurrentGeneralAttribute("Block");
int block = attributeSubmodule.GetGeneralAttribute("Block");
if (block > 0)
{
@@ -178,7 +178,7 @@ namespace Continentis.MainGame.Character
/// <returns>护盾之后的剩余伤害</returns>
public int CheckShield(int damage)
{
int shield = attributeSubmodule.GetRoundCurrentGeneralAttribute("Shield");
int shield = attributeSubmodule.GetGeneralAttribute("Shield");
if (shield > 0)
{

View File

@@ -30,22 +30,22 @@ namespace Continentis.MainGame.Character
public partial class AttributeSubmodule
{
public float GetCurrentCoreAttribute(string attributeName, float defaultValue = 0)
public float GetRawCurrentCoreAttribute(string attributeName, float defaultValue = 0)
{
return coreAttributeGroup.current.GetValueOrDefault(attributeName, defaultValue);
}
public int GetRoundCurrentCoreAttribute(string attributeName, int defaultValue = 0)
public int GetCurrentCoreAttribute(string attributeName, int defaultValue = 0)
{
return coreAttributeGroup.current.GetRoundValue(attributeName, defaultValue);
}
public float GetCurrentGeneralAttribute(string attributeName, float defaultValue = 0)
public float GetRawGeneralAttribute(string attributeName, float defaultValue = 0)
{
return generalAttributeGroup.current.GetValueOrDefault(attributeName, defaultValue);
}
public int GetRoundCurrentGeneralAttribute(string attributeName, int defaultValue = 0)
public int GetGeneralAttribute(string attributeName, int defaultValue = 0)
{
return generalAttributeGroup.current.GetRoundValue(attributeName, defaultValue);
}
@@ -64,7 +64,7 @@ namespace Continentis.MainGame.Character
/// <returns>最终概率</returns>
public float Probability(string coreAttributeName, int requirement, bool higherPass = true, int additionalAmount = 0)
{
return Probability(GetRoundCurrentCoreAttribute(coreAttributeName), requirement, higherPass, additionalAmount);
return Probability(GetCurrentCoreAttribute(coreAttributeName), requirement, higherPass, additionalAmount);
}
/// <summary>
@@ -77,7 +77,7 @@ namespace Continentis.MainGame.Character
/// <returns>本次检定是否通过</returns>
public bool Check(string coreAttributeName, int requirement, bool higherPass = true, int additionalAmount = 0)
{
return Check(GetRoundCurrentCoreAttribute(coreAttributeName), requirement, higherPass, additionalAmount);
return Check(GetCurrentCoreAttribute(coreAttributeName), requirement, higherPass, additionalAmount);
}
private float Calculate(int value, int requirement)

View File

@@ -110,8 +110,7 @@ namespace Continentis.MainGame.Combat
{
var cardLogic = intendedCard.cardInstance.cardLogic;
cardLogic.eventSubmodule.onTargeting(intendedCard.targets[0]);
CardTextInterpreter.InterpretText(cardLogic);
cardLogic.intentionCardView.cardDescriptionText.text = cardLogic.contentSubmodule.interpretedFunctionText;
cardLogic.contentSubmodule.dirtyMark = true;
//TODO: 现在仅对第一个目标显示指向,后续可以对多目标进行优化
}
}

View File

@@ -18,8 +18,8 @@ namespace Continentis.MainGame.UI
public void SetInfoText(CharacterBase character)
{
int currentValue = character.attributeSubmodule.GetRoundCurrentGeneralAttribute(currentAttributeName);
int maximumValue = character.attributeSubmodule.GetRoundCurrentGeneralAttribute(maximumAttributeName);
int currentValue = character.attributeSubmodule.GetGeneralAttribute(currentAttributeName);
int maximumValue = character.attributeSubmodule.GetGeneralAttribute(maximumAttributeName);
string displayText = currentValue + "/" + maximumValue;
resourceText.text = displayText;
}

View File

@@ -46,8 +46,6 @@ namespace Continentis.MainGame.UI
{
c.user = CombatMainManager.Instance.currentCharacter;
c.cardLogic.RefreshCardAttributes();
CardTextInterpreter.InterpretText(c.cardLogic);
c.handCardView.Setup(c);
});
}));

View File

@@ -25,6 +25,7 @@ namespace SLSFramework.General
public abstract class CommandBase
{
public bool insertAtFirst = false;
public CommandContext selfContext;
protected readonly Subject<Unit> forceCompleteSubject = new Subject<Unit>();

View File

@@ -70,22 +70,27 @@ namespace SLSFramework.General
*/
}
public CommandBase AddCommand(CommandBase command, CommandContext context = null)
public List<CommandBase> AddCommands(List<CommandBase> command, CommandContext outerContext = null)
{
return AddCommand(command, true, context);
return command.Select(cmd => AddCommand(cmd, outerContext)).ToList();
}
public CommandBase AddCommand(CommandBase command, bool insertAtTail, CommandContext context = null)
public CommandBase AddCommand(CommandBase command, CommandContext context = null)
{
return AddCommand(command, false, context);
}
public CommandBase AddCommand(CommandBase command, bool insertAtFirst, CommandContext context = null)
{
context ??= new CommandContext();
// 将指令和其上下文入队
if (insertAtTail)
if (insertAtFirst || command.insertAtFirst)
{
commandQueue.AddLast(Tuple.Create(command, context));
commandQueue.AddFirst(Tuple.Create(command, context));
}
else
{
commandQueue.AddFirst(Tuple.Create(command, context));
commandQueue.AddLast(Tuple.Create(command, context));
}
//Debug.Log($"[Queue] 添加指令: {command.GetType()},队列长度: {commandQueue.Count}");
@@ -113,8 +118,9 @@ namespace SLSFramework.General
// 4. 标记为“忙碌”,并从队列中取出下一个指令。
isBusy = true;
var nextEntry = commandQueue.First.Value;
Tuple<CommandBase, CommandContext> nextEntry = commandQueue.First.Value;
commandQueue.RemoveFirst();
Debug.Log($"[Queue] 开始执行指令: {nextEntry.Item1.GetType()},队列剩余长度: {commandQueue.Count}");
var commandToExecute = nextEntry.Item1;
var context = nextEntry.Item2;