AttackController.cs 15 KB

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