562 lines
17 KiB
C#
562 lines
17 KiB
C#
using System.Collections.Generic;
|
||
using cfg.BuffCfg;
|
||
using Framework;
|
||
using Gameplay.Area;
|
||
using Gameplay.Unit;
|
||
|
||
namespace Gameplay.Buff
|
||
{
|
||
public class UnitBuffManager
|
||
{
|
||
private const int EXPECTED_MAX_BUFFS = 10; // 预期每个单位最多携带的buff数量
|
||
private const int EXPECTED_MAX_GROUPS = 5; // 预期每个单位最多的buff分组数量
|
||
|
||
public readonly GameUnit owner;
|
||
|
||
public readonly List<BaseBuff> totalBuffList;
|
||
private readonly Dictionary<int, BaseBuff> _groupMap;
|
||
private readonly List<BaseBuff> _needRemoveList;
|
||
|
||
public List<int> avoidBuffIds;
|
||
|
||
/// <summary>
|
||
/// 伤害转移buff
|
||
/// </summary>
|
||
public BuffDamageRedirect damageRedirectBuff
|
||
{
|
||
get;
|
||
set;
|
||
}
|
||
|
||
public UnitBuffManager(GameUnit owner)
|
||
{
|
||
this.owner = owner;
|
||
totalBuffList = new List<BaseBuff>(EXPECTED_MAX_BUFFS);
|
||
_groupMap = new Dictionary<int, BaseBuff>(EXPECTED_MAX_GROUPS);
|
||
_needRemoveList = new List<BaseBuff>(EXPECTED_MAX_BUFFS);
|
||
avoidBuffIds = new List<int>(EXPECTED_MAX_BUFFS);
|
||
}
|
||
|
||
public bool HasBuffGroup(int groupId)
|
||
{
|
||
return _groupMap.ContainsKey(groupId);
|
||
}
|
||
|
||
public void AddBuffByIds(List<int> buffIds)
|
||
{
|
||
for (var i = 0; i < buffIds.Count; ++i)
|
||
{
|
||
var buffId = buffIds[i];
|
||
AddBuffById(buffId);
|
||
}
|
||
}
|
||
|
||
public void AddBuffById(int buffId)
|
||
{
|
||
var addBuff = BuffManager.instance.CreateBuffById(owner, buffId);
|
||
AddBuff(addBuff);
|
||
}
|
||
|
||
public void AddBuffById(int buffId, GameUnit creator)
|
||
{
|
||
var addBuff = BuffManager.instance.CreateBuffById(creator, buffId);
|
||
AddBuff(addBuff);
|
||
}
|
||
|
||
public void RemoveBuffByIds(List<int> buffIds, bool imdRemove = false)
|
||
{
|
||
for (var i = 0; i < buffIds.Count; ++i)
|
||
{
|
||
var buffId = buffIds[i];
|
||
RemoveBuffById(buffId, imdRemove);
|
||
}
|
||
}
|
||
|
||
public bool CheckHasBuffId(int buffId)
|
||
{
|
||
for (int i = 0; i < totalBuffList.Count; i++)
|
||
{
|
||
var buff = totalBuffList[i];
|
||
if (buff.configData.ID == buffId)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public bool CheckHasBuffType(EBuffType buffType)
|
||
{
|
||
for (var i = 0; i < totalBuffList.Count; ++i)
|
||
{
|
||
var buff = totalBuffList[i];
|
||
if (buff.configData.BuffType == buffType)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public bool CheckHasBuffTypeExcept(EBuffType buffType, BaseBuff exceptBuff)
|
||
{
|
||
for (var i = 0; i < totalBuffList.Count; ++i)
|
||
{
|
||
var buff = totalBuffList[i];
|
||
if (buff == exceptBuff)
|
||
{
|
||
continue;
|
||
}
|
||
if (buff.configData.BuffType == buffType)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public List<BaseBuff> GetBuffsByType(EBuffType buffType)
|
||
{
|
||
var findList = new List<BaseBuff>();
|
||
for (var i = 0; i < totalBuffList.Count; ++i)
|
||
{
|
||
var buff = totalBuffList[i];
|
||
if (buff.configData.BuffType == buffType)
|
||
{
|
||
findList.Add(buff);
|
||
}
|
||
}
|
||
return findList;
|
||
}
|
||
|
||
public BaseBuff GetBuffByType(EBuffType buffType)
|
||
{
|
||
for (var i = 0; i < totalBuffList.Count; ++i)
|
||
{
|
||
var buff = totalBuffList[i];
|
||
if (buff.configData.BuffType == buffType)
|
||
{
|
||
return buff;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
public void RemoveBuff(BaseBuff buff, bool imdRemove = false)
|
||
{
|
||
var isInList = totalBuffList.Contains(buff);
|
||
if (!isInList)
|
||
{
|
||
return;
|
||
}
|
||
AddNeedRemoveBuff(buff, imdRemove);
|
||
}
|
||
|
||
public void RemoveBuffById(int buffId, bool imdRemove = false)
|
||
{
|
||
var findBuff = totalBuffList.Find(buff => buff.configData.ID == buffId);
|
||
if (findBuff == null)
|
||
{
|
||
return;
|
||
}
|
||
AddNeedRemoveBuff(findBuff, imdRemove);
|
||
}
|
||
|
||
public void AddBuff(BaseBuff buff)
|
||
{
|
||
if (buff == null)
|
||
{
|
||
DebugUtil.LogError("buff为空");
|
||
return;
|
||
}
|
||
|
||
if (avoidBuffIds.Contains(buff.configData.ID))
|
||
{
|
||
// 需要把buff返回池
|
||
BuffManager.ReturnBuff(buff);
|
||
return;
|
||
}
|
||
|
||
if (buff.configData.BuffEffectType == EBuffEffectType.NegativeBuff)
|
||
{
|
||
// 负面buff
|
||
var randomValue = UnityEngine.Random.Range(0, 1f);
|
||
var ignoreRate = owner.fightData.ignoreDebuffRate;
|
||
if (randomValue < ignoreRate)
|
||
{
|
||
// 免疫
|
||
DebugUtil.Log("触发免疫debuff");
|
||
// 需要把buff返回池
|
||
BuffManager.ReturnBuff(buff);
|
||
return;
|
||
}
|
||
}
|
||
if (!buff.configData.CanTriggerOnDead && owner.statusData.isDead)
|
||
{
|
||
// 不可添加
|
||
// 需要把buff返回池
|
||
BuffManager.ReturnBuff(buff);
|
||
return;
|
||
}
|
||
|
||
var repeatType = buff.configData.RepeatType;
|
||
var noAdd = false;
|
||
switch (repeatType)
|
||
{
|
||
case EBuffRepeatType.None:
|
||
// 不做处理
|
||
break;
|
||
case EBuffRepeatType.Replace:
|
||
{
|
||
// 找到旧的,全部删除
|
||
if (_groupMap.TryGetValue(buff.configData.GroupId, out var oldBuff))
|
||
{
|
||
// 判断强度
|
||
if (oldBuff.configData.Level == buff.configData.Level)
|
||
{
|
||
noAdd = true;
|
||
// 刷新持续时间
|
||
oldBuff.RefreshDuring();
|
||
}
|
||
else if (oldBuff.configData.Level > buff.configData.Level)
|
||
{
|
||
// 新的buff强度不够,不添加
|
||
noAdd = true;
|
||
}
|
||
else
|
||
{
|
||
AddNeedRemoveBuff(oldBuff, true);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case EBuffRepeatType.RefreshTime:
|
||
{
|
||
// 找到旧的,刷新持续时间
|
||
if (_groupMap.TryGetValue(buff.configData.GroupId, out var oldBuff))
|
||
{
|
||
oldBuff.RefreshDuring();
|
||
noAdd = true;
|
||
}
|
||
}
|
||
break;
|
||
case EBuffRepeatType.Merge:
|
||
{
|
||
if (_groupMap.TryGetValue(buff.configData.GroupId, out var oldBuff))
|
||
{
|
||
AddNeedRemoveBuff(oldBuff);
|
||
var combineLevel = oldBuff.configData.Level + buff.configData.Level;
|
||
var searchBuffConfig = GroupBuffManager.instance.SearchBuff(buff.configData.GroupId, combineLevel);
|
||
if (searchBuffConfig == null)
|
||
{
|
||
DebugUtil.LogError("合并buff失败,找不到对应的buff配置");
|
||
noAdd = true;
|
||
}
|
||
else
|
||
{
|
||
// 替换新的buff
|
||
var newBuff = BuffManager.instance.CreateBuffByConfig(owner, searchBuffConfig);
|
||
// 需要把buff返回池
|
||
BuffManager.ReturnBuff(buff);
|
||
buff = newBuff;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
DebugUtil.LogError("暂未处理的repeatType:{0}", repeatType);
|
||
break;
|
||
}
|
||
|
||
if (noAdd)
|
||
{
|
||
// 需要把buff返回池
|
||
BuffManager.ReturnBuff(buff);
|
||
}
|
||
else
|
||
{
|
||
_AddBuff(buff);
|
||
}
|
||
}
|
||
|
||
public void TriggerOnAddDebuff()
|
||
{
|
||
_DebuffCountChanged();
|
||
}
|
||
|
||
public void TriggerOnRemoveDebuff()
|
||
{
|
||
_DebuffCountChanged();
|
||
}
|
||
|
||
private void _DebuffCountChanged()
|
||
{
|
||
var getBuff = GetBuffByType(EBuffType.DownScaleOnDebuff);
|
||
if (getBuff == null) return;
|
||
var buff = getBuff as BuffSetBeHitScaleOnDebuffChange;
|
||
if (buff == null)
|
||
{
|
||
DebugUtil.LogError("BuffSetBeHitScaleOnDebuffChange类型错误");
|
||
return;
|
||
}
|
||
var nowDebuffCount = GetDebuffCount();
|
||
var oldDebuffCount = buff.oldDebuffCount;
|
||
var oldChangeValue = buff.GetBeHitScale(oldDebuffCount);
|
||
owner.fightData.beDamageScale -= oldChangeValue;
|
||
var newChangeValue = buff.GetBeHitScale(nowDebuffCount);
|
||
owner.fightData.beDamageScale += newChangeValue;
|
||
buff.oldDebuffCount = nowDebuffCount;
|
||
}
|
||
|
||
public bool CheckHasAnyDebuff()
|
||
{
|
||
for (var i = 0; i < totalBuffList.Count; ++i)
|
||
{
|
||
var buff = totalBuffList[i];
|
||
if (buff.configData.BuffEffectType == EBuffEffectType.NegativeBuff)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public int GetDebuffCount()
|
||
{
|
||
var count = 0;
|
||
for (int i = 0; i < totalBuffList.Count; i++)
|
||
{
|
||
var buff = totalBuffList[i];
|
||
if (buff.configData.BuffEffectType == EBuffEffectType.NegativeBuff)
|
||
{
|
||
count++;
|
||
}
|
||
}
|
||
return count;
|
||
}
|
||
|
||
private void _AddBuff(BaseBuff buff)
|
||
{
|
||
buff.owner = owner;
|
||
|
||
// 优化:提前检查容量
|
||
if (totalBuffList.Count == totalBuffList.Capacity)
|
||
{
|
||
totalBuffList.Capacity *= 2;
|
||
}
|
||
|
||
// 这里会调用buff的OnInit方法
|
||
buff.Init();
|
||
buff.TriggerAdd();
|
||
totalBuffList.Add(buff);
|
||
|
||
if (buff.configData.GroupId != 0)
|
||
{
|
||
_groupMap[buff.configData.GroupId] = buff;
|
||
}
|
||
|
||
if (buff.configData.BuffEffectType == EBuffEffectType.NegativeBuff)
|
||
{
|
||
// 负面buff
|
||
owner.buffManager.TriggerOnAddDebuff();
|
||
}
|
||
}
|
||
|
||
private void _RemoveBuff(BaseBuff buff)
|
||
{
|
||
var index = totalBuffList.IndexOf(buff);
|
||
if (index < 0)
|
||
{
|
||
return;
|
||
}
|
||
buff.TriggerRemove();
|
||
totalBuffList.RemoveAt(index);
|
||
|
||
if (buff.configData.BuffEffectType == EBuffEffectType.NegativeBuff)
|
||
{
|
||
// 负面buff
|
||
owner.buffManager.TriggerOnRemoveDebuff();
|
||
}
|
||
|
||
BuffManager.ReturnBuff(buff);
|
||
|
||
if (buff.configData.GroupId != 0)
|
||
{
|
||
if (_groupMap.TryGetValue(buff.configData.GroupId, out var oldBuff) && oldBuff == buff)
|
||
{
|
||
// 移除
|
||
_groupMap.Remove(buff.configData.GroupId);
|
||
}
|
||
}
|
||
}
|
||
|
||
public void AddNeedRemoveBuff(BaseBuff buff, bool imdRemove = false)
|
||
{
|
||
if (imdRemove)
|
||
{
|
||
_RemoveBuff(buff);
|
||
return;
|
||
}
|
||
if (_needRemoveList.Contains(buff))
|
||
{
|
||
return;
|
||
}
|
||
_needRemoveList.Add(buff);
|
||
}
|
||
|
||
public void UpdateOnlyRemoveAdd()
|
||
{
|
||
var count = _needRemoveList.Count;
|
||
if (count > 0)
|
||
{
|
||
for (var i = 0; i < count; ++i)
|
||
{
|
||
var buff = _needRemoveList[i];
|
||
_RemoveBuff(buff);
|
||
}
|
||
_needRemoveList.Clear();
|
||
}
|
||
}
|
||
|
||
public void LogicUpdate(float dt)
|
||
{
|
||
var buffCount = totalBuffList.Count;
|
||
|
||
// 从后向前遍历,这样删除元素时不会影响到未处理的元素的索引
|
||
for (var i = buffCount - 1; i >= 0; i--)
|
||
{
|
||
if (i >= totalBuffList.Count) continue; // 安全检查
|
||
|
||
var buff = totalBuffList[i];
|
||
if (buff.needRemove)
|
||
{
|
||
_RemoveBuff(buff);
|
||
continue;
|
||
}
|
||
|
||
buff.LogicUpdate(dt);
|
||
|
||
if (buff.needRemove)
|
||
{
|
||
_RemoveBuff(buff);
|
||
}
|
||
}
|
||
|
||
// 处理待移除列表
|
||
var removeCount = _needRemoveList.Count;
|
||
if (removeCount > 0)
|
||
{
|
||
for (var i = 0; i < removeCount; ++i)
|
||
{
|
||
var buff = _needRemoveList[i];
|
||
_RemoveBuff(buff);
|
||
}
|
||
_needRemoveList.Clear();
|
||
}
|
||
}
|
||
|
||
public void TriggerPreReload()
|
||
{
|
||
_InnerTrigger(ETriggerType.ON_RELOAD);
|
||
}
|
||
|
||
public void TriggerAfterReload()
|
||
{
|
||
_InnerTrigger(ETriggerType.ON_AFTER_RELOAD);
|
||
}
|
||
|
||
public void TriggerNormalAttack()
|
||
{
|
||
_InnerTrigger(ETriggerType.ON_NORMAL_ATTACK);
|
||
}
|
||
|
||
public void TriggerEnterBattle()
|
||
{
|
||
_InnerTrigger(ETriggerType.ON_ENTER_BATTLE);
|
||
}
|
||
|
||
public void TriggerExitBattle()
|
||
{
|
||
_InnerTrigger(ETriggerType.ON_EXIT_BATTLE);
|
||
}
|
||
|
||
public void TriggerKillUnit(GameUnit unit)
|
||
{
|
||
_InnerTrigger(ETriggerType.ON_KILL_UNIT);
|
||
|
||
if (owner.debugShowInfo.cacheConfigId != 0)
|
||
{
|
||
EventManager.Instance.Send(EventManager.EventName.INFIGHT_AUDIO_KILL_ENEMY, owner.debugShowInfo.cacheConfigId);
|
||
}
|
||
|
||
if (unit.debugShowInfo.cacheConfigId != 0)
|
||
{
|
||
EventManager.Instance.Send(EventManager.EventName.INFIGHT_AUDIO_BE_ATTACK_AND_DEAD, unit.debugShowInfo.cacheConfigId);
|
||
}
|
||
}
|
||
|
||
public void TriggerCellIndexChange()
|
||
{
|
||
_InnerTrigger(ETriggerType.ON_CELLINDEX_CHANGE);
|
||
}
|
||
|
||
public void TriggerFriendRetreat(GameUnit friendUnit)
|
||
{
|
||
var getBuff = GetBuffByType(EBuffType.AddOnFriendRetreat);
|
||
if (getBuff == null) return;
|
||
var buff = getBuff as BuffAddBuffOnFriendRetreat;
|
||
if (buff == null)
|
||
{
|
||
DebugUtil.LogError("BuffAddBuffOnFriendRetreat类型错误");
|
||
return;
|
||
}
|
||
var checkRange = buff.checkRange;
|
||
var distance = AreaManager.instance.GetDistance(friendUnit.transData.cellIndex, owner.transData.cellIndex);
|
||
if (distance <= checkRange)
|
||
{
|
||
AddBuffByIds(buff.buffIds);
|
||
}
|
||
}
|
||
|
||
public void TriggerOnRetreat()
|
||
{
|
||
_InnerTrigger(ETriggerType.ON_RETREAT);
|
||
|
||
// 触发buff的特殊事件
|
||
var allUnits = GameUnitManager.instance.infightUnits.unitList;
|
||
for (int i = 0; i < allUnits.Count; i++)
|
||
{
|
||
var unit = allUnits[i];
|
||
if (unit == owner) continue;
|
||
if (unit.commonData.troopId == owner.commonData.troopId)
|
||
{
|
||
unit.buffManager.TriggerFriendRetreat(owner);
|
||
}
|
||
}
|
||
}
|
||
|
||
public void TriggerOnTakeDamage()
|
||
{
|
||
_InnerTrigger(ETriggerType.ON_TAKEDAMAGE);
|
||
|
||
// 触发buff的特殊事件
|
||
for (int i = 0; i < totalBuffList.Count; i++)
|
||
{
|
||
var buff = totalBuffList[i];
|
||
if (buff.needRemove) continue;
|
||
buff.TriggerOnTakeDamage();
|
||
}
|
||
}
|
||
|
||
private void _InnerTrigger(ETriggerType triggerType)
|
||
{
|
||
for (int i = 0; i < totalBuffList.Count; i++)
|
||
{
|
||
var buff = totalBuffList[i];
|
||
if (buff.needRemove) continue;
|
||
buff.SpecialTrigger(triggerType);
|
||
}
|
||
}
|
||
}
|
||
}
|