AttackProcess.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using Photon.Pun;
  5. using System;
  6. using System.Linq;
  7. using UnityEngine.UI;
  8. public class AttackProcess : MonoBehaviourPunCallbacks
  9. {
  10. public Permanent AttackingPermanent { get; private set; } = null;
  11. public Permanent DefendingPermanent { get; private set; } = null;
  12. public int AttackCount { get; set; } = 0;
  13. public bool IsAttacking { get; set; } = false;
  14. public bool HasDefender { get; set; } = false;
  15. public bool IsBlocking { get; set; } = false;
  16. public CardSource SecurityDigimon { get; set; } = null;
  17. public bool DoSecurityCheck { get; set; } = false;
  18. public bool IsEndAttack { get; set; } = false;
  19. public Hashtable EffectHashtable { get; set; } = null;
  20. public Hashtable CounterEffectHashtable { get; set; } = null;
  21. public AttackState State { get; set; } = AttackState.None;
  22. public enum AttackState
  23. {
  24. None,
  25. Counter,
  26. Block,
  27. Battle,
  28. End
  29. }
  30. public bool ActiveAttack()
  31. {
  32. return State != null && State != AttackState.None;
  33. }
  34. public IEnumerator ProcessNextState()
  35. {
  36. switch (State)
  37. {
  38. case AttackState.Counter:
  39. yield return ContinuousController.instance.StartCoroutine(CounterTiming());
  40. break;
  41. case AttackState.Block:
  42. yield return ContinuousController.instance.StartCoroutine(BlockTiming());
  43. break;
  44. case AttackState.Battle:
  45. yield return ContinuousController.instance.StartCoroutine(DetermineAttackOutcome());
  46. break;
  47. case AttackState.End:
  48. yield return ContinuousController.instance.StartCoroutine(EndAttack());
  49. break;
  50. default:
  51. yield break;
  52. }
  53. }
  54. void SetAttackerDefender(Permanent attackingPermanent, Permanent defendingPermanent)
  55. {
  56. AttackingPermanent = attackingPermanent;
  57. DefendingPermanent = defendingPermanent;
  58. if (defendingPermanent != null)
  59. HasDefender = true;
  60. }
  61. public IEnumerator Attack(Permanent attackingPermanent, Permanent defendingPermanent, ICardEffect attackEffect, bool withoutTap = false, Func<IEnumerator> beforeOnAttackCoroutine = null)
  62. {
  63. if (IsAttacking)
  64. {
  65. if (beforeOnAttackCoroutine != null)
  66. {
  67. yield return ContinuousController.instance.StartCoroutine(beforeOnAttackCoroutine());
  68. }
  69. yield break;
  70. }
  71. AttackingPermanent = null;
  72. DefendingPermanent = null;
  73. DoSecurityCheck = false;
  74. IsBlocking = false;
  75. SecurityDigimon = null;
  76. IsAttacking = false;
  77. HasDefender = false;
  78. IsEndAttack = false;
  79. CounterEffectHashtable = null;
  80. SetAttackerDefender(attackingPermanent, defendingPermanent);
  81. EffectHashtable = CardEffectCommons.OnAttackCheckHashtableOfPermanent(AttackingPermanent, attackEffect);
  82. CounterEffectHashtable = CardEffectCommons.OnAttackCheckHashtableOfPermanent(new Permanent(AttackingPermanent.cardSources), attackEffect);
  83. IsAttacking = true;
  84. GManager.instance.turnStateMachine.IsSelecting = true;
  85. // force to end attack
  86. if (IsEndAttack)
  87. {
  88. State = AttackState.End;
  89. yield break;
  90. }
  91. #region Attack Process
  92. if (CardEffectCommons.IsPermanentExistsOnBattleAreaDigimon(AttackingPermanent))
  93. {
  94. AttackCount++;
  95. GManager.instance.turnStateMachine.IsSelecting = true;
  96. if (DefendingPermanent != null)
  97. {
  98. if (CardEffectCommons.IsPermanentExistsOnBattleAreaDigimon(DefendingPermanent))
  99. {
  100. DefendingPermanent.ShowingPermanentCard.SetOrangeOutline();
  101. DefendingPermanent.ShowingPermanentCard.Outline_Select.gameObject.SetActive(true);
  102. GManager.instance.turnStateMachine.gameContext.NonTurnPlayer.securityObject.securityBreakGlass.gameObject.SetActive(false);
  103. }
  104. }
  105. else
  106. {
  107. if (GManager.instance.turnStateMachine.gameContext.NonTurnPlayer.SecurityCards.Count >= 1)
  108. {
  109. GManager.instance.turnStateMachine.gameContext.NonTurnPlayer.securityObject.securityBreakGlass.ShowBlueMatarial();
  110. }
  111. }
  112. AttackingPermanent.ShowingPermanentCard.SetOrangeOutline();
  113. AttackingPermanent.ShowingPermanentCard.Outline_Select.gameObject.SetActive(true);
  114. // add log
  115. string log = $"\nAttack:\n{AttackingPermanent.TopCard.BaseENGCardNameFromEntity}({AttackingPermanent.TopCard.CardID})";
  116. if (DefendingPermanent != null)
  117. {
  118. if (CardEffectCommons.IsPermanentExistsOnBattleAreaDigimon(DefendingPermanent))
  119. log += $"\n«\n{DefendingPermanent.TopCard.BaseENGCardNameFromEntity}({DefendingPermanent.TopCard.CardID})\n";
  120. }
  121. else
  122. {
  123. log += $"\n«\nSecurity\n";
  124. }
  125. PlayLog.OnAddLog?.Invoke(log);
  126. // suspend
  127. if (!withoutTap)
  128. {
  129. Hashtable attackerTapHashtable = new Hashtable()
  130. {
  131. {"IsAttack", true}
  132. };
  133. yield return ContinuousController.instance.StartCoroutine(new SuspendPermanentsClass(
  134. new List<Permanent>() { AttackingPermanent },
  135. attackerTapHashtable).Tap());
  136. }
  137. // target arrow
  138. if (DefendingPermanent == null)
  139. {
  140. yield return GManager.instance.OnTargetArrow(
  141. AttackingPermanent.PermanentFrame.GetLocalCanvasPosition() + AttackingPermanent.TopCard.Owner.playerUIObjectParent.localPosition,
  142. GManager.instance.turnStateMachine.gameContext.NonTurnPlayer.SecurityAttackLocalCanvasPosition + GManager.instance.turnStateMachine.gameContext.NonTurnPlayer.playerUIObjectParent.localPosition,
  143. null,
  144. null);
  145. }
  146. else
  147. {
  148. if (CardEffectCommons.IsPermanentExistsOnBattleAreaDigimon(DefendingPermanent))
  149. {
  150. yield return GManager.instance.OnTargetArrow(
  151. AttackingPermanent.PermanentFrame.GetLocalCanvasPosition() + AttackingPermanent.TopCard.Owner.playerUIObjectParent.localPosition,
  152. DefendingPermanent.PermanentFrame.GetLocalCanvasPosition() + DefendingPermanent.TopCard.Owner.playerUIObjectParent.localPosition,
  153. null,
  154. null);
  155. }
  156. }
  157. // callback that is processed before [On Attack]
  158. if (beforeOnAttackCoroutine != null)
  159. {
  160. yield return ContinuousController.instance.StartCoroutine(beforeOnAttackCoroutine());
  161. }
  162. // trigger [On Attack] effect
  163. yield return ContinuousController.instance.StartCoroutine(GManager.instance.autoProcessing.StackSkillInfos(
  164. EffectHashtable,
  165. EffectTiming.OnAllyAttack));
  166. GManager.instance.turnStateMachine.IsSelecting = true;
  167. if (AttackingPermanent.TopCard != null)
  168. {
  169. AttackingPermanent.ShowingPermanentCard.SetOrangeOutline();
  170. AttackingPermanent.ShowingPermanentCard.Outline_Select.gameObject.SetActive(true);
  171. }
  172. if (DefendingPermanent != null)
  173. {
  174. if (CardEffectCommons.IsPermanentExistsOnBattleAreaDigimon(DefendingPermanent))
  175. {
  176. DefendingPermanent.ShowingPermanentCard.SetOrangeOutline();
  177. DefendingPermanent.ShowingPermanentCard.Outline_Select.gameObject.SetActive(true);
  178. }
  179. }
  180. GManager.instance.turnStateMachine.IsSelecting = true;
  181. // force to end attack
  182. if (IsEndAttack)
  183. {
  184. State = AttackState.End;
  185. yield break;
  186. }
  187. if (AttackingPermanent.TopCard != null)
  188. {
  189. AttackingPermanent.ShowingPermanentCard.SetOrangeOutline();
  190. AttackingPermanent.ShowingPermanentCard.Outline_Select.gameObject.SetActive(true);
  191. }
  192. if (DefendingPermanent != null)
  193. {
  194. if (CardEffectCommons.IsPermanentExistsOnBattleAreaDigimon(DefendingPermanent))
  195. {
  196. DefendingPermanent.ShowingPermanentCard.SetOrangeOutline();
  197. DefendingPermanent.ShowingPermanentCard.Outline_Select.gameObject.SetActive(true);
  198. }
  199. }
  200. State = AttackState.Counter;
  201. }
  202. else
  203. {
  204. if (beforeOnAttackCoroutine != null)
  205. {
  206. yield return ContinuousController.instance.StartCoroutine(beforeOnAttackCoroutine());
  207. }
  208. State = AttackState.End;
  209. }
  210. #endregion
  211. }
  212. IEnumerator CounterTiming()
  213. {
  214. // force to end attack
  215. if (IsEndAttack)
  216. {
  217. State = AttackState.End;
  218. yield break;
  219. }
  220. // trigger effects when counter timing (except [Counter] effects)
  221. yield return ContinuousController.instance.StartCoroutine(GManager.instance.autoProcessing_CutIn.StackSkillInfos(
  222. CounterEffectHashtable,
  223. EffectTiming.OnCounterTiming,
  224. cardEffect => !cardEffect.IsCounterEffect));
  225. // activate cutin effects
  226. yield return ContinuousController.instance.StartCoroutine(GManager.instance.autoProcessing_CutIn.TriggeredSkillProcess(true, null));
  227. GManager.instance.turnStateMachine.IsSelecting = true;
  228. // force to end attack
  229. if (IsEndAttack)
  230. {
  231. State = AttackState.End;
  232. yield break;
  233. }
  234. // trigger effects when counter timing ([Counter] effects)
  235. yield return ContinuousController.instance.StartCoroutine(GManager.instance.autoProcessing_CutIn.StackSkillInfos(
  236. CounterEffectHashtable,
  237. EffectTiming.OnCounterTiming,
  238. cardEffect => cardEffect.IsCounterEffect));
  239. bool HasCounterEffect(List<SkillInfo> skillInfos, SkillInfo skillInfo)
  240. {
  241. return skillInfos.Count((skillInfo1) => skillInfo1.CardEffect.IsCounterEffect) >= 1;
  242. }
  243. // activate cutin effects
  244. yield return ContinuousController.instance.StartCoroutine(GManager.instance.autoProcessing_CutIn.TriggeredSkillProcess(true, HasCounterEffect));
  245. GManager.instance.turnStateMachine.IsSelecting = true;
  246. // force to end attack
  247. if (IsEndAttack || AttackingPermanent.TopCard == null || !AttackingPermanent.IsDigimon)
  248. {
  249. State = AttackState.End;
  250. yield break;
  251. }
  252. AttackingPermanent.ShowingPermanentCard.SetOrangeOutline();
  253. AttackingPermanent.ShowingPermanentCard.Outline_Select.gameObject.SetActive(true);
  254. if (DefendingPermanent != null)
  255. {
  256. if (CardEffectCommons.IsPermanentExistsOnBattleAreaDigimon(DefendingPermanent))
  257. {
  258. DefendingPermanent.ShowingPermanentCard.SetOrangeOutline();
  259. DefendingPermanent.ShowingPermanentCard.Outline_Select.gameObject.SetActive(true);
  260. }
  261. }
  262. State = AttackState.Block;
  263. }
  264. IEnumerator BlockTiming()
  265. {
  266. // force to end attack
  267. if (IsEndAttack || AttackingPermanent.TopCard == null || !AttackingPermanent.IsDigimon)
  268. {
  269. State = AttackState.End;
  270. yield break;
  271. }
  272. #region select blocker
  273. bool CanSelectBlockerCondition(Permanent permanent)
  274. {
  275. return CardEffectCommons.IsPermanentExistsOnOpponentBattleAreaDigimon(permanent, AttackingPermanent.TopCard)
  276. && permanent != DefendingPermanent
  277. && permanent.HasBlocker
  278. && permanent.CanBlock(AttackingPermanent);
  279. }
  280. if (AttackingPermanent.TopCard.Owner.Enemy.GetBattleAreaDigimons().Count(CanSelectBlockerCondition) >= 1)
  281. {
  282. int maxCount = 1;
  283. Permanent selectedPermanent = null;
  284. SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
  285. selectPermanentEffect.SetUp(
  286. selectPlayer: AttackingPermanent.TopCard.Owner.Enemy,
  287. canTargetCondition: CanSelectBlockerCondition,
  288. canTargetCondition_ByPreSelecetedList: null,
  289. canEndSelectCondition: null,
  290. maxCount: maxCount,
  291. canNoSelect: (!IsBlocking),
  292. canEndNotMax: false,
  293. selectPermanentCoroutine: SelectPermanentCoroutine,
  294. afterSelectPermanentCoroutine: null,
  295. mode: SelectPermanentEffect.Mode.Custom,
  296. cardEffect: null);
  297. selectPermanentEffect.SetUpCustomMessage("Select 1 Digimon that will block.", "The opponent is selecting 1 Digimon that will block.");
  298. if(!IsBlocking)
  299. selectPermanentEffect.SetUpCustomBackButtonMessage("Not Block");
  300. yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
  301. IEnumerator SelectPermanentCoroutine(Permanent permanent)
  302. {
  303. selectedPermanent = permanent;
  304. yield return null;
  305. }
  306. if (selectedPermanent != null)
  307. {
  308. yield return ContinuousController.instance.StartCoroutine(SwitchDefender(null, true, selectedPermanent));
  309. }
  310. }
  311. #endregion
  312. GManager.instance.turnStateMachine.IsSelecting = true;
  313. //end attack
  314. if (IsEndAttack || AttackingPermanent.TopCard == null || !AttackingPermanent.IsDigimon)
  315. {
  316. State = AttackState.End;
  317. yield break;
  318. }
  319. AttackingPermanent.ShowingPermanentCard.SetOrangeOutline();
  320. AttackingPermanent.ShowingPermanentCard.Outline_Select.gameObject.SetActive(true);
  321. if (DefendingPermanent != null)
  322. {
  323. if (CardEffectCommons.IsPermanentExistsOnBattleAreaDigimon(DefendingPermanent))
  324. {
  325. DefendingPermanent.ShowingPermanentCard.SetOrangeOutline();
  326. DefendingPermanent.ShowingPermanentCard.Outline_Select.gameObject.SetActive(true);
  327. }
  328. }
  329. State = AttackState.Battle;
  330. }
  331. IEnumerator DetermineAttackOutcome()
  332. {
  333. //end attack
  334. if (IsEndAttack || AttackingPermanent.TopCard == null || !AttackingPermanent.IsDigimon)
  335. {
  336. State = AttackState.End;
  337. yield break;
  338. }
  339. #region there is no Defending Permanent
  340. if (DefendingPermanent == null)
  341. {
  342. if (AttackingPermanent.Strike >= 1)
  343. {
  344. //if there is no security, end the game
  345. if (AttackingPermanent.TopCard.Owner.Enemy.SecurityCards.Count == 0)
  346. {
  347. GManager.instance.turnStateMachine.EndGame(AttackingPermanent.TopCard.Owner, false);
  348. yield break;
  349. }
  350. }
  351. DoSecurityCheck = true;
  352. }
  353. #endregion
  354. #region there is Defending Permanent
  355. else
  356. {
  357. if (!CardEffectCommons.IsPermanentExistsOnBattleAreaDigimon(DefendingPermanent) || !CardEffectCommons.IsPermanentExistsOnBattleAreaDigimon(AttackingPermanent))
  358. {
  359. State = AttackState.End;
  360. yield break;
  361. }
  362. DefendingPermanent.TopCard.Owner.securityObject.securityBreakGlass.gameObject.SetActive(false);
  363. DefendingPermanent.ShowingPermanentCard.SetOrangeOutline();
  364. DefendingPermanent.ShowingPermanentCard.Outline_Select.gameObject.SetActive(true);
  365. // battle
  366. IBattle battle = new IBattle(AttackingPermanent: AttackingPermanent, DefendingPermanent: DefendingPermanent, null);
  367. yield return ContinuousController.instance.StartCoroutine(battle.Battle());
  368. //TODO: Reimplement the below to ensure full correctness of battle by effect.
  369. //Will need bool AttackProcess.WasDigimonDestroyedInBattle and change to piercing to check it
  370. /*#region effect when determine whether to do security check
  371. Hashtable hashtable = new Hashtable()
  372. {
  373. {"battle", battle}
  374. };
  375. List<SkillInfo> skillInfos_Pierce = AutoProcessing.GetSkillInfos(hashtable, EffectTiming.OnDetermineDoSecurityCheck)
  376. .Filter(skillInfo => skillInfo.CardEffect != null && skillInfo.CardEffect.CanActivate(skillInfo.Hashtable));
  377. if (skillInfos_Pierce.Count >= 1)
  378. {
  379. GManager.instance.autoProcessing.PutStackedSkill(skillInfos_Pierce[0]);
  380. }
  381. #endregion*/
  382. yield return ContinuousController.instance.StartCoroutine(GManager.instance.autoProcessing.TriggeredSkillProcess(true, null));
  383. GManager.instance.turnStateMachine.IsSelecting = true;
  384. }
  385. #endregion
  386. if (AttackingPermanent.TopCard == null)
  387. {
  388. State = AttackState.End;
  389. yield break;
  390. }
  391. #region do security check
  392. if (DoSecurityCheck && AttackingPermanent.TopCard.Owner.Enemy.SecurityCards.Count >= 1)
  393. {
  394. //security check process
  395. yield return ContinuousController.instance.StartCoroutine(new ISecurityCheck(
  396. AttackingPermanent: AttackingPermanent,
  397. player: GManager.instance.turnStateMachine.gameContext.NonTurnPlayer).SecurityCheck());
  398. }
  399. #endregion
  400. State = AttackState.End;
  401. }
  402. #region End Attack
  403. IEnumerator EndAttack()
  404. {
  405. // [On End Attack] effect
  406. if (AttackingPermanent != null && AttackingPermanent.TopCard != null)
  407. {
  408. yield return ContinuousController.instance.StartCoroutine(GManager.instance.autoProcessing.StackSkillInfos(EffectHashtable, EffectTiming.OnEndAttack));
  409. }
  410. // activate cutin effects
  411. yield return ContinuousController.instance.StartCoroutine(GManager.instance.autoProcessing.AutoProcessCheck());
  412. #region reset effects which continues until the end of attack
  413. foreach (Player player in GManager.instance.turnStateMachine.gameContext.Players_ForTurnPlayer)
  414. {
  415. foreach (Permanent permanent in player.GetFieldPermanents())
  416. {
  417. permanent.UntilEndAttackEffects = new List<Func<EffectTiming, ICardEffect>>();
  418. }
  419. }
  420. #endregion
  421. GManager.instance.turnStateMachine.IsSelecting = true;
  422. #endregion
  423. DoSecurityCheck = false;
  424. IsBlocking = false;
  425. SecurityDigimon = null;
  426. IsAttacking = false;
  427. IsEndAttack = false;
  428. CounterEffectHashtable = null;
  429. State = AttackState.None;
  430. }
  431. public IEnumerator SwitchDefender(ICardEffect cardEffect, bool isBlock, Permanent newDefendingPermanent)
  432. {
  433. if (AttackingPermanent == null) yield break;
  434. if (AttackingPermanent.TopCard == null) yield break;
  435. if (newDefendingPermanent != null && newDefendingPermanent.TopCard == null) yield break;
  436. if (!AttackingPermanent.CanSwitchAttackTarget) yield break;
  437. Permanent oldDefendingPermanent = DefendingPermanent;
  438. DefendingPermanent = newDefendingPermanent;
  439. IsBlocking = isBlock;
  440. if (DefendingPermanent != null)
  441. {
  442. if (DefendingPermanent.ShowingPermanentCard != null)
  443. {
  444. DefendingPermanent.ShowingPermanentCard.SetOrangeOutline();
  445. DefendingPermanent.ShowingPermanentCard.Outline_Select.gameObject.SetActive(true);
  446. }
  447. }
  448. Hashtable hashtable = new Hashtable(){
  449. {"AttackingPermanent", AttackingPermanent},
  450. {"DefendingPermanent", DefendingPermanent},
  451. {"CardEffect", cardEffect}
  452. };
  453. if (isBlock)
  454. {
  455. hashtable.Add("IsBlock", isBlock);
  456. }
  457. if (isBlock)
  458. {
  459. if (DefendingPermanent != null)
  460. {
  461. // add log
  462. string log1 = $"\nBlock:\n{DefendingPermanent.TopCard.BaseENGCardNameFromEntity}({DefendingPermanent.TopCard.CardID})\n";
  463. PlayLog.OnAddLog?.Invoke(log1);
  464. // suspend
  465. yield return ContinuousController.instance.StartCoroutine(new SuspendPermanentsClass(new List<Permanent>() { DefendingPermanent }, hashtable).Tap());
  466. // the effects when blocking
  467. yield return ContinuousController.instance.StartCoroutine(GManager.instance.autoProcessing.StackSkillInfos(
  468. hashtable,
  469. EffectTiming.OnBlockAnyone));
  470. }
  471. }
  472. if (AttackingPermanent != null)
  473. {
  474. if (AttackingPermanent.TopCard == null)
  475. {
  476. IsBlocking = false;
  477. yield break;
  478. }
  479. }
  480. if (DefendingPermanent != null)
  481. {
  482. if (DefendingPermanent.TopCard == null)
  483. {
  484. IsBlocking = false;
  485. yield break;
  486. }
  487. }
  488. if (AttackingPermanent != null)
  489. {
  490. // target arrow
  491. for (int i = 0; i < 3; i++)
  492. {
  493. GManager.instance.OffTargetArrow();
  494. yield return null;
  495. }
  496. if (DefendingPermanent != null)
  497. {
  498. DefendingPermanent.ShowingPermanentCard.SetOrangeOutline();
  499. DefendingPermanent.ShowingPermanentCard.Outline_Select.gameObject.SetActive(true);
  500. yield return GManager.instance.OnTargetArrow(
  501. AttackingPermanent.PermanentFrame.GetLocalCanvasPosition() + AttackingPermanent.TopCard.Owner.playerUIObjectParent.localPosition,
  502. DefendingPermanent.PermanentFrame.GetLocalCanvasPosition() + DefendingPermanent.TopCard.Owner.playerUIObjectParent.localPosition,
  503. null,
  504. null);
  505. }
  506. else
  507. {
  508. yield return GManager.instance.OnTargetArrow(
  509. AttackingPermanent.PermanentFrame.GetLocalCanvasPosition() + AttackingPermanent.TopCard.Owner.playerUIObjectParent.localPosition,
  510. GManager.instance.turnStateMachine.gameContext.NonTurnPlayer.SecurityAttackLocalCanvasPosition + GManager.instance.turnStateMachine.gameContext.NonTurnPlayer.playerUIObjectParent.localPosition,
  511. null,
  512. null);
  513. }
  514. AttackingPermanent.ShowingPermanentCard.SetOrangeOutline();
  515. AttackingPermanent.ShowingPermanentCard.Outline_Select.gameObject.SetActive(true);
  516. }
  517. if (newDefendingPermanent != oldDefendingPermanent)
  518. {
  519. // the effects when attack target switched
  520. yield return ContinuousController.instance.StartCoroutine(GManager.instance.autoProcessing.StackSkillInfos(
  521. hashtable,
  522. EffectTiming.OnAttackTargetChanged));
  523. }
  524. }
  525. }