Files
daluandou/Assets/Scripts/技能脚本/ShieldGuardSkill.cs
T
2026-10-11 22:56:46 +08:00

293 lines
10 KiB
C#

using System.Collections;
using UnityEngine;
/// <summary>
/// 盾卫技能:圣盾壁垒体系(1/3/6/10 级完整阶梯)
/// 1级【圣盾壁垒】:举盾生成 35% 最大生命值的护盾(持续 5s),挂 MagicShieldBlue 特效
/// 3级【坚不可摧】:护盾厚度提升至 50% 最大生命值,持续时间延长至 6s
/// 6级【战吼嘲讽】:技能拍地 OnSkillHit1 瞬间爆发 NovaBlue 蓝色声波冲击环,强制周围 4 米所有敌人攻击自己 3s!
/// 10级【圣盾清算】:护盾期间霸体免眩晕;当护盾被打破或超时结束时爆发神圣冲击波,将吸收伤害的 50% 转化为真实伤害反弹全场!
/// </summary>
public class ShieldGuardSkill : UnitSkill
{
[Header("护盾配置")]
[Tooltip("基础护盾持续时间(秒)")]
public float baseShieldDuration = 5.0f;
[Tooltip("3级以上护盾持续时间(秒)")]
public float upgradedShieldDuration = 6.0f;
[Header("6级战吼嘲讽配置")]
[Tooltip("嘲讽半径(米)")]
public float tauntRadius = 4.0f;
[Tooltip("嘲讽持续时间(秒)")]
public float tauntDuration = 3.0f;
[Header("特效资源")]
public GameObject shieldVfxPrefab; // 护盾特效 (MagicShieldBlue)
public GameObject tauntWaveVfxPrefab; // 拍地嘲讽声波环特效 (NovaBlue)
public GameObject shieldBurstVfxPrefab; // 破盾清算冲击波特效 (NovaLightningBlue 或 TargetHitExplosion)
private GameObject activeShieldVfx;
private Coroutine activeShieldCoroutine;
private float totalAbsorbedDamage = 0f;
private bool isSkillPending = false;
private float currentMaxShield = 0f;
private void EnsureUnit()
{
if (unit == null)
{
unit = GetComponent<UnitBase>();
}
}
/// <summary>
/// 当能量蓄满时触发:播放盾卫专属技能动画(举盾蓄力后砸地)
/// </summary>
public override void ReleaseSkill()
{
EnsureUnit();
if (unit == null) return;
WorldHealthBar healthBar = unit.GetComponent<WorldHealthBar>();
if (healthBar == null || healthBar.IsDead) return;
unit.FaceCurrentTarget(0f);
isSkillPending = true;
// 播放盾卫技能动画,并在 1.09s 的 OnSkillHit1 帧触发核心效果
unit.PlaySkillAnimation(OnSkillAnimationFinished, 1.87f);
Debug.Log($"<color=cyan>盾卫开始吟唱技能【圣盾壁垒】</color>,等待 OnSkillHit1 拍地!");
}
/// <summary>
/// 动画事件帧方法:在双手持盾猛烈砸地的瞬间触发 (1.095 秒处)
/// </summary>
public void OnSkillHit1()
{
if (!isSkillPending) return;
isSkillPending = false;
EnsureUnit();
if (unit == null) return;
WorldHealthBar healthBar = unit.GetComponent<WorldHealthBar>();
if (healthBar == null || healthBar.IsDead) return;
int level = unit.level;
// 1. 计算护盾数值 (1级 35%, 3级+ 50%)
float ratio = level >= 3 ? 0.50f : 0.35f;
float shieldAmount = healthBar.maxHealth * ratio;
currentMaxShield = shieldAmount;
totalAbsorbedDamage = 0f;
// 2. 赋予自身护盾
healthBar.AddShield(shieldAmount);
// 3. 挂载护盾环绕特效 (MagicShieldBlue)
PlayShieldVfx();
// 4. 10 级解锁:霸体免疫眩晕
StatusEffectController statusCtrl = unit.GetComponent<StatusEffectController>();
if (level >= 10 && statusCtrl != null)
{
statusCtrl.isStunImmune = true;
}
// 5. 6 级解锁:拍地激发声波光环 + 强力嘲讽周围 4 米所有敌人
if (level >= 6)
{
ExecuteTauntAndWave();
}
// 6. 监听护盾伤害吸收 (用于 10 级破盾清算)
healthBar.OnShieldAbsorbedDamage -= RecordAbsorbedDamage;
healthBar.OnShieldAbsorbedDamage += RecordAbsorbedDamage;
// 7. 启动护盾生命周期协程 (监测破盾与超时结算)
float duration = level >= 3 ? upgradedShieldDuration : baseShieldDuration;
if (activeShieldCoroutine != null)
{
StopCoroutine(activeShieldCoroutine);
}
activeShieldCoroutine = StartCoroutine(ShieldLifecycleRoutine(duration, shieldAmount));
Debug.Log($"<color=cyan>【盾卫】拍地爆发!</color> 获得护盾 {shieldAmount:F1} (等级: {level})");
}
private void ExecuteTauntAndWave()
{
// 播放声波光环特效 (NovaBlue)
PlayTauntWaveVfx();
// 范围嘲讽所有敌人
UnitTeam myTeam = unit.GetComponent<UnitTeam>();
UnitBase[] allUnits = FindObjectsOfType<UnitBase>();
float radiusSq = tauntRadius * tauntRadius;
int tauntedCount = 0;
foreach (var other in allUnits)
{
if (other == null || other == unit || !other.gameObject.activeInHierarchy || other.IsDead) continue;
UnitTeam otherTeam = other.GetComponent<UnitTeam>();
if (myTeam != null && otherTeam != null && !myTeam.IsEnemy(otherTeam.gameObject)) continue; // 只嘲讽敌方
Vector3 diff = other.transform.position - unit.transform.position;
diff.y = 0f;
if (diff.sqrMagnitude <= radiusSq)
{
other.ApplyTaunt(unit.gameObject, tauntDuration);
tauntedCount++;
}
}
Debug.Log($"<color=yellow>【盾卫战吼嘲讽】激发!</color> 强制嘲讽周围 {tauntedCount} 个敌人持续 {tauntDuration:F1} 秒!");
}
private void RecordAbsorbedDamage(float absorbed)
{
totalAbsorbedDamage += absorbed;
}
private IEnumerator ShieldLifecycleRoutine(float duration, float initialShieldAmount)
{
float timer = duration;
WorldHealthBar healthBar = unit != null ? unit.GetComponent<WorldHealthBar>() : null;
StatusEffectController statusCtrl = unit != null ? unit.GetComponent<StatusEffectController>() : null;
while (timer > 0f)
{
if (unit == null || healthBar == null || healthBar.IsDead || healthBar.currentShield <= 0f)
{
break;
}
timer -= Time.deltaTime;
yield return null;
}
// 护盾解除/破盾清算
bool isShieldBroken = healthBar != null && healthBar.currentShield <= 0f && timer > 0f;
int level = unit != null ? unit.level : 1;
// 10 级解锁【圣盾清算】:将吸收的伤害按 50% 转化为真实伤害反弹全场周围
if (level >= 10 && totalAbsorbedDamage > 0f && unit != null)
{
TriggerShieldBurst(totalAbsorbedDamage * 0.50f);
}
// 清理状态与特效
if (statusCtrl != null)
{
statusCtrl.isStunImmune = false;
}
if (healthBar != null)
{
healthBar.OnShieldAbsorbedDamage -= RecordAbsorbedDamage;
if (timer <= 0f && healthBar.currentShield > 0f)
{
healthBar.RemoveShield(initialShieldAmount);
}
}
if (activeShieldVfx != null)
{
Destroy(activeShieldVfx);
activeShieldVfx = null;
}
Debug.Log($"<color=cyan>【盾卫】护盾结算完毕</color> (是否被击破: {isShieldBroken}, 总共吸收伤害: {totalAbsorbedDamage:F1})");
}
private void TriggerShieldBurst(float burstDamage)
{
Debug.Log($"<color=yellow>【圣盾清算】护盾爆发!</color> 造成 {burstDamage:F1} 范围反击真实伤害!");
// 播放破盾爆发特效
PlayShieldBurstVfx();
// 对周围 4 米造成反弹伤害
if (unit != null)
{
unit.ApplyAreaSkillDamage(tauntRadius, burstDamage, false);
}
}
private void PlayShieldVfx()
{
if (activeShieldVfx != null) Destroy(activeShieldVfx);
GameObject prefab = shieldVfxPrefab;
#if UNITY_EDITOR
if (prefab == null)
{
prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/TJGeneratorLibEffects/Prefabs/Combat/Magic/Shield/MagicShieldBlue.prefab");
}
#endif
if (prefab != null && unit != null)
{
activeShieldVfx = Instantiate(prefab, unit.transform.position + Vector3.up * 1.0f, Quaternion.identity);
activeShieldVfx.transform.SetParent(unit.transform, true);
}
}
private void PlayTauntWaveVfx()
{
GameObject prefab = tauntWaveVfxPrefab;
#if UNITY_EDITOR
if (prefab == null)
{
prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/TJGeneratorLibEffects/Prefabs/Combat/Nova/Standard/NovaBlue.prefab");
}
#endif
if (prefab != null && unit != null)
{
Vector3 spawnPos = unit.transform.position;
spawnPos.y = 0.05f; // 贴地
var vfx = Instantiate(prefab, spawnPos, prefab.transform.rotation);
// 调整 scale 以匹配 4 米嘲讽范围
vfx.transform.localScale = new Vector3(1.6f, 1.6f, 1.6f);
Destroy(vfx, 2.5f);
}
}
private void PlayShieldBurstVfx()
{
GameObject prefab = shieldBurstVfxPrefab;
#if UNITY_EDITOR
if (prefab == null)
{
prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/TJGeneratorLibEffects/Prefabs/Combat/Nova/Lightning/NovaLightningBlue.prefab");
}
#endif
if (prefab != null && unit != null)
{
Vector3 spawnPos = unit.transform.position;
spawnPos.y = 0.05f;
var vfx = Instantiate(prefab, spawnPos, prefab.transform.rotation);
vfx.transform.localScale = new Vector3(1.5f, 1.5f, 1.5f);
Destroy(vfx, 2.5f);
}
}
private void OnSkillAnimationFinished()
{
isSkillPending = false;
}
private void OnDestroy()
{
if (activeShieldVfx != null) Destroy(activeShieldVfx);
if (unit != null)
{
WorldHealthBar healthBar = unit.GetComponent<WorldHealthBar>();
if (healthBar != null) healthBar.OnShieldAbsorbedDamage -= RecordAbsorbedDamage;
StatusEffectController statusCtrl = unit.GetComponent<StatusEffectController>();
if (statusCtrl != null) statusCtrl.isStunImmune = false;
}
}
}