AttackController.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using System;
  5. using Sirenix.OdinInspector;
  6. using System.Linq;
  7. //攻击所附带的状态
  8. public enum AttackEffect
  9. {
  10. Null = -1,
  11. //控制
  12. [LabelText("漂浮")]FloatState = 0,
  13. [LabelText("击飞")]BlowUp = 1,
  14. [LabelText("击落")]ShotDown = 2,
  15. [LabelText("击晕")]Weak = 3,
  16. //非控制
  17. [LabelText("穿甲")]ArmorPiercing,
  18. [LabelText("易伤")]Vulnerable,
  19. ChangeDamage, //更改攻击力
  20. SustainedInjury, //持续伤害
  21. Burn = 104, //灼烧
  22. //中毒
  23. //麻痹
  24. }
  25. [Serializable]
  26. public class AttackInfo
  27. {
  28. [LabelText("击打值")] public int attackValue;
  29. public int damage;
  30. public Vector3 attackDir;
  31. public AttackEffect[] attackEffect;
  32. //漂浮
  33. [Serializable]public struct FloatState
  34. {
  35. [LabelText("持续时间")] public float time;
  36. [LabelText("上升最大耗时")] public Vector2 upTime;
  37. [LabelText("往后退的速度")] public Vector2 backSpeed;
  38. [LabelText("旋转速度")] public Vector2 rotateSpeed;
  39. [LabelText("上升高度")] public Vector2 height;
  40. [LabelText("控制层级")] public int ControlOrder;
  41. }
  42. private bool ShowFloatStateValue() => attackEffect.Contains(AttackEffect.FloatState);
  43. [ShowIf("ShowFloatStateValue")][LabelText("漂浮参数")]
  44. public FloatState floatState;
  45. //击飞
  46. [Serializable]public struct BlowUp
  47. {
  48. public enum DirectionType
  49. {
  50. [LabelText("角色朝向方向")] Common,
  51. [LabelText("X轴方向以角色为中心向外")] Spread,
  52. }
  53. [LabelText("击飞模式")] public DirectionType directionType;
  54. [LabelText("方向")] public Vector3 dir;
  55. [LabelText("力")] public float force;
  56. [LabelText("落地后眩晕时间")] public float time;
  57. [LabelText("落地是否有伤害")] [ToggleLeft] public bool haveLandingDamage;
  58. [LabelText("落地伤害")] [ShowIf("haveLandingDamage")] public int landingDamage;
  59. [LabelText("控制层级")] public int ControlOrder;
  60. }
  61. private bool ShowBlowUpValue() => attackEffect.Contains(AttackEffect.BlowUp);
  62. [ShowIf("ShowBlowUpValue")][LabelText("击飞参数")]
  63. public BlowUp blowUp;
  64. //击落
  65. [Serializable]public struct ShotDown
  66. {
  67. public enum DirectionType
  68. {
  69. [LabelText("角色朝向方向")] Common,
  70. [LabelText("X轴方向以角色为中心向外")] Spread,
  71. }
  72. [LabelText("击落模式")] public DirectionType directionType;
  73. [LabelText("方向")] public Vector3 dir;
  74. [LabelText("力")] public float force;
  75. [LabelText("落地后眩晕时间")] public float time;
  76. [LabelText("落地是否有伤害")] [ToggleLeft]public bool haveLandingDamage;
  77. [LabelText("落地伤害")] [ShowIf("haveLandingDamage")] public int landingDamage;
  78. [LabelText("控制层级")] public int ControlOrder;
  79. }
  80. private bool ShowShotDownValue() => attackEffect.Contains(AttackEffect.ShotDown);
  81. [ShowIf("ShowShotDownValue")][LabelText("击落参数")]
  82. public ShotDown shotDown;
  83. //击晕
  84. [Serializable]public struct Weak
  85. {
  86. [LabelText("持续时间")] public float time;
  87. [LabelText("控制层级")] public int ControlOrder;
  88. }
  89. private bool ShowWeakValue() => attackEffect.Contains(AttackEffect.Weak);
  90. [ShowIf("ShowWeakValue")][LabelText("击晕参数")]
  91. public Weak weak;
  92. //穿甲
  93. [Serializable]public struct ArmorPiercing
  94. {
  95. [LabelText("穿甲值")]
  96. public int rate;
  97. }
  98. private bool ShowArmorValue() => attackEffect.Contains(AttackEffect.ArmorPiercing);
  99. [ShowIf("ShowArmorValue")][LabelText("穿甲参数")]
  100. public ArmorPiercing armorPiercing;
  101. //易伤
  102. [Serializable]public struct Vulnerable
  103. {
  104. [LabelText("倍率")]
  105. public float rate;
  106. [LabelText("持续时间")]
  107. public float time;
  108. }
  109. private bool ShowVulnerable() => attackEffect.Contains(AttackEffect.Vulnerable);
  110. [ShowIf("ShowVulnerable")][LabelText("易伤参数")]
  111. public Vulnerable vulnerable;
  112. //增加和减少攻击力
  113. [Serializable]public struct ChangeDamage
  114. {
  115. public float rate; //增加或减少攻击倍率
  116. }
  117. private bool ShowChangeDamageValue() => attackEffect.Contains(AttackEffect.ChangeDamage);
  118. [ShowIf("ShowChangeDamageValue")][LabelText("更改攻击力参数")]
  119. public ChangeDamage changeDamage;
  120. //持续伤害
  121. [Serializable]public struct SustainedInjury
  122. {
  123. public float damage; //每次造成的伤害数值
  124. }
  125. private bool ShowSustainedInjuryValue() => attackEffect.Contains(AttackEffect.SustainedInjury);
  126. [ShowIf("ShowSustainedInjuryValue")][LabelText("持续伤害参数")]
  127. public SustainedInjury sustainedInjury;
  128. [DisplayOnly]
  129. public bool isDemSummon;
  130. public void CopyTo(AttackInfo ai)
  131. {
  132. ai.damage = damage;
  133. ai.attackDir = attackDir;
  134. ai.blowUp = blowUp;
  135. ai.shotDown = shotDown;
  136. ai.weak = weak;
  137. ai.armorPiercing = armorPiercing;
  138. ai.changeDamage = changeDamage;
  139. ai.sustainedInjury = sustainedInjury;
  140. }
  141. }
  142. public class AttackController : MonoBehaviour
  143. {
  144. //攻击类型
  145. public enum AttackType
  146. {
  147. Melee = 0, //近战
  148. Shoot = 1, //射击
  149. Special = 2, //非普攻
  150. Dash = 3, //英灵刺客,后面请删掉
  151. }
  152. [System.Serializable]
  153. public struct SpineAniKey
  154. {
  155. public string aniName;
  156. public List<AttackKeyType> keys;
  157. }
  158. public enum KeyType
  159. {
  160. AttackStart,
  161. AttackEnd,
  162. }
  163. [System.Serializable]
  164. public struct AttackKeyType
  165. {
  166. public int attackMethod;
  167. public KeyType attackType;
  168. public string startKeyName;
  169. public float startKeyTime;
  170. public KeyType endType;
  171. public string endKeyName;
  172. public float endKeyTime;
  173. }
  174. [System.Serializable]
  175. public struct AttackMethod
  176. {
  177. [Header("起手式id=0,行军式id>=1")]
  178. public int id;
  179. [LabelText("攻击名称")]
  180. public string attackName;
  181. [LabelText("攻击类型")]
  182. public AttackType attackType;
  183. [Header("攻击参数")]
  184. public AttackInfo attackInfo;
  185. public AttackTrigger attackTrigger;
  186. [Header("攻击距离")]
  187. public float attackDistance;
  188. [ShowIf("needToChange")]
  189. public float maxAttackDis, minAttackDis;
  190. public bool needToChange;
  191. [Header("目标")]
  192. public List<TargetType> targetTypes;
  193. public bool canHitFly;
  194. public int armorPiercing; //穿甲率
  195. [Header("远程单位")]
  196. [ShowIf("attackType",AttackType.Shoot)]
  197. public GameObject bulletPrefab; //子弹
  198. [ShowIf("attackType", AttackType.Shoot)]
  199. public List<Transform> shootPos; //子弹发射位置
  200. [ShowIf("attackType", AttackType.Shoot)][LabelText("水平向上最大夹角")]
  201. public float maxUpAngle;
  202. [ShowIf("attackType", AttackType.Shoot)][LabelText("水平向下最大夹角")]
  203. public float maxDownAngle;
  204. [ShowIf("attackType", AttackType.Shoot)]
  205. public bool shootTrack; //是否初始时瞄准目标
  206. [ShowIf("attackType", AttackType.Shoot)]
  207. public bool shootAlwaysTrack; //是否始终追踪
  208. [Header("特殊攻击")]
  209. [ShowIf("attackType", AttackType.Special)]
  210. public SpecialSkills skill;
  211. }
  212. private Character owner;
  213. [Header("所有攻击帧事件及时间")]
  214. public List<SpineAniKey> attackKeys;
  215. public List<float> keyTimes; //所有的帧事件时间
  216. [DisplayOnly]
  217. public float attackTime; //攻击剩余时间
  218. [HideInInspector]
  219. public float attackKeyCount; //攻击进行时间
  220. [HideInInspector]
  221. public float nextStartKeyTime, nextEndKeyTime;
  222. [HideInInspector]
  223. public int curKeyNum; //当前锁定到第几个帧事件
  224. [Header("攻击类型")]
  225. public AttackType attackType;
  226. [Header("攻击参数")]
  227. [LabelText("攻击间隔")]
  228. public float attackInterval;
  229. [DisplayOnly]
  230. public int curDamage;
  231. [DisplayOnly]
  232. public bool canHitFly;
  233. [DisplayOnly]
  234. public AttackInfo attackInfo;
  235. [DisplayOnly]
  236. public GameObject addAttackEffect;
  237. [DisplayOnly]
  238. public SpecialSkills skill;
  239. [DisplayOnly]
  240. public float attackDistance;
  241. [Header("攻击范围")]
  242. [HideInInspector]
  243. public AttackTrigger attackTrigger;
  244. [HideInInspector]
  245. public bool isAttackTriggerOn = false; //当前Attack Trigger是否开启
  246. [Header("远程单位")]
  247. [HideInInspector]
  248. public GameObject bulletPrefab; //子弹
  249. [HideInInspector]
  250. public List<Transform> shootPos; //子弹发射位置
  251. [HideInInspector]
  252. public bool shootTrack = false; //是否初始时瞄准目标
  253. [HideInInspector]
  254. public bool shootAlwaysTrack = false; //是否始终追踪
  255. [Header("目标")]
  256. [HideInInspector]
  257. public List<TargetType> targetTypes;
  258. [DisplayOnly]
  259. public List<Character> beTargetCharacter = new List<Character>(); //被哪些锁定
  260. //public float getDistanceOffset = 0f;
  261. [Header("攻击模式")]
  262. public AttackMethod[] attackMethod;
  263. [HideInInspector]
  264. public AttackMethod curAttackMethod;
  265. private SoldierLevelRecord slr;
  266. public void Init()
  267. {
  268. owner = GetComponent<Character>();
  269. if (attackMethod.Length > 0)
  270. {
  271. attackInfo = attackMethod[0].attackInfo;
  272. curDamage = attackInfo.damage;
  273. }
  274. for (int i = 0; i < attackMethod.Length; i++)
  275. {
  276. if (attackMethod[i].needToChange)
  277. {
  278. attackMethod[i].attackDistance = UnityEngine.Random.Range(attackMethod[i].minAttackDis,
  279. attackMethod[i].maxAttackDis);
  280. }
  281. }
  282. attackDistance = attackMethod[0].attackDistance;
  283. slr = GameManager.instance.GetComponent<SoldierLevelRecord>();
  284. }
  285. private void OnEnable()
  286. {
  287. if (attackTrigger != null)
  288. {
  289. attackTrigger.gameObject.SetActive(false);
  290. }
  291. }
  292. public void ChooseAttack(int id)
  293. {
  294. //默认起手式只使用一次,id=0为起手式
  295. curAttackMethod = attackMethod[id];
  296. attackType = curAttackMethod.attackType;
  297. canHitFly = curAttackMethod.canHitFly;
  298. attackInfo = curAttackMethod.attackInfo;
  299. curDamage = attackInfo.damage;
  300. attackTrigger = curAttackMethod.attackTrigger;
  301. Demonic dem = owner.GetComponent<Demonic>();
  302. if (dem)
  303. {
  304. for (int i = 0; i < 3; i++)
  305. {
  306. if (GameManager.curSoldiers[i] == dem.soldierType)
  307. {
  308. attackTrigger.attackInfo.armorPiercing.rate += slr.seb[i].armorPiercing;
  309. }
  310. }
  311. }
  312. bulletPrefab = curAttackMethod.bulletPrefab;
  313. shootPos = curAttackMethod.shootPos;
  314. shootTrack = curAttackMethod.shootTrack;
  315. shootAlwaysTrack = curAttackMethod.shootAlwaysTrack;
  316. targetTypes = curAttackMethod.targetTypes;
  317. if (attackType == AttackType.Special && skill == null)
  318. {
  319. skill = curAttackMethod.skill;
  320. skill.owner = owner;
  321. }
  322. attackDistance = curAttackMethod.attackDistance;
  323. if (id == 0 && GetComponent<Demonic>())
  324. {
  325. attackInfo.isDemSummon = true;
  326. }
  327. else
  328. {
  329. attackInfo.isDemSummon = false;
  330. }
  331. }
  332. public void SetNextKeyTimes()
  333. {
  334. if (curKeyNum < keyTimes.Count)
  335. {
  336. nextStartKeyTime = keyTimes[curKeyNum];
  337. nextEndKeyTime = keyTimes[curKeyNum + 1];
  338. curKeyNum += 2;
  339. }
  340. }
  341. public virtual void Attack_summon()
  342. {
  343. owner.ani.Play("attack_summon", 0, 0);
  344. if (attackType == AttackType.Shoot)
  345. {
  346. attackTrigger.isShoot = true;
  347. attackTrigger.type = AttackTrigger.attackType.summon;
  348. }
  349. attackTime = owner.totalAttack_summonTime;
  350. attackKeyCount = 0;
  351. keyTimes = new List<float>();
  352. foreach (SpineAniKey sak in attackKeys)
  353. {
  354. if (sak.aniName == "attack_summon")
  355. {
  356. foreach (AttackKeyType akt in sak.keys)
  357. {
  358. keyTimes.Add(akt.startKeyTime);
  359. keyTimes.Add(akt.endKeyTime);
  360. }
  361. break;
  362. }
  363. }
  364. curKeyNum = 0;
  365. SetNextKeyTimes();
  366. switch (attackType)
  367. {
  368. case AttackType.Melee:
  369. attackTrigger.attackInfo = attackInfo;
  370. break;
  371. default:
  372. break;
  373. }
  374. ChooseAttack(attackMethod[0].id);
  375. owner.ChangeState(CharacterState.Attack);
  376. }
  377. public virtual void Attack_march(int id)
  378. {
  379. Vector3 leftDir = owner.GetMoveDir();
  380. if (leftDir.x > 0.3f)
  381. {
  382. if (owner.bodyTrans.localScale.x > 0)
  383. {
  384. owner.Turn();
  385. }
  386. }
  387. else if (leftDir.x < -0.3f)
  388. {
  389. if (owner.bodyTrans.localScale.x < 0)
  390. {
  391. owner.Turn();
  392. }
  393. }
  394. owner.ani.Play("attack_march", 0, 0);
  395. if (attackType == AttackType.Shoot)
  396. {
  397. attackTrigger.isShoot = true;
  398. attackTrigger.type = AttackTrigger.attackType.march;
  399. }
  400. if (attackType == AttackType.Special)
  401. {
  402. skill.Attack();
  403. }
  404. attackTime = owner.totalAttack_marchTime;
  405. attackKeyCount = 0;
  406. keyTimes = new List<float>();
  407. foreach (SpineAniKey sak in attackKeys)
  408. {
  409. if (sak.aniName == "attack_march")
  410. {
  411. foreach (AttackKeyType akt in sak.keys)
  412. {
  413. keyTimes.Add(akt.startKeyTime);
  414. keyTimes.Add(akt.endKeyTime);
  415. break;
  416. }
  417. }
  418. }
  419. curKeyNum = 0;
  420. SetNextKeyTimes();
  421. attackTrigger.attackInfo = attackInfo;
  422. owner.ChangeState(CharacterState.Attack);
  423. }
  424. public virtual void AttackShootEvent(int attackId, int shootId)
  425. {
  426. GameObject bulletObj = PoolManager.Instantiate(bulletPrefab);
  427. Bullet bullet = bulletObj.GetComponent<Bullet>();
  428. Vector3 attackDir = attackInfo.attackDir.normalized;
  429. if (owner.bodyTrans.localScale.x < 0)
  430. {
  431. attackDir.x = -attackDir.x;
  432. }
  433. if (attackId == 1 && owner.Attack_summonShootCanTransmit)
  434. {
  435. bullet.canTransmit = true;
  436. }
  437. bullet.BeShoot(owner, shootPos[shootId].position, attackDir, shootTrack,
  438. shootAlwaysTrack, owner.attackTarget ? owner.attackTarget : null);
  439. }
  440. public void JudgeTriggerOnOff()
  441. {
  442. attackTime -= Time.deltaTime;
  443. attackKeyCount += Time.deltaTime;
  444. if (!isAttackTriggerOn && attackKeyCount >= nextStartKeyTime && attackKeyCount <= nextEndKeyTime)
  445. {
  446. isAttackTriggerOn = true;
  447. attackTrigger.gameObject.SetActive(true);
  448. }
  449. else if (isAttackTriggerOn && attackKeyCount >= nextEndKeyTime)
  450. {
  451. isAttackTriggerOn = false;
  452. attackTrigger.gameObject.SetActive(false);
  453. SetNextKeyTimes();
  454. }
  455. }
  456. }