using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using AOT.PostProcess.BlackArea; using Gameplay.PostProcess.BlackArea; using Gameplay.Summon; using Gameplay.Unit; using PhxhSDK; using UnityEngine; namespace Gameplay.Bullet { using cfg.BuffCfg; using cfg.BulletCfg; using Character; using Framework; using Buff; using Skill; using Area; using Common; using cfg.SkillCfg; public class BulletManager { private static BulletManager _instance; public static BulletManager instance { get { if (_instance == null) { DebugUtil.LogError("Bullet尚未初始化,请先初始化"); return null; } return _instance; } } public static BulletManager CreateInstance() { if (_instance != null) { DebugUtil.LogError("请勿重复创建BulletManager"); return _instance; } _instance = new BulletManager(); return _instance; } public GameObject rootObj; private readonly List _bullets; private readonly List _readyBullets; private readonly Dictionary _loadCount; private BulletManager() { _bullets = new List(); _readyBullets = new List(); _loadCount = new Dictionary(); } public void Init() { rootObj = new GameObject("BulletManager"); } public void RecordLoadCount(string path) { if (_loadCount.ContainsKey(path)) { _loadCount[path]++; } else { _loadCount.Add(path, 1); } } public void Dispose() { // 进行资源清理 foreach (var kv in _loadCount) { var path = kv.Key; var count = kv.Value; for (var i = 0; i < count; ++i) { AssetManager.Instance.Unload(path); } } _bullets.Clear(); _readyBullets.Clear(); _loadCount.Clear(); rootObj.Destroy(); _instance = null; } public void LogicUpdate(float dt) { for (var i = 0; i < _readyBullets.Count; ++i) { var bullet = _readyBullets[i]; bullet.Init(); } _bullets.AddRange(_readyBullets); _readyBullets.Clear(); for (var i = 0; i < _bullets.Count; ++i) { var bullet = _bullets[i]; // 技能特殊暂停 if (SkillManager.instance.needSkillPaused && bullet.sender != SkillManager.instance.inSkillingUnit) { continue; } bullet.LogicUpdate(dt); if (bullet.needRemove) { _bullets.RemoveAt(i); i--; } } } /// /// 普通攻击走特殊处理 /// /// /// public void DoNormalShoot(GameUnit sender, GameUnit receiver) { // _ = AudioManager.Instance.PlayAudio(1001, sender.transData.pos); // 理论上可以走立马销毁的子弹逻辑,但是这里处理成直接addbuff,减少性能消耗 // 造成伤害 var normalDamageBuff = BuffManager.instance.CreateBuffById(sender, InnerBuffID.NORMAL_DAMAGE); BuffManager.instance.AddBuff(receiver, normalDamageBuff); // 打击士气 var moraleDamageBuff = BuffManager.instance.CreateBuffById(sender, InnerBuffID.MORALE_DAMAGE); BuffManager.instance.AddBuff(receiver, moraleDamageBuff); } public ViewBullet EmitBullet(int bulletId, GameUnit targetUnit, GameUnit sender) { var bulletConfig = GetConfigById(bulletId); if (bulletConfig == null) { DebugUtil.LogError("不存在的子弹配置:{0}", bulletId); return null; } ViewBullet result = null; switch (bulletConfig.BulletType) { case EBulletType.DIRECT_DAMAGE: // 直接造成伤害 AddBuffs2Unit(targetUnit, sender, bulletConfig); break; case EBulletType.POS_LOCK: // 锁地板 result = _EmitLockPosBullet(targetUnit.transData.cellIndex, sender, bulletConfig); break; case EBulletType.UNIT_LOCK: // 锁单位 result = _EmitLockUnitBullet(targetUnit, sender, bulletConfig); break; default: DebugUtil.LogError("暂未实现的子弹类型:{0}", bulletConfig.BulletType); break; } if (result != null) { _readyBullets.Add(result); } return result; } public ViewBullet EmitBulletFromSummon(int bulletId, int cellIndex, BaseSummon summon) { return EmitBullet(bulletId, cellIndex, summon.creator); } public ViewBullet EmitBulletFromSummon(int bulletId, GameUnit target, BaseSummon summon) { return EmitBullet(bulletId, target, summon.creator); } public ViewBullet EmitBullet(int bulletId, int cellIndex, GameUnit sender) { var bulletConfig = GetConfigById(bulletId); if (bulletConfig == null) { DebugUtil.LogError("不存在的子弹配置:{0}", bulletId); return null; } ViewBullet result = null; switch (bulletConfig.BulletType) { case EBulletType.DIRECT_DAMAGE: // 直接造成伤害 AddBuffs2CellIndex(cellIndex, sender, bulletConfig); break; case EBulletType.POS_LOCK: // 锁地板 result = _EmitLockPosBullet(cellIndex, sender, bulletConfig); break; case EBulletType.UNIT_LOCK: // 锁单位 result = _EmitLockUnitBullet(cellIndex, sender, bulletConfig); break; default: DebugUtil.LogError("暂未实现的子弹类型:{0}", bulletConfig.BulletType); break; } if (result != null) { _readyBullets.Add(result); } return result; } private ViewBullet _EmitLockUnitBullet(GameUnit targetUnit, GameUnit sender, DataBullet bulletConfig) { var bullet = new ViewBullet(bulletConfig, sender); if (!_CheckBulletFilter(sender, targetUnit, bulletConfig)) { bullet.LockPos(targetUnit.transData.cellIndex); return bullet; } bullet.LockUnit(targetUnit); return bullet; } private ViewBullet _EmitLockUnitBullet(int targetCellIndex, GameUnit sender, DataBullet bulletConfig) { var bullet = new ViewBullet(bulletConfig, sender); var units = AreaManager.instance.GetUnitsByCellIndex(targetCellIndex); var isLocked = false; for (var i = 0; i < units.Count; ++i) { var unit = units[i]; if (!_CheckBulletFilter(sender, unit, bulletConfig)) { continue; } bullet.LockUnit(unit); isLocked = true; break; } if (!isLocked) { // 如果没有目标,锁地板 DebugUtil.LogError("目标错误.保护处理,锁定当前地板"); bullet.LockPos(targetCellIndex); } return bullet; } public void PreSelectUnits(int cellIndex, int bulletId, GameUnit sender, List selectUnits) { var bulletConfig = GetConfigById(bulletId); if (bulletConfig == null) return; var units = AreaManager.instance.GetUnitsByCellIndex(cellIndex); for (var i = 0; i < units.Count; ++i) { var unit = units[i]; if (_CheckBulletFilter(sender, unit, bulletConfig)) { selectUnits.Add(unit); } } } private ViewBullet _EmitLockPosBullet(int targetCellIndex, GameUnit creator, DataBullet bulletConfig) { var bullet = new ViewBullet(bulletConfig, creator); bullet.LockPos(targetCellIndex); return bullet; } public void AddBuffs2Unit(GameUnit unit, GameUnit creator, DataBullet bulletConfig) { var sender = creator; if (!_CheckBulletFilter(sender, unit, bulletConfig)) { return; } _CreateNoLineBullet(bulletConfig, creator, unit); if (bulletConfig.LightDuring > 0) { var cellIndex = unit.transData.cellIndex; BlackAreaManager.instance.LightUpCell(cellIndex, bulletConfig.LightDuring); } } public void AddBuffs2CellIndex(int targetCellIndex, GameUnit creator, DataBullet bulletConfig) { var areaId = bulletConfig.AreaId; if (areaId == -1) { // 做全局处理 var units = GameUnitManager.instance.infightUnits.unitList; for (var i = 0; i < units.Count; ++i) { var unit = units[i]; AddBuffs2Unit(unit, creator, bulletConfig); } } else { var cellIndexs = AreaManager.instance.GetCellIndexs(targetCellIndex, areaId); for (var i = 0; i < cellIndexs.Count; ++i) { var cellIndex = cellIndexs[i]; // 根据filterType 和 cellIndex进行处理 var units = AreaManager.instance.GetUnitsByCellIndex(cellIndex); for (var j = 0; j < units.Count; ++j) { var unit = units[j]; AddBuffs2Unit(unit, creator, bulletConfig); } } } } private bool _CheckBulletFilter(GameUnit sender, GameUnit beHitter, DataBullet bulletConfig) { var onlyCharacterCheck = _CheckOnlyCharacter(beHitter, bulletConfig); if (!onlyCharacterCheck) { return false; } var troopCheck = _CheckTroopSide(sender, beHitter, bulletConfig.FilterType); if (!troopCheck) { return false; } var jobCheck = _CheckJobSide(beHitter, bulletConfig); if (!jobCheck) { return false; } var pretentCheck = _CheckPretentAvaliable(beHitter, bulletConfig); if (!pretentCheck) { return false; } var moraleCheck = _CheckMoraleState(beHitter, bulletConfig); if (!moraleCheck) { return false; } var buffGroupCheck = _CheckHasBuffGroup(beHitter, bulletConfig); if (!buffGroupCheck) { return false; } return true; } private bool _CheckPretentAvaliable(GameUnit beHitter, DataBullet bulletConfig) { if (bulletConfig.CanUseOnPretent) { return true; } if (beHitter.statusData.isPretend) { return false; } return true; } private bool _CheckMoraleState(GameUnit beHitter, DataBullet bulletConfig) { if (bulletConfig.MoraleFilter.Count == 0) { return true; } var behitCharacter = beHitter as Character; if (behitCharacter == null) { return false; } var moraleState = behitCharacter.runtimeData.moraleState; if (bulletConfig.MoraleFilter.Contains(moraleState)) { return true; } return false; } private bool _CheckHasBuffGroup(GameUnit beHitter, DataBullet bulletConfig) { if (bulletConfig.ExistBuffGroupIdFilter.Count == 0) { return true; } var buffManager = beHitter.buffManager; if (buffManager == null) { return false; } for (var i = 0; i < bulletConfig.ExistBuffGroupIdFilter.Count; ++i) { var buffGroupId = bulletConfig.ExistBuffGroupIdFilter[i]; if (buffManager.HasBuffGroup(buffGroupId)) { return true; } } return false; } private bool _CheckOnlyCharacter(GameUnit beHitter, DataBullet bulletConfig) { var require = bulletConfig.OnlyCharacter; if (!require) { return true; } var behitCharacter = beHitter as Character; if (behitCharacter == null) { return false; } return true; } private bool _CheckJobSide(GameUnit beHitter, DataBullet bulletConfig) { if (bulletConfig.JobFilters == null || bulletConfig.JobFilters.Count == 0) { return true; } // 只针对character var behitCharacter = beHitter as Character; if (behitCharacter == null) { return false; } var behitJob = behitCharacter.runtimeData.configData.job; if (bulletConfig.JobFilters.Contains(behitJob)) { return true; } return false; } private bool _CheckTroopSide(GameUnit sender, GameUnit beHitter, ETargetType filterType) { switch (filterType) { case ETargetType.SelfSide: if (sender.commonData.troopId == beHitter.commonData.troopId) { return true; } return false; case ETargetType.EnemySide: if (sender.commonData.troopId != beHitter.commonData.troopId) { return true; } return false; case ETargetType.Self: if (sender == beHitter) { return true; } return false; default: DebugUtil.LogError("_CheckBulletFilter 暂未实现的filterType:{0}", filterType); return false; } } private void _CreateNoLineBullet(DataBullet bulletConfig, GameUnit creator, GameUnit beHitter) { var buffIdList = bulletConfig.BuffList; for (var i = 0; i < buffIdList.Count; ++i) { var buffId = buffIdList[i]; var addBuff = BuffManager.instance.CreateBuffById(creator, buffId); if (addBuff == null) { continue; } BuffManager.instance.AddBuff(beHitter, addBuff); } } public DataBullet GetConfigById(int id) { return TableManager.Instance.Tables.BulletConfig.Get(id); } } }