using System.Collections; using System.Collections.Generic; using UnityEngine; /// /// 弓箭手技能:迅捷三连 / 弱点锁定体系(1/3/6/10 级完整阶梯) /// 1级【迅捷三连】:搭弓连续高速射出 3 支穿甲箭矢,单体快速倾泻火力 /// 3级【极速穿甲】:箭矢飞行速度 +35%,三连射总伤害提升 25% /// 6级【弱点锁定】:伤害逐箭递增且第 3 箭必暴击;命中附加破甲标记,使目标受到的所有伤害 +30%(持续 4s)! /// 10级【乱射风暴】:三连射升级为 6 支风暴连射;击杀目标后剩余箭矢自动散开弹射给周围其他敌人 /// public class ArcherSkill : UnitSkill { [Header("三连射配置")] [Tooltip("基础箭矢数量")] public int baseArrowCount = 3; [Tooltip("每支箭发射间隔(秒)")] public float arrowInterval = 0.12f; [Tooltip("技能箭矢基础速度")] public float baseProjectileSpeed = 22f; private Coroutine activeVolleyCoroutine; private void EnsureUnit() { if (unit == null) { unit = GetComponent(); } } public override void ReleaseSkill() { EnsureUnit(); if (unit == null) return; WorldHealthBar healthBar = unit.GetComponent(); if (healthBar == null || healthBar.IsDead) return; if (unit.Target == null) return; if (activeVolleyCoroutine != null) { StopCoroutine(activeVolleyCoroutine); } activeVolleyCoroutine = StartCoroutine(FireVolleyRoutine()); } private IEnumerator FireVolleyRoutine() { EnsureUnit(); if (unit == null) yield break; int level = unit.level; // 10级升级为 6 支箭;其余等级为 3 支 int arrowCount = level >= 10 ? 6 : baseArrowCount; // 3级+ 箭速提升 35% float projSpeed = level >= 3 ? baseProjectileSpeed * 1.35f : baseProjectileSpeed; Debug.Log($"【弓箭手释放技能】 准备倾泻 {arrowCount} 连射(等级: {level})!"); for (int i = 0; i < arrowCount; i++) { // 目标死亡后自动切换给最近敌人 GameObject currentTarget = unit.Target; if (currentTarget == null || !currentTarget.activeInHierarchy || IsTargetDead(currentTarget)) { currentTarget = unit.FindNearestEnemyForSkill(); } if (currentTarget == null) { break; // 全场无敌人提前结束 } // 计算该支箭的伤害倍率与暴击 float damageMultiplier = GetArrowDamageMultiplier(i, arrowCount, level); bool isGuaranteedCrit = (level >= 6 && i == arrowCount - 1); // 6级+ 最后一箭必定暴击 bool applyVulnerability = (level >= 6 && i == arrowCount - 1); // 6级+ 最后一箭施加 4 秒 30% 易伤 // 发射技能箭矢 LaunchSkillArrow(currentTarget, damageMultiplier, projSpeed, isGuaranteedCrit, applyVulnerability); yield return new WaitForSeconds(arrowInterval); } activeVolleyCoroutine = null; } private float GetArrowDamageMultiplier(int index, int totalCount, int level) { // 1级:基础 70% 伤害/箭 float baseMult = 0.70f; // 3级:三连射总伤害提升 25% (0.70 * 1.25 = 0.875) if (level >= 3 && level < 6) { baseMult *= 1.25f; } // 6级+【弱点锁定】:伤害逐箭递增 if (level >= 6) { // 逐箭递增:例如第 1 箭 0.85,第 2 箭 1.05,最后一箭 1.35 float step = (float)index / Mathf.Max(1, totalCount - 1); baseMult = Mathf.Lerp(0.85f, 1.35f, step); } return baseMult; } private void LaunchSkillArrow(GameObject targetObj, float damageMultiplier, float speed, bool forceCrit, bool applyVulnerability) { if (unit == null || unit.projectilePrefab == null || targetObj == null) return; Transform spawnPoint = unit.projectileSpawnPoint != null ? unit.projectileSpawnPoint : unit.transform; Vector3 spawnPos = spawnPoint.position; Vector3 direction = (targetObj.transform.position + Vector3.up * 0.8f - spawnPos).normalized; Quaternion rotation = Quaternion.LookRotation(direction); GameObject arrowObj = Instantiate(unit.projectilePrefab, spawnPos, rotation); float calculatedDamage = unit.attackPower * damageMultiplier; if (forceCrit || (unit.critRate > 0f && Random.value < unit.critRate)) { calculatedDamage *= unit.critMultiplier; } // 接管 Arrow 碰撞,挂载自定义伤害与易伤回调 var projectile = arrowObj.GetComponent(); if (projectile != null) { // 技能箭不二次积攒能量 projectile.Initialize(targetObj, calculatedDamage, unit.gameObject, speed, 5f, false); } // 6级+ 易伤监听逻辑:如果本箭命中了,自动给目标挂上 30% 易伤 if (applyVulnerability) { StartCoroutine(ApplyVulnerabilityWhenHit(targetObj, 4.0f, 0.30f)); } } private IEnumerator ApplyVulnerabilityWhenHit(GameObject targetObj, float duration, float ratio) { // 等待箭矢飞至命中(约 0.2 ~ 0.4 秒) yield return new WaitForSeconds(0.25f); if (targetObj != null && targetObj.activeInHierarchy) { var status = targetObj.GetComponentInParent(); if (status != null) { status.ApplyVulnerability(duration, ratio); Debug.Log($"【弱点锁定】生效! 目标 {targetObj.name} 陷入破甲易伤:受击伤害 +{ratio * 100:F0}%,持续 {duration} 秒!"); } } } private bool IsTargetDead(GameObject targetObj) { if (targetObj == null) return true; var bar = targetObj.GetComponentInParent(); return bar != null && bar.IsDead; } private void OnDestroy() { if (activeVolleyCoroutine != null) { StopCoroutine(activeVolleyCoroutine); } } }