123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- using FL.Battle.Actions;
- using FL.Battle.Skills;
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- using XGame.Database;
- using XGame.Framework;
- using XGame.Framework.Components;
- using XGame.Framework.Time;
- namespace FL.Battle.Components.AI
- {
- public interface IAOEEntityAIContext
- {
- long UID { get; }
- long MasterId { get; }
- int TableId { get; }
- ITargetSelector Selector { get; }
- ITimeModule Time { get; }
- Vector3 Position { get; }
- Transform Tr { get; }
- MoveComponent Move { get; }
- VfxComponent Vfx { get; }
- }
- /// <summary>
- /// AI组件和具体的EntityView绑定,其他Component最好不要尝试获取AI组件
- /// 虫群特效半径为1,配置宽高需要X2,该特效不适合缩放,预制按照目标尺寸重复摆放基础特效
- /// </summary>
- public class AOEEntityAI : Component<IAOEEntityAIContext>
- {
- private EEntityType _targetType;
- private ITimer _aoeTimer;
- private ITimer _stopTimer;
- private SkillTable _skill;
- private SkillVfxsTable _skillVfxs;
- private List<ITarget> _targets = new List<ITarget>();
- private HashSet<long> _selectedTargetIds = new();
- private Dictionary<long, int> _targetHitTimesMap = new();
- protected override void OnDispose()
- {
- _selectedTargetIds.Clear();
- _targetHitTimesMap.Clear();
- _targets.Clear();
- _aoeTimer?.Cancel();
- _aoeTimer = null;
- _stopTimer?.Cancel();
- _stopTimer = null;
- _skill = null;
- _skillVfxs = null;
- }
- public void Start(Vector3 targetPosition, EEntityType targetType)
- {
- _skill = SkillTableRepo.Get(Context.TableId);
- _skillVfxs = SkillVfxsTableRepo.Get(Context.TableId);
- _targetType = targetType;
- //Context.ParticleTr.localScale = new Vector3(_skill.Ranges[1] * 0.5f, _skill.Ranges[2] * 0.5f, 1);
- // 飞到目标位置
- if (_skill.SkillVfxType == (int)ESkillVfxType.AOE)
- {
- var moveArgs = new MoveArgs()
- {
- target = targetPosition,
- speed = _skillVfxs.SkillVfxSpeed,
- timeScale = 1,
- onComplete = StopAOE
- };
- if (Enum.TryParse<DG.Tweening.Ease>(_skillVfxs.SkillVfxMoveEase, true, out var ease))
- {
- moveArgs.ease = ease;
- }
- //Context.Tr.forward = (targetPosition - Context.Position).normalized;
- Context.Move.MoveTo(moveArgs);
- }
- else
- { //TODO 判断是否需要左右镜像
- Context.Tr.localScale = new Vector3(-1, 1, 1);
- _stopTimer = Context.Time.AddDelayTimer(_skillVfxs.SkillVfxTime, StopAOE);
- }
- _aoeTimer = Context.Time.AddDelayLooperTimer(_skill.DamageArgs[1], _skill.DamageArgs[2], OnAOE, _skill.DamageArgs[0]);
- }
- private void OnAOE(int obj)
- {
- // 是否重复选中,0:false
- var isSelectOnce = _skill.DamageArgs[3] == 0;
- // 受击次数,-1:不限,1:1次
- var hitLimit = _skill.DamageArgs[4];
- bool IsFilt(ITarget a)
- {
- if (isSelectOnce)
- return _selectedTargetIds.Contains(a.Entity.EntityId);
- return false;
- }
- bool isHaveTargets;
- if (_skill.Ranges[0] == 1)
- { // 矩形
- var size = new Vector2(_skill.Ranges[1], _skill.Ranges[2]);
- Vector2 position = Context.Position;
- position -= (size * 0.5f);
- var rect = new Rect(position, size);
- isHaveTargets = Context.Selector.FindTargets(rect, _targetType, ETargetFindType.InRangeAlive, IsFilt, ref _targets);
- }
- else
- {
- var finder = new FinderInfo()
- {
- uid = Context.UID,
- position = Context.Position,
- radius = _skill.Ranges[1]
- };
- isHaveTargets = Context.Selector.FindTargets(finder, _targetType, ETargetFindType.InRangeAlive, IsFilt, ref _targets);
- }
- if (isHaveTargets)
- {
- // 计算受击伤害
- foreach (var target in _targets)
- {
- var targetId = target.Entity.EntityId;
- var hitTimes = 0;
- var damage = _skill.Damage;
- if (hitLimit < 0 || _targetHitTimesMap.TryGetValue(targetId, out hitTimes) == false || hitTimes < hitLimit)
- { // 没有有受击次数限制 或 受击次数未达到上限
- PlayHitVfx(target.Position);
- if (_skill.Ranges[0] == 2 && _skill.Ranges.Length == 5)
- { // 圆形,有半径递减
- var distance = Vector3.Distance(target.Position, Context.Position);
- if (distance > _skill.Ranges[3])
- {
- // 向上取整
- damage = Mathf.CeilToInt((1 - _skill.Ranges[4]) * damage);
- }
- }
- }
- else
- { // 本次受击不造成伤害,但是还是要判断触发buff等
- damage = 0;
- }
- //if (_skill.SkillVfxType == (int)ESkillVfxType.AOETarget)
- //{
- // Log.Debug($"Skill AOE Id:{_skill.Id} target:{targetId} damage:{damage}");
- //}
- target.Calculation.Damage(-damage, Context.MasterId, _skill);
- if (hitLimit > 0)
- { // 记录目标受击次数
- _targetHitTimesMap[targetId] = ++hitTimes;
- }
- if (isSelectOnce)
- _selectedTargetIds.Add(targetId);
- }
- _targets.Clear();
- }
- //if (_skill.SkillVfxType == (int)ESkillVfxType.AOENoMove)
- //{
- // StopAOE();
- //}
- }
- /// <summary>
- /// 受击特效
- /// </summary>
- /// <param name="targetPosition"></param>
- private void PlayHitVfx(Vector3 targetPosition)
- {
- if (string.IsNullOrEmpty(_skillVfxs.HitVfx))
- return;
- var actPosition = ObjectPool.Acquire<PositionAction>();
- actPosition.position = targetPosition;
- var hitArgs = ObjectPool.Acquire<VfxArgs>();
- hitArgs.vfxName = _skillVfxs.HitVfx;
- hitArgs.duration = _skillVfxs.HitVfxTime;
- hitArgs.followType = EVfxFollowType.World;
- hitArgs.action = actPosition;
- Context.Vfx.Play(hitArgs);
- }
- private void StopAOE()
- {
- _aoeTimer?.Cancel();
- _aoeTimer = null;
- _stopTimer?.Cancel();
- _stopTimer = null;
- EventSingle.Instance.Notify(EventDefine.GameMainMapRemoveSimpleEntity, Context.UID);
- }
- }
- }
|