123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- using FL.Battle.Actions;
- using FL.Battle.Components;
- using System;
- using UnityEngine;
- using XGame.Database;
- using XGame.Framework;
- using XGame.Framework.Interfaces;
- using XGame.Framework.Time;
- namespace FL.Battle.Skills
- {
- /// <summary>
- /// 简单的技能表现
- /// </summary>
- internal class SimpleSkillActor : ISkillActor, IReference
- {
- public ISkillContext Context { get; set; }
- private ITimer _skillTimer; //技能施法时间
- private ITimer _bulletTimer;
- private ITimer _noAniTimer; // 没有动作时受击特效的定时器
- private SkillTable _skill;
- private SkillVfxsTable _skillVfxs;
- void ISkillActor.Play(int skillId, ITarget target, Action<int, int> onCompleted)
- {
- _skill = SkillTableRepo.Get(skillId);
- _skillVfxs = SkillVfxsTableRepo.Get(skillId);
- var owner = Context.Entity;
- //if (/*_skill.BuffTie.Length == 0*/ (ESkillVfxType)_skill.SkillVfxType is ESkillVfxType.AOE or ESkillVfxType.Trap)
- //{
- // onCompleted(skillId, _skill.RestTime);
- // return;
- //}
- PlayCastVfx(target);
- var isHaveBullet = PlayBullets(target);
- PlaySkillAnimation(target, isHaveBullet);
- //TODO 最少900毫秒
- var duration = _skill.EndureTime;
- //var startTime = Time.realtimeSinceStartup;
- _skillTimer = Context.Time.AddDelayTimer(duration, () =>
- {
- //Log.Debug($"SimpleSkillActor Completed. Entity:{Context.Entity.EntityId} Name:{Context.Entity.Attr.Name} SkillId:{_skill.Id} Frame:{Time.frameCount} duration:{duration} start:{startTime} used:{Time.realtimeSinceStartup - startTime}");
- var skillCD = _skill.RestTime;
- onCompleted.SafeInvoke(skillId, skillCD);
- });
- }
- public void Stop()
- {
- _skill = null;
- _skillVfxs = null;
- _skillTimer?.Cancel();
- _skillTimer = null;
- _bulletTimer?.Cancel();
- _bulletTimer = null;
- _noAniTimer?.Cancel();
- _noAniTimer = null;
- }
- /// <summary>
- /// 播放施法特效
- /// </summary>
- /// <param name="target"></param>
- private void PlayCastVfx(ITarget target)
- {
- if (!string.IsNullOrEmpty(_skillVfxs.CastVfx))
- {
- VfxArgs vfxArgs = ObjectPool.Acquire<VfxArgs>();
- vfxArgs.vfxName = _skillVfxs.CastVfx;
- vfxArgs.duration = _skillVfxs.CastVfxTime;
- vfxArgs.followType = EVfxFollowType.CastPoint; //(EVfxFollowType)_skillVfxs.VfxFollowType;
- if (_skill.Id == 200705)
- { // TODO
- var actFoword = ObjectPool.Acquire<ForwordAction>();
- actFoword.forword = (target.Position - Context.Position).normalized;
- vfxArgs.action = actFoword;
- }
- //vfxArgs.onFinish = OnSkillVfxFinish;
- Context.Vfx.Play(vfxArgs);
- }
- }
- /// <summary>
- /// 播放施法动作
- /// </summary>
- /// <param name="target"></param>
- /// <param name="isHaveBullet">是否有子弹,没子弹才需要播放受击特效</param>
- private void PlaySkillAnimation(ITarget target, bool isHaveBullet)
- {
- var actionName = _skillVfxs.AniName;
- if (actionName == EAnimationName.skill && Context.Entity.EntityType != EEntityType.Partner)
- { //TODO 现在只有随从有施法动作
- actionName = EAnimationName.attack;
- }
- //if (skill.Id == 200707)
- //{
- // actionName = EAnimationName.skill2;
- //}
- var skillVfxTyp = (ESkillVfxType)_skill.SkillVfxType;
- void onTrigger()
- {
- _noAniTimer = null;
- if (skillVfxTyp is ESkillVfxType.Trap or ESkillVfxType.AOE or ESkillVfxType.AOENoMove or ESkillVfxType.AOETarget)
- { //播放召唤兽特效
- SummonBeat(target);
- }
- else
- { // target不为空,播放受击特效
- PlayHitVfx(target);
- }
- }
- if (actionName >= EAnimationName.attack)
- { // 有攻击动作
- var skillId = _skillVfxs.Id;
- var entityName = Context.Entity.Attr.Name;
- var actArgs = new AnimationPlayArgs()
- {
- aniName = actionName,
- //onCompleted = () =>
- //{
- // Assert.IsNotNull(Context, $"技能动作回调,Context不能为空. skillId:{skillId} entityName:{entityName}");
- // Context.Animator.Play(EAnimationName.idle/* + UnityEngine.Random.Range(0, 100) % 2*/);
- //}
- };
- if (!isHaveBullet)
- { // 没有子弹,300毫秒后召唤或者播放受击特效
- actArgs.triggerFrame = _skillVfxs.SkillVfxDelay;
- actArgs.onTrigger = onTrigger;
- }
- Context.Animator.Play(actArgs);
- }
- else if (!isHaveBullet)
- { // 没有子弹,300毫秒后召唤或者播放受击特效
- _noAniTimer = Context.Time.AddDelayTimer(_skillVfxs.SkillVfxDelay, onTrigger);
- }
- }
- /// <summary>
- /// 播放子弹
- /// </summary>
- /// <param name="target"></param>
- /// <returns></returns>
- private bool PlayBullets(ITarget target)
- {
- var bulletCount = _skill.SkillVfxType / 100 == 1 ? _skillVfxs.SkillVfxCount : 0;
- if (bulletCount > 0)
- { // 有子弹,设置子弹的定时器
- var targetId = target?.Entity.EntityId ?? 0;
- var to = target?.Position ?? Vector3.zero;
- var randomIdx = -1;
- if (_skill.SkillVfxType == (int)ESkillVfxType.BulletMortar)
- { // 随机一个索引确保有一个目标坐标在敌人位置
- randomIdx = UnityEngine.Random.Range(0, 1000) % bulletCount;
- }
- _bulletTimer = Context.Time.AddDelayLooperTimer(_skillVfxs.SkillVfxDelay, _skillVfxs.SkillVfxInterval > 0 ? _skillVfxs.SkillVfxInterval : 500, (times) =>
- {
- //XGame.Log.Debug($"Skill bullet loop Id:{skillId} Count:{bulletCount} Times:{times}");
- if (times == bulletCount)
- _bulletTimer = null;
-
- var bulletArgs = new GenBulletDto()
- {
- masterId = Context.Entity.EntityId,
- masterType = Context.Entity.EntityType,
- targetId = targetId,
- tableId = _skill.Id,
- from = Context.Position,
- to = to,
- };
- if (randomIdx != -1)
- {
- bulletArgs.to = Context.Selector.RandomPosition(Context.Entity.EntityType == EEntityType.Monster ? EEntityType.Player : EEntityType.Monster, times - 1 == randomIdx);
- }
- EventSingle.Instance.Notify(EventDefine.GameMainMapGenBullet, bulletArgs);
- }, bulletCount);
- return true;
- }
- return false;
- }
- /// <summary>
- /// 召唤技能
- /// </summary>
- private void SummonBeat(ITarget target)
- {
- var dto = new GenSummonsDto()
- {
- masterId = Context.Entity.EntityId,
- masterType = Context.Entity.EntityType,
- tableId = _skill.Id,
- from = Context.Position,
- count = _skillVfxs.SkillVfxCount
- };
- if (target != null)
- {
- dto.targetId = target.Entity.EntityId;
- dto.targetType = target.Entity.EntityType;
- dto.from = target.Position;
- }
- else
- { //TODO 根据技能配置确定目标类型
- dto.targetType = dto.masterType == EEntityType.Monster ? EEntityType.Player : EEntityType.Monster;
- }
- EventSingle.Instance.Notify(EventDefine.GameMainMapGenCommons, dto);
- }
- /// <summary>
- /// 受击特效
- /// </summary>
- /// <param name="target"></param>
- private void PlayHitVfx(ITarget target)
- {
- var to = target?.Position ?? Vector3.zero;
- var hitVfx = _skillVfxs.HitVfx;
- if (!string.IsNullOrEmpty(hitVfx))
- {
- var actPosition = ObjectPool.Acquire<PositionAction>();
- actPosition.position = to;
- var hitArgs = ObjectPool.Acquire<VfxArgs>();
- hitArgs.vfxName = _skillVfxs.HitVfx;
- hitArgs.duration = _skillVfxs.HitVfxTime; //hitEffect == "effect_sk_hit_13521" ? 3000 : 2000;
- hitArgs.followType = EVfxFollowType.World;
- hitArgs.action = actPosition;
- Context.Vfx.Play(hitArgs);
- }
- Assert.IsNotNull(target, $"PlayHitVfx target null. skill:{_skill.Id}");
- if (!target.IsDead)
- {
- target.Calculation.Damage(-_skill.Damage, Context.Entity.EntityId, _skill);
- }
- }
- void IReference.Clear()
- {
- Stop();
- Context = null;
- }
- }
- }
|