CardEffectCommons.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System;
  4. using System.Linq;
  5. using UnityEngine;
  6. using UnityEditor;
  7. public partial class CardEffectCommons
  8. {
  9. #region Play cards as new permanents
  10. public static IEnumerator PlayPermanentCards(List<CardSource> cardSources, ICardEffect activateClass, bool payCost, bool isTapped, SelectCardEffect.Root root, bool activateETB, bool isBreedingArea = false, int fixedCost = -1)
  11. {
  12. if (cardSources == null) yield break;
  13. cardSources = cardSources
  14. .Filter(cardSource => cardSource != null)
  15. .Filter(cardSource => CanPlayAsNewPermanent(
  16. cardSource: cardSource,
  17. payCost: payCost,
  18. cardEffect: activateClass,
  19. isBreedingArea: isBreedingArea,
  20. fixedCost: fixedCost));
  21. if (cardSources.Count == 0) yield break;
  22. PlayCardClass playCardClass = new PlayCardClass(
  23. cardSources: cardSources,
  24. hashtable: CardEffectHashtable(activateClass),
  25. payCost: payCost,
  26. targetPermanent: null,
  27. isTapped: isTapped,
  28. root: root,
  29. activateETB: activateETB);
  30. if (isBreedingArea)
  31. playCardClass.SetIsBreedingArea();
  32. playCardClass.SetFixedCost(fixedCost);
  33. yield return ContinuousController.instance.StartCoroutine(playCardClass.PlayCard());
  34. }
  35. #endregion
  36. #region Play option cards
  37. public static IEnumerator PlayOptionCards(List<CardSource> cardSources, ICardEffect activateClass, bool payCost, SelectCardEffect.Root root,
  38. bool setAddSecurityEndOption = false)
  39. {
  40. if (cardSources == null) yield break;
  41. cardSources = cardSources
  42. .Filter(cardSource => cardSource != null)
  43. .Filter(cardSource => !cardSource.CanNotPlayThisOption);
  44. if (cardSources.Count == 0) yield break;
  45. PlayCardClass playCard = new PlayCardClass(
  46. cardSources: cardSources,
  47. hashtable: CardEffectHashtable(activateClass),
  48. payCost: payCost,
  49. targetPermanent: null,
  50. isTapped: false,
  51. root: root,
  52. activateETB: true);
  53. if (activateClass != null)
  54. {
  55. playCard.SetShowEffect();
  56. }
  57. if (setAddSecurityEndOption)
  58. {
  59. playCard.SetAddSecurityEndOption();
  60. }
  61. yield return ContinuousController.instance.StartCoroutine(playCard.PlayCard());
  62. }
  63. #endregion
  64. #region Play Delay Option cards as new permanents
  65. public static IEnumerator PlaceDelayOptionCards(CardSource card, ICardEffect cardEffect, SelectCardEffect.Root root = SelectCardEffect.Root.Execution)
  66. {
  67. if (CanPlayAsNewPermanent(cardSource: card, payCost: false, cardEffect: cardEffect, isPlayOption: true))
  68. {
  69. PlayPermanentClass playPermanent = new PlayPermanentClass(
  70. cardSources: new List<CardSource>() { card },
  71. hashtable: CardEffectHashtable(cardEffect),
  72. targetPermanent: null,
  73. isTapped: false,
  74. root: root,
  75. ActivateETB: true);
  76. playPermanent.SetISPlayOption();
  77. yield return ContinuousController.instance.StartCoroutine(playPermanent.PlayPermanent());
  78. if (IsExistOnBattleArea(card))
  79. {
  80. card.PermanentOfThisCard().IsPlayedOptionPermanent = true;
  81. }
  82. }
  83. }
  84. #endregion
  85. #region Play 1 Token
  86. public static IEnumerator PlayToken(CEntity_Base tokenData, ICardEffect activateClass, bool isOwnerPermanent, bool isTapped)
  87. {
  88. if (activateClass == null) yield break;
  89. if (activateClass.EffectSourceCard == null) yield break;
  90. if (tokenData == null) yield break;
  91. CardSource card = activateClass.EffectSourceCard;
  92. Player player = isOwnerPermanent ? card.Owner : card.Owner.Enemy;
  93. if (card.Owner.fieldCardFrames.Count((frame) => frame.IsEmptyFrame() && frame.IsBattleAreaFrame()) >= 1)
  94. {
  95. CardSource tokenCard = CardObjectController.CreateCardSource(
  96. player.PlayerID,
  97. tokenData,
  98. true);
  99. if (CanPlayAsNewPermanent(cardSource: tokenCard, payCost: false, cardEffect: activateClass))
  100. {
  101. yield return ContinuousController.instance.StartCoroutine(new PlayCardClass(
  102. cardSources: new List<CardSource>() { tokenCard },
  103. hashtable: CardEffectHashtable(activateClass),
  104. payCost: false,
  105. targetPermanent: null,
  106. isTapped: isTapped,
  107. root: SelectCardEffect.Root.None,
  108. activateETB: true).PlayCard());
  109. }
  110. }
  111. }
  112. #endregion
  113. #region Play 1 [Diaboromon] Token
  114. public static IEnumerator PlayDiaboromonToken(ICardEffect activateClass)
  115. {
  116. yield return ContinuousController.instance.StartCoroutine(PlayToken(
  117. tokenData: ContinuousController.instance.DiaboromonToken,
  118. activateClass: activateClass,
  119. isOwnerPermanent: true,
  120. isTapped: false
  121. ));
  122. }
  123. #endregion
  124. #region Play 1 [Amon of Crimson Flame] Token
  125. public static IEnumerator PlayAmonToken(ICardEffect activateClass)
  126. {
  127. yield return ContinuousController.instance.StartCoroutine(PlayToken(
  128. tokenData: ContinuousController.instance.AmonToken,
  129. activateClass: activateClass,
  130. isOwnerPermanent: true,
  131. isTapped: false
  132. ));
  133. }
  134. #endregion
  135. #region Play 1 [Umon of Blue Thunder] Token
  136. public static IEnumerator PlayUmonToken(ICardEffect activateClass)
  137. {
  138. yield return ContinuousController.instance.StartCoroutine(PlayToken(
  139. tokenData: ContinuousController.instance.UmonToken,
  140. activateClass: activateClass,
  141. isOwnerPermanent: true,
  142. isTapped: false
  143. ));
  144. }
  145. #endregion
  146. #region Play 1 [Fujitsumon] Token
  147. public static IEnumerator PlayFujitsumonToken(ICardEffect activateClass, bool isOwnerPermanent)
  148. {
  149. yield return ContinuousController.instance.StartCoroutine(PlayToken(
  150. tokenData: ContinuousController.instance.FujitsumonToken,
  151. activateClass: activateClass,
  152. isOwnerPermanent: isOwnerPermanent,
  153. isTapped: true
  154. ));
  155. }
  156. #endregion
  157. #region Play 1 [Gyuukimon] Token
  158. public static IEnumerator PlayGyuukimonToken(ICardEffect activateClass)
  159. {
  160. yield return ContinuousController.instance.StartCoroutine(PlayToken(
  161. tokenData: ContinuousController.instance.GyuukimonToken,
  162. activateClass: activateClass,
  163. isOwnerPermanent: true,
  164. isTapped: false
  165. ));
  166. }
  167. #endregion
  168. #region Play 1 [KoHagurumon] Token
  169. public static IEnumerator PlayKoHagurumonToken(ICardEffect activateClass)
  170. {
  171. yield return ContinuousController.instance.StartCoroutine(PlayToken(
  172. tokenData: ContinuousController.instance.KoHagurumonToken,
  173. activateClass: activateClass,
  174. isOwnerPermanent: true,
  175. isTapped: false
  176. ));
  177. }
  178. #endregion
  179. #region Play 1 [Familiar] Token
  180. public static IEnumerator PlayFamiliarToken(ICardEffect activateClass)
  181. {
  182. yield return ContinuousController.instance.StartCoroutine(PlayToken(
  183. tokenData: ContinuousController.instance.FamiliarToken,
  184. activateClass: activateClass,
  185. isOwnerPermanent: true,
  186. isTapped: false
  187. ));
  188. }
  189. #endregion
  190. #region Security effect of "add this card to hand"
  191. public static IEnumerator AddThisCardToHand(CardSource card1, ICardEffect activateClass)
  192. {
  193. yield return new WaitForSeconds(0.5f);
  194. yield return ContinuousController.instance.StartCoroutine(card1.Owner.brainStormObject.CloseBrainstrorm(card1));
  195. yield return ContinuousController.instance.StartCoroutine(CardObjectController.AddHandCards(new List<CardSource>() { card1 }, false, activateClass));
  196. }
  197. #endregion
  198. #region Delete target permanents, and the effect determines whether the permanent has been deleted or not
  199. public static IEnumerator DeletePeremanentAndProcessAccordingToResult(List<Permanent> targetPermanents, ICardEffect activateClass, Func<List<Permanent>, IEnumerator> successProcess, Func<IEnumerator> failureProcess)
  200. {
  201. DestroyPermanentsClass destroyPermanentsClass = new DestroyPermanentsClass(targetPermanents, CardEffectHashtable(activateClass));
  202. yield return ContinuousController.instance.StartCoroutine(destroyPermanentsClass.Destroy());
  203. if (targetPermanents.Some((permanent) => destroyPermanentsClass.IsDestroyed(permanent)))
  204. {
  205. if (successProcess != null)
  206. {
  207. yield return ContinuousController.instance.StartCoroutine(successProcess(destroyPermanentsClass.DestroyedPermanents));
  208. }
  209. }
  210. else
  211. {
  212. if (failureProcess != null)
  213. {
  214. yield return ContinuousController.instance.StartCoroutine(failureProcess());
  215. }
  216. }
  217. }
  218. #endregion
  219. #region Bounce target 1 permanent, and the effect determines whether the permanent has been bounced or not
  220. public static IEnumerator BouncePeremanentAndProcessAccordingToResult(List<Permanent> targetPermanents, ICardEffect activateClass, IEnumerator successProcess, IEnumerator failureProcess)
  221. {
  222. HandBounceClaass bouncePermanentClass = new HandBounceClaass(targetPermanents, CardEffectHashtable(activateClass));
  223. yield return ContinuousController.instance.StartCoroutine(bouncePermanentClass.Bounce());
  224. if (targetPermanents.Some((permanent) => bouncePermanentClass.IsBounced(permanent)))
  225. {
  226. if (successProcess != null)
  227. {
  228. yield return ContinuousController.instance.StartCoroutine(successProcess);
  229. }
  230. }
  231. else
  232. {
  233. if (failureProcess != null)
  234. {
  235. yield return ContinuousController.instance.StartCoroutine(failureProcess);
  236. }
  237. }
  238. }
  239. #endregion
  240. #region Deck Bounce target 1 permanent, and the effect determines whether the permanent has been bounced or not
  241. public static IEnumerator DeckBouncePeremanentAndProcessAccordingToResult(List<Permanent> targetPermanents, ICardEffect activateClass, IEnumerator successProcess, IEnumerator failureProcess)
  242. {
  243. DeckBottomBounceClass deckBounceClass = new DeckBottomBounceClass(targetPermanents, CardEffectHashtable(activateClass));
  244. yield return ContinuousController.instance.StartCoroutine(deckBounceClass.DeckBounce());
  245. if (targetPermanents.Some((permanent) => deckBounceClass.IsDeckBounced(permanent)))
  246. {
  247. if (successProcess != null)
  248. {
  249. yield return ContinuousController.instance.StartCoroutine(successProcess);
  250. }
  251. }
  252. else
  253. {
  254. if (failureProcess != null)
  255. {
  256. yield return ContinuousController.instance.StartCoroutine(failureProcess);
  257. }
  258. }
  259. }
  260. #endregion
  261. #region Trash digivolution cards from top or bottom
  262. public static IEnumerator TrashDigivolutionCardsFromTopOrBottom(Permanent targetPermanent, int trashCount, bool isFromTop, ICardEffect activateClass)
  263. {
  264. if (activateClass == null) yield break;
  265. if (targetPermanent == null) yield break;
  266. if (targetPermanent.TopCard == null) yield break;
  267. if (targetPermanent.DigivolutionCards.Count((cardSource) => !cardSource.CanNotTrashFromDigivolutionCards(activateClass)) == 0) yield break;
  268. Debug.Log($"Trashing Digivolution Cards From Top/Bottom: Target Can Not Be Affected - {targetPermanent.TopCard.CanNotBeAffected(activateClass)}");
  269. if (targetPermanent.TopCard.CanNotBeAffected(activateClass)) yield break;
  270. if (trashCount <= 0) yield break;
  271. List<CardSource> trashTargetCards = new List<CardSource>();
  272. for (int i = 0; i < trashCount; i++)
  273. {
  274. if (targetPermanent.DigivolutionCards.Count >= i + 1)
  275. {
  276. int index = isFromTop ? i : targetPermanent.DigivolutionCards.Count - 1 - i;
  277. CardSource trashTargetCard = targetPermanent.DigivolutionCards[index];
  278. trashTargetCards.Add(trashTargetCard);
  279. }
  280. }
  281. yield return ContinuousController.instance.StartCoroutine(new ITrashDigivolutionCards(targetPermanent, trashTargetCards, activateClass).TrashDigivolutionCards());
  282. }
  283. #endregion
  284. #region this Option card's Main effect
  285. public static ActivateClass OptionMainEffect(CardSource card) => card.EffectList(EffectTiming.OptionSkill).Find(cardEffect => cardEffect != null && cardEffect is ActivateClass && cardEffect.EffectDiscription.Contains("[Main]")) as ActivateClass;
  286. #endregion
  287. #region this Option card's Security effect
  288. public static ActivateClass OptionSecurityEffect(CardSource card) => card.EffectList(EffectTiming.SecuritySkill).Find(cardEffect => cardEffect != null && cardEffect is ActivateClass && cardEffect.EffectDiscription.Contains("[Security]")) as ActivateClass;
  289. #endregion
  290. #region Add Option's Security effect that "Activate this card's Main effect" to cardEffects
  291. public static void AddActivateMainOptionSecurityEffect(CardSource card, ref List<ICardEffect> cardEffects, string effectName, string effectDiscription = "", Func<ICardEffect, IEnumerator> afterMainEffect = null)
  292. {
  293. if (OptionMainEffect(card) == null) return;
  294. cardEffects.Add(CardEffectFactory.ActivateMainOptionSecurityEffect(card, effectName, effectDiscription, afterMainEffect));
  295. }
  296. #endregion
  297. #region Target permanent Digivolves into Digimon card from hand or trash
  298. public static IEnumerator DigivolveIntoHandOrTrashCard(
  299. Permanent targetPermanent,
  300. Func<CardSource, bool> cardCondition,
  301. bool payCost,
  302. (int reduceCost, Func<CardSource, bool> reduceCostCardCondition)? reduceCostTuple,
  303. (int fixedCost, Func<CardSource, bool> fixedCostCardCondition)? fixedCostTuple,
  304. int ignoreDigivolutionRequirementFixedCost,
  305. bool isHand,
  306. ICardEffect activateClass,
  307. IEnumerator successProcess,
  308. bool ignoreLevel = false,
  309. bool ignoreSelection = false)
  310. {
  311. if (targetPermanent == null) yield break;
  312. if (targetPermanent.TopCard == null) yield break;
  313. if (activateClass == null) yield break;
  314. if (activateClass.EffectSourceCard == null) yield break;
  315. Player owner = targetPermanent.TopCard.Owner;
  316. SelectCardEffect.Root root = isHand ? SelectCardEffect.Root.Hand : SelectCardEffect.Root.Trash;
  317. bool ignoreDigivolutionRequirement = ignoreDigivolutionRequirementFixedCost >= 0;
  318. int fixedCost = -1;
  319. if (fixedCostTuple != null)
  320. {
  321. fixedCost = fixedCostTuple.Value.fixedCost;
  322. }
  323. if (ignoreDigivolutionRequirement)
  324. {
  325. fixedCost = ignoreDigivolutionRequirementFixedCost;
  326. }
  327. bool CanSelectCardCondition(CardSource cardSource)
  328. {
  329. if (cardSource.IsDigimon)
  330. {
  331. if (cardCondition == null || cardCondition(cardSource))
  332. {
  333. if (!cardSource.CanNotEvolve(targetPermanent))
  334. {
  335. if (ignoreLevel
  336. || cardSource.CanPlayCardTargetFrame(
  337. frame: targetPermanent.PermanentFrame,
  338. PayCost: payCost,
  339. cardEffect: activateClass,
  340. root: root,
  341. fixedCost: fixedCost))
  342. {
  343. return true;
  344. }
  345. }
  346. }
  347. }
  348. return false;
  349. }
  350. #region reduce cost
  351. Func<EffectTiming, ICardEffect> getChangeCostEffect = null;
  352. if (reduceCostTuple != null)
  353. {
  354. bool PermanentCondition(Permanent permanent)
  355. {
  356. return permanent == targetPermanent;
  357. }
  358. bool CardCondition(CardSource cardSource)
  359. {
  360. if (cardSource != null)
  361. {
  362. if (cardSource.Owner == owner)
  363. {
  364. if (reduceCostTuple.Value.reduceCostCardCondition == null || reduceCostTuple.Value.reduceCostCardCondition(cardSource))
  365. {
  366. return true;
  367. }
  368. }
  369. }
  370. return false;
  371. }
  372. getChangeCostEffect = ChangeDigivolutionCostPlayerEffect(
  373. permanentCondition: PermanentCondition,
  374. cardCondition: CardCondition,
  375. rootCondition: null,
  376. changeValue: -reduceCostTuple.Value.reduceCost,
  377. activateClass: activateClass,
  378. setFixedCost: false);
  379. if (getChangeCostEffect != null)
  380. {
  381. AddEffectToPlayer(
  382. effectDuration: EffectDuration.UntilCalculateFixedCost,
  383. card: targetPermanent.TopCard,
  384. cardEffect: null,
  385. timing: EffectTiming.None,
  386. getCardEffect: getChangeCostEffect);
  387. }
  388. }
  389. #endregion
  390. #region set fixed cost
  391. Func<EffectTiming, ICardEffect> getFixedCostEffect = null;
  392. if (fixedCostTuple != null)
  393. {
  394. bool PermanentCondition(Permanent permanent)
  395. {
  396. return permanent == targetPermanent;
  397. }
  398. bool CardCondition(CardSource cardSource)
  399. {
  400. if (cardSource != null)
  401. {
  402. if (cardSource.Owner == owner)
  403. {
  404. if (fixedCostTuple.Value.fixedCostCardCondition == null || fixedCostTuple.Value.fixedCostCardCondition(cardSource))
  405. {
  406. return true;
  407. }
  408. }
  409. }
  410. return false;
  411. }
  412. getFixedCostEffect = ChangeDigivolutionCostPlayerEffect(
  413. permanentCondition: PermanentCondition,
  414. cardCondition: CardCondition,
  415. rootCondition: null,
  416. changeValue: fixedCost,
  417. activateClass: activateClass,
  418. setFixedCost: true);
  419. if (getChangeCostEffect != null)
  420. {
  421. AddEffectToPlayer(
  422. effectDuration: EffectDuration.UntilCalculateFixedCost,
  423. card: targetPermanent.TopCard,
  424. cardEffect: null,
  425. timing: EffectTiming.None,
  426. getCardEffect: getFixedCostEffect);
  427. }
  428. }
  429. #endregion
  430. #region ignore digivolution requirement
  431. Func<EffectTiming, ICardEffect> getIgnoreDigivolutionRequirementEffect = null;
  432. if (ignoreDigivolutionRequirement)
  433. {
  434. bool PermanentCondition(Permanent permanent)
  435. {
  436. return permanent == targetPermanent;
  437. }
  438. bool CardCondition(CardSource cardSource)
  439. {
  440. if (cardSource == null)
  441. {
  442. return false;
  443. }
  444. if (cardSource.Owner != owner)
  445. {
  446. return false;
  447. }
  448. if (cardCondition == null || cardCondition(cardSource))
  449. {
  450. return true;
  451. }
  452. return false;
  453. }
  454. getIgnoreDigivolutionRequirementEffect = GainIgnoreDigivolutionRequirementPlayerEffect(
  455. permanentCondition: PermanentCondition,
  456. cardCondition: CardCondition,
  457. ignoreDigivolutionRequirement: ignoreDigivolutionRequirement,
  458. digivolutionCost: fixedCost,
  459. activateClass: activateClass);
  460. if (getIgnoreDigivolutionRequirementEffect != null)
  461. {
  462. AddEffectToPlayer(
  463. effectDuration: EffectDuration.UntilCalculateFixedCost,
  464. card: targetPermanent.TopCard,
  465. cardEffect: null,
  466. timing: EffectTiming.None,
  467. getCardEffect: getIgnoreDigivolutionRequirementEffect);
  468. }
  469. }
  470. #endregion
  471. List<CardSource> selectedCards = new List<CardSource>();
  472. IEnumerator SelectCardCoroutine(CardSource cardSource)
  473. {
  474. selectedCards.Add(cardSource);
  475. yield return null;
  476. }
  477. if (isHand)
  478. {
  479. if (owner.HandCards.Count(CanSelectCardCondition) >= 1)
  480. {
  481. int maxCount = 1;
  482. SelectHandEffect selectHandEffect = GManager.instance.GetComponent<SelectHandEffect>();
  483. selectHandEffect.SetUp(
  484. selectPlayer: owner,
  485. canTargetCondition: CanSelectCardCondition,
  486. canTargetCondition_ByPreSelecetedList: null,
  487. canEndSelectCondition: null,
  488. maxCount: maxCount,
  489. canNoSelect: true,
  490. canEndNotMax: false,
  491. isShowOpponent: true,
  492. selectCardCoroutine: SelectCardCoroutine,
  493. afterSelectCardCoroutine: null,
  494. mode: SelectHandEffect.Mode.Custom,
  495. cardEffect: activateClass);
  496. selectHandEffect.SetUpCustomMessage("Select 1 card to digivolve.", "The opponent is selecting 1 card to digivolve.");
  497. selectHandEffect.SetUpCustomMessage_ShowCard("Selected Card");
  498. yield return ContinuousController.instance.StartCoroutine(selectHandEffect.Activate());
  499. }
  500. }
  501. else
  502. {
  503. if (HasMatchConditionOwnersCardInTrash(targetPermanent.TopCard, CanSelectCardCondition) && !ignoreSelection)
  504. {
  505. int maxCount = 1;
  506. SelectCardEffect selectCardEffect = GManager.instance.GetComponent<SelectCardEffect>();
  507. selectCardEffect.SetUp(
  508. canTargetCondition: CanSelectCardCondition,
  509. canTargetCondition_ByPreSelecetedList: null,
  510. canEndSelectCondition: null,
  511. canNoSelect: () => true,
  512. selectCardCoroutine: SelectCardCoroutine,
  513. afterSelectCardCoroutine: null,
  514. message: "Select 1 card to digivolve.",
  515. maxCount: maxCount,
  516. canEndNotMax: false,
  517. isShowOpponent: true,
  518. mode: SelectCardEffect.Mode.Custom,
  519. root: SelectCardEffect.Root.Trash,
  520. customRootCardList: null,
  521. canLookReverseCard: true,
  522. selectPlayer: owner,
  523. cardEffect: activateClass);
  524. selectCardEffect.SetUpCustomMessage("Select 1 card to digivolve.", "The opponent is selecting 1 card to digivolve.");
  525. selectCardEffect.SetUpCustomMessage_ShowCard("Selected Card");
  526. yield return ContinuousController.instance.StartCoroutine(selectCardEffect.Activate());
  527. }
  528. else
  529. {
  530. selectedCards.Add(activateClass.EffectSourceCard);
  531. }
  532. }
  533. PlayCardClass playCardClass = new PlayCardClass(
  534. cardSources: selectedCards,
  535. hashtable: CardEffectHashtable(activateClass),
  536. payCost: payCost,
  537. targetPermanent: targetPermanent,
  538. isTapped: false,
  539. root: root,
  540. activateETB: true);
  541. if (ignoreLevel) playCardClass.SetIgnoreLevel();
  542. if (!ignoreDigivolutionRequirement && fixedCost >= 0) playCardClass.SetFixedCost(fixedCost);
  543. yield return ContinuousController.instance.StartCoroutine(playCardClass.PlayCard());
  544. #region release effect
  545. if (getChangeCostEffect != null) owner.UntilCalculateFixedCostEffect.Remove(getChangeCostEffect);
  546. #endregion
  547. #region release effect
  548. if (getFixedCostEffect != null) owner.UntilCalculateFixedCostEffect.Remove(getFixedCostEffect);
  549. #endregion
  550. #region release effect
  551. if (getIgnoreDigivolutionRequirementEffect != null) owner.UntilCalculateFixedCostEffect.Remove(getIgnoreDigivolutionRequirementEffect);
  552. #endregion
  553. if (selectedCards.Count >= 1)
  554. {
  555. if (IsDigivolvedByTheEffect(targetPermanent, selectedCards[0], activateClass))
  556. {
  557. if (successProcess != null)
  558. {
  559. yield return ContinuousController.instance.StartCoroutine(successProcess);
  560. }
  561. }
  562. }
  563. }
  564. #endregion
  565. #region Target permanent Digivolves into Digimon card execution area
  566. public static IEnumerator DigivolveIntoExcecutingAreaCard(
  567. Permanent targetPermanent,
  568. Func<CardSource, bool> cardCondition,
  569. bool payCost,
  570. (int reduceCost, Func<CardSource, bool> reduceCostCardCondition)? reduceCostTuple,
  571. (int fixedCost, Func<CardSource, bool> fixedCostCardCondition)? fixedCostTuple,
  572. int ignoreDigivolutionRequirementFixedCost,
  573. ICardEffect activateClass,
  574. IEnumerator successProcess,
  575. bool ignoreLevel = false,
  576. bool ignoreSelection = false)
  577. {
  578. if (targetPermanent == null) yield break;
  579. if (targetPermanent.TopCard == null) yield break;
  580. if (activateClass == null) yield break;
  581. if (activateClass.EffectSourceCard == null) yield break;
  582. Player owner = targetPermanent.TopCard.Owner;
  583. SelectCardEffect.Root root = SelectCardEffect.Root.Execution;
  584. bool ignoreDigivolutionRequirement = ignoreDigivolutionRequirementFixedCost >= 0;
  585. int fixedCost = -1;
  586. if (fixedCostTuple != null)
  587. {
  588. fixedCost = fixedCostTuple.Value.fixedCost;
  589. }
  590. if (ignoreDigivolutionRequirement)
  591. {
  592. fixedCost = ignoreDigivolutionRequirementFixedCost;
  593. }
  594. bool CanSelectCardCondition(CardSource cardSource)
  595. {
  596. if (cardSource.IsDigimon)
  597. {
  598. if (cardCondition == null || cardCondition(cardSource))
  599. {
  600. if (!cardSource.CanNotEvolve(targetPermanent))
  601. {
  602. if (ignoreLevel
  603. || cardSource.CanPlayCardTargetFrame(
  604. frame: targetPermanent.PermanentFrame,
  605. PayCost: payCost,
  606. cardEffect: activateClass,
  607. root: root,
  608. fixedCost: fixedCost))
  609. {
  610. return true;
  611. }
  612. }
  613. }
  614. }
  615. return false;
  616. }
  617. #region reduce cost
  618. Func<EffectTiming, ICardEffect> getChangeCostEffect = null;
  619. if (reduceCostTuple != null)
  620. {
  621. bool PermanentCondition(Permanent permanent)
  622. {
  623. return permanent == targetPermanent;
  624. }
  625. bool CardCondition(CardSource cardSource)
  626. {
  627. if (cardSource != null)
  628. {
  629. if (cardSource.Owner == owner)
  630. {
  631. if (reduceCostTuple.Value.reduceCostCardCondition == null || reduceCostTuple.Value.reduceCostCardCondition(cardSource))
  632. {
  633. return true;
  634. }
  635. }
  636. }
  637. return false;
  638. }
  639. getChangeCostEffect = ChangeDigivolutionCostPlayerEffect(
  640. permanentCondition: PermanentCondition,
  641. cardCondition: CardCondition,
  642. rootCondition: null,
  643. changeValue: -reduceCostTuple.Value.reduceCost,
  644. activateClass: activateClass,
  645. setFixedCost: false);
  646. if (getChangeCostEffect != null)
  647. {
  648. AddEffectToPlayer(
  649. effectDuration: EffectDuration.UntilCalculateFixedCost,
  650. card: targetPermanent.TopCard,
  651. cardEffect: null,
  652. timing: EffectTiming.None,
  653. getCardEffect: getChangeCostEffect);
  654. }
  655. }
  656. #endregion
  657. #region set fixed cost
  658. Func<EffectTiming, ICardEffect> getFixedCostEffect = null;
  659. if (fixedCostTuple != null)
  660. {
  661. bool PermanentCondition(Permanent permanent)
  662. {
  663. return permanent == targetPermanent;
  664. }
  665. bool CardCondition(CardSource cardSource)
  666. {
  667. if (cardSource != null)
  668. {
  669. if (cardSource.Owner == owner)
  670. {
  671. if (fixedCostTuple.Value.fixedCostCardCondition == null || fixedCostTuple.Value.fixedCostCardCondition(cardSource))
  672. {
  673. return true;
  674. }
  675. }
  676. }
  677. return false;
  678. }
  679. getFixedCostEffect = ChangeDigivolutionCostPlayerEffect(
  680. permanentCondition: PermanentCondition,
  681. cardCondition: CardCondition,
  682. rootCondition: null,
  683. changeValue: fixedCost,
  684. activateClass: activateClass,
  685. setFixedCost: true);
  686. if (getChangeCostEffect != null)
  687. {
  688. AddEffectToPlayer(
  689. effectDuration: EffectDuration.UntilCalculateFixedCost,
  690. card: targetPermanent.TopCard,
  691. cardEffect: null,
  692. timing: EffectTiming.None,
  693. getCardEffect: getFixedCostEffect);
  694. }
  695. }
  696. #endregion
  697. #region ignore digivolution requirement
  698. Func<EffectTiming, ICardEffect> getIgnoreDigivolutionRequirementEffect = null;
  699. if (ignoreDigivolutionRequirement)
  700. {
  701. bool PermanentCondition(Permanent permanent)
  702. {
  703. return permanent == targetPermanent;
  704. }
  705. bool CardCondition(CardSource cardSource)
  706. {
  707. if (cardSource == null)
  708. {
  709. return false;
  710. }
  711. if (cardSource.Owner != owner)
  712. {
  713. return false;
  714. }
  715. if (cardCondition == null || cardCondition(cardSource))
  716. {
  717. return true;
  718. }
  719. return false;
  720. }
  721. getIgnoreDigivolutionRequirementEffect = GainIgnoreDigivolutionRequirementPlayerEffect(
  722. permanentCondition: PermanentCondition,
  723. cardCondition: CardCondition,
  724. ignoreDigivolutionRequirement: ignoreDigivolutionRequirement,
  725. digivolutionCost: fixedCost,
  726. activateClass: activateClass);
  727. if (getIgnoreDigivolutionRequirementEffect != null)
  728. {
  729. AddEffectToPlayer(
  730. effectDuration: EffectDuration.UntilCalculateFixedCost,
  731. card: targetPermanent.TopCard,
  732. cardEffect: null,
  733. timing: EffectTiming.None,
  734. getCardEffect: getIgnoreDigivolutionRequirementEffect);
  735. }
  736. }
  737. #endregion
  738. List<CardSource> selectedCards = new List<CardSource>();
  739. IEnumerator SelectCardCoroutine(CardSource cardSource)
  740. {
  741. selectedCards.Add(cardSource);
  742. yield return null;
  743. }
  744. if (owner.ExecutingCards.Count(CanSelectCardCondition) >= 1)
  745. {
  746. int maxCount = 1;
  747. SelectCardEffect selectCardEffect = GManager.instance.GetComponent<SelectCardEffect>();
  748. selectCardEffect.SetUp(
  749. canTargetCondition: CanSelectCardCondition,
  750. canTargetCondition_ByPreSelecetedList: null,
  751. canEndSelectCondition: null,
  752. canNoSelect: () => true,
  753. selectCardCoroutine: SelectCardCoroutine,
  754. afterSelectCardCoroutine: null,
  755. message: "Select 1 card to digivolve.",
  756. maxCount: maxCount,
  757. canEndNotMax: false,
  758. isShowOpponent: true,
  759. mode: SelectCardEffect.Mode.Custom,
  760. root: SelectCardEffect.Root.Execution,
  761. customRootCardList: null,
  762. canLookReverseCard: true,
  763. selectPlayer: owner,
  764. cardEffect: activateClass);
  765. selectCardEffect.SetUpCustomMessage("Select 1 card to digivolve.", "The opponent is selecting 1 card to digivolve.");
  766. selectCardEffect.SetUpCustomMessage_ShowCard("Selected Card");
  767. yield return ContinuousController.instance.StartCoroutine(selectCardEffect.Activate());
  768. }
  769. else
  770. {
  771. selectedCards.Add(activateClass.EffectSourceCard);
  772. }
  773. PlayCardClass playCardClass = new PlayCardClass(
  774. cardSources: selectedCards,
  775. hashtable: CardEffectHashtable(activateClass),
  776. payCost: payCost,
  777. targetPermanent: targetPermanent,
  778. isTapped: false,
  779. root: root,
  780. activateETB: true);
  781. if (ignoreLevel) playCardClass.SetIgnoreLevel();
  782. if (!ignoreDigivolutionRequirement && fixedCost >= 0) playCardClass.SetFixedCost(fixedCost);
  783. yield return ContinuousController.instance.StartCoroutine(playCardClass.PlayCard());
  784. #region release effect
  785. if (getChangeCostEffect != null) owner.UntilCalculateFixedCostEffect.Remove(getChangeCostEffect);
  786. #endregion
  787. #region release effect
  788. if (getFixedCostEffect != null) owner.UntilCalculateFixedCostEffect.Remove(getFixedCostEffect);
  789. #endregion
  790. #region release effect
  791. if (getIgnoreDigivolutionRequirementEffect != null) owner.UntilCalculateFixedCostEffect.Remove(getIgnoreDigivolutionRequirementEffect);
  792. #endregion
  793. if (selectedCards.Count >= 1)
  794. {
  795. if (IsDigivolvedByTheEffect(targetPermanent, selectedCards[0], activateClass))
  796. {
  797. if (successProcess != null)
  798. {
  799. yield return ContinuousController.instance.StartCoroutine(successProcess);
  800. }
  801. }
  802. }
  803. }
  804. #endregion
  805. #region Get the effect given by EffectTiming
  806. public static Func<EffectTiming, ICardEffect> GetCardEffectByEffectTiming(EffectTiming timing, ICardEffect cardEffect) => (_timing) => _timing == timing ? cardEffect : null;
  807. #endregion
  808. }