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.  
  92. public override void EnterTree()
  93. {
  94. if (!World.Enemy_InstanceList.Contains(this))
  95. {
  96. World.Enemy_InstanceList.Add(this);
  97. }
  98. }
  99.  
  100. public override void ExitTree()
  101. {
  102. World.Enemy_InstanceList.Remove(this);
  103. }
  104.  
  105. protected override void OnDie()
  106. {
  107. var effPos = Position + new Vector2(0, -Altitude);
  108. //血液特效
  109. var blood = ObjectManager.GetPoolItem<AutoDestroyParticles>(ResourcePath.prefab_effect_enemy_EnemyBlood0001_tscn);
  110. blood.Position = effPos - new Vector2(0, 12);
  111. blood.AddToActivityRoot(RoomLayerEnum.NormalLayer);
  112. blood.PlayEffect();
  113. var realVelocity = GetRealVelocity();
  114. //创建敌人碎片
  115. var count = Utils.Random.RandomRangeInt(3, 6);
  116. for (var i = 0; i < count; i++)
  117. {
  118. var debris = Create(Ids.Id_enemy_dead0001);
  119. debris.PutDown(effPos, RoomLayerEnum.NormalLayer);
  120. debris.MoveController.AddForce(Velocity + realVelocity);
  121. }
  122. //派发敌人死亡信号
  123. EventManager.EmitEvent(EventEnum.OnEnemyDie, this);
  124. base.OnDie();
  125. }
  126.  
  127. protected override void Process(float delta)
  128. {
  129. base.Process(delta);
  130. if (IsDie)
  131. {
  132. return;
  133. }
  134. //看向目标
  135. if (LookTarget != null && MountLookTarget)
  136. {
  137. var pos = LookTarget.Position;
  138. LookPosition = pos;
  139. //脸的朝向
  140. var gPos = Position;
  141. if (pos.X > gPos.X && Face == FaceDirection.Left)
  142. {
  143. Face = FaceDirection.Right;
  144. }
  145. else if (pos.X < gPos.X && Face == FaceDirection.Right)
  146. {
  147. Face = FaceDirection.Left;
  148. }
  149. //枪口跟随目标
  150. MountPoint.SetLookAt(pos);
  151. }
  152.  
  153. if (RoleState.CanPickUpWeapon)
  154. {
  155. //拾起武器操作
  156. DoPickUpWeapon();
  157. }
  158. }
  159.  
  160. public override bool IsAllWeaponTotalAmmoEmpty()
  161. {
  162. if (!_enemyAttribute.CanPickUpWeapon)
  163. {
  164. return false;
  165. }
  166. return base.IsAllWeaponTotalAmmoEmpty();
  167. }
  168.  
  169. protected override void OnHit(ActivityObject target, int damage, float angle, bool realHarm)
  170. {
  171. //受到伤害
  172. var state = StateController.CurrState;
  173. if (state == AIStateEnum.AiNormal)
  174. {
  175. LookTarget = target;
  176. //判断是否进入通知状态
  177. if (World.Enemy_InstanceList.FindIndex(enemy =>
  178. enemy != this && !enemy.IsDie && enemy.AffiliationArea == AffiliationArea &&
  179. enemy.StateController.CurrState == AIStateEnum.AiNormal) != -1)
  180. {
  181. //进入惊讶状态, 然后再进入通知状态
  182. StateController.ChangeState(AIStateEnum.AiAstonished, AIStateEnum.AiNotify);
  183. }
  184. else
  185. {
  186. //进入惊讶状态, 然后再进入跟随状态
  187. StateController.ChangeState(AIStateEnum.AiAstonished, AIStateEnum.AiTailAfter);
  188. }
  189. }
  190. else if (state == AIStateEnum.AiLeaveFor)
  191. {
  192. LookTarget = target;
  193. StateController.ChangeState(AIStateEnum.AiAstonished, AIStateEnum.AiTailAfter);
  194. }
  195. else if (state == AIStateEnum.AiFindAmmo)
  196. {
  197. if (LookTarget == null)
  198. {
  199. LookTarget = target;
  200. var findAmmo = (AiFindAmmoState)StateController.CurrStateBase;
  201. StateController.ChangeState(AIStateEnum.AiAstonished, AIStateEnum.AiFindAmmo, findAmmo.TargetWeapon);
  202. }
  203. }
  204. }
  205.  
  206. /// <summary>
  207. /// 从标记出生时调用, 预加载波不会调用
  208. /// </summary>
  209. public virtual void OnBornFromMark()
  210. {
  211. //罚站 0.7 秒
  212. StateController.Enable = false;
  213. this.CallDelay(0.7f, () => StateController.Enable = true);
  214. }
  215. }