AttackProcess.cs 24 KB

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