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
{
///
/// 简单的技能表现
///
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 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;
}
///
/// 播放施法特效
///
///
private void PlayCastVfx(ITarget target)
{
if (!string.IsNullOrEmpty(_skillVfxs.CastVfx))
{
VfxArgs vfxArgs = ObjectPool.Acquire();
vfxArgs.vfxName = _skillVfxs.CastVfx;
vfxArgs.duration = _skillVfxs.CastVfxTime;
vfxArgs.followType = EVfxFollowType.CastPoint; //(EVfxFollowType)_skillVfxs.VfxFollowType;
if (_skill.Id == 200705)
{ // TODO
var actFoword = ObjectPool.Acquire();
actFoword.forword = (target.Position - Context.Position).normalized;
vfxArgs.action = actFoword;
}
//vfxArgs.onFinish = OnSkillVfxFinish;
Context.Vfx.Play(vfxArgs);
}
}
///
/// 播放施法动作
///
///
/// 是否有子弹,没子弹才需要播放受击特效
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);
}
}
///
/// 播放子弹
///
///
///
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;
}
///
/// 召唤技能
///
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);
}
///
/// 受击特效
///
///
private void PlayHitVfx(ITarget target)
{
var to = target?.Position ?? Vector3.zero;
var hitVfx = _skillVfxs.HitVfx;
if (!string.IsNullOrEmpty(hitVfx))
{
var actPosition = ObjectPool.Acquire();
actPosition.position = to;
var hitArgs = ObjectPool.Acquire();
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;
}
}
}