using Cal; using System; using System.Collections.Generic; using System.Linq; namespace ET { public class ModifierContainerComponentUpdateSystem : UpdateSystem { public override void Update(ModifierContainerComponent self) { var now = TimeHelper.ClientNow(); using var needModifedListComponent = ListComponent.Create(); using var _needModifedListComponent = ListComponent.Create(); using var optionListComponent = ListComponent<(SkillOptionBase, ISkillSender)>.Create(); var needModifedList = needModifedListComponent.List; var _needModifedList = _needModifedListComponent.List; var optionList = optionListComponent.List; foreach (var kv in self.timeDic) { if (now < kv.Value) continue; if (!self.modifierDic.TryGetValue(kv.Key, out var modifierLogic)) { _needModifedList.Add(kv.Key); Log.Error($"{self.GetParent()?.GetComponent()?.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()?.GetComponent()?.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()?.GetComponent()?.GetLearnedSkills().FirstOrDefault()?.Id} this skill {modifierLogic?.skillLogic.skillId}"); continue; } needModifedList.Add(modifierLogic); var dic = modifierLogic.modifierConfig?.modifierEventDic; if (dic == null) continue; if (dic.TryGetValue(ModifierEventCondition.循环执行定时器操作, out var list)) { foreach (var item in list) { optionList.Add((item, new ModifierSkillSender { caster = modifierLogic.skillLogic.owner, skillLogic = modifierLogic.skillLogic, modifierLogic = modifierLogic, target = self.GetParent() })); } } } foreach (var item in _needModifedList) { self.timeDic.Remove(item); } foreach (var logic in needModifedList) { self.timeDic[logic.modifierId] = now + logic.interval; } foreach (var (option, skillSender) in optionList) { var skillOptionLogicBase = SkillOptionFactory.AcquireSkillOptionLogic(option); skillSender.skillLogic.skillOptionLogics.Add(skillOptionLogicBase); skillOptionLogicBase.HandleEvent(skillSender); } } } public class ModifierContainerComponentDestroySystem : DestroySystem { public override void Destroy(ModifierContainerComponent self) { foreach (var 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 var modifierConfig)) { return; } if (!modifierConfig.levelList.Contains(skillLogic.skillLevel)) return; var target = self.GetParent(); if (!SkillHelper.GetParam(modifierConfig.continueTime, skillLogic.skillConfigId, out var continueTime)) { continueTime = 0; } if (!self.modifierDic.TryGetValue(modifierId, out var logic) || logic.IsDisposed) { logic = EntityFactory.CreateWithParent(self); logic.skillLogic = skillLogic; logic.modifierConfig = modifierConfig; //!特殊处理 if (continueTime == 0) { if (!IgnoreInvalid(modifierConfig.attribute)) return; logic.overlay += 1; OnBeforeCreateEvent(); DealEffect(owner, target, logic, modifierConfig); OnAfterCreateEvent(); //!改变状态 logic.skillLogic.multipleDamageX10000 -= logic.multiDamageX10000; logic.skillLogic.playAmount -= logic.playAmount; logic.Dispose(); return; } } else { if (AppConfig.inst.isTest) Log.Warning($"dic already has the key:{modifierId} when create"); } if (!logic) { Log.Error($"logic is invalid where id = {logic?.modifierId}"); return; } //!已经存在此modifier if (self.modifierDic.ContainsKey(logic.modifierId)) { var modifierAttribute = modifierConfig.attribute; //!不改变属性(时间) if (modifierAttribute == ModifierAttribute.无 || !IgnoreInvalid(modifierAttribute)) return; //!可叠加的情况 if (modifierAttribute.HasFlag(ModifierAttribute.可叠加)) { int maxOverlay = SkillHotfixHelper.GetOverlableBuffMaxLayer(modifierConfig.overlayType); if (!SkillHelper.GetParam(modifierConfig.perOverlay, logic.skillLogic.skillConfigId, out var perOverlay)) { perOverlay = 1; } logic.overlay += (int)perOverlay; logic.overlay = Math.Clamp(logic.overlay, 1, maxOverlay); } //!可刷新的情况 if (modifierAttribute.HasFlag(ModifierAttribute.可刷新)) { if (logic.continueTime != -1 * 1000) { var now = TimeHelper.ClientNow(); logic.cancellationToken?.Cancel(); logic.cancellationToken = new ETCancellationToken(); //Log.Debug($"modifier 原本结束时间:{TimeHelper.GetTime(logic.leastTime)},刷新后结束时间:{TimeHelper.GetTime(TimeHelper.ClientNow() + logic.continueTime)}"); logic.leastTime = now + logic.continueTime; self.RemoveModifierIntetnal(logic).Coroutine(); } } } //!不存在此modifier else { OnBeforeCreateEvent(); AddToDic(); OnAfterCreateEvent(); if (modifierConfig.valueK != Cal.ModifierValueType.无) self.ChangeNumeric(target, logic, ValueChangeType.Plus); if (modifierConfig.stateK != ModifierStateType.无) self.ChangeState(owner, target, logic, ValueChangeType.Plus); logic.continueTime = (int)(continueTime * 1000); var now = TimeHelper.ClientNow(); int iconId = modifierConfig.iconId; if (iconId != 0) { 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, }); } DealEffect(owner, target, logic, modifierConfig); SetThinkerInterval(self, now, logic); if (logic.continueTime != -1 * 1000) { logic.cancellationToken = new ETCancellationToken(); logic.leastTime = logic.continueTime + now; self.RemoveModifierIntetnal(logic).Coroutine(); } } bool IgnoreInvalid(ModifierAttribute modifierAttribute) { if (modifierAttribute.HasFlag(ModifierAttribute.忽视无敌)) return self.HasState(ModifierStateType.无敌); return true; } void AddToDic() { 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 { var dic = logic.modifierConfig.modifierEventDic; if (dic != null) foreach (var kv in dic) { self.modifierOptionByConditionDic.Add(kv.Key, logic); } } } void OnBeforeCreateEvent() { logic.HandleEvent(ModifierEventCondition.当modifier被创建前, new ModifierSkillSender { caster = owner, target = target, skillLogic = logic.skillLogic, modifierLogic = logic }); } void OnAfterCreateEvent() { logic.HandleEvent(ModifierEventCondition.当modifier被创建后, new ModifierSkillSender { caster = owner, target = target, skillLogic = logic.skillLogic, modifierLogic = logic }); } } private static void DealEffect(Unit owner, Unit target, ModifierLogic logic, ModifierConfig modifierConfig) { int effectId = modifierConfig.effectId; if (effectId != 0) { target.GetComponent().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 SetThinkerInterval(ModifierContainerComponent self, long now, ModifierLogic logic) { var modifierConfig = logic.modifierConfig; if (modifierConfig.thinkerType == ThinkerType.无) { return; } else if (modifierConfig.thinkerType == ThinkerType.自定义 && SkillHelper.GetParam(modifierConfig.thinkInterval, logic.skillLogic.skillConfigId, out var inteval)) { if (inteval <= 0) { return; } logic.interval = (int)(inteval * 1000); } else { logic.interval = SkillHotfixHelper.GetThinkerInterval(thinkerType: modifierConfig.thinkerType); } 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 var 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.ListToString()}"); } self.modifierStateDic.Clear(); } public static ModifierLogic GetModifierLogic(this ModifierContainerComponent self, ModifierId modifierId) { self.modifierDic.TryGetValue(modifierId, out var modifierLogic); return modifierLogic; } public static (SkillOptionBase[], ModifierLogic) GetSkillOptionBaseArr(this ModifierContainerComponent self, ModifierEventCondition modifierEventCondition) { var set = self.modifierOptionByConditionDic[modifierEventCondition]; if (set.Count > 0) foreach (var modifierLogic in set) { if (modifierLogic.IsDisposed) continue; var dic = modifierLogic.modifierConfig.modifierEventDic; if (dic != null) if (dic.TryGetValue(modifierEventCondition, out var list)) return (list, modifierLogic); } return (null, null); } private static async ETVoid RemoveModifierIntetnal(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 { var key = logic.modifierConfig.valueK; if (key == Cal.ModifierValueType.无) return; var configValue = logic.modifierConfig.valueV; var numTarget = target.GetComponent(); float sign = valueChangeType switch { ValueChangeType.Zero => 0, ValueChangeType.Plus => 1, ValueChangeType.Minus => -1, _ => throw new Exception("类型错误"), }; if (!SkillHelper.GetParam(configValue, logic.skillLogic.skillConfigId, out var 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 Cal.ModifierValueType.无: break; case Cal.ModifierValueType.修改基础_生命值上限: numTarget.AddSet(NumericType.MaxHpAdd, numTarget.Get(NumericType.MaxHpBase) * finalValue); break; case Cal.ModifierValueType.修改基础_精力值上限: numTarget.AddSet(NumericType.MaxMpAdd, numTarget.Get(NumericType.MaxMpBase) * finalValue); break; case Cal.ModifierValueType.修改攻防_攻击力: numTarget.AddSet(NumericType.PhyAtkAdd, numTarget.Get(NumericType.PhyAtkBase) * finalValue); numTarget.AddSet(NumericType.SpiAtkAdd, numTarget.Get(NumericType.SpiAtkBase) * finalValue); break; case Cal.ModifierValueType.修改攻防_物理攻击力: numTarget.AddSet(NumericType.PhyAtkAdd, numTarget.Get(NumericType.PhyAtkBase) * finalValue); break; case Cal.ModifierValueType.修改攻防_精神攻击力: numTarget.AddSet(NumericType.SpiAtkAdd, numTarget.Get(NumericType.SpiAtkBase) * finalValue); break; case Cal.ModifierValueType.修改攻防_防御力: numTarget.AddSet(NumericType.PhyDefAdd, numTarget.Get(NumericType.PhyDefBase) * finalValue); numTarget.AddSet(NumericType.SpiDefAdd, numTarget.Get(NumericType.SpiDefBase) * finalValue); break; case Cal.ModifierValueType.修改攻防_物理防御力: numTarget.AddSet(NumericType.PhyDefAdd, numTarget.Get(NumericType.PhyDefBase) * finalValue); break; case Cal.ModifierValueType.修改攻防_精神防御力: numTarget.AddSet(NumericType.SpiDefAdd, numTarget.Get(NumericType.SpiDefBase) * finalValue); break; case Cal.ModifierValueType.修改暴击_暴击率: numTarget.AddSet(NumericType.PcrirAdd, finalValue); numTarget.AddSet(NumericType.McrirAdd, finalValue); break; case Cal.ModifierValueType.修改暴击_物理暴击率: numTarget.AddSet(NumericType.PcrirAdd, finalValue); break; case Cal.ModifierValueType.修改暴击_精神暴击率: numTarget.AddSet(NumericType.McrirAdd, finalValue); break; case Cal.ModifierValueType.修改暴击_暴击值: numTarget.AddSet(NumericType.PcriAdd, finalValue); numTarget.AddSet(NumericType.McriAdd, finalValue); break; case Cal.ModifierValueType.修改暴击_物理暴击值: numTarget.AddSet(NumericType.PcriAdd, finalValue); break; case Cal.ModifierValueType.修改暴击_精神暴击值: numTarget.AddSet(NumericType.McriAdd, finalValue); break; case Cal.ModifierValueType.修改抗暴击_抗暴击率: numTarget.AddSet(NumericType.RpcrirAdd, finalValue); numTarget.AddSet(NumericType.RmcrirAdd, finalValue); break; case Cal.ModifierValueType.修改抗暴击_抗物理暴击率: numTarget.AddSet(NumericType.RpcrirAdd, finalValue); break; case Cal.ModifierValueType.修改抗暴击_抗精神暴击率: numTarget.AddSet(NumericType.RmcrirAdd, finalValue); break; case Cal.ModifierValueType.修改抗暴击_抗暴击值: numTarget.AddSet(NumericType.RpcriAdd, finalValue); numTarget.AddSet(NumericType.RmcriAdd, finalValue); break; case Cal.ModifierValueType.修改抗暴击_抗物理暴击值: numTarget.AddSet(NumericType.RpcriAdd, finalValue); break; case Cal.ModifierValueType.修改抗暴击_抗精神暴击值: numTarget.AddSet(NumericType.RmcriAdd, finalValue); break; case Cal.ModifierValueType.修改免伤_免伤: numTarget.AddSet(NumericType.NphyiAdd, finalValue); numTarget.AddSet(NumericType.NmeniAdd, finalValue); break; case Cal.ModifierValueType.修改免伤_物理免伤: numTarget.AddSet(NumericType.NphyiAdd, finalValue); break; case Cal.ModifierValueType.修改免伤_精神免伤: numTarget.AddSet(NumericType.NmeniAdd, finalValue); break; case Cal.ModifierValueType.修改辅助值: numTarget.AddSet(NumericType.DvoAdd, finalValue); break; case Cal.ModifierValueType.修改速度: numTarget.AddSet(NumericType.SpdAdd, numTarget.Get(NumericType.SpdBase) * finalValue); break; case Cal.ModifierValueType.修改命中: numTarget.AddSet(NumericType.HitAdd, numTarget.Get(NumericType.HitBase) * finalValue); break; case Cal.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 { var 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 { var 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); } } private static List<(ModifierEventCondition, ModifierLogic)> needRemoveModifierSet = new List<(ModifierEventCondition, ModifierLogic)>(); public static void RemoveModifier(this ModifierContainerComponent self, ModifierLogic modifierLogic) { try { if (!modifierLogic) return; //!取消协程 modifierLogic.cancellationToken?.Cancel(); var owner = modifierLogic.skillLogic.owner; var target = self.GetParent(); var modifierId = modifierLogic.modifierId; modifierLogic.HandleEvent(ModifierEventCondition.当modifier被移除前, new ModifierSkillSender { caster = owner, target = target, skillLogic = modifierLogic.skillLogic, modifierLogic = modifierLogic }); //!改变状态 try { modifierLogic.skillLogic.multipleDamageX10000 -= modifierLogic.multiDamageX10000; modifierLogic.skillLogic.playAmount -= modifierLogic.playAmount; } catch (Exception e) { Log.Error(e); } var dic = modifierLogic.skillLogic.skillLogicConfig?.modifierDic; if (dic != null) { if (dic.TryGetValue(modifierId, out var modifierConfig)) { if (modifierConfig.valueK != Cal.ModifierValueType.无) self.ChangeNumeric(target, modifierLogic, ValueChangeType.Minus); if (modifierConfig.stateK != ModifierStateType.无) self.ChangeState(owner, target, modifierLogic, ValueChangeType.Minus); } } self.timeDic.Remove(modifierId); needRemoveModifierSet.Clear(); foreach (var kv in self.modifierOptionByConditionDic.GetDictionary()) { foreach (var _logic in kv.Value) { try { if (!_logic.IsDisposed && _logic.modifierId == modifierId) { needRemoveModifierSet.Add((kv.Key, _logic)); } } catch (Exception e) { Log.Error(e); } } } foreach (var (eventCondition, __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()?.GetComponent()?.GetLearnedSkills().FirstOrDefault()?.Id} this skill {modifierLogic?.skillLogic.skillId}"); } modifierLogic.HandleEvent(ModifierEventCondition.当modifier被移除后, new ModifierSkillSender { caster = owner, target = target, skillLogic = modifierLogic.skillLogic, modifierLogic = modifierLogic }); modifierLogic.Dispose(); } catch (Exception e) { Log.Error(e); modifierLogic.Dispose(); } } } }