AttackController.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  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. [DisplayOnly]
  121. public bool isDemSummon;
  122. public void CopyTo(AttackInfo ai)
  123. {
  124. ai.damage = damage;
  125. ai.attackDir = attackDir;
  126. ai.blowUp = blowUp;
  127. ai.shotDown = shotDown;
  128. ai.weak = weak;
  129. ai.armor = armor;
  130. ai.changeDamage = changeDamage;
  131. ai.sustainedInjury = sustainedInjury;
  132. }
  133. }
  134. public class AttackController : MonoBehaviour
  135. {
  136. //攻击类型
  137. public enum AttackType
  138. {
  139. Melee = 0, //近战
  140. Shoot = 1, //射击
  141. Special = 2, //非普攻
  142. Dash = 3, //英灵刺客,后面请删掉
  143. }
  144. [System.Serializable]
  145. public struct SpineAniKey
  146. {
  147. public string aniName;
  148. public List<AttackKeyType> keys;
  149. }
  150. public enum KeyType
  151. {
  152. AttackStart,
  153. AttackEnd,
  154. }
  155. [System.Serializable]
  156. public struct AttackKeyType
  157. {
  158. public int attackMethod;
  159. public KeyType attackType;
  160. public string startKeyName;
  161. public float startKeyTime;
  162. public KeyType endType;
  163. public string endKeyName;
  164. public float endKeyTime;
  165. }
  166. [System.Serializable]
  167. public struct AttackMethod
  168. {
  169. [Header("起手式id=0,行军式id>=1")]
  170. public int id;
  171. [LabelText("攻击名称")]
  172. public string attackName;
  173. [LabelText("攻击类型")]
  174. public AttackType attackType;
  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. attackDistance = curAttackMethod.attackDistance;
  328. if (id == 0 && GetComponent<Demonic>())
  329. {
  330. attackInfo.isDemSummon = true;
  331. }
  332. else
  333. {
  334. attackInfo.isDemSummon = false;
  335. }
  336. }
  337. public void SetNextKeyTimes()
  338. {
  339. if (curKeyNum < keyTimes.Count)
  340. {
  341. nextStartKeyTime = keyTimes[curKeyNum];
  342. nextEndKeyTime = keyTimes[curKeyNum + 1];
  343. curKeyNum += 2;
  344. }
  345. }
  346. public virtual void Attack_summon()
  347. {
  348. owner.ani.Play("attack_summon", 0, 0);
  349. if (attackType == AttackType.Shoot)
  350. {
  351. attackTrigger.isShoot = true;
  352. attackTrigger.type = AttackTrigger.attackType.summon;
  353. }
  354. attackTime = owner.totalAttack_summonTime;
  355. attackKeyCount = 0;
  356. keyTimes = new List<float>();
  357. foreach (SpineAniKey sak in attackKeys)
  358. {
  359. if (sak.aniName == "attack_summon")
  360. {
  361. foreach (AttackKeyType akt in sak.keys)
  362. {
  363. keyTimes.Add(akt.startKeyTime);
  364. keyTimes.Add(akt.endKeyTime);
  365. }
  366. break;
  367. }
  368. }
  369. curKeyNum = 0;
  370. SetNextKeyTimes();
  371. switch (attackType)
  372. {
  373. case AttackType.Melee:
  374. attackTrigger.attackInfo = attackInfo;
  375. break;
  376. default:
  377. break;
  378. }
  379. ChooseAttack(attackMethod[0].id);
  380. owner.ChangeState(CharacterState.Attack);
  381. }
  382. public virtual void Attack_march(int id)
  383. {
  384. if (attackEffect != null)
  385. {
  386. if (effects.ContainsKey(attackEffect.name))
  387. {
  388. effect = effects[attackEffect.name];
  389. effect.SetActive(true);
  390. }
  391. else
  392. {
  393. effects[attackEffect.name] = Instantiate(attackEffect, owner.bodyTrans);
  394. effect = effects[attackEffect.name];
  395. effect.SetActive(true);
  396. }
  397. }
  398. Vector3 leftDir = owner.GetMoveDir();
  399. if (leftDir.x > 0.3f)
  400. {
  401. if (owner.bodyTrans.localScale.x > 0)
  402. {
  403. owner.Turn();
  404. }
  405. }
  406. else if (leftDir.x < -0.3f)
  407. {
  408. if (owner.bodyTrans.localScale.x < 0)
  409. {
  410. owner.Turn();
  411. }
  412. }
  413. owner.ani.Play("attack_march", 0, 0);
  414. if (attackType == AttackType.Shoot)
  415. {
  416. attackTrigger.isShoot = true;
  417. attackTrigger.type = AttackTrigger.attackType.march;
  418. }
  419. if (attackType == AttackType.Special)
  420. {
  421. skill.Attack();
  422. }
  423. attackTime = owner.totalAttack_marchTime;
  424. attackKeyCount = 0;
  425. keyTimes = new List<float>();
  426. foreach (SpineAniKey sak in attackKeys)
  427. {
  428. if (sak.aniName == "attack_march")
  429. {
  430. foreach (AttackKeyType akt in sak.keys)
  431. {
  432. keyTimes.Add(akt.startKeyTime);
  433. keyTimes.Add(akt.endKeyTime);
  434. break;
  435. }
  436. }
  437. }
  438. curKeyNum = 0;
  439. SetNextKeyTimes();
  440. attackTrigger.attackInfo = attackInfo;
  441. owner.ChangeState(CharacterState.Attack);
  442. }
  443. public virtual void AttackShootEvent(int attackId, int shootId)
  444. {
  445. GameObject bulletObj = PoolManager.Instantiate(bulletPrefab);
  446. Bullet bullet = bulletObj.GetComponent<Bullet>();
  447. Vector3 attackDir = attackInfo.attackDir.normalized;
  448. if (owner.bodyTrans.localScale.x < 0)
  449. {
  450. attackDir.x = -attackDir.x;
  451. }
  452. if (attackId == 1 && owner.Attack_summonShootCanTransmit)
  453. {
  454. bullet.canTransmit = true;
  455. }
  456. bullet.BeShoot(owner, shootPos[shootId].position, attackDir, shootTrack,
  457. shootAlwaysTrack, owner.attackTarget ? owner.attackTarget : null);
  458. }
  459. public void JudgeTriggerOnOff()
  460. {
  461. attackTime -= Time.deltaTime;
  462. attackKeyCount += Time.deltaTime;
  463. if (!isAttackTriggerOn && attackKeyCount >= nextStartKeyTime && attackKeyCount <= nextEndKeyTime)
  464. {
  465. isAttackTriggerOn = true;
  466. attackTrigger.gameObject.SetActive(true);
  467. }
  468. else if (isAttackTriggerOn && attackKeyCount >= nextEndKeyTime)
  469. {
  470. isAttackTriggerOn = false;
  471. attackTrigger.gameObject.SetActive(false);
  472. SetNextKeyTimes();
  473. }
  474. }
  475. }