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