using FL.Battle.Buffs; using System; using System.Collections.Generic; using XGame.Framework; using XGame.Framework.Interfaces; namespace FL.Map.TestMainMap { public partial class EntitiesComponent : ILateUpdate { private HashSet _buffOwnerIds; private bool _isElementBuffDirty; private BuffPreviewDto _buffPreview; void ILateUpdate.LateUpdate(int millisecond) { Context.VM.UpdateMapMoveTime(millisecond); Context.VM.Camera.OnLateUpdate(millisecond); //RefreshElementBuffs(); } #region 元素buff private void RefreshElementBuffs() { if (!_isElementBuffDirty) return; _isElementBuffDirty = false; CollectElementBuffs((elementBuffs, partners) => { var isMatch = false; if (elementBuffs != null) { foreach (var buff in elementBuffs) { foreach (var partner in partners) { if (MatchTargetBuff(partner, buff)) { isMatch = true; break; } } if (isMatch) { break; } } } if (!isMatch) { // 没有匹配的项 ResetBuffPreview(); } }); } private void CollectElementBuffs(Action, List> callback) { if (_buffOwnerIds == null || _buffOwnerIds.Count == 0) { callback.SafeInvoke(null, null); return; } var buffOwnerIds = ListPool.Acquire(); buffOwnerIds.AddRange(_buffOwnerIds); var elementBuffs = ListPool.Acquire(); foreach (var ownerId in buffOwnerIds) { if (_monsterMap.TryGetValue(ownerId, out var monster) && monster.IsDead == false && monster.Buffs.GetElementBuffs(ref elementBuffs)) { continue; } //非怪物 || 没有满足要求的元素buff _buffOwnerIds.Remove(ownerId); } elementBuffs.Sort((a, b) => { // 层数高的排前面 var orderA = a.Layers * 1000 / a.LayerLimit; var orderB = b.Layers * 1000 / b.LayerLimit; return orderB - orderA; }); // 随从 按照技能冷却时间排序 var partners = ListPool.Acquire(); partners.AddRange(_partnerMap.Values); var skillCdMap = new Dictionary(); partners.Sort((a, b) => { var id_a = a.Entity.EntityId; if (!skillCdMap.TryGetValue(id_a, out var cd_a)) { cd_a = a.Skill.GetMinCooldown(); skillCdMap.Add(id_a, cd_a); } var id_b = b.Entity.EntityId; if (!skillCdMap.TryGetValue(id_b, out var cd_b)) { cd_b = a.Skill.GetMinCooldown(); skillCdMap.Add(id_b, cd_b); } // 冷却时间短的排前面 return cd_a - cd_b; }); //回调 callback.SafeInvoke(elementBuffs, partners); //回收临时变量 ListPool.Recycle(partners); ListPool.Recycle(buffOwnerIds); ListPool.Recycle(elementBuffs); } private bool MatchTargetBuff(PartnerEntityView partner, IBuff buff) { if (partner.Epigraphics.IsTargetBuff(buff.TableId, out var epigrapId)) { NotifyBuffPreview(buff, partner.Entity.Attr.UID, false, epigrapId); return true; } if (partner.Skill.FindSkillByElementType(buff.ElementType, out var skillId)) { NotifyBuffPreview(buff, partner.Entity.Attr.UID, true, skillId); return true; } return false; } private void NotifyBuffPreview(IBuff buff, long partnerUID, bool isSkill, int skillId) { _buffPreview = new BuffPreviewDto() { ownerId = buff.OwnerId, buffTableId = buff.TableId, partnerUID = partnerUID, isSkill = isSkill, skillId = skillId, layer = buff.Layers, layerLimit = buff.LayerLimit, }; EventSingle.Instance.Notify(EventDefine.GameMainMapPreviewBuff, _buffPreview); } private void ResetBuffPreview() { _buffPreview = default; EventSingle.Instance.Notify(EventDefine.GameMainMapPreviewBuff, _buffPreview); } private void OnAddBuff(int eventId, object args) { var dto = (BuffEventDto)args; var buffOwners = _buffOwnerIds ??= new HashSet(); buffOwners.Add(dto.ownerId); _isElementBuffDirty = true; } private void OnRemoveBuff(int eventId, object args) { var dto = (BuffEventDto)args; if (_buffPreview.ownerId == dto.ownerId && _buffPreview.buffTableId == dto.buffTableId) { ResetBuffPreview(); _isElementBuffDirty = true; } } private void OnRequestBuffList(int eventId, object args) { var buffPreviewDtos = new List(); CollectElementBuffs((elementBuffs, partners) => { if (elementBuffs != null) { foreach (var buff in elementBuffs) { foreach (var partner in partners) { var partnerUID = partner.Entity.Attr.UID; if (partner.Epigraphics.IsTargetBuff(buff.TableId, out var epigrapId)) { var dto = new BuffPreviewDto() { ownerId = buff.OwnerId, buffTableId = buff.TableId, partnerUID = partnerUID, isSkill = false, skillId = epigrapId, layer = buff.Layers, layerLimit = buff.LayerLimit, }; buffPreviewDtos.Add(dto); } if (partner.Skill.FindSkillByElementType(buff.ElementType, out var skillId)) { var dto = new BuffPreviewDto() { ownerId = buff.OwnerId, buffTableId = buff.TableId, partnerUID = partnerUID, isSkill = true, skillId = skillId, layer = buff.Layers, layerLimit = buff.LayerLimit, }; buffPreviewDtos.Add(dto); } } } } EventSingle.Instance.Notify(EventDefine.GameMainMapPushPreviewBuffs, buffPreviewDtos); }); } private void RemoveElementBuff(long ownerId) { if (_buffPreview.ownerId == ownerId) { ResetBuffPreview(); } if (_buffOwnerIds?.Remove(ownerId) ?? false) { _isElementBuffDirty = true; } } private void ClearElementBuffs() { _buffOwnerIds?.Clear(); _isElementBuffDirty = false; _buffPreview = default; } #endregion } }