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);
}
}
}