Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / enemy / state / AiAttackState.cs
@小李xl 小李xl on 25 Feb 2024 9 KB 敌人添加攻击间隔配置
  1. using System;
  2. using Godot;
  3.  
  4. namespace EnemyState;
  5.  
  6. /// <summary>
  7. /// ai 攻击状态
  8. /// </summary>
  9. public class AiAttackState : StateBase<Enemy, AIStateEnum>
  10. {
  11. /// <summary>
  12. /// 上一个状态
  13. /// </summary>
  14. public AIStateEnum PrevState;
  15.  
  16. /// <summary>
  17. /// 武器攻击状态
  18. /// </summary>
  19. public AiAttackEnum AttackState;
  20.  
  21. //是否移动结束
  22. private bool _isMoveOver;
  23.  
  24. //移动停顿计时器
  25. private float _pauseTimer;
  26. private bool _moveFlag;
  27. //下一个移动点
  28. private Vector2 _nextPosition;
  29. //上一帧位置
  30. private Vector2 _prevPos;
  31. //卡在一个位置的时间
  32. private float _lockTimer;
  33. //进入状态的时候是否有武器
  34. private bool _hasWeapon = true;
  35. public AiAttackState() : base(AIStateEnum.AiAttack)
  36. {
  37. }
  38.  
  39. public override void Enter(AIStateEnum prev, params object[] args)
  40. {
  41. if (Master.LookTarget == null)
  42. {
  43. throw new Exception("进入 AIAdvancedStateEnum.AiAttack 状态时角色没有攻击目标!");
  44. }
  45. var weapon = Master.WeaponPack.ActiveItem;
  46.  
  47. if (weapon != null)
  48. {
  49. _hasWeapon = true;
  50. if (Master.IsAttack || !weapon.TriggerIsReady())
  51. {
  52. throw new Exception("进入 AIAdvancedStateEnum.AiAttack 状态时角色武器还无法触动扳机!");
  53. }
  54. }
  55. else
  56. {
  57. _hasWeapon = false;
  58. if (Master.IsAttack)
  59. {
  60. throw new Exception("进入 AIAdvancedStateEnum.AiAttack 状态时角色攻击状态还没准备好");
  61. }
  62. }
  63. Master.BasisVelocity = Vector2.Zero;
  64. AttackState = AiAttackEnum.None;
  65. Master.LockTargetTime = 0;
  66. PrevState = prev;
  67. _isMoveOver = true;
  68. _pauseTimer = 0;
  69. _moveFlag = false;
  70. }
  71.  
  72. public override void Exit(AIStateEnum next)
  73. {
  74. Master.MountLookTarget = true;
  75. Master.LockTargetTime = 0;
  76. }
  77.  
  78. public override void Process(float delta)
  79. {
  80. //更新标记位置
  81. Master.UpdateMarkTargetPosition();
  82.  
  83. if (_hasWeapon)
  84. {
  85. WeaponRoleProcess(delta);
  86. }
  87. else
  88. {
  89. NoWeaponRoleProcess(delta);
  90. }
  91. }
  92.  
  93. //有武器的敌人更新逻辑
  94. private void WeaponRoleProcess(float delta)
  95. {
  96. var weapon = Master.WeaponPack.ActiveItem;
  97. if (weapon == null)
  98. {
  99. //攻击结束
  100. ChangeState(PrevState);
  101. }
  102. else if (AttackState == AiAttackEnum.AttackInterval) //攻击完成
  103. {
  104. if (weapon.GetAttackTimer() <= 0) //攻击冷却完成
  105. {
  106. Master.MountLookTarget = true;
  107. //这里要做换弹判断, 还有上膛判断
  108. if (weapon.CurrAmmo <= 0) //换弹判断
  109. {
  110. if (!weapon.Reloading)
  111. {
  112. weapon.Reload();
  113. }
  114. }
  115. else if (weapon.GetBeLoadedStateState() != 2) //上膛
  116. {
  117. if (weapon.GetBeLoadedStateState() == 0)
  118. {
  119. weapon.BeLoaded();
  120. }
  121. }
  122. else
  123. {
  124. //攻击结束
  125. ChangeState(PrevState);
  126. }
  127. }
  128. MoveHandler(delta);
  129. }
  130. else //攻击状态
  131. {
  132. //触发扳机
  133. AttackState = weapon.AiTriggerAttackState(AttackState);
  134.  
  135. if (AttackState == AiAttackEnum.LockingTime) //锁定玩家状态
  136. {
  137. Master.LockTargetTime += delta;
  138.  
  139. var aiLockRemainderTime = Master.GetLockRemainderTime();
  140. Master.MountLookTarget = aiLockRemainderTime >= weapon.Attribute.AiAttackAttr.LockAngleTime;
  141. //更新瞄准辅助线
  142. if (weapon.Attribute.AiAttackAttr.ShowSubline)
  143. {
  144. if (Master.SubLine == null)
  145. {
  146. Master.InitSubLine();
  147. }
  148. else
  149. {
  150. Master.SubLine.Enable = true;
  151. }
  152.  
  153. //播放警告删掉动画
  154. if (!Master.SubLine.IsPlayWarnAnimation && aiLockRemainderTime <= 0.5f)
  155. {
  156. Master.SubLine.PlayWarnAnimation(0.5f);
  157. }
  158. }
  159. if (weapon.Attribute.AiAttackAttr.LockingStand) //锁定目标时站立不动
  160. {
  161. Master.DoIdle();
  162. }
  163. else //正常移动
  164. {
  165. MoveHandler(delta);
  166. }
  167. }
  168. else
  169. {
  170. Master.LockTargetTime = 0;
  171. //关闭辅助线
  172. if (Master.SubLine != null)
  173. {
  174. Master.SubLine.Enable = false;
  175. }
  176.  
  177. if (AttackState == AiAttackEnum.Attack || AttackState == AiAttackEnum.AttackInterval)
  178. {
  179. if (weapon.Attribute.AiAttackAttr.AttackLockAngle) //开火时锁定枪口角度
  180. {
  181. //连发状态锁定角度
  182. Master.MountLookTarget = !(weapon.GetContinuousCount() > 0 || weapon.GetAttackTimer() > 0);
  183. }
  184. else
  185. {
  186. Master.MountLookTarget = true;
  187. }
  188. }
  189. else
  190. {
  191. Master.MountLookTarget = true;
  192. }
  193. if (AttackState == AiAttackEnum.Attack && weapon.Attribute.AiAttackAttr.FiringStand) //开火时站立不动
  194. {
  195. Master.DoIdle();
  196. }
  197. else //正常移动
  198. {
  199. MoveHandler(delta);
  200. }
  201.  
  202. if (AttackState == AiAttackEnum.AttackInterval) //触发攻击完成
  203. {
  204. Master.AttackTimer = weapon.Attribute.TriggerInterval + Master.EnemyRoleState.AttackInterval;
  205. }
  206. }
  207. }
  208. }
  209.  
  210. //没有武器的敌人攻击逻辑
  211. private void NoWeaponRoleProcess(float delta)
  212. {
  213. var weapon = Master.WeaponPack.ActiveItem;
  214. if (weapon != null)
  215. {
  216. //找到武器了, 攻击结束
  217. ChangeState(PrevState);
  218. }
  219. else if (Master.AttackTimer > 0 || Master.MeleeAttackTimer > 0) //攻击结束
  220. {
  221. ChangeState(PrevState);
  222. }
  223. else //攻击状态
  224. {
  225. Master.Attack();
  226. }
  227. }
  228. private void MoveHandler(float delta)
  229. {
  230.  
  231. if (_pauseTimer >= 0)
  232. {
  233. Master.AnimatedSprite.Play(AnimatorNames.Idle);
  234. _pauseTimer -= delta;
  235. }
  236. else if (_isMoveOver) //移动已经完成
  237. {
  238. RunOver(Master.LookTarget.Position);
  239. _isMoveOver = false;
  240. }
  241. else
  242. {
  243. var masterPosition = Master.Position;
  244. if (_lockTimer >= 1) //卡在一个点超过一秒
  245. {
  246. RunOver(Master.LookTarget.Position);
  247. _isMoveOver = false;
  248. _lockTimer = 0;
  249. }
  250. else if (Master.NavigationAgent2D.IsNavigationFinished()) //到达终点
  251. {
  252. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.5f);
  253. _isMoveOver = true;
  254. _moveFlag = false;
  255. //站立
  256. Master.DoIdle();
  257. }
  258. else if (!_moveFlag)
  259. {
  260. _moveFlag = true;
  261. //移动
  262. Master.DoMove();
  263. }
  264. else
  265. {
  266. var lastSlideCollision = Master.GetLastSlideCollision();
  267. if (lastSlideCollision != null && lastSlideCollision.GetCollider() is Role) //碰到其他角色
  268. {
  269. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.3f);
  270. _isMoveOver = true;
  271. _moveFlag = false;
  272. //站立
  273. Master.DoIdle();
  274. }
  275. else
  276. {
  277. //移动
  278. Master.DoMove();
  279. }
  280.  
  281. if (_prevPos.DistanceSquaredTo(masterPosition) <= 1 * delta)
  282. {
  283. _lockTimer += delta;
  284. }
  285. else
  286. {
  287. _lockTimer = 0;
  288. _prevPos = masterPosition;
  289. }
  290. }
  291. }
  292. }
  293.  
  294. private void RunOver(Vector2 targetPos)
  295. {
  296. var weapon = Master.WeaponPack.ActiveItem;
  297. var distance = (int)(weapon == null ? 150 : (Utils.GetConfigRangeStart(weapon.Attribute.Bullet.DistanceRange) * 0.7f));
  298. _nextPosition = new Vector2(
  299. targetPos.X + Utils.Random.RandomRangeInt(-distance, distance),
  300. targetPos.Y + Utils.Random.RandomRangeInt(-distance, distance)
  301. );
  302. Master.NavigationAgent2D.TargetPosition = _nextPosition;
  303. }
  304. }