Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / enemy / Enemy.cs
  1.  
  2. using System;
  3. using System.Collections.Generic;
  4. using Config;
  5. using AiState;
  6. using Godot;
  7.  
  8. /// <summary>
  9. /// 敌人,可以携带武器
  10. /// </summary>
  11. [Tool]
  12. public partial class Enemy : AiRole
  13. {
  14. /// <summary>
  15. /// 敌人属性
  16. /// </summary>
  17. private ExcelConfig.EnemyBase _enemyAttribute;
  18.  
  19. private static bool _init = false;
  20. private static Dictionary<string, ExcelConfig.EnemyBase> _enemyAttributeMap =
  21. new Dictionary<string, ExcelConfig.EnemyBase>();
  22. /// <summary>
  23. /// 初始化敌人属性数据
  24. /// </summary>
  25. public static void InitEnemyAttribute()
  26. {
  27. if (_init)
  28. {
  29. return;
  30. }
  31.  
  32. _init = true;
  33. foreach (var enemyAttr in ExcelConfig.EnemyBase_List)
  34. {
  35. if (enemyAttr.Activity != null)
  36. {
  37. if (!_enemyAttributeMap.TryAdd(enemyAttr.Activity.Id, enemyAttr))
  38. {
  39. Debug.LogError("发现重复注册的敌人属性: " + enemyAttr.Id);
  40. }
  41. }
  42. }
  43. }
  44.  
  45. /// <summary>
  46. /// 根据 ActivityBase.Id 获取对应敌人的属性数据
  47. /// </summary>
  48. public static ExcelConfig.EnemyBase GetEnemyAttribute(string itemId)
  49. {
  50. if (itemId == null)
  51. {
  52. return null;
  53. }
  54. if (_enemyAttributeMap.TryGetValue(itemId, out var attr))
  55. {
  56. return attr;
  57. }
  58.  
  59. throw new Exception($"敌人'{itemId}'没有在 EnemyBase 表中配置属性数据!");
  60. }
  61. public override void OnInit()
  62. {
  63. base.OnInit();
  64. Camp = CampEnum.Camp2;
  65.  
  66. RoleState.MoveSpeed = 20;
  67.  
  68. MaxHp = 20;
  69. Hp = 20;
  70. }
  71.  
  72. protected override RoleState OnCreateRoleState()
  73. {
  74. var roleState = new RoleState();
  75. var enemyBase = GetEnemyAttribute(ActivityBase.Id).Clone();
  76. _enemyAttribute = enemyBase;
  77.  
  78. MaxHp = enemyBase.Hp;
  79. Hp = enemyBase.Hp;
  80. roleState.CanPickUpWeapon = enemyBase.CanPickUpWeapon;
  81. roleState.MoveSpeed = enemyBase.MoveSpeed;
  82. roleState.Acceleration = enemyBase.Acceleration;
  83. roleState.Friction = enemyBase.Friction;
  84. ViewRange = enemyBase.ViewRange;
  85. TailAfterViewRange = enemyBase.TailAfterViewRange;
  86. BackViewRange = enemyBase.BackViewRange;
  87. AttackInterval = enemyBase.AttackInterval;
  88. roleState.Gold = Mathf.Max(0, Utils.Random.RandomConfigRange(enemyBase.Gold));
  89. return roleState;
  90. }
  91. protected override void OnDie()
  92. {
  93. var effPos = Position + new Vector2(0, -Altitude);
  94. //血液特效
  95. var blood = ObjectManager.GetPoolItem<AutoDestroyParticles>(ResourcePath.prefab_effect_enemy_EnemyBlood0001_tscn);
  96. blood.Position = effPos - new Vector2(0, 12);
  97. blood.AddToActivityRoot(RoomLayerEnum.NormalLayer);
  98. blood.PlayEffect();
  99. var realVelocity = GetRealVelocity();
  100. //创建敌人碎片
  101. var count = Utils.Random.RandomRangeInt(3, 6);
  102. for (var i = 0; i < count; i++)
  103. {
  104. var debris = Create(Ids.Id_enemy_dead0001);
  105. debris.PutDown(effPos, RoomLayerEnum.NormalLayer);
  106. debris.MoveController.AddForce(Velocity + realVelocity);
  107. }
  108. //派发敌人死亡信号
  109. EventManager.EmitEvent(EventEnum.OnEnemyDie, this);
  110. base.OnDie();
  111. }
  112.  
  113. protected override void Process(float delta)
  114. {
  115. base.Process(delta);
  116. if (IsDie)
  117. {
  118. return;
  119. }
  120. //看向目标
  121. if (LookTarget != null && MountLookTarget)
  122. {
  123. if (LookTarget.IsDestroyed)
  124. {
  125. LookTarget = null;
  126. }
  127. else
  128. {
  129. var pos = LookTarget.Position;
  130. LookPosition = pos;
  131. //脸的朝向
  132. var gPos = Position;
  133. if (pos.X > gPos.X && Face == FaceDirection.Left)
  134. {
  135. Face = FaceDirection.Right;
  136. }
  137. else if (pos.X < gPos.X && Face == FaceDirection.Right)
  138. {
  139. Face = FaceDirection.Left;
  140. }
  141. //枪口跟随目标
  142. MountPoint.SetLookAt(pos);
  143. }
  144. }
  145.  
  146. if (RoleState.CanPickUpWeapon)
  147. {
  148. //拾起武器操作
  149. DoPickUpWeapon();
  150. }
  151. }
  152.  
  153. public override bool IsAllWeaponTotalAmmoEmpty()
  154. {
  155. if (!_enemyAttribute.CanPickUpWeapon)
  156. {
  157. return false;
  158. }
  159. return base.IsAllWeaponTotalAmmoEmpty();
  160. }
  161.  
  162. protected override void OnHit(ActivityObject target, int damage, float angle, bool realHarm)
  163. {
  164. //受到伤害
  165. var state = StateController.CurrState;
  166. if (state == AIStateEnum.AiNormal)
  167. {
  168. LookTarget = target;
  169. //判断是否进入通知状态
  170. if (World.Role_InstanceList.FindIndex(role =>
  171. role is AiRole enemy &&
  172. enemy != this && !enemy.IsDie && enemy.AffiliationArea == AffiliationArea &&
  173. enemy.StateController.CurrState == AIStateEnum.AiNormal) != -1)
  174. {
  175. //进入惊讶状态, 然后再进入通知状态
  176. StateController.ChangeState(AIStateEnum.AiAstonished, AIStateEnum.AiNotify);
  177. }
  178. else
  179. {
  180. //进入惊讶状态, 然后再进入跟随状态
  181. StateController.ChangeState(AIStateEnum.AiAstonished, AIStateEnum.AiTailAfter);
  182. }
  183. }
  184. else if (state == AIStateEnum.AiLeaveFor)
  185. {
  186. LookTarget = target;
  187. StateController.ChangeState(AIStateEnum.AiAstonished, AIStateEnum.AiTailAfter);
  188. }
  189. else if (state == AIStateEnum.AiFindAmmo)
  190. {
  191. if (LookTarget == null)
  192. {
  193. LookTarget = target;
  194. var findAmmo = (AiFindAmmoState)StateController.CurrStateBase;
  195. StateController.ChangeState(AIStateEnum.AiAstonished, AIStateEnum.AiFindAmmo, findAmmo.TargetWeapon);
  196. }
  197. }
  198. }
  199.  
  200. /// <summary>
  201. /// 从标记出生时调用, 预加载波不会调用
  202. /// </summary>
  203. public virtual void OnBornFromMark()
  204. {
  205. //罚站 0.7 秒
  206. StateController.Enable = false;
  207. this.CallDelay(0.7f, () => StateController.Enable = true);
  208. }
  209. }