更新
This commit is contained in:
@@ -79,22 +79,38 @@ namespace Continentis.MainGame.Character
|
||||
public partial class CharacterBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 攻击目标
|
||||
/// 攻击目标(新版本,使用 AttackContext 携带标签与来源信息)。
|
||||
/// </summary>
|
||||
/// <param name="target">目标</param>
|
||||
/// <param name="target">攻击目标</param>
|
||||
/// <param name="startDamage">初始伤害</param>
|
||||
/// <param name="ignoreDodge">是否无视闪避</param>
|
||||
/// <param name="ignoreBlock">是否无视格挡</param>
|
||||
/// <param name="ignoreShield">是否无视护盾</param>
|
||||
/// <returns>实际造成的伤害</returns>
|
||||
public AttackResult Attack(CharacterBase target, int startDamage, CardInstance attackCard = null, bool triggerAttackEvent = true, bool ignoreDodge = false, bool ignoreBlock = false, bool ignoreShield = false)
|
||||
/// <param name="context">攻击上下文(包含来源卡牌、标签等);传 null 等价于默认上下文</param>
|
||||
/// <returns>攻击结果</returns>
|
||||
public AttackResult Attack(CharacterBase target, int startDamage, AttackContext context)
|
||||
{
|
||||
if (triggerAttackEvent)
|
||||
context ??= new AttackContext();
|
||||
|
||||
bool isSilent = context.HasTag(AttackTags.Silent);
|
||||
bool isHpRemoval = context.HasTag(AttackTags.HpRemoval);
|
||||
bool isReactive = context.HasTag(AttackTags.Reactive);
|
||||
bool ignoreDodge = context.HasAnyTag(AttackTags.GuaranteedHit, AttackTags.HpRemoval);
|
||||
bool ignoreBlock = context.HasAnyTag(AttackTags.Penetrating, AttackTags.HpRemoval);
|
||||
bool ignoreShield = context.HasAnyTag(AttackTags.HpRemoval);
|
||||
|
||||
// 静默和生命移除均不触发 onStartAttack
|
||||
if (!isSilent && !isHpRemoval)
|
||||
{
|
||||
eventSubmodule.onStartAttack.Invoke(target);
|
||||
}
|
||||
|
||||
//闪避检测:如果闪避成功,直接结束
|
||||
// 生命移除:直接扣血,跳过所有防御和事件
|
||||
if (isHpRemoval)
|
||||
{
|
||||
target.HealthRemoval(startDamage, context);
|
||||
target.characterView.hudContainer.enablingHUDs["MainAttributesBar"].UpdateHud();
|
||||
return new AttackResult(this, target, startDamage, context, false, 0, 0, startDamage);
|
||||
}
|
||||
|
||||
// 闪避检测
|
||||
int modifiedStartDamageForDodge = Mathf.RoundToInt(startDamage * GetRawAttribute("DodgeCheckStartDamageMultiplier", 1));
|
||||
bool dodged = !ignoreDodge && target.CheckDodge(modifiedStartDamageForDodge);
|
||||
|
||||
@@ -113,25 +129,51 @@ namespace Continentis.MainGame.Character
|
||||
{
|
||||
shielded = remainingDamageAfterBlock - remainingDamageAfterShield;
|
||||
hurt = remainingDamageAfterShield;
|
||||
target.HealthRemoval(remainingDamageAfterShield);
|
||||
target.HealthRemoval(remainingDamageAfterShield, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target.characterView.hudContainer.enablingHUDs["MainAttributesBar"].UpdateHud();
|
||||
AttackResult attackResult = new AttackResult(this, target, startDamage, attackCard, dodged, blocked, shielded, hurt);
|
||||
if (triggerAttackEvent)
|
||||
AttackResult attackResult = new AttackResult(this, target, startDamage, context, dodged, blocked, shielded, hurt);
|
||||
|
||||
if (!isSilent)
|
||||
{
|
||||
// 角色 EventSubmodule 级别事件(始终触发,用于日志等)
|
||||
eventSubmodule.onFinishAttack.Invoke(target, attackResult);
|
||||
combatBuffSubmodule.buffList.For(buff =>
|
||||
target.eventSubmodule.onGetAttacked.Invoke(this, attackResult);
|
||||
|
||||
// Buff 层事件:响应式攻击不触发,防止无限递归
|
||||
if (!isReactive)
|
||||
{
|
||||
buff.eventSubmodule?.onDealAttack.Invoke(attackResult);
|
||||
});
|
||||
combatBuffSubmodule.buffList.For(buff =>
|
||||
{
|
||||
buff.eventSubmodule?.onDealAttack.Invoke(attackResult);
|
||||
});
|
||||
|
||||
target.combatBuffSubmodule.buffList.For(buff =>
|
||||
{
|
||||
buff.eventSubmodule?.onGetAttacked.Invoke(attackResult);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return attackResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 攻击目标(兼容旧版 API,内部转换为 AttackContext 调用)。
|
||||
/// 新代码请优先使用 Attack(target, damage, AttackContext) 重载。
|
||||
/// </summary>
|
||||
public AttackResult Attack(CharacterBase target, int startDamage, CardInstance attackCard = null, bool triggerAttackEvent = true, bool ignoreDodge = false, bool ignoreBlock = false, bool ignoreShield = false)
|
||||
{
|
||||
var context = new AttackContext(attackCard);
|
||||
if (!triggerAttackEvent) context.WithTag(AttackTags.Silent);
|
||||
if (ignoreDodge) context.WithTag(AttackTags.GuaranteedHit);
|
||||
if (ignoreBlock) context.WithTag(AttackTags.Penetrating);
|
||||
return Attack(target, startDamage, context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查闪避(闪避失败后会清空闪避值)
|
||||
/// </summary>
|
||||
@@ -145,12 +187,16 @@ namespace Continentis.MainGame.Character
|
||||
{
|
||||
bool success = damage <= dodge;
|
||||
|
||||
if (!success)
|
||||
if (success)
|
||||
{
|
||||
MainGameManager.Instance.basePrefabs.GenerateInfoText("Dodged!", characterView);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
attributeSubmodule.generalAttributeGroup.current["Dodge"] = 0;
|
||||
return false;
|
||||
}
|
||||
MainGameManager.Instance.basePrefabs.GenerateInfoText("Dodged!", characterView);
|
||||
return success;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -190,13 +236,13 @@ namespace Continentis.MainGame.Character
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查护盾(并且扣除护盾值)
|
||||
/// 检查临时生命(并且扣除临时生命值)
|
||||
/// </summary>
|
||||
/// <param name="damage">即将受到的伤害</param>
|
||||
/// <returns>护盾之后的剩余伤害</returns>
|
||||
/// <returns>临时生命吸收后的剩余伤害</returns>
|
||||
public int CheckShield(int damage)
|
||||
{
|
||||
int shield = attributeSubmodule.GetGeneralAttribute("Shield");
|
||||
int shield = attributeSubmodule.GetGeneralAttribute("TemporaryHealth");
|
||||
|
||||
if (shield > 0)
|
||||
{
|
||||
@@ -206,12 +252,12 @@ namespace Continentis.MainGame.Character
|
||||
|
||||
if (!success)
|
||||
{
|
||||
attributeSubmodule.generalAttributeGroup.current["Shield"] = 0;
|
||||
attributeSubmodule.generalAttributeGroup.current["TemporaryHealth"] = 0;
|
||||
remainingDamage = damage - shield;
|
||||
}
|
||||
else
|
||||
{
|
||||
attributeSubmodule.generalAttributeGroup.current["Shield"] = shield - damage;
|
||||
attributeSubmodule.generalAttributeGroup.current["TemporaryHealth"] = shield - damage;
|
||||
blockedDamage = damage;
|
||||
}
|
||||
|
||||
@@ -222,11 +268,68 @@ namespace Continentis.MainGame.Character
|
||||
return damage;
|
||||
}
|
||||
|
||||
public void HealthRemoval(int damage)
|
||||
public void HealthRemoval(int damage, AttackContext context = null)
|
||||
{
|
||||
int healthBefore = GetAttribute("Health");
|
||||
ModifyAttribute("Health", -damage);
|
||||
MainGameManager.Instance.basePrefabs.GenerateHurtText(damage, characterView);
|
||||
int healthAfter = GetAttribute("Health");
|
||||
int maxHealth = GetAttribute("MaximumHealth");
|
||||
|
||||
Color dmgTextColor = Color.white;
|
||||
if (context is { damageKeywords: { Count: > 0 } })
|
||||
{
|
||||
foreach (string elementTag in MainGameManager.Instance.elementTags)
|
||||
{
|
||||
if (context.damageKeywords.Contains(elementTag))
|
||||
{
|
||||
switch (elementTag)
|
||||
{
|
||||
case "Fire":
|
||||
dmgTextColor = Color.red;
|
||||
break;
|
||||
case "Ice":
|
||||
dmgTextColor = Color.cyan;
|
||||
break;
|
||||
case "Wind":
|
||||
dmgTextColor = Color.lightGreen;
|
||||
break;
|
||||
case "Earth":
|
||||
dmgTextColor = Color.darkGoldenRod;
|
||||
break;
|
||||
case "Storm":
|
||||
dmgTextColor = Color.magenta;
|
||||
break;
|
||||
case "Light":
|
||||
dmgTextColor = Color.yellowNice;
|
||||
break;
|
||||
case "Darkness":
|
||||
dmgTextColor = Color.rebeccaPurple;
|
||||
break;
|
||||
default:
|
||||
dmgTextColor = Color.white;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MainGameManager.Instance.basePrefabs.GenerateHurtText(damage, characterView, dmgTextColor);
|
||||
// 血量百分比阈值检查:穿越整十档时通知 LogicBase(如 Boss 阶段切换)
|
||||
if (maxHealth > 0 && logicBase != null)
|
||||
{
|
||||
float percentBefore = (float)healthBefore / maxHealth;
|
||||
float percentAfter = (float)healthAfter / maxHealth;
|
||||
// 找出所有被穿越的整十档(从高到低依次触发)
|
||||
for (int threshold = 9; threshold >= 0; threshold--)
|
||||
{
|
||||
float t = threshold * 0.1f;
|
||||
if (percentBefore > t && percentAfter <= t)
|
||||
{
|
||||
logicBase.OnHealthThreshold(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GetAttribute("Health") <= 0)
|
||||
{
|
||||
Die();
|
||||
@@ -282,15 +385,15 @@ namespace Continentis.MainGame.Character
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加护盾(护盾不会自动清空)
|
||||
/// 添加临时生命(不会自动清空)
|
||||
/// </summary>
|
||||
public void AddShield(int shield, CharacterBase target = null)
|
||||
{
|
||||
int baseShieldAfterOffset = shield + GetAttribute("ShieldGainOffset");
|
||||
int finalShield = Mathf.RoundToInt(baseShieldAfterOffset * GetRawAttribute("ShieldGainMultiplier", 1));
|
||||
int baseShieldAfterOffset = shield + GetAttribute("TemporaryHealthGainOffset");
|
||||
int finalShield = Mathf.RoundToInt(baseShieldAfterOffset * GetRawAttribute("TemporaryHealthGainMultiplier", 1));
|
||||
|
||||
target ??= this;
|
||||
target.ModifyAttribute("Shield", finalShield);
|
||||
target.ModifyAttribute("TemporaryHealth", finalShield);
|
||||
target.characterView.hudContainer.UpdateAllHUD();
|
||||
}
|
||||
}
|
||||
@@ -355,8 +458,8 @@ namespace Continentis.MainGame.Character
|
||||
}
|
||||
|
||||
intended.Add(new IntendedCard(card, targets));
|
||||
remainingStamina -= card.GetAttribute("StaminaCost");
|
||||
remainingMana -= card.GetAttribute("ManaCost");
|
||||
remainingStamina -= card.GetAttribute(CardAttributes.StaminaCost);
|
||||
remainingMana -= card.GetAttribute(CardAttributes.ManaCost);
|
||||
}
|
||||
// 行动力不足则跳过该卡
|
||||
}
|
||||
@@ -398,8 +501,8 @@ namespace Continentis.MainGame.Character
|
||||
|
||||
intended.Add(new IntendedCard(chosen, targets));
|
||||
normal.Remove(chosen);
|
||||
remainingStamina -= chosen.GetAttribute("StaminaCost");
|
||||
remainingMana -= chosen.GetAttribute("ManaCost");
|
||||
remainingStamina -= chosen.GetAttribute(CardAttributes.StaminaCost);
|
||||
remainingMana -= chosen.GetAttribute(CardAttributes.ManaCost);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,8 +511,8 @@ namespace Continentis.MainGame.Character
|
||||
|
||||
bool CanAfford(CardInstance card, int stamina, int mana)
|
||||
{
|
||||
return card.GetAttribute("StaminaCost") <= stamina &&
|
||||
card.GetAttribute("ManaCost") <= mana;
|
||||
return card.GetAttribute(CardAttributes.StaminaCost) <= stamina &&
|
||||
card.GetAttribute(CardAttributes.ManaCost) <= mana;
|
||||
}
|
||||
|
||||
public bool CheckAvailabilityAndSetTargets(CardInstance card, out List<CharacterBase> targets)
|
||||
|
||||
Reference in New Issue
Block a user