using System; 
 | 
using System.Collections.Generic; 
 | 
using System.Linq; 
 | 
using Cysharp.Threading.Tasks; 
 | 
using DG.Tweening; 
 | 
using UnityEngine; 
 | 
  
 | 
public class BulletSkillEffect : SkillEffect 
 | 
{ 
 | 
    // protected SkillConfig skillConfig; 
 | 
    // protected BattleObject caster; 
 | 
    // protected List<BattleObject> targets; // 目标列表 
 | 
  
 | 
    protected List<BulletCurve> bulletCurves = new List<BulletCurve>(); 
 | 
     
 | 
    // 散射技能击中计数器,用于判断是否所有目标都已击中 
 | 
    private int scatterHitCount = 0; 
 | 
    private int scatterTotalTargets = 0; 
 | 
  
 | 
  
 | 
    public BulletSkillEffect(SkillConfig _skillConfig, BattleObject _caster, HB427_tagSCUseSkill _tagUseSkillAttack) 
 | 
        : base(_skillConfig, _caster, _tagUseSkillAttack) 
 | 
    { 
 | 
  
 | 
    } 
 | 
     
 | 
  
 | 
  
 | 
    public override void OnMiddleFrameEnd(int times, int index) 
 | 
    { 
 | 
        base.OnMiddleFrameEnd(times, index); 
 | 
        //  弹射 另外的做法了 
 | 
        if (skillConfig.effectType == SkillEffectType.Bullet && skillConfig.BulletPath == 4) 
 | 
        { 
 | 
            var hurt = tagUseSkillAttack.HurtList[0]; 
 | 
            BattleObject targetObject = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); 
 | 
            if (targetObject == null) 
 | 
            { 
 | 
                Debug.LogError("目标为空 target == null ObjId : " + hurt.ObjID); 
 | 
                return; 
 | 
            } 
 | 
            ShotToTarget(targetObject, index); 
 | 
        } 
 | 
        //  普通的做法 区分打向阵营或者打向个体 
 | 
        else 
 | 
        { 
 | 
            //  区分散射跟范围攻击 
 | 
            if (skillConfig.Scattering == 1) 
 | 
            { 
 | 
                //  散射 
 | 
                ScatterShot(index); 
 | 
            } 
 | 
            else 
 | 
            { 
 | 
                switch (skillConfig.TagAim) 
 | 
                { 
 | 
                    case 0: 
 | 
                        AllAreaShoting(index); 
 | 
                        break; 
 | 
                    case 1: 
 | 
                        OneTargetShoting(index); 
 | 
                        break; 
 | 
                    case 2: 
 | 
                        FrontRowShoting(index); 
 | 
                        break; 
 | 
                    case 3: 
 | 
                        BackRowShoting(index); 
 | 
                        break; 
 | 
                    case 4: 
 | 
                        VerticalRowShoting(index); 
 | 
                        break; 
 | 
                    case 5: 
 | 
                        SelfShoting(index); 
 | 
                        break; 
 | 
                    default: 
 | 
                        Debug.LogError("子弹特效没有配置正确的TagAim,强制结束子弹特效 TagAim: " + skillConfig.TagAim); 
 | 
                        ForceFinished(); 
 | 
                        break; 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    // 0   全部范围: 
 | 
    private void AllAreaShoting(int index) 
 | 
    { 
 | 
        if (skillConfig.TagCount == 0 || skillConfig.TagCount >= 6) 
 | 
        { 
 | 
            // 若TagCount目标个数为0或6,根据TagFriendly敌我配置,代表作用于敌方全体或我方全体,此时主目标为敌我站位中的2号位置 
 | 
            BattleCamp battleCamp = skillConfig.TagFriendly != 0 ? caster.Camp : caster.GetEnemyCamp(); 
 | 
            ShotToIndex(battleCamp, 1, index); 
 | 
        } 
 | 
        else 
 | 
        { 
 | 
            // 若TagCount目标个数为1~5个,代表随机作用于敌方或我方x个武将,此时所有被随机到的对象都为主目标(施法位置会用客户端配置) 
 | 
            ShotEachTargets(index); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    // 1    对位: 
 | 
    private void OneTargetShoting(int index) 
 | 
    { 
 | 
        // 默认只选1个,对位规则为A1优先打B1,A2优先打B2,A3优先打B3,对位目标死亡时,优先前排, 
 | 
        // 比如B2已经死亡,那么A2将优先打B1,前排1、2、3号位置全部死亡之后才开始选择后排4、5、6号位置, 
 | 
        // 对位只可选1个目标,即主目标 
 | 
  
 | 
        if (tagUseSkillAttack.HurtList.Length > 1) 
 | 
        { 
 | 
            Debug.LogError("服务器 对位攻击目标数量错误,应该只有一个目标 技能id" + skillConfig.SkillID); 
 | 
        } 
 | 
  
 | 
        var hurt = tagUseSkillAttack.HurtList[0]; 
 | 
        BattleObject targetObject = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); 
 | 
        if (targetObject == null) 
 | 
        { 
 | 
            Debug.LogError("目标为空 target == null ObjId : " + hurt.ObjID); 
 | 
            return; 
 | 
        } 
 | 
        ShotToTarget(targetObject, index); 
 | 
    } 
 | 
  
 | 
    // 2    前排: 
 | 
    private void FrontRowShoting(int index) 
 | 
    { 
 | 
        // 1、2、3号位为前排,默认2号位置为主目标,当1、2、3号位置角色全部死亡,前排将替换成后排,5号位置变更为主目标, 
 | 
        // 若配置TagAffect细分目标,且人数小于3,则所有被选择目标均为主目标(施法位置会用客户端配置) 
 | 
        // (即前排默认2号位或5号位规则无效,实际作用多少人就是多少个主目标) 
 | 
  
 | 
        BattleCamp battleCamp = skillConfig.TagFriendly != 0 ? caster.Camp : caster.GetEnemyCamp(); 
 | 
  
 | 
        if (skillConfig.TagAffect != 0 || skillConfig.TagCount < 3) 
 | 
        { 
 | 
            ShotEachTargets(index); 
 | 
        } 
 | 
        else 
 | 
        { 
 | 
            int targetIndex = int.MaxValue; 
 | 
            int minimumIndex = int.MaxValue; 
 | 
  
 | 
            foreach (var hurt in tagUseSkillAttack.HurtList) 
 | 
            { 
 | 
                BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); 
 | 
                if (target == null) 
 | 
                { 
 | 
                    Debug.LogError("特效目标为空 target == null ObjId : " + hurt.ObjID); 
 | 
                    continue; 
 | 
                } 
 | 
  
 | 
                minimumIndex = Mathf.Min(target.teamHero.positionNum, minimumIndex); 
 | 
  
 | 
                if (target.Camp == battleCamp && target.teamHero.positionNum < 3) 
 | 
                { 
 | 
                    targetIndex = 1; 
 | 
                    break; 
 | 
                } 
 | 
            } 
 | 
  
 | 
            if (targetIndex == int.MaxValue) 
 | 
            { 
 | 
                targetIndex = (minimumIndex >= 3) ? 4 : 1; 
 | 
            } 
 | 
            else 
 | 
            { 
 | 
                targetIndex = 1; 
 | 
            } 
 | 
  
 | 
            ShotToIndex(battleCamp, targetIndex, index); 
 | 
        } 
 | 
  
 | 
    } 
 | 
  
 | 
    private void ShotToIndex(BattleCamp camp, int targetIndex, int bulletIndex) 
 | 
    { 
 | 
        RectTransform targetTransform = caster.battleField.GetTeamNode(camp, targetIndex); 
 | 
        BattleEffectPlayer effectPlayer = caster.battleField.battleEffectMgr.PlayEffect(caster, skillConfig.BulletEffectId, caster.heroRectTrans, caster.Camp); 
 | 
  
 | 
        RectTransform effectTrans = effectPlayer.transform as RectTransform; 
 | 
  
 | 
        var bulletCurve = BulletCurveFactory.CreateBulletCurve(caster, skillConfig, effectPlayer, targetTransform, tagUseSkillAttack.HurtList.ToList(), bulletIndex, (index, hitList) => 
 | 
        { 
 | 
            if (isFinish) 
 | 
                return; 
 | 
            // 击中就销毁子弹 
 | 
            caster.battleField.battleEffectMgr.RemoveEffect(skillConfig.BulletEffectId, effectPlayer); 
 | 
            // 播放子弹爆炸特效 
 | 
  
 | 
            BattleCamp battleCamp = skillConfig.TagFriendly != 0 ? caster.Camp : caster.GetEnemyCamp(); 
 | 
            //  首先是目标身上爆炸 
 | 
            PlayExplosionEffect(skillConfig.ExplosionEffectId, targetTransform, caster.Camp); 
 | 
            PlayExplosionEffect(skillConfig.ExplosionEffect2, targetTransform, caster.Camp); 
 | 
  
 | 
            foreach (var hurt in hitList) 
 | 
            { 
 | 
                BattleObject targetObj = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); 
 | 
                if (targetObj == null) 
 | 
                { 
 | 
                    Debug.LogError("目标为空 target == null ObjId : " + hurt.ObjID); 
 | 
                    continue; 
 | 
                } 
 | 
  
 | 
                PlayExplosionEffect(skillConfig.ExplosionEffect3, targetObj.heroGo.transform, caster.Camp); 
 | 
                PlayExplosionEffect(skillConfig.ExplosionEffect4, targetObj.heroGo.transform, caster.Camp); 
 | 
            } 
 | 
  
 | 
            // 表现子弹飞行到目标位置 
 | 
            onHit?.Invoke(index, hitList); 
 | 
  
 | 
            isFinish = true; 
 | 
        }); 
 | 
  
 | 
        bulletCurves.Add(bulletCurve); 
 | 
    } 
 | 
  
 | 
    // 3    后排: 
 | 
    private void BackRowShoting(int index) 
 | 
    { 
 | 
        // 4、5、6号位为后排,默认5号位置为主目标,当4、5、6号位置角色全部死亡,后排排将替换成前排,2号位置变更为主目标, 
 | 
        // 若配置TagAffect细分目标,且人数小于3,则所有被选择目标均为主目标(施法位置会用客户端配置) 
 | 
        // (即前排默认2号位或5号位规则无效,实际作用多少人就是多少个主目标) 
 | 
  
 | 
        BattleCamp battleCamp = skillConfig.TagFriendly != 0 ? caster.Camp : caster.GetEnemyCamp(); 
 | 
  
 | 
        if (skillConfig.TagAffect != 0 || skillConfig.TagCount < 3) 
 | 
        { 
 | 
            ShotEachTargets(index); 
 | 
        } 
 | 
        else 
 | 
        { 
 | 
            int targetIndex = int.MaxValue; 
 | 
            int maxinumIndex = int.MinValue; 
 | 
  
 | 
            foreach (var hurt in tagUseSkillAttack.HurtList) 
 | 
            { 
 | 
                BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); 
 | 
                if (target == null) 
 | 
                { 
 | 
                    Debug.LogError("特效目标为空 target == null ObjId : " + hurt.ObjID); 
 | 
                    continue; 
 | 
                } 
 | 
  
 | 
                if (target.Camp == battleCamp && target.teamHero.positionNum > 3) 
 | 
                { 
 | 
                    targetIndex = 4; 
 | 
                    break; 
 | 
                } 
 | 
  
 | 
                maxinumIndex = Mathf.Max(target.teamHero.positionNum, maxinumIndex); 
 | 
            } 
 | 
  
 | 
            if (targetIndex == int.MaxValue) 
 | 
            { 
 | 
                targetIndex = (maxinumIndex < 3) ? 1 : 4; 
 | 
            } 
 | 
            else 
 | 
            { 
 | 
                targetIndex = 4; 
 | 
            } 
 | 
  
 | 
            ShotToIndex(battleCamp, targetIndex, index); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    // 4    纵排: 
 | 
    private void VerticalRowShoting(int index) 
 | 
    { 
 | 
        // 纵排分别为1、4,2、5,3、6,三组纵排,按对位规则选择,默认1号、2号或3号为主目标,前排1、2、3号位置全部死完后,4号、5号或6号为主目标 
 | 
        BattleCamp battleCamp = skillConfig.TagFriendly != 0 ? caster.Camp : caster.GetEnemyCamp(); 
 | 
        //  攻击mininumIndex目标 
 | 
        int minimumIndex = int.MaxValue; 
 | 
        foreach (var hurt in tagUseSkillAttack.HurtList) 
 | 
        { 
 | 
            BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); 
 | 
            if (target == null) 
 | 
            { 
 | 
                Debug.LogError("特效目标为空 target == null ObjId : " + hurt.ObjID); 
 | 
                continue; 
 | 
            } 
 | 
  
 | 
            minimumIndex = Mathf.Min(target.teamHero.positionNum, minimumIndex); 
 | 
        } 
 | 
  
 | 
        if (minimumIndex != int.MaxValue) 
 | 
        { 
 | 
            ShotToIndex(battleCamp, minimumIndex, index); 
 | 
        } 
 | 
        else 
 | 
        { 
 | 
            Debug.LogError("纵排攻击没有目标 强制结束子弹特效"); 
 | 
            ForceFinished(); 
 | 
        } 
 | 
  
 | 
  
 | 
    } 
 | 
  
 | 
    // 5    自己: 
 | 
    private void SelfShoting(int index) 
 | 
    { 
 | 
        // 默认只选自己,自己为主目标 
 | 
        ShotToIndex(caster.Camp, caster.teamHero.positionNum, index); 
 | 
    } 
 | 
  
 | 
    //  散射 
 | 
    private void ScatterShot(int index) 
 | 
    { 
 | 
        // 只在第一次发射时初始化散射计数器 
 | 
        if (index == 0) 
 | 
        { 
 | 
            scatterHitCount = 0; 
 | 
            // 总击中数 = 发射次数 × 目标数量 
 | 
            scatterTotalTargets = skillConfig.ActiveFrames.Length * tagUseSkillAttack.HurtList.Length; 
 | 
        } 
 | 
         
 | 
        // 处理散射逻辑 
 | 
        for (int i = 0; i < tagUseSkillAttack.HurtList.Length; i++) 
 | 
        { 
 | 
            var hurt = tagUseSkillAttack.HurtList[i]; 
 | 
            BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); 
 | 
            if (target == null) 
 | 
            { 
 | 
                Debug.LogError("特效目标为空 target == null ObjId : " + hurt.ObjID); 
 | 
                // 目标为空时减少对应发射次数的总目标数 
 | 
                if (index == 0) scatterTotalTargets--; 
 | 
                continue; 
 | 
            } 
 | 
            ScatterShot(target, hurt, index, i); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    private void ScatterShot(BattleObject target, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, int bulletIndex, int order) 
 | 
    { 
 | 
        BattleEffectPlayer effectPlayer = caster.battleField.battleEffectMgr.PlayEffect(caster, skillConfig.BulletEffectId, caster.heroRectTrans, caster.Camp); 
 | 
  
 | 
        bool shotToSelf = target.ObjID == caster.ObjID; 
 | 
  
 | 
        effectPlayer.Alpha = shotToSelf ? 0f : 1f; 
 | 
  
 | 
        var tempOrder = order; 
 | 
  
 | 
        var bulletCurve = BulletCurveFactory.CreateBulletCurve(caster, skillConfig, effectPlayer, target.heroRectTrans, 
 | 
            new List<HB427_tagSCUseSkill.tagSCUseSkillHurt> { hurt }, bulletIndex, (index, hitList) => 
 | 
        { 
 | 
            foreach (var hurt in hitList) 
 | 
            { 
 | 
                BattleObject targetObj = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); 
 | 
                if (targetObj == null) 
 | 
                { 
 | 
                    Debug.LogError("目标为空 target == null ObjId : " + hurt.ObjID); 
 | 
                    continue; 
 | 
                } 
 | 
  
 | 
                PlayExplosionEffect(skillConfig.ExplosionEffectId, targetObj.heroGo.transform, caster.Camp); 
 | 
                PlayExplosionEffect(skillConfig.ExplosionEffect2, targetObj.heroGo.transform, caster.Camp); 
 | 
                PlayExplosionEffect(skillConfig.ExplosionEffect3, targetObj.heroGo.transform, caster.Camp); 
 | 
                PlayExplosionEffect(skillConfig.ExplosionEffect4, targetObj.heroGo.transform, caster.Camp); 
 | 
            } 
 | 
  
 | 
            // 表现子弹飞行到目标位置 
 | 
            onHit?.Invoke(index, hitList); 
 | 
            // 击中就销毁子弹 
 | 
            caster.battleField.battleEffectMgr.RemoveEffect(skillConfig.BulletEffectId, effectPlayer); 
 | 
  
 | 
            // 增加散射击中计数 
 | 
            scatterHitCount++; 
 | 
             
 | 
            // 判断是否所有发射次数的所有目标都已击中 
 | 
            if (scatterHitCount >= scatterTotalTargets) 
 | 
            { 
 | 
                isFinish = true; 
 | 
            } 
 | 
        }); 
 | 
  
 | 
        bulletCurves.Add(bulletCurve); 
 | 
    } 
 | 
  
 | 
    protected void ShotToTarget(BattleObject target, int bulletIndex) 
 | 
    { 
 | 
        BattleEffectPlayer effectPlayer = caster.battleField.battleEffectMgr.PlayEffect(caster, skillConfig.BulletEffectId, caster.heroRectTrans, caster.Camp); 
 | 
  
 | 
        bool shotToSelf = target.ObjID == caster.ObjID; 
 | 
  
 | 
        effectPlayer.Alpha = shotToSelf ? 0f : 1f; 
 | 
  
 | 
        var bulletCurve = BulletCurveFactory.CreateBulletCurve(caster, skillConfig, effectPlayer, target.heroRectTrans, tagUseSkillAttack.HurtList.ToList(), bulletIndex, (index, hitList) => 
 | 
        { 
 | 
            foreach (var hurt in hitList) 
 | 
            { 
 | 
                BattleObject targetObj = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); 
 | 
                if (targetObj == null) 
 | 
                { 
 | 
                    Debug.LogError("目标为空 target == null ObjId : " + hurt.ObjID); 
 | 
                    continue; 
 | 
                } 
 | 
  
 | 
                PlayExplosionEffect(skillConfig.ExplosionEffectId, targetObj.heroGo.transform, caster.Camp); 
 | 
                PlayExplosionEffect(skillConfig.ExplosionEffect2, targetObj.heroGo.transform, caster.Camp); 
 | 
                PlayExplosionEffect(skillConfig.ExplosionEffect3, targetObj.heroGo.transform, caster.Camp); 
 | 
                PlayExplosionEffect(skillConfig.ExplosionEffect4, targetObj.heroGo.transform, caster.Camp); 
 | 
            } 
 | 
  
 | 
            // 表现子弹飞行到目标位置 
 | 
            onHit?.Invoke(index, hitList); 
 | 
            // 击中就销毁子弹 
 | 
            caster.battleField.battleEffectMgr.RemoveEffect(skillConfig.BulletEffectId, effectPlayer); 
 | 
  
 | 
            if (isFinish) 
 | 
                return; 
 | 
  
 | 
            if (bulletIndex >= skillConfig.ActiveFrames.Length - 1) 
 | 
            { 
 | 
                isFinish = true; 
 | 
            } 
 | 
        }); 
 | 
  
 | 
        bulletCurves.Add(bulletCurve); 
 | 
    } 
 | 
  
 | 
    protected void PlayExplosionEffect(int effectId, Transform parent, BattleCamp camp) 
 | 
    { 
 | 
        if (effectId <= 0) 
 | 
            return; 
 | 
  
 | 
        var effect = caster.battleField.battleEffectMgr.PlayEffect(caster, effectId, parent, camp); 
 | 
        if (effect != null) 
 | 
        { 
 | 
            effect.transform.localRotation = parent.localRotation; 
 | 
            if (effect.transform.localScale.x < 0f) 
 | 
            { 
 | 
                effect.transform.localRotation *= Quaternion.Euler(0, 180, 0); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    private void ShotEachTargets(int index) 
 | 
    { 
 | 
        for (int i = 0; i < tagUseSkillAttack.HurtList.Length; i++) 
 | 
        { 
 | 
            var hurt = tagUseSkillAttack.HurtList[i]; 
 | 
            BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); 
 | 
            if (target == null) 
 | 
            { 
 | 
                Debug.LogError("特效目标为空 target == null ObjId : " + hurt.ObjID); 
 | 
                continue; 
 | 
            } 
 | 
            ShotToTarget(target, index); 
 | 
        } 
 | 
    } 
 | 
  
 | 
  
 | 
    public override void Run() 
 | 
    { 
 | 
        foreach (var bulletCurve in bulletCurves) 
 | 
        { 
 | 
            if (!bulletCurve.IsFinished) 
 | 
                bulletCurve.Run(); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    public override void ForceFinished() 
 | 
    { 
 | 
        base.ForceFinished(); 
 | 
        foreach (var bulletCurve in bulletCurves) 
 | 
        { 
 | 
            bulletCurve.ForceFinish(); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    public override bool IsFinished() 
 | 
    { 
 | 
        bool isCurveFinish = bulletCurves.Count <= 0; 
 | 
  
 | 
        foreach (var bulletCurve in bulletCurves) 
 | 
        { 
 | 
            isCurveFinish |= bulletCurve.IsFinished; 
 | 
        } 
 | 
  
 | 
        return isCurveFinish && base.IsFinished(); 
 | 
    } 
 | 
} 
 |