using Cal; using System; using System.Collections.Generic; using System.Linq; namespace ET { public class ModifierContainerComponentUpdateSystem: UpdateSystem { public override void Update(ModifierContainerComponent self) { long now = TimeHelper.ClientNow(); using ListComponent needModifedListComponent = ListComponent.Create(); using ListComponent _needModifedListComponent = ListComponent.Create(); using ListComponent<(SkillOptionBase, ISkillSender)> optionListComponent = ListComponent<(SkillOptionBase, ISkillSender)>.Create(); List needModifedList = needModifedListComponent.List; List _needModifedList = _needModifedListComponent.List; List<(SkillOptionBase, ISkillSender)> optionList = optionListComponent.List; foreach (KeyValuePair 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()?.GetComponent()?.GetLearnedSkills().FirstOrDefault()?.Id} this skill {modifierLogic?.skillConfigId}"); 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?.skillConfigId}"); 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?.skillConfigId}"); continue; } needModifedList.Add(modifierLogic); Dictionary 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(modifierLogic.owner,self.GetParent(),modifierLogic.skillConfigId,modifierLogic))); } } 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); skillOptionLogicBase.HandleEvent(skillSender); } } } public class ModifierContainerComponentDestroySystem: DestroySystem { 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) return; if(skillLogic.skillLogicConfig.modifierDic==null) return; if (!skillLogic.skillLogicConfig.modifierDic.TryGetValue(modifierId, out ModifierConfig modifierConfig)) { return; } if (!modifierConfig.levelList.Contains(skillLogic.skillLevel)) return; Unit target = self.GetParent(); 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(owner.DomainScene()); logic.skillConfigId = skillLogic.skillConfigId; logic.modifierConfig = modifierConfig; logic.owner = owner; logic.target = target; 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) { logic.owner = owner; logic.target = target; 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.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; } /// /// 处理瞬时效果 /// /// /// /// /// private static void DealNoContinuteModifier(this ModifierContainerComponent self, Unit owner, Unit target, ModifierLogic logic) { ModifierConfig modifierConfig = logic.modifierConfig; if (!IgnoreInvalid(self, modifierConfig.attribute)) { logic.Dispose(); return; } logic.overlay += 1; OnBeforeCreateEvent(owner, target, logic); DealEffect(owner, target, logic); OnAfterCreateEvent(owner, target, logic); //!改变状态 AttackComponent attackComponent = logic.target.GetComponent(); attackComponent.multipleDamageX10000 -= logic.multiDamageX10000; attackComponent.playAmount -= 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.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 dic = logic.modifierConfig.modifierEventDic; if (dic != null) foreach (KeyValuePair 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().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(owner,target,logic.skillConfigId,logic)); } private static void OnAfterCreateEvent(Unit owner, Unit target, ModifierLogic logic) { logic.HandleEvent(ModifierEventCondition.当modifier被创建后, new ModifierSkillSender(owner,target,logic.skillConfigId,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.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 RemoveState(this ModifierContainerComponent self, ModifierStateType stateType) { self.modifierStateDic.Remove(stateType); } 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 set = self.modifierOptionByConditionDic[modifierEventCondition]; if (set.Count > 0) foreach (ModifierLogic modifierLogic in set) { if (modifierLogic.IsDisposed) continue; Dictionary dic = modifierLogic.modifierConfig.modifierEventDic; if (dic != null) if (dic.TryGetValue(modifierEventCondition, out SkillOptionBase[] list)) return (list, modifierLogic); } return (null, null); } /// /// 设置定时器,定时销毁 /// /// /// 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(); float sign = valueChangeType switch { ValueChangeType.Zero => 0, ValueChangeType.Plus => 1, ValueChangeType.Minus => -1, _ => throw new Exception("类型错误"), }; if (!SkillHelper.GetParam(configValue, logic.skillConfigId, out float value)) { Log.Error($"cann't get the value where modifier = {logic.modifierId} type = {key}"); return; } if (sign == -1) { sign *= logic.dataOldX10000; } else { sign *= logic.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 { // ModifierId modifierId = ((ModifierSkillSender) skillSender).modifierId; // ModifierLogic modifierLogic = self.GetModifierLogic(modifierId); 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 ,is null? {modifierLogic == null}"); return; } //!取消协程 modifierLogic.cancellationToken?.Cancel(); Unit owner = modifierLogic.owner; Unit target = self.GetParent(); if (target != modifierLogic.target) { Log.Error($"target is diff:{target} {modifierLogic.target}"); } ModifierId modifierId = modifierLogic.modifierId; modifierLogic.HandleEvent(ModifierEventCondition.当modifier被移除前, new ModifierSkillSender( owner, target, modifierLogic.skillConfigId, modifierLogic )); //!改变状态 try { AttackComponent attackComponent = modifierLogic.target.GetComponent(); attackComponent.multipleDamageX10000 -= modifierLogic.multiDamageX10000; attackComponent.playAmount -= modifierLogic.playAmount; // modifierLogicSkillLogic.SetMultipleDamage(modifierLogicSkillLogic.GetMultipleDamage() - modifierLogic.multiDamageX10000); // modifierLogicSkillLogic.SetPlayAmount(modifierLogicSkillLogic.GetPlayAmount() - modifierLogic.playAmount); } catch (Exception e) { Log.Error(e); Log.Info($"{self.Id} {modifierLogic.owner} {modifierLogic.target}"); } ModifierConfig modifierConfig = modifierLogic.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> 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()?.GetComponent()?.GetLearnedSkills().FirstOrDefault()?.Id} this skill {modifierLogic?.skillConfigId}"); } modifierLogic.HandleEvent(ModifierEventCondition.当modifier被移除后, new ModifierSkillSender( owner, target, modifierLogic.skillConfigId, modifierLogic )); modifierLogic.Dispose(); } catch (Exception e) { Log.Error(e); modifierLogic.Dispose(); } } } }