CTT/Server/Hotfix/Game/SkillSystem/NewSkill/System/ModifierContainerComponentS...

680 lines
31 KiB
C#

using Cal;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ET
{
public class ModifierContainerComponentUpdateSystem : UpdateSystem<ModifierContainerComponent>
{
public override void Update(ModifierContainerComponent self)
{
long now = TimeHelper.ClientNow();
using ListComponent<ModifierLogic> needModifedListComponent = ListComponent<ModifierLogic>.Create();
using ListComponent<ModifierId> _needModifedListComponent = ListComponent<ModifierId>.Create();
using ListComponent<(SkillOptionBase, ISkillSender)> optionListComponent = ListComponent<(SkillOptionBase, ISkillSender)>.Create();
List<ModifierLogic> needModifedList = needModifedListComponent.List;
List<ModifierId> _needModifedList = _needModifedListComponent.List;
List<(SkillOptionBase, ISkillSender)> optionList = optionListComponent.List;
foreach (KeyValuePair<ModifierId, long> kv in self.timeDic)
{
if (now < kv.Value) continue;
if (!self.modifierDic.TryGetValue(kv.Key, out ModifierLogic modifierLogic))
{
_needModifedList.Add(kv.Key);
Log.Error($"{self.GetParent<Unit>()?.GetComponent<UnitSkillComponent>()?.GetLearnedSkills().FirstOrDefault()?.Id} this skill {modifierLogic?.skillLogic.skillId}");
continue;
}
if (!modifierLogic)
{
_needModifedList.Add(kv.Key);
Log.Error($"modifierLogic == null id= {self.Parent.Id} where {modifierLogic.IsDisposed}");
Log.Error($"{self.GetParent<Unit>()?.GetComponent<UnitSkillComponent>()?.GetLearnedSkills().FirstOrDefault()?.Id} this skill {modifierLogic?.skillLogic?.skillId}");
continue;
}
if (modifierLogic.modifierConfig == null)
{
Log.Error($"modifierLogic.modifierConfig == null where id= {self.Parent.Id} modifierId = {kv.Key}");
Log.Error($"{self.GetParent<Unit>()?.GetComponent<UnitSkillComponent>()?.GetLearnedSkills().FirstOrDefault()?.Id} this skill {modifierLogic?.skillLogic.skillId}");
continue;
}
needModifedList.Add(modifierLogic);
Dictionary<ModifierEventCondition, SkillOptionBase[]> dic = modifierLogic.modifierConfig?.modifierEventDic;
if (dic == null)
continue;
if (!dic.TryGetValue(ModifierEventCondition., out SkillOptionBase[] list))
{
continue;
}
foreach (SkillOptionBase item in list)
{
optionList.Add((item, new ModifierSkillSender
{
caster = modifierLogic.skillLogic.owner,
skillLogic = modifierLogic.skillLogic,
modifierLogic = modifierLogic,
target = self.GetParent<Unit>()
}));
}
}
foreach (ModifierId item in _needModifedList)
{
self.timeDic.Remove(item);
}
foreach (ModifierLogic logic in needModifedList)
{
self.timeDic[logic.modifierId] = now + logic.interval;
}
foreach ((SkillOptionBase option, ISkillSender skillSender) in optionList)
{
SkillOptionLogicBase skillOptionLogicBase = SkillOptionFactory.AcquireSkillOptionLogic(option);
skillSender.skillLogic.skillOptionLogics.Add(skillOptionLogicBase);
skillOptionLogicBase.HandleEvent(skillSender);
}
}
}
public class ModifierContainerComponentDestroySystem : DestroySystem<ModifierContainerComponent>
{
public override void Destroy(ModifierContainerComponent self)
{
foreach (ModifierLogic item in self.modifierDic.Values)
{
try
{
self.RemoveModifier(item);
}
catch (Exception e)
{
Log.Error(e);
}
}
self.modifierDic.Clear();
self.modifierStateDic.Clear();
self.timeDic.Clear();
self.modifierOptionByConditionDic.Clear();
}
}
public static class ModifierContainerComponentSystem
{
public static void ApplyModifier(this ModifierContainerComponent self, Unit owner, SkillLogic skillLogic, ModifierId modifierId)
{
if (!skillLogic.skillLogicConfig.modifierDic.TryGetValue(modifierId, out ModifierConfig modifierConfig))
{
return;
}
if (!modifierConfig.levelList.Contains(skillLogic.skillLevel))
return;
Unit target = self.GetParent<Unit>();
if (!SkillHelper.GetParam(modifierConfig.continueTime, skillLogic.skillConfigId, out float continueTime))
{
continueTime = 0;
}
if (!self.modifierDic.TryGetValue(modifierId, out ModifierLogic logic) || logic.IsDisposed)
{
logic = EntityFactory.CreateWithParent<ModifierLogic>(owner.DomainScene());
logic.skillLogic = skillLogic;
logic.modifierConfig = modifierConfig;
logic.continueTime = (int)(continueTime * 1000);
AddNewModifier(self,owner, target, logic);
}
else
{
AddExistModifier(self, owner, target, logic);
}
}
private static void AddExistModifier(ModifierContainerComponent self, Unit owner, Unit target, ModifierLogic logic)
{
ModifierConfig modifierConfig = logic.modifierConfig;
ModifierAttribute modifierAttribute = modifierConfig.attribute;
//!不改变属性(时间)
if (modifierAttribute == ModifierAttribute. ||
!IgnoreInvalid(self, modifierAttribute))
return;
//!可叠加的情况
if (modifierAttribute.HasFlag(ModifierAttribute.))
{
int maxOverlay = SkillHotfixHelper.GetOverlableBuffMaxLayer(modifierConfig.overlayType);
if (!SkillHelper.GetParam(modifierConfig.perOverlay, logic.skillLogic.skillConfigId, out float perOverlay))
{
perOverlay = 1;
}
logic.overlay += (int)perOverlay;
logic.overlay = Math.Clamp(logic.overlay, 1, maxOverlay);
}
//!可刷新的情况
if (modifierAttribute.HasFlag(ModifierAttribute.))
{
if (logic.continueTime != -1 * 1000)
{
long now = TimeHelper.ClientNow();
logic.cancellationToken?.Cancel();
logic.cancellationToken = new ETCancellationToken();
logic.leastTime = now + logic.continueTime;
self.SetModifierTimer(logic).Coroutine();
}
}
}
private static void AddNewModifier(ModifierContainerComponent self, Unit owner, Unit target, ModifierLogic logic)
{
//!特殊处理
if (logic.continueTime == 0)
{
DealNoContinuteModifier(self, owner, target, logic);
return;
}
ModifierConfig modifierConfig = logic.modifierConfig;
if (!CheckModifierTag(self, modifierConfig.tag)) return;
OnBeforeCreateEvent(owner, target, logic);
AddToDic(self, logic);
OnAfterCreateEvent(owner, target, logic);
if (modifierConfig.valueK != ModifierValueType.)
self.ChangeNumeric(target, logic, ValueChangeType.Plus);
if (modifierConfig.stateK != ModifierStateType.)
self.ChangeState(owner, target, logic, ValueChangeType.Plus);
long now = TimeHelper.ClientNow();
DealBuffIcon(owner, target, logic);
DealEffect(owner, target, logic);
SetThinkerInterval(self, now, logic);
//非被动都需要定时移除
if (logic.continueTime != -1 * 1000)
{
logic.cancellationToken?.Cancel();
logic.cancellationToken = new ETCancellationToken();
logic.leastTime = logic.continueTime + now;
self.SetModifierTimer(logic).Coroutine();
}
}
private static bool CheckModifierTag(ModifierContainerComponent self, ModifierTag tag)
{
if (tag == ModifierTag.) return true;
foreach (ModifierLogic _logic in self.modifierDic.Values)
{
try
{
if (_logic.modifierConfig.immuneTag == tag)
return false;
foreach (ModifierTag immuneTag in _logic.modifierConfig.immuneTagArr)
{
if (immuneTag == tag)
return false;
}
}
catch (Exception e)
{
Log.Error(e);
return false;
}
}
return true;
}
/// <summary>
/// 处理瞬时效果
/// </summary>
/// <param name="self"></param>
/// <param name="owner"></param>
/// <param name="target"></param>
/// <param name="logic"></param>
private static void DealNoContinuteModifier(this ModifierContainerComponent self, Unit owner, Unit target, ModifierLogic logic)
{
ModifierConfig modifierConfig = logic.modifierConfig;
if (!IgnoreInvalid(self, modifierConfig.attribute))
return;
logic.overlay += 1;
OnBeforeCreateEvent(owner, target, logic);
DealEffect(owner, target, logic);
OnAfterCreateEvent(owner, target, logic);
//!改变状态
SkillLogic modifierLogicSkillLogic = logic.skillLogic;
modifierLogicSkillLogic.SetMultipleDamage(modifierLogicSkillLogic.GetMultipleDamage() - logic.multiDamageX10000);
modifierLogicSkillLogic.SetPlayAmount(modifierLogicSkillLogic.GetPlayAmount() - logic.playAmount);
logic.Dispose();
return;
}
private static void AddToDic(this ModifierContainerComponent self, ModifierLogic logic)
{
ModifierConfig modifierConfig = logic.modifierConfig;
float perOverlay = 1;
if (modifierConfig.attribute.HasFlag(ModifierAttribute.))
{
if (!SkillHelper.GetParam(modifierConfig.perOverlay, logic.skillLogic.skillConfigId, out perOverlay))
{
Log.Error($"perOnerlay is invalid where modifierId = {logic.modifierId}");
perOverlay = 1;
}
}
logic.overlay += (int)perOverlay;
if (!self.modifierDic.TryAdd(logic.modifierId, logic))
{
Log.Error($"dic add the modifier failly:{logic.modifierId} when apply");
}
else
{
Dictionary<ModifierEventCondition, SkillOptionBase[]> dic = logic.modifierConfig.modifierEventDic;
if (dic != null)
foreach (KeyValuePair<ModifierEventCondition, SkillOptionBase[]> kv in dic)
{
self.modifierOptionByConditionDic.Add(kv.Key, logic);
}
}
}
private static bool IgnoreInvalid(this ModifierContainerComponent self, ModifierAttribute modifierAttribute)
{
if (modifierAttribute.HasFlag(ModifierAttribute.))
return self.HasState(ModifierStateType.);
return true;
}
private static void DealEffect(Entity owner, Entity target, ModifierLogic logic)
{
ModifierConfig modifierConfig = logic.modifierConfig;
int effectId = modifierConfig.effectId;
if (effectId != 0)
{
target.GetComponent<BrocastComponent>().BrocastInterval(new M2C_PlaySkillEffect
{
UnitId = owner.Id,
TargetId = target.Id,
EffectId = effectId,
EffectPos = (int)modifierConfig.effectAttachType,
EffectTargetType = (int)EffectTargetType.Target,
Time = logic.continueTime,
});
}
}
private static void DealBuffIcon(Unit owner, Unit target, ModifierLogic logic)
{
ModifierConfig modifierConfig = logic.modifierConfig;
string iconId = modifierConfig.iconId;
if (string.IsNullOrWhiteSpace(iconId) || iconId.Equals("0"))
{
return;
}
string iconDesc = modifierConfig.iconDesc;
BuffBrocastComponent.Instance.AddChangeState(0, new EventType.BuffStateRet
{
Id = logic.Id,
targetUnit = target,
type = M2C_BattleChangeState.ChangeType.Add,
IconDesc = iconDesc,
IconId = iconId,
isBuff = logic.modifierConfig.buffType == BuffType.Buff,
time = logic.continueTime,
});
}
private static void OnBeforeCreateEvent(Unit owner, Unit target, ModifierLogic logic)
{
logic.HandleEvent(ModifierEventCondition.modifier, new ModifierSkillSender
{
caster = owner,
target = target,
skillLogic = logic.skillLogic,
modifierLogic = logic
});
}
private static void OnAfterCreateEvent(Unit owner, Unit target, ModifierLogic logic)
{
logic.HandleEvent(ModifierEventCondition.modifier, new ModifierSkillSender
{
caster = owner,
target = target,
skillLogic = logic.skillLogic,
modifierLogic = logic
});
}
private static void SetThinkerInterval(ModifierContainerComponent self, long now, ModifierLogic logic)
{
ModifierConfig modifierConfig = logic.modifierConfig;
switch (modifierConfig.thinkerType)
{
case ThinkerType.:
return;
case ThinkerType. when SkillHelper.GetParam(modifierConfig.thinkInterval, logic.skillLogic.skillConfigId, out float inteval):
{
if (inteval <= 0)
return;
logic.interval = (int)(inteval * 1000);
break;
}
default:
logic.interval = SkillHotfixHelper.GetThinkerInterval(thinkerType: modifierConfig.thinkerType);
break;
}
self.timeDic.Add(logic.modifierId, now + logic.interval);
}
public static void AddState(this ModifierContainerComponent self, ModifierStateType stateType, StateStateType stateStateType = StateStateType.)
{
self.modifierStateDic.TryAdd(stateType, stateStateType);
}
public static bool HasState(this ModifierContainerComponent self, ModifierStateType stateType)
{
if (self.modifierStateDic.TryGetValue(stateType, out StateStateType stateStateType))
return stateStateType == StateStateType.;
return false;
}
public static void ClearState(this ModifierContainerComponent self)
{
if (self.modifierStateDic.Count > 0)
{
if (AppConfig.inst.isTest)
Log.Error($"{self.Id} 清理 {self.modifierStateDic.Keys.ToCustomString()}");
}
self.modifierStateDic.Clear();
}
public static ModifierLogic GetModifierLogic(this ModifierContainerComponent self, ModifierId modifierId)
{
self.modifierDic.TryGetValue(modifierId, out ModifierLogic modifierLogic);
return modifierLogic;
}
public static (SkillOptionBase[], ModifierLogic) GetSkillOptionBaseArr(this ModifierContainerComponent self, ModifierEventCondition modifierEventCondition)
{
HashSet<ModifierLogic> set = self.modifierOptionByConditionDic[modifierEventCondition];
if (set.Count > 0)
foreach (ModifierLogic modifierLogic in set)
{
if (modifierLogic.IsDisposed) continue;
Dictionary<ModifierEventCondition, SkillOptionBase[]> dic = modifierLogic.modifierConfig.modifierEventDic;
if (dic != null)
if (dic.TryGetValue(modifierEventCondition, out SkillOptionBase[] list))
return (list, modifierLogic);
}
return (null, null);
}
/// <summary>
/// 设置定时器,定时销毁
/// </summary>
/// <param name="self"></param>
/// <param name="modifierLogic"></param>
private static async ETVoid SetModifierTimer(this ModifierContainerComponent self, ModifierLogic modifierLogic)
{
bool ret = await TimerComponent.Instance.WaitTillAsync(modifierLogic.leastTime, modifierLogic.cancellationToken);
if (ret)
self.RemoveModifier(modifierLogic);
}
private static void ChangeNumeric(this ModifierContainerComponent self, Unit target, ModifierLogic logic, ValueChangeType valueChangeType)
{
try
{
ModifierValueType key = logic.modifierConfig.valueK;
if (key == ModifierValueType.) return;
SkillParam configValue = logic.modifierConfig.valueV;
NumericComponent numTarget = target.GetComponent<NumericComponent>();
float sign = valueChangeType switch
{
ValueChangeType.Zero => 0,
ValueChangeType.Plus => 1,
ValueChangeType.Minus => -1,
_ => throw new Exception("类型错误"),
};
if (!SkillHelper.GetParam(configValue, logic.skillLogic.skillConfigId, out float value))
{
Log.Error($"cann't get the value where modifier = {logic.modifierId} type = {key}");
return;
}
if (sign == -1)
{
sign *= logic.skillLogic.dataOldX10000;
}
else
{
sign *= logic.skillLogic.dataX10000;
}
float finalValue = value * sign * 0.01f;
if (AppConfig.inst.showBattleDamageInfo)
Log.Debug($"{valueChangeType}了数值属性:{key} 改变量:{finalValue:p2}");
switch (key)
{
case ModifierValueType.:
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.MaxHpAdd, numTarget.Get(NumericType.MaxHpBase) * finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.MaxMpAdd, numTarget.Get(NumericType.MaxMpBase) * finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.PhyAtkAdd, numTarget.Get(NumericType.PhyAtkBase) * finalValue);
numTarget.AddSet(NumericType.SpiAtkAdd, numTarget.Get(NumericType.SpiAtkBase) * finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.PhyAtkAdd, numTarget.Get(NumericType.PhyAtkBase) * finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.SpiAtkAdd, numTarget.Get(NumericType.SpiAtkBase) * finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.PhyDefAdd, numTarget.Get(NumericType.PhyDefBase) * finalValue);
numTarget.AddSet(NumericType.SpiDefAdd, numTarget.Get(NumericType.SpiDefBase) * finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.PhyDefAdd, numTarget.Get(NumericType.PhyDefBase) * finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.SpiDefAdd, numTarget.Get(NumericType.SpiDefBase) * finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.PcrirAdd, finalValue);
numTarget.AddSet(NumericType.McrirAdd, finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.PcrirAdd, finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.McrirAdd, finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.PcriAdd, finalValue);
numTarget.AddSet(NumericType.McriAdd, finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.PcriAdd, finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.McriAdd, finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.RpcrirAdd, finalValue);
numTarget.AddSet(NumericType.RmcrirAdd, finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.RpcrirAdd, finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.RmcrirAdd, finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.RpcriAdd, finalValue);
numTarget.AddSet(NumericType.RmcriAdd, finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.RpcriAdd, finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.RmcriAdd, finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.NphyiAdd, finalValue);
numTarget.AddSet(NumericType.NmeniAdd, finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.NphyiAdd, finalValue);
break;
case ModifierValueType._:
numTarget.AddSet(NumericType.NmeniAdd, finalValue);
break;
case ModifierValueType.:
numTarget.AddSet(NumericType.DvoAdd, finalValue);
break;
case ModifierValueType.:
numTarget.AddSet(NumericType.SpdAdd, numTarget.Get(NumericType.SpdBase) * finalValue);
break;
case ModifierValueType.:
numTarget.AddSet(NumericType.HitAdd, numTarget.Get(NumericType.HitBase) * finalValue);
break;
case ModifierValueType.:
numTarget.AddSet(NumericType.ResAdd, numTarget.Get(NumericType.ResBase) * finalValue);
break;
default:
break;
}
}
catch (Exception e)
{
Log.Error(e);
}
}
private static void ChangeState(this ModifierContainerComponent self, Unit owner, Unit target, ModifierLogic logic, ValueChangeType valueChangeType)
{
try
{
ModifierConfig config = logic.modifierConfig;
if (config.stateK == ModifierStateType.) return;
if (AppConfig.inst.showBattleDamageInfo)
Log.Debug($"{valueChangeType}了状态属性:{config.stateK} ");
if (valueChangeType == ValueChangeType.Plus)
{
if (!self.modifierStateDic.ContainsKey(config.stateK))
self.modifierStateDic.Add(config.stateK, config.stateV);
}
else
if (valueChangeType == ValueChangeType.Minus)
self.modifierStateDic.Remove(config.stateK);
}
catch (Exception e)
{
Log.Error(e);
}
}
public static void RemoveModifier(this ModifierContainerComponent self, ISkillSender skillSender)
{
try
{
ModifierLogic modifierLogic = ((ModifierSkillSender)skillSender).modifierLogic;
if (modifierLogic == null)
Log.Error($"modifier is null where id = {modifierLogic.modifierId}");
self.RemoveModifier(modifierLogic);
}
catch (Exception e)
{
Log.Error(e);
}
}
public static void RemoveModifier(this ModifierContainerComponent self, ModifierLogic modifierLogic)
{
try
{
if (!modifierLogic)
{
Log.Error($"logic is invalid ,isnull? {modifierLogic==null}");
return;
}
//!取消协程
modifierLogic.cancellationToken?.Cancel();
SkillLogic modifierLogicSkillLogic = modifierLogic.skillLogic;
Unit owner = modifierLogicSkillLogic.owner;
Unit target = self.GetParent<Unit>();
ModifierId modifierId = modifierLogic.modifierId;
modifierLogic.HandleEvent(ModifierEventCondition.modifier, new ModifierSkillSender
{
caster = owner,
target = target,
skillLogic = modifierLogicSkillLogic,
modifierLogic = modifierLogic
});
//!改变状态
try
{
modifierLogicSkillLogic.SetMultipleDamage(modifierLogicSkillLogic.GetMultipleDamage() - modifierLogic.multiDamageX10000);
modifierLogicSkillLogic.SetPlayAmount(modifierLogicSkillLogic.GetPlayAmount() - modifierLogic.playAmount);
}
catch (Exception e)
{
Log.Error(e);
}
Dictionary<ModifierId, ModifierConfig> dic = modifierLogicSkillLogic.skillLogicConfig?.modifierDic;
if (dic != null)
{
if (dic.TryGetValue(modifierId, out ModifierConfig modifierConfig))
{
if (modifierConfig.valueK != ModifierValueType.)
self.ChangeNumeric(target, modifierLogic, ValueChangeType.Minus);
if (modifierConfig.stateK != ModifierStateType.)
self.ChangeState(owner, target, modifierLogic, ValueChangeType.Minus);
}
}
self.timeDic.Remove(modifierId);
using ListComponent<(ModifierEventCondition, ModifierLogic)> listComponent = ListComponent<(ModifierEventCondition, ModifierLogic)>.Create();
List<(ModifierEventCondition, ModifierLogic)> needRemoveModifierSet = listComponent.List;
foreach (KeyValuePair<ModifierEventCondition, HashSet<ModifierLogic>> kv in self.modifierOptionByConditionDic.GetDictionary())
{
foreach (ModifierLogic _logic in kv.Value)
{
try
{
if (!_logic.IsDisposed && _logic.modifierId == modifierId)
{
needRemoveModifierSet.Add((kv.Key, _logic));
}
}
catch (Exception e)
{
Log.Error(e);
}
}
}
foreach ((ModifierEventCondition eventCondition, ModifierLogic __logic) in needRemoveModifierSet)
{
self.modifierOptionByConditionDic.Remove(eventCondition, __logic);
}
if (!self.modifierDic.Remove(modifierId))
{
Log.Error($"modifierDic remove the key fail :{modifierId}");
Log.Error($" id= {self.Parent.Id} {self.GetParent<Unit>()?.GetComponent<UnitSkillComponent>()?.GetLearnedSkills().FirstOrDefault()?.Id} this skill {modifierLogic?.skillLogic.skillId}");
}
modifierLogic.HandleEvent(ModifierEventCondition.modifier, new ModifierSkillSender
{
caster = owner,
target = target,
skillLogic = modifierLogicSkillLogic,
modifierLogic = modifierLogic
});
modifierLogic.Dispose();
}
catch (Exception e)
{
Log.Error(e);
modifierLogic.Dispose();
}
}
}
}