using System.Collections; using System.Collections.Generic; using UnityEngine; /// /// 石巨人技能:大地震击 / 天崩地裂体系(重装控制 / 护盾控场 · 1/3/6/10 级完整阶梯) /// 1级【大地震击】:双拳猛砸地面引发冲击波,对周围 3.5 米造成 160% 物理伤害并【眩晕 1.5 秒】 /// 3级【震荡强化】:伤害提升至 200%,范围扩大 25% (4.4米),【眩晕时间延长至 2.0 秒】 /// 6级【坚石护体】:拍地瞬间获得相当于 30% 最大生命值的坚固护盾(MagicShieldBlue),护盾期间霸体免控,【依然保留 2.0 秒大范围眩晕】 /// 10级【天崩地裂】:双拳轰砸地面爆发全场重度地裂(GroundCrack),范围 4.5 米造成 260% 巨额物理伤害, /// 【强力向外震退 3.0 米 + 眩晕 2.0 秒(击退加眩晕双重效果)】!护盾厚度提升至 45% 最大生命值,且护盾存在期间自身受到伤害降低 35%! /// public class StoneGolemSkill : UnitSkill { [Header("技能基础配置")] [Tooltip("基础震荡波半径 (米)")] public float baseRadius = 3.5f; [Tooltip("技能动画完整时长 (秒)")] public float skillAnimationDuration = 2.3f; [Header("特效资源")] [Tooltip("砸地冲击波核心特效 (ToonBodySlam)")] public GameObject slamVfxPrefab; [Tooltip("环形扩散光圈特效 (ShockwaveRing)")] public GameObject shockwaveEffectPrefab; [Tooltip("地面重度地裂特效 (地裂.prefab)")] public GameObject groundCrackPrefab; [Tooltip("坚石护体护盾特效 (MagicShieldBlue)")] public GameObject shieldVfxPrefab; private bool isSkillPending = false; private GameObject activeShieldVfxInstance; private Coroutine activeShieldCoroutine; private void EnsureUnit() { if (unit == null) { unit = GetComponent(); } } protected override void Awake() { base.Awake(); EnsureUnit(); } /// /// 当能量蓄满时触发:播放石巨人双拳高举蓄力猛砸地面动作 /// public override void ReleaseSkill() { EnsureUnit(); if (unit == null) return; WorldHealthBar healthBar = unit.GetComponent(); if (healthBar == null || healthBar.IsDead) return; unit.FaceCurrentTarget(0f); isSkillPending = true; // 播放石巨人技能动作,由 OnSkillHit1 帧触发双拳砸地命中 unit.PlaySkillAnimation(OnSkillAnimationFinished, skillAnimationDuration); Debug.Log($"【石巨人】释放技能【大地震击/天崩地裂】,蓄力猛砸地面!"); } /// /// 动画命中帧方法:双拳猛砸接触地面的瞬间触发 (OnSkillHit1) /// public void OnSkillHit1() { ExecuteGroundSlam(); } public void OnAttackEffect() { if (isSkillPending) { ExecuteGroundSlam(); } } /// /// 执行砸地冲击波伤害、眩晕、击退与生成护盾 /// private void ExecuteGroundSlam() { if (!isSkillPending) return; isSkillPending = false; EnsureUnit(); if (unit == null) return; WorldHealthBar healthBar = unit.GetComponent(); if (healthBar == null || healthBar.IsDead) return; int level = unit.level; float currentRadius = baseRadius; float damageMultiplier = 1.60f; float stunDuration = 1.5f; float knockbackDist = 0f; if (level >= 10) { currentRadius = 4.5f; damageMultiplier = 2.60f; stunDuration = 2.0f; // 10级:眩晕 2.0 秒 knockbackDist = 3.0f; // 10级:击退加眩晕双重效果! } else if (level >= 3) { currentRadius = baseRadius * 1.25f; // 4.375 米 damageMultiplier = 2.00f; stunDuration = 2.0f; // 3~9级:眩晕 2.0 秒,无击退 knockbackDist = 0f; } else { currentRadius = baseRadius; damageMultiplier = 1.60f; stunDuration = 1.5f; // 1~2级:眩晕 1.5 秒,无击退 knockbackDist = 0f; } float totalDamage = unit.attackPower * damageMultiplier; // 1. 播放砸地冲击波特效 (ToonBodySlam + ShockwaveRing) PlayShockwaveVfx(currentRadius, level >= 10); // 2. 10级额外播放地面重度地裂特效 (GroundCrack) if (level >= 10) { PlayGroundCrackVfx(currentRadius); } // 3. 结算大范围物理伤害、眩晕控制,以及10级强力震退 ApplyAreaImpact(currentRadius, totalDamage, stunDuration, knockbackDist); // 4. 6级+ 激活【坚石护体】护盾 (6级 30%, 10级 45% 最大血量) float shieldRatio = level >= 10 ? 0.45f : (level >= 6 ? 0.30f : 0f); if (shieldRatio > 0f) { float shieldAmount = healthBar.maxHealth * shieldRatio; healthBar.AddShield(shieldAmount); PlayShieldVfx(); if (activeShieldCoroutine != null) { StopCoroutine(activeShieldCoroutine); } activeShieldCoroutine = StartCoroutine(ShieldTimeoutRoutine(6.0f, shieldAmount)); } Debug.Log($"【石巨人·大地震击】轰地! 伤害: {totalDamage:F1} ({damageMultiplier * 100:F0}%), 半径: {currentRadius:F1}m, 眩晕: {stunDuration:F1}s, 震退: {knockbackDist:F1}m (等级: {level})"); } private void PlayShockwaveVfx(float radius, bool isUltimate) { // 1. 砸地核心冲击波特效 (ToonBodySlam: 气浪扩散 + 尘烟飞散 + 火星) GameObject slamPrefab = slamVfxPrefab; #if UNITY_EDITOR if (slamPrefab == null) { slamPrefab = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/TJGeneratorLibEffects/Prefabs/Combat/Brawling/Toon/ToonBodySlam.prefab"); } #endif if (slamPrefab != null && unit != null) { Vector3 slamPos = unit.transform.position + unit.transform.forward * 0.8f; slamPos.y = 0.05f; var slamObj = Instantiate(slamPrefab, slamPos, Quaternion.identity); slamObj.transform.localScale = Vector3.one * (radius / 2.2f); Destroy(slamObj, 2.0f); } // 2. 地面扩散光圈 (ShockwaveRing) GameObject ringPrefab = shockwaveEffectPrefab; #if UNITY_EDITOR if (ringPrefab == null) { ringPrefab = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Prefabs/特效/扩散光圈/ShockwaveRing.prefab"); } #endif if (ringPrefab != null && unit != null) { Vector3 effectPos = unit.transform.position; effectPos.y = 0.05f; var effectObj = Instantiate(ringPrefab, effectPos, ringPrefab.transform.rotation); var shockwave = effectObj.GetComponent(); if (shockwave != null) { Color ringColor = isUltimate ? new Color(1.0f, 0.45f, 0.15f, 1f) : new Color(0.9f, 0.7f, 0.35f, 1f); shockwave.SetupEffect(radius, 0.8f, ringColor); } } } private void PlayGroundCrackVfx(float radius) { GameObject prefab = groundCrackPrefab; #if UNITY_EDITOR if (prefab == null) { prefab = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Prefabs/特效/地裂特效/地裂.prefab"); } #endif if (prefab != null && unit != null) { Vector3 crackPos = unit.transform.position; crackPos.y = 0.06f; var crackObj = Instantiate(prefab, crackPos, prefab.transform.rotation); crackObj.transform.localScale = Vector3.one * (radius * 1.4f); var groundCrack = crackObj.GetComponent(); if (groundCrack != null) { groundCrack.Play(); } Destroy(crackObj, 3.0f); } } private void PlayShieldVfx() { if (activeShieldVfxInstance != null) { Destroy(activeShieldVfxInstance); } GameObject prefab = shieldVfxPrefab; #if UNITY_EDITOR if (prefab == null) { prefab = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/TJGeneratorLibEffects/Prefabs/Combat/Magic/Shield/MagicShieldBlue.prefab"); } #endif if (prefab != null && unit != null) { // 调整护盾挂载高度与缩放:与盾卫视觉比例一致协调 (1.15倍),不再过于庞大 activeShieldVfxInstance = Instantiate(prefab, unit.transform.position + Vector3.up * 1.1f, Quaternion.identity); activeShieldVfxInstance.transform.SetParent(unit.transform, true); activeShieldVfxInstance.transform.localScale = Vector3.one * 1.15f; } } private IEnumerator ShieldTimeoutRoutine(float duration, float amount) { float timer = duration; WorldHealthBar healthBar = unit != null ? unit.GetComponent() : null; var status = unit != null ? unit.GetComponent() : null; // 护盾期间霸体免控 if (status != null) { status.isStunImmune = true; } while (timer > 0f) { if (unit == null || healthBar == null || healthBar.IsDead || healthBar.currentShield <= 0f) { break; } timer -= Time.deltaTime; yield return null; } // 护盾解除恢复正常免控状态 if (status != null) { status.isStunImmune = false; } // 超时或护盾清空时销毁护盾特效 if (activeShieldVfxInstance != null) { Destroy(activeShieldVfxInstance); activeShieldVfxInstance = null; } // 超时扣除护盾 if (healthBar != null && healthBar.currentShield > 0f && timer <= 0f) { healthBar.RemoveShield(amount); } } private void ApplyAreaImpact(float radius, float damage, float stunDuration, float knockback) { UnitTeam myTeam = unit.GetComponent(); if (myTeam == null) return; float sqrRadius = radius * radius; Vector3 myPos = unit.transform.position; var allTeams = FindObjectsOfType(); HashSet hitRoots = new HashSet(); foreach (var t in allTeams) { if (t == null || !t.gameObject.activeInHierarchy || !myTeam.IsEnemy(t.gameObject)) continue; GameObject opponent = t.gameObject; if (opponent == unit.gameObject || opponent.transform.IsChildOf(unit.transform) || unit.transform.IsChildOf(opponent.transform)) continue; Vector3 offset = opponent.transform.position - myPos; offset.y = 0f; if (offset.sqrMagnitude <= sqrRadius) { GameObject rootGo = opponent.transform.root.gameObject; if (!hitRoots.Add(rootGo)) continue; // 1. 伤害与眩晕结算 UnitBase targetUnit = opponent.GetComponentInParent(); WorldHealthBar targetBar = opponent.GetComponentInParent(); if (targetUnit != null) { targetUnit.ReceiveDamage(damage, unit.gameObject); if (stunDuration > 0f && targetUnit.IsAlive) { targetUnit.ApplyStun(stunDuration); Debug.Log($"【大地震击】眩晕生效! 目标 {targetUnit.gameObject.name} 眩晕 {stunDuration:F1} 秒!"); } } else if (targetBar != null && !targetBar.IsDead) { targetBar.TakeDamage(damage, unit.gameObject); var status = opponent.GetComponentInParent(); if (status != null && stunDuration > 0f) { status.ApplyStun(stunDuration); } } // 2. 10级强力向外震退 (与眩晕并存) if (knockback > 0f) { Vector3 pushDir = offset.sqrMagnitude > 0.001f ? offset.normalized : unit.transform.forward; ApplyKnockback(opponent, pushDir * knockback); } } } } private void ApplyKnockback(GameObject victim, Vector3 displacement) { UnityEngine.AI.NavMeshAgent agent = victim.GetComponentInParent(); Transform targetTr = agent != null ? agent.transform : victim.transform; Vector3 targetPos = targetTr.position + displacement; if (UnityEngine.AI.NavMesh.SamplePosition(targetPos, out UnityEngine.AI.NavMeshHit hit, 2.0f, UnityEngine.AI.NavMesh.AllAreas)) { targetPos = hit.position; } if (agent != null && agent.enabled && agent.isOnNavMesh) { agent.Warp(targetPos); } else { targetTr.position = targetPos; } Debug.Log($"【天崩地裂·排山倒海】! 目标 {victim.name} 被强力震飞推开 {displacement.magnitude:F1} 米!"); } public override float ModifyIncomingDamage(float damage, GameObject attacker) { EnsureUnit(); // 10级解锁:护盾存在期间自身受到伤害降低 35% if (unit != null && unit.level >= 10) { WorldHealthBar healthBar = unit.GetComponent(); if (healthBar != null && healthBar.currentShield > 0f) { return damage * (1f - 0.35f); } } return damage; } private void OnSkillAnimationFinished() { if (isSkillPending) { ExecuteGroundSlam(); // 容错兜底:动画结束若未触发命中帧,自动执行 } } private void OnDestroy() { if (activeShieldVfxInstance != null) { Destroy(activeShieldVfxInstance); } var status = unit != null ? unit.GetComponent() : null; if (status != null) { status.isStunImmune = false; } } }