更新
This commit is contained in:
@@ -17,6 +17,32 @@ namespace Continentis.MainGame.Card
|
||||
{
|
||||
return contentSubmodule.keywords.Contains(keyword);
|
||||
}
|
||||
|
||||
public bool HasAnyKeyword(params string[] keywords)
|
||||
{
|
||||
bool hasAny = false;
|
||||
|
||||
foreach (var keyword in keywords)
|
||||
{
|
||||
hasAny = HasKeyword(keyword);
|
||||
if (hasAny) break;
|
||||
}
|
||||
|
||||
return hasAny;
|
||||
}
|
||||
|
||||
public bool HasAllKeywords(params string[] keywords)
|
||||
{
|
||||
bool hasAll = true;
|
||||
|
||||
foreach (var keyword in keywords)
|
||||
{
|
||||
hasAll = HasKeyword(keyword);
|
||||
if (!hasAll) break;
|
||||
}
|
||||
|
||||
return hasAll;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
public static class CardAttributes
|
||||
{
|
||||
/// <summary> 体力值消耗 </summary>
|
||||
public const string StaminaCost = "StaminaCost";
|
||||
public const string StaminaCost = "Stamina_Cost";
|
||||
|
||||
/// <summary> 魔力值消耗 </summary>
|
||||
public const string ManaCost = "ManaCost";
|
||||
public const string ManaCost = "Mana_Cost";
|
||||
|
||||
/// <summary> 目标数量(0为自身,-1为全体) </summary>
|
||||
public const string TargetCount = "TargetCount";
|
||||
public const string TargetCount = "Target_Count";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +69,10 @@ namespace Continentis.MainGame.Card
|
||||
[LabelText("功能文本 Key")]
|
||||
public string functionText;
|
||||
|
||||
[FormerlySerializedAs("cardDescription")]
|
||||
[BoxGroup("Display"), PropertyOrder(9)]
|
||||
[LabelText("卡牌描述 Key")]
|
||||
public string cardDescription;
|
||||
public string descriptionText;
|
||||
|
||||
[BoxGroup("Display"), PropertyOrder(10)]
|
||||
[ListDrawerSettings(ShowIndexLabels = false), LabelText("布局标签")]
|
||||
|
||||
@@ -26,6 +26,12 @@ namespace Continentis.MainGame.Card
|
||||
public CharacterBase user;
|
||||
public CombatTeam usingTeam;
|
||||
|
||||
/// <summary>
|
||||
/// 当前用于文本条件标签解析的目标角色。
|
||||
/// 玩家拖拽卡牌时由 Targeting/Untargeting 设置;NPC 意图创建时由意图系统设置。
|
||||
/// </summary>
|
||||
public CharacterBase currentTextTarget;
|
||||
|
||||
public CardLogicBase cardLogic;
|
||||
public int upgradeLevel;
|
||||
|
||||
@@ -117,18 +123,8 @@ namespace Continentis.MainGame.Card
|
||||
.UpdateTeamPileText(CombatMainManager.Instance.characterController.playerTeam);
|
||||
}
|
||||
|
||||
//下面的部分后续放入CardLogic的初始化函数中
|
||||
card.RefreshCardAttributes();
|
||||
|
||||
if (card.HasKeyword("Instant")) //如果是“瞬发”牌,添加抽牌后立刻打出的事件
|
||||
{
|
||||
card.eventSubmodule.onDraw.InsertByPriority("Instant", new PrioritizedAction(() =>
|
||||
{
|
||||
card.DetectTargetsValidity(out List<CharacterBase> valid, out _, out _);
|
||||
card.Play(card.SetRandomTargets(valid), card.user);
|
||||
}, 99));
|
||||
}
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
@@ -250,4 +246,4 @@ namespace Continentis.MainGame.Card
|
||||
this.index = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
|
||||
/// <summary> 可选目标为全体角色 </summary>
|
||||
public const string TargetAll = "TargetAll";
|
||||
|
||||
/// <summary> 多目标选择时允许复选 </summary>
|
||||
public const string AllowDuplicateTargets = "AllowDuplicateTargets";
|
||||
|
||||
/// <summary> 物理 </summary>
|
||||
public const string Physics = "Physics";
|
||||
@@ -24,6 +27,27 @@
|
||||
/// <summary> 魔法 </summary>
|
||||
public const string Magic = "Magic";
|
||||
|
||||
/// <summary> 风 </summary>
|
||||
public const string Wind = "Wind";
|
||||
|
||||
/// <summary> 火 </summary>
|
||||
public const string Fire = "Fire";
|
||||
|
||||
/// <summary> 冰 </summary>
|
||||
public const string Ice = "Ice";
|
||||
|
||||
/// <summary> 土 </summary>
|
||||
public const string Earth = "Earth";
|
||||
|
||||
/// <summary> 雷 </summary>
|
||||
public const string Storm = "Storm";
|
||||
|
||||
/// <summary> 光 </summary>
|
||||
public const string Light = "Light";
|
||||
|
||||
/// <summary> 暗 </summary>
|
||||
public const string Darkness = "Darkness";
|
||||
|
||||
/// <summary> 打击(力量) </summary>
|
||||
public const string Strike = "Strike";
|
||||
|
||||
@@ -74,5 +98,8 @@
|
||||
|
||||
/// <summary> 复用(打出后回到手牌) </summary>
|
||||
public const string Reuse = "Reuse";
|
||||
|
||||
/// <summary> 先决(在手牌中时,必须先打出此牌) </summary>
|
||||
public const string Prerequisite = "Prerequisite";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Continentis.MainGame.Character;
|
||||
using Continentis.MainGame.Equipment;
|
||||
using SoftCircuits.Collections;
|
||||
using SLSFramework.General;
|
||||
using SLSFramework.UModAssistance;
|
||||
using UnityEngine;
|
||||
@@ -36,14 +37,129 @@ namespace Continentis.MainGame.Card
|
||||
return null;
|
||||
}
|
||||
|
||||
// 存储所有通过 SubscribeCombatEvent 注册的订阅的移除委托
|
||||
private readonly List<Action> _managedUnsubscribers = new List<Action>();
|
||||
|
||||
public virtual void Initialize(CardInstance cardInstance)
|
||||
{
|
||||
card = cardInstance;
|
||||
logicComponents = new HashSet<CardLogicComponentBase>();
|
||||
card.eventSubmodule.onTargeting += TargetingEffect;
|
||||
card.eventSubmodule.onUntargeting += UntargetingEffect;
|
||||
|
||||
// 自动将卡牌事件子模块的生命周期钩子接入虚方法
|
||||
card.eventSubmodule.onDraw.InsertByPriority(
|
||||
$"{GetType().Name}_OnDraw_{GetHashCode()}",
|
||||
new PrioritizedAction(OnDraw));
|
||||
|
||||
card.eventSubmodule.onCombatStart.InsertByPriority(
|
||||
$"{GetType().Name}_OnCombatStart_{GetHashCode()}",
|
||||
new PrioritizedAction(OnCombatStart));
|
||||
|
||||
card.eventSubmodule.onCombatEnd.InsertByPriority(
|
||||
$"{GetType().Name}_OnCombatEnd_{GetHashCode()}",
|
||||
new PrioritizedAction(OnCombatEnd));
|
||||
|
||||
card.eventSubmodule.onRoundStart.InsertByPriority(
|
||||
$"{GetType().Name}_OnRoundStart_{GetHashCode()}",
|
||||
new PrioritizedAction(OnRoundStart));
|
||||
|
||||
card.eventSubmodule.onRoundEnd.InsertByPriority(
|
||||
$"{GetType().Name}_OnRoundEnd_{GetHashCode()}",
|
||||
new PrioritizedAction(OnRoundEnd));
|
||||
|
||||
card.eventSubmodule.onActionStart.InsertByPriority(
|
||||
$"{GetType().Name}_OnActionStart_{GetHashCode()}",
|
||||
new PrioritizedAction(OnActionStart));
|
||||
|
||||
card.eventSubmodule.onActionEnd.InsertByPriority(
|
||||
$"{GetType().Name}_OnActionEnd_{GetHashCode()}",
|
||||
new PrioritizedAction(OnActionEnd));
|
||||
|
||||
// 关键词驱动的行为统一在此处注册
|
||||
if (card.HasKeyword("Instant"))
|
||||
{
|
||||
//含有Instant关键词,抽到后直接打出
|
||||
card.eventSubmodule.onDraw.InsertByPriority("Instant", new PrioritizedAction(() =>
|
||||
{
|
||||
card.DetectTargetsValidity(out List<CharacterBase> valid, out _, out _);
|
||||
card.Play(card.SetRandomTargets(valid), card.user);
|
||||
}, 99));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向战斗全局事件字典注册一个托管订阅。
|
||||
/// Dispose() 时无需手动取消——基类会自动移除所有通过此方法注册的订阅。
|
||||
/// </summary>
|
||||
protected void SubscribeCombatEvent(
|
||||
OrderedDictionary<string, PrioritizedAction> eventDict,
|
||||
PrioritizedAction action,
|
||||
int priority = 0)
|
||||
{
|
||||
string key = $"{GetType().Name}_{GetHashCode()}_{_managedUnsubscribers.Count}";
|
||||
action.Priority = priority;
|
||||
eventDict.InsertByPriority(key, action);
|
||||
_managedUnsubscribers.Add(() => eventDict.Remove(key));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向战斗全局事件字典注册一个带参数的托管订阅。
|
||||
/// Dispose() 时无需手动取消——基类会自动移除所有通过此方法注册的订阅。
|
||||
/// </summary>
|
||||
protected void SubscribeCombatEvent<T>(
|
||||
OrderedDictionary<string, PrioritizedAction<T>> eventDict,
|
||||
PrioritizedAction<T> action,
|
||||
int priority = 0)
|
||||
{
|
||||
string key = $"{GetType().Name}_{GetHashCode()}_{_managedUnsubscribers.Count}";
|
||||
action.Priority = priority;
|
||||
eventDict.InsertByPriority(key, action);
|
||||
_managedUnsubscribers.Add(() => eventDict.Remove(key));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 卡牌销毁时调用(打出、弃牌、消耗)。
|
||||
/// 自动清理所有通过 SubscribeCombatEvent 注册的托管订阅。
|
||||
/// 子类重写时无需调用 base.Dispose(),除非有额外资源需要释放。
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (Action unsubscribe in _managedUnsubscribers)
|
||||
unsubscribe();
|
||||
_managedUnsubscribers.Clear();
|
||||
OnDispose();
|
||||
}
|
||||
|
||||
// ── 生命周期虚方法 ─────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>抽到此卡牌时调用。</summary>
|
||||
protected virtual void OnDraw() { }
|
||||
|
||||
/// <summary>战斗开始时调用。</summary>
|
||||
protected virtual void OnCombatStart() { }
|
||||
|
||||
/// <summary>战斗结束时调用。</summary>
|
||||
protected virtual void OnCombatEnd() { }
|
||||
|
||||
/// <summary>每回合开始时调用。</summary>
|
||||
protected virtual void OnRoundStart() { }
|
||||
|
||||
/// <summary>每回合结束时调用。</summary>
|
||||
protected virtual void OnRoundEnd() { }
|
||||
|
||||
/// <summary>每次行动开始时调用。</summary>
|
||||
protected virtual void OnActionStart() { }
|
||||
|
||||
/// <summary>每次行动结束时调用。</summary>
|
||||
protected virtual void OnActionEnd() { }
|
||||
|
||||
/// <summary>
|
||||
/// 卡牌销毁时的扩展清理钩子。
|
||||
/// 子类有额外资源需要释放时重写此方法,无需处理 SubscribeCombatEvent 的取消订阅。
|
||||
/// </summary>
|
||||
protected virtual void OnDispose() { }
|
||||
|
||||
public virtual void SetUpLogicComponents() { }
|
||||
|
||||
public T AddLogicComponent<T>() where T : CardLogicComponentBase, new()
|
||||
@@ -233,43 +349,66 @@ namespace Continentis.MainGame.Card
|
||||
#region Attack
|
||||
public partial class CardLogicBase
|
||||
{
|
||||
/// <summary>获取对指定目标的最终伤害值。</summary>
|
||||
public virtual int GetTargetedFinalDamage(CharacterBase target, List<string> elementalTags = null)
|
||||
/// <summary>
|
||||
/// 以当前卡牌作为来源,对目标发动攻击。
|
||||
/// 内部自动构建携带 sourceCard 的 AttackContext,确保 Buff 层能正确识别来源卡牌信息。
|
||||
/// 卡牌脚本中所有的攻击调用都应优先使用此方法,而非直接调用 user.Attack()。
|
||||
/// </summary>
|
||||
protected AttackResult AttackTarget(CharacterBase target, int damage, AttackContext ctx = null)
|
||||
{
|
||||
return GetFinalDamage(target, elementalTags, out _, out _, out _, out _);
|
||||
ctx ??= new AttackContext(card);
|
||||
if (ctx.sourceCard == null) ctx.sourceCard = card;
|
||||
return user.Attack(target, damage, ctx);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对指定目标的最终伤害值。
|
||||
/// ctx 中的 damageKeywords 驱动 offset 和元素乘区计算,baseDamageAttributeName 指定基础伤害属性名。
|
||||
/// ctx 为 null 时回退到卡牌元素关键词和默认 "Damage" 属性(向后兼容)。
|
||||
/// </summary>
|
||||
public virtual int GetTargetedFinalDamage(CharacterBase target, AttackContext ctx = null)
|
||||
{
|
||||
return GetFinalDamage(target, ctx, out _, out _, out _, out _);
|
||||
}
|
||||
|
||||
/// <summary>获取无目标时的最终伤害值。</summary>
|
||||
public virtual int GetNoTargetFinalDamage(List<string> elementalTags = null)
|
||||
public virtual int GetNoTargetFinalDamage(AttackContext ctx = null)
|
||||
{
|
||||
return GetFinalDamage(null, elementalTags, out _, out _, out _, out _);
|
||||
return GetFinalDamage(null, ctx, out _, out _, out _, out _);
|
||||
}
|
||||
|
||||
protected virtual int GetFinalDamage(
|
||||
CharacterBase target, List<string> elementalTags,
|
||||
CharacterBase target, AttackContext ctx,
|
||||
out float baseDamageAfterOffset, out float elementalMultiplier,
|
||||
out float magicMultiplier, out float finalMultiplier)
|
||||
{
|
||||
bool haveTarget = target != null;
|
||||
elementalTags ??= card.GetElementalKeywords();
|
||||
|
||||
// 从 AttackContext 中读取伤害关键词和属性名,null 时回退到卡牌默认值
|
||||
List<string> damageKeywords = ctx?.damageKeywords ?? card.GetElementalKeywords();
|
||||
string baseDamageAttr = ctx?.baseDamageAttributeName;
|
||||
|
||||
// Physics / Magic offset 由 damageKeywords 驱动,与卡牌标记关键词无关
|
||||
int physicsOffset = 0;
|
||||
if (card.HasKeyword("Physics") || card.HasKeyword("Slash") || card.HasKeyword("Prick") || card.HasKeyword("Strike"))
|
||||
physicsOffset = user.GetAttribute("PhysicsDamageDealtOffset");
|
||||
if (damageKeywords.Contains("Physics"))
|
||||
physicsOffset = user.GetAttribute(CharacterAttributes.PhysicsDamageDealtOffset);
|
||||
|
||||
int magicOffset = 0;
|
||||
if (card.HasKeyword("Magic") || card.HasKeyword("Arcane") || card.HasKeyword("Sorcery"))
|
||||
magicOffset = user.GetAttribute("MagicDamageDealtOffset");
|
||||
if (damageKeywords.Contains("Magic"))
|
||||
magicOffset = user.GetAttribute(CharacterAttributes.MagicDamageDealtOffset);
|
||||
|
||||
// 元素乘区:遍历 damageKeywords 中属于 elementTags 的部分
|
||||
elementalMultiplier = 1f;
|
||||
foreach (string element in elementalTags)
|
||||
foreach (string keyword in damageKeywords)
|
||||
{
|
||||
float targetGain = haveTarget ? target.GetRawAttribute(element + "DamageGainMultiplier", 1f) : 1f;
|
||||
elementalMultiplier *= user.GetRawAttribute(element + "DamageDealtMultiplier", 1f) * targetGain;
|
||||
if (!MainGameManager.Instance.elementTags.Contains(keyword)) continue;
|
||||
float targetGain = haveTarget ? target.GetRawAttribute(keyword + "DamageGainMultiplier", 1f) : 1f;
|
||||
elementalMultiplier *= user.GetRawAttribute(keyword + "DamageDealtMultiplier", 1f) * targetGain;
|
||||
}
|
||||
|
||||
// 魔法乘区:由 damageKeywords 中含 Magic/Arcane/Sorcery 时触发
|
||||
magicMultiplier = 1f;
|
||||
if (card.HasKeyword("Magic") || card.HasKeyword("Arcane") || card.HasKeyword("Sorcery"))
|
||||
if (damageKeywords.Contains("Magic") || damageKeywords.Contains("Arcane") || damageKeywords.Contains("Sorcery"))
|
||||
{
|
||||
float targetGain = haveTarget ? target.GetRawAttribute("MagicDamageGainMultiplier", 1f) : 1f;
|
||||
magicMultiplier = user.GetRawAttribute("MagicDamageDealtMultiplier", 1f) * targetGain;
|
||||
@@ -278,7 +417,8 @@ namespace Continentis.MainGame.Card
|
||||
float targetFinalGain = haveTarget ? target.GetRawAttribute("FinalDamageGainMultiplier", 1f) : 1f;
|
||||
finalMultiplier = user.GetRawAttribute("FinalDamageDealtMultiplier", 1f) * targetFinalGain;
|
||||
|
||||
baseDamageAfterOffset = card.attributeSubmodule.GetCurrentAttribute("Damage") + physicsOffset + magicOffset;
|
||||
string damageAttr = string.IsNullOrEmpty(baseDamageAttr) ? "Damage" : baseDamageAttr;
|
||||
baseDamageAfterOffset = card.attributeSubmodule.GetCurrentAttribute(damageAttr) + physicsOffset + magicOffset;
|
||||
float finalDamage = baseDamageAfterOffset * elementalMultiplier * magicMultiplier * finalMultiplier;
|
||||
|
||||
return Mathf.RoundToInt(finalDamage);
|
||||
@@ -358,6 +498,17 @@ namespace Continentis.MainGame.Card
|
||||
|
||||
/// <summary>取消选中目标时触发的效果(在逻辑组件的 Untargeting 之前执行)。</summary>
|
||||
public virtual void UntargetingEffect() { }
|
||||
|
||||
/// <summary>
|
||||
/// 标记 hint shadow 在下一帧刷新,不触发文本重解析。
|
||||
/// 子类在战场状态变化时调用此方法,而非直接操作 dirtyMark。
|
||||
/// </summary>
|
||||
protected void InvalidateHint() => card.contentSubmodule.hintDirtyMark = true;
|
||||
/// 返回 null 表示不显示提示阴影;返回具体颜色则启用对应颜色的 hintShadow。
|
||||
/// 此方法在 ContentSubmodule.RefreshContent() 时自动调用,
|
||||
/// 子类可重写以实现"有可用目标时绿色/无可用目标时红色"等动态提示。
|
||||
/// </summary>
|
||||
public virtual Color? GetHintColor() => null;
|
||||
}
|
||||
|
||||
/// <summary>卡牌逻辑组件基类。</summary>
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace Continentis.MainGame.Card
|
||||
/// </summary>
|
||||
public virtual void Targeting(CharacterBase target)
|
||||
{
|
||||
currentTextTarget = target;
|
||||
eventSubmodule.onTargeting.Invoke(target);
|
||||
}
|
||||
|
||||
@@ -29,6 +30,7 @@ namespace Continentis.MainGame.Card
|
||||
/// </summary>
|
||||
public virtual void Untargeting()
|
||||
{
|
||||
currentTextTarget = null;
|
||||
eventSubmodule.onUntargeting.Invoke();
|
||||
}
|
||||
}
|
||||
@@ -136,11 +138,26 @@ namespace Continentis.MainGame.Card
|
||||
}
|
||||
else
|
||||
{
|
||||
while (targets.Count < maximumTargets && valid.Count > 0)
|
||||
bool allowDuplicate = HasKeyword(CardKeywords.AllowDuplicateTargets);
|
||||
|
||||
if (allowDuplicate)
|
||||
{
|
||||
CharacterBase target = valid[Random.Range(0, valid.Count)];
|
||||
valid.Remove(target);
|
||||
targets.Add(target);
|
||||
// 放回抽样:可重复选中同一目标
|
||||
for (int i = 0; i < maximumTargets; i++)
|
||||
{
|
||||
targets.Add(valid[Random.Range(0, valid.Count)]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 不放回抽样(原逻辑)
|
||||
List<CharacterBase> pool = new List<CharacterBase>(valid);
|
||||
while (targets.Count < maximumTargets && pool.Count > 0)
|
||||
{
|
||||
CharacterBase target = pool[Random.Range(0, pool.Count)];
|
||||
pool.Remove(target);
|
||||
targets.Add(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,13 +166,13 @@ namespace Continentis.MainGame.Card
|
||||
|
||||
public virtual bool CheckBeforePlay()
|
||||
{
|
||||
if (!user.CheckEnoughStamina(GetAttribute("StaminaCost")))
|
||||
if (!user.CheckEnoughStamina(GetAttribute(CardAttributes.StaminaCost)))
|
||||
{
|
||||
MainGameManager.Instance.basePrefabs.GenerateInfoText("Not Enough Stamina", user.characterView);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!user.CheckEnoughMana(GetAttribute("ManaCost")))
|
||||
if (!user.CheckEnoughMana(GetAttribute(CardAttributes.ManaCost)))
|
||||
{
|
||||
MainGameManager.Instance.basePrefabs.GenerateInfoText("Not Enough Mana", user.characterView);
|
||||
return false;
|
||||
@@ -192,13 +209,13 @@ namespace Continentis.MainGame.Card
|
||||
{
|
||||
if (!noConsumption)
|
||||
{
|
||||
this.user.ModifyStamina(-GetAttribute("StaminaCost"));
|
||||
this.user.ModifyMana(-GetAttribute("ManaCost"));
|
||||
this.user.ModifyStamina(-GetAttribute(CardAttributes.StaminaCost));
|
||||
this.user.ModifyMana(-GetAttribute(CardAttributes.ManaCost));
|
||||
}
|
||||
|
||||
Debug.Log($"Starting to play card: {contentSubmodule.cardName}");
|
||||
|
||||
CommandQueueManager.Instance.AddCommand(new Cmd_Function(() =>
|
||||
CommandQueueManager.Instance.AddCommand(Cmd.Do(() =>
|
||||
{
|
||||
playSubmodule.isDuringPlayEffect = true;
|
||||
eventSubmodule.onBeforePlay.Invoke(targetList);
|
||||
@@ -211,7 +228,7 @@ namespace Continentis.MainGame.Card
|
||||
|
||||
CommandQueueManager.Instance.AddCommand(PlayEffect(targetList));
|
||||
CommandQueueManager.Instance.AddCommand(cardLogic.PlayEffect(targetList));
|
||||
CommandQueueManager.Instance.AddCommand(new Cmd_Function(() =>
|
||||
CommandQueueManager.Instance.AddCommand(Cmd.Do(() =>
|
||||
{
|
||||
eventSubmodule.onAfterPlay.Invoke(targetList);
|
||||
combatBuffSubmodule.buffList.For(buff => buff.usageSubmodule?.UpdateModule());
|
||||
@@ -308,6 +325,8 @@ namespace Continentis.MainGame.Card
|
||||
KeyValuePair<string, List<CardInstance>> currentPile = deck.GetCardLocation(this, out int index);
|
||||
if (!cardData.upgradeNode.isTerminalNode)
|
||||
{
|
||||
// 先 Dispose 旧 Logic,再替换,避免旧 Logic 的托管订阅泄漏
|
||||
cardLogic?.Dispose();
|
||||
DestroyHandCardView();
|
||||
|
||||
CardData newData = cardData.upgradeNode.upgradeCards[0]; //后续可改为选择升级方向
|
||||
|
||||
@@ -111,6 +111,6 @@ namespace Continentis.MainGame.Card
|
||||
|
||||
public partial class AttributeSubmodule
|
||||
{
|
||||
public int targetCount => GetRoundCurrentAttribute("TargetCount", -2);
|
||||
public int targetCount => GetRoundCurrentAttribute(CardAttributes.TargetCount, -2);
|
||||
}
|
||||
}
|
||||
@@ -22,15 +22,21 @@ namespace Continentis.MainGame.Card
|
||||
/// </summary>
|
||||
public bool dirtyMark;
|
||||
|
||||
/// <summary>
|
||||
/// 标记:hint shadow 颜色需要刷新,不触发文本重解析
|
||||
/// </summary>
|
||||
public bool hintDirtyMark;
|
||||
|
||||
public ContentSubmodule(CardInstance card) : base(card)
|
||||
{
|
||||
keywords = card.cardData.keywords;
|
||||
cardName = card.cardData.displayName.Localize();
|
||||
cardSprite = card.cardData.cardSprite;
|
||||
cardSprite = card.cardData.cardSprite ?? MainGameManager.Instance.basePrefabs.defaultCardImage;
|
||||
originalFunctionText = card.cardData.functionText.Localize();
|
||||
cardRarity = card.cardData.cardRarity;
|
||||
cardType = card.cardData.cardType;
|
||||
dirtyMark = false;
|
||||
hintDirtyMark = false;
|
||||
|
||||
Observable.EveryLateUpdate().Subscribe(_ =>
|
||||
{
|
||||
@@ -39,11 +45,12 @@ namespace Continentis.MainGame.Card
|
||||
RefreshContent();
|
||||
dirtyMark = false;
|
||||
}
|
||||
if (hintDirtyMark)
|
||||
{
|
||||
RefreshHintShadow();
|
||||
hintDirtyMark = false;
|
||||
}
|
||||
}).AddTo(card.disposables);
|
||||
|
||||
//CardDescriptionInterpreter.InterpretDescription(card);
|
||||
//keywords = CardDescriptionInterpreter.GetKeywords(card.cardData.cardDescription);
|
||||
//Debug.Log($"Extracted Keywords: {string.Join(", ", keywords)}");
|
||||
}
|
||||
|
||||
public void RefreshContent()
|
||||
@@ -51,6 +58,19 @@ namespace Continentis.MainGame.Card
|
||||
CardTextInterpreter.InterpretText(owner);
|
||||
owner.handCardView?.Setup();
|
||||
owner.intentionCardView?.Setup();
|
||||
|
||||
// 文本刷新后,hint 也需要同步更新
|
||||
hintDirtyMark = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 仅刷新 hint shadow 颜色,不触发文本重解析。
|
||||
/// </summary>
|
||||
public void RefreshHintShadow()
|
||||
{
|
||||
if (owner.handCardView == null || owner.handCardView.isSelecting) return;
|
||||
Color? hintColor = owner.cardLogic?.GetHintColor();
|
||||
owner.handCardView.UpdateHintShadow(hintColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ namespace Continentis.MainGame.Card
|
||||
|
||||
public bool isDuringPlaying;
|
||||
|
||||
private void Update()
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (isHovering)
|
||||
{
|
||||
@@ -110,9 +110,9 @@ namespace Continentis.MainGame.Card
|
||||
cardTypeText.text = this.card.contentSubmodule.cardType.ToString();
|
||||
|
||||
staminaCostText.rectTransform.parent.gameObject.SetActive(true);
|
||||
staminaCostText.text = this.card.attributeSubmodule.GetRoundCurrentAttribute("StaminaCost").ToString();
|
||||
staminaCostText.text = this.card.attributeSubmodule.GetRoundCurrentAttribute(CardAttributes.StaminaCost).ToString();
|
||||
|
||||
int manaCost = this.card.attributeSubmodule.GetRoundCurrentAttribute("ManaCost");
|
||||
int manaCost = this.card.attributeSubmodule.GetRoundCurrentAttribute(CardAttributes.ManaCost);
|
||||
manaCostText.rectTransform.parent.gameObject.SetActive(manaCost > 0);
|
||||
manaCostText.text = manaCost.ToString();
|
||||
|
||||
|
||||
@@ -43,6 +43,46 @@ namespace Continentis.MainGame.Card
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据颜色智能更新提示阴影:null 关闭,非 null 启用对应颜色。
|
||||
/// 避免相同颜色重复 tween 导致闪烁。
|
||||
/// </summary>
|
||||
public void UpdateHintShadow(Color? color)
|
||||
{
|
||||
if (color == null)
|
||||
{
|
||||
if (hintShadow.gameObject.activeSelf)
|
||||
{
|
||||
DisableHintShadow();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Color targetColor = color.Value;
|
||||
|
||||
if (hintShadow.gameObject.activeSelf)
|
||||
{
|
||||
// 已启用:仅在颜色差异足够大时 tween,避免每帧闪烁
|
||||
if (!ApproximatelyEqualColor(hintShadow.color, targetColor))
|
||||
{
|
||||
hintShadowTweener?.Kill();
|
||||
hintShadowTweener = hintShadow.DOColor(targetColor, 0.2f).Play();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnableHintShadow(targetColor);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ApproximatelyEqualColor(Color a, Color b, float tolerance = 0.01f)
|
||||
{
|
||||
return Mathf.Abs(a.r - b.r) < tolerance
|
||||
&& Mathf.Abs(a.g - b.g) < tolerance
|
||||
&& Mathf.Abs(a.b - b.b) < tolerance
|
||||
&& Mathf.Abs(a.a - b.a) < tolerance;
|
||||
}
|
||||
|
||||
public void EnableSelectShadow()
|
||||
{
|
||||
selectShadow.gameObject.SetActive(true);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -145,6 +145,7 @@ namespace Continentis.MainGame.Card
|
||||
categoryName = resolvedCategory;
|
||||
displayName = $"Card_{resolvedMod}_{className}_DisplayName";
|
||||
functionText = $"Card_{resolvedMod}_{className}_FunctionText";
|
||||
descriptionText = $"Card_{resolvedMod}_{className}_Description";
|
||||
|
||||
EditorUtility.SetDirty(this);
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using Continentis.MainGame.Character;
|
||||
using Continentis.Mods.Basic.Cards;
|
||||
using UnityEngine;
|
||||
@@ -19,66 +20,67 @@ namespace Continentis.MainGame.Card
|
||||
/// <summary>
|
||||
/// 设置伤害值
|
||||
/// </summary>
|
||||
/// <param name="additive">是否为叠加,true为叠加,false为覆盖</param>
|
||||
/// <param name="originalDamage">原始伤害值,仅在additive为true时有效,否则被覆盖为BaseDamage</param>
|
||||
/// <param name="damageAttributeName">要写入的属性名,默认为 "Damage"</param>
|
||||
/// <param name="damageOffset">伤害增量</param>
|
||||
public void SetDamage(int damageOffset, bool additive = false, int originalDamage = 0)
|
||||
/// <param name="additive">是否为叠加,true为叠加,false为覆盖</param>
|
||||
/// <param name="originalDamage">原始伤害值,仅在additive为true时有效</param>
|
||||
public void SetDamage(int damageOffset, string damageAttributeName = "Damage", bool additive = false, int originalDamage = 0)
|
||||
{
|
||||
card.SetVariableAttribute("Damage", damageOffset, additive, originalDamage);
|
||||
card.SetVariableAttribute(damageAttributeName, damageOffset, additive, originalDamage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 默认伤害计算,仅使用卡牌基础伤害(无任何属性加成)
|
||||
/// </summary>
|
||||
public void SetDamage_Default()
|
||||
public void SetDamage_Default(string damageAttributeName = "Damage")
|
||||
{
|
||||
SetDamage(0);
|
||||
SetDamage(0, damageAttributeName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 斩击伤害计算,伤害=基础伤害+(力量加成+敏捷加成)/2
|
||||
/// </summary>
|
||||
public void SetDamage_Slash(bool additive = false, int originalDamage = 0)
|
||||
public void SetDamage_Slash(string damageAttributeName = "Damage", bool additive = false, int originalDamage = 0)
|
||||
{
|
||||
float rawDamageOffsetFromStrength = user.GetRawAttribute("OffsetFromStrength");
|
||||
float rawDamageOffsetFromAgility = user.GetRawAttribute("OffsetFromAgility");
|
||||
SetDamage(Mathf.RoundToInt((rawDamageOffsetFromStrength + rawDamageOffsetFromAgility) / 2f), additive, originalDamage);
|
||||
SetDamage(Mathf.RoundToInt((rawDamageOffsetFromStrength + rawDamageOffsetFromAgility) / 2f), damageAttributeName, additive, originalDamage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打击伤害计算,伤害=基础伤害+力量加成
|
||||
/// </summary>
|
||||
public void SetDamage_Strike(bool additive = false, int originalDamage = 0)
|
||||
public void SetDamage_Strike(string damageAttributeName = "Damage", bool additive = false, int originalDamage = 0)
|
||||
{
|
||||
int damageOffset = user.GetAttribute("OffsetFromStrength");
|
||||
SetDamage(damageOffset, additive, originalDamage);
|
||||
SetDamage(damageOffset, damageAttributeName, additive, originalDamage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 突刺伤害计算,伤害=基础伤害+敏捷加成
|
||||
/// </summary>
|
||||
public void SetDamage_Prick(bool additive = false, int originalDamage = 0)
|
||||
public void SetDamage_Prick(string damageAttributeName = "Damage", bool additive = false, int originalDamage = 0)
|
||||
{
|
||||
int damageOffset = user.GetAttribute("OffsetFromAgility");
|
||||
SetDamage(damageOffset, additive, originalDamage);
|
||||
SetDamage(damageOffset, damageAttributeName, additive, originalDamage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 奥术伤害计算,伤害=基础伤害+智力加成
|
||||
/// </summary>
|
||||
public void SetDamage_Arcane(bool additive = false, int originalDamage = 0)
|
||||
public void SetDamage_Arcane(string damageAttributeName = "Damage", bool additive = false, int originalDamage = 0)
|
||||
{
|
||||
int damageOffset = user.GetAttribute("OffsetFromIntelligence");
|
||||
SetDamage(damageOffset, additive, originalDamage);
|
||||
SetDamage(damageOffset, damageAttributeName, additive, originalDamage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 契术伤害计算,伤害=基础伤害+魅力加成
|
||||
/// </summary>
|
||||
public void SetDamage_Sorcery(bool additive = false, int originalDamage = 0)
|
||||
public void SetDamage_Sorcery(string damageAttributeName = "Damage", bool additive = false, int originalDamage = 0)
|
||||
{
|
||||
int damageOffset = user.GetAttribute("OffsetFromCharisma");
|
||||
SetDamage(damageOffset, additive, originalDamage);
|
||||
SetDamage(damageOffset, damageAttributeName, additive, originalDamage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,9 @@ namespace Continentis.MainGame.Card
|
||||
{
|
||||
card.SetAttribute("DisplayDodge", card.GetAttribute("Dodge"));
|
||||
}
|
||||
else if(card.HasAttribute("Shield"))
|
||||
else if(card.HasAttribute("TemporaryHealth"))
|
||||
{
|
||||
card.SetAttribute("DisplayShield", card.GetAttribute("Shield"));
|
||||
card.SetAttribute("DisplayTemporaryHealth", card.GetAttribute("TemporaryHealth"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ namespace Continentis.MainGame.Card
|
||||
{
|
||||
card.SetAttribute("DisplayDodge", card.GetAttribute("Dodge"));
|
||||
}
|
||||
else if(card.HasAttribute("Shield"))
|
||||
else if(card.HasAttribute("TemporaryHealth"))
|
||||
{
|
||||
card.SetAttribute("DisplayShield", card.GetAttribute("Shield"));
|
||||
card.SetAttribute("DisplayTemporaryHealth", card.GetAttribute("TemporaryHealth"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,11 +102,11 @@ namespace Continentis.MainGame.Card
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置护盾值,默认无加成
|
||||
/// 设置临时生命值,默认无加成
|
||||
/// </summary>
|
||||
public void SetShield(bool additive = false, int originalShield = 0)
|
||||
{
|
||||
card.SetVariableAttribute("Shield", 0, additive, originalShield);
|
||||
card.SetVariableAttribute("TemporaryHealth", 0, additive, originalShield);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user