AttackComponent.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. using DG.Tweening;
  2. using FL.Battle.Vfxs;
  3. using FL.Nodes.GameMain;
  4. using System;
  5. using UnityEngine;
  6. using XGame;
  7. using XGame.Database;
  8. using XGame.Framework;
  9. using XGame.Framework.Components;
  10. using XGame.Framework.Interfaces;
  11. using XGame.Framework.Map;
  12. using XGame.Framework.Time;
  13. namespace FL.Battle
  14. {
  15. public interface IAttackContext
  16. {
  17. IEntity Entity { get; }
  18. Transform ActionRoot { get; }
  19. Vector3 Position { get; }
  20. ITimeModule Time { get; }
  21. SpineComponent Spine { get; }
  22. VfxComponent Vfx { get; }
  23. void FindTarget(int skillId);
  24. void EnqueueSkill(int skillId);
  25. }
  26. /// <summary>
  27. /// 普通攻击
  28. /// </summary>
  29. public class AttackComponent : Component<IAttackContext>, IReset
  30. {
  31. public override int Order => 0;
  32. private IEntityView _targetView;
  33. private IEntity _target;
  34. private IAlarm _cdAlarm;
  35. private long _lastAtkTime;
  36. public void SetTarget(IEntityView targetView, IEntity target)
  37. {
  38. _targetView = targetView;
  39. _target = target;
  40. }
  41. public void Start(Action onCompleted)
  42. {
  43. var owner = Context.Entity;
  44. //if (_target == null)
  45. //{
  46. // Log.Error($"OnStartAttack Error: Target is null. TableId:{Context.Owner.TableId} State:{Context.Owner.State}");
  47. // return;
  48. //}
  49. if (_target == null || _target.State == EEntityState.Dead)
  50. {
  51. Stop();
  52. onCompleted.SafeInvoke();
  53. Context.FindTarget(0);
  54. return;
  55. }
  56. if (owner.State == EEntityState.Dead)
  57. {
  58. Stop();
  59. onCompleted.SafeInvoke();
  60. return;
  61. }
  62. if (Context.Entity.EntityType != EEntityType.Partner)
  63. { // 玩家或者怪物
  64. PlaySkillAtk(onCompleted);
  65. //Context.Spine.Play(ActionName.attack, () =>
  66. //{
  67. // OnHitFrame();
  68. // OnAttackEnd();
  69. // Context.Spine.Play(ActionName.idle);
  70. // onCompleted?.Invoke();
  71. //});
  72. return;
  73. }
  74. // 随从
  75. PartnerType partnerType = (PartnerType)((Context.Entity.TableId / 100) % 10);
  76. //单手剑、双手剑、法杖使用法术类型攻击
  77. var isSkill = partnerType == PartnerType.Sword || partnerType == PartnerType.SwordTH || partnerType == PartnerType.Staff;
  78. if (isSkill)
  79. {
  80. PlaySkillAtk(onCompleted);
  81. }
  82. else
  83. {
  84. if (partnerType == PartnerType.Axe)
  85. {
  86. Log.Debug($"Axe Attack. Frame:{UnityEngine.Time.frameCount}");
  87. }
  88. PartnerNormalAtk(onCompleted);
  89. }
  90. }
  91. private void PlaySkillAtk(Action onCompleted)
  92. {
  93. Context.Spine.Play(ActionName.attack, () =>
  94. {
  95. Context.Spine.Play(ActionName.idle/* + UnityEngine.Random.Range(0, 100) % 2*/);
  96. if (_target == null || _target.State == EEntityState.Dead)
  97. {
  98. OnAttackEnd();
  99. onCompleted.SafeInvoke();
  100. return;
  101. }
  102. var hpValue = _targetView.GetComponent<HpComponent>().CalculateHit(-Context.Entity.Attr.Attack);
  103. var to = _targetView.Position;
  104. void PushHpAdd()
  105. {
  106. var hpAdd = new HpAddDto()
  107. {
  108. position = to,
  109. hpValue = hpValue,
  110. };
  111. EventSingle.Instance.Notify(EventDefine.GameMainMapHpAdd, hpAdd);
  112. }
  113. var actMove = ObjectPool.Acquire<VfxActionMove>();
  114. actMove.from = Context.Position;
  115. actMove.to = to;
  116. actMove.duration = 500;
  117. var bulletArgs = ObjectPool.Acquire<VfxArgs>();
  118. bulletArgs.vfxName = Context.Entity.EntityType == EEntityType.Partner ? "effect_atk_bullet_20181" : "atk_007";
  119. bulletArgs.duration = 500;
  120. bulletArgs.followType = EVfxFollowType.World;
  121. bulletArgs.action = actMove;
  122. bulletArgs.onFinish = PushHpAdd;
  123. var actPosition = ObjectPool.Acquire<VfxActionPosition>();
  124. actPosition.position = to;
  125. var hitArgs = ObjectPool.Acquire<VfxArgs>();
  126. hitArgs.vfxName = Context.Entity.EntityType == EEntityType.Partner ? "effect_atk_hit_20181" : "hit_007";
  127. hitArgs.duration = 2000;
  128. hitArgs.followType = EVfxFollowType.World;
  129. hitArgs.action = actPosition;
  130. bulletArgs.next = hitArgs;
  131. Context.Vfx.Play(bulletArgs);
  132. //var dto = new SkillEffectDto()
  133. //{
  134. // skillEffect = "",
  135. // skillTime = 667,
  136. // from = Context.Position,
  137. // to = _targetView.Position,
  138. // hpAdd = new HpAddDto()
  139. // {
  140. // position = _targetView.Position,
  141. // hpValue = hpValue,
  142. // }
  143. //};
  144. //if (Context.Entity.EntityType == EEntityType.Partner)
  145. //{
  146. // dto.hitEffect = "effect_atk_hit_20181";
  147. // dto.bulletEffect = "effect_atk_bullet_20181";
  148. //}
  149. //else
  150. //{
  151. // dto.hitEffect = "hit_007";
  152. // dto.bulletEffect = "atk_007";
  153. //}
  154. //EventSingle.Instance.Notify(EventDefine.GameMainMapSkillEffect, dto);
  155. OnAttackEnd();
  156. onCompleted.SafeInvoke();
  157. });
  158. }
  159. private void PartnerNormalAtk(Action onCompleted)
  160. {
  161. var from = Context.Position;
  162. var to = _targetView.Position;
  163. var distance = Vector3.Distance(from, to);
  164. var atkRange = 0;// _target.Attr.Radius;
  165. if (distance > atkRange)
  166. { // 大于攻击距离
  167. //Log.Info($"PlayAttack:Owner:{Handle.Owner.EntityId} Target:{_target.EntityId}");
  168. var dir = (to - from).normalized;
  169. var moveDis = distance - atkRange;
  170. var atkPosition = Context.ActionRoot.localPosition + dir * moveDis;
  171. var moveTime = 0.3f;// Mathf.Abs(moveDis) / 5;
  172. //Context.ActionRoot.localPosition = atkPosition;
  173. //Context.Spine.Play(ActionName.attack, () =>
  174. //{
  175. // Context.Spine.Play(ActionName.idle/* + UnityEngine.Random.Range(0, 100) % 2*/);
  176. // Context.ActionRoot.localPosition = Vector3.zero;
  177. // var endArgs = ObjectPool.Acquire<VfxArgs>();
  178. // endArgs.vfxName = "effect_melee_appear";
  179. // endArgs.duration = 500;
  180. // Context.Vfx.Play(endArgs);
  181. // OnHitFrame();
  182. // OnAttackEnd();
  183. // onCompleted?.Invoke();
  184. //});
  185. var startArgs = ObjectPool.Acquire<VfxArgs>();
  186. startArgs.vfxName = "effect_trail";
  187. startArgs.duration = 300;
  188. startArgs.followType= EVfxFollowType.CastPoint;
  189. Context.Vfx.Play(startArgs);
  190. MoveTo(atkPosition, moveTime, 0, () =>
  191. {
  192. OnHitFrame();
  193. //等待拖尾消失
  194. MoveTo(Vector3.zero, moveTime, 0.2f, () =>
  195. {
  196. OnAttackEnd();
  197. onCompleted?.Invoke();
  198. });
  199. });
  200. }
  201. else
  202. {
  203. OnHitFrame();
  204. OnAttackEnd();
  205. onCompleted?.Invoke();
  206. }
  207. }
  208. public void Stop()
  209. {
  210. Context.ActionRoot.DOKill();
  211. Context.ActionRoot.localPosition = Vector3.zero;
  212. _cdAlarm?.Cancel();
  213. _cdAlarm = null;
  214. _targetView = null;
  215. _target = null;
  216. }
  217. protected override void OnDispose()
  218. {
  219. Stop();
  220. }
  221. private void MoveTo(Vector3 to, float duration, float delay, Action callback)
  222. {
  223. var tween = Context.ActionRoot.DOLocalMove(to, duration);
  224. if (delay > 0)
  225. {
  226. tween.SetDelay(delay);
  227. }
  228. tween.onComplete = () =>
  229. {
  230. callback.SafeInvoke();
  231. };
  232. }
  233. private void OnHitFrame()
  234. { // 攻击帧回调
  235. //TODO 目标受击
  236. if (_target == null || _target.State == EEntityState.Dead)
  237. return;
  238. var position = _targetView.Position;
  239. var hpValue = _targetView.GetComponent<HpComponent>().CalculateHit(-Context.Entity.Attr.Attack);
  240. EventSingle.Instance.Notify(EventDefine.GameMainMapHpAdd, new HpAddDto()
  241. {
  242. position = position,
  243. hpValue = hpValue
  244. });
  245. }
  246. private void OnAttackEnd()
  247. {
  248. _lastAtkTime = Context.Time.GetNowTime();
  249. //冷却计时
  250. var time = _lastAtkTime + Context.Entity.Attr.AttackCD;
  251. _cdAlarm = Context.Time.AddAlarm(() =>
  252. {
  253. Context.EnqueueSkill(0);
  254. }, time);
  255. }
  256. void IReset.Reset()
  257. {
  258. Stop();
  259. }
  260. }
  261. }