BT15_102.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. // Apocalymon
  6. namespace DCGO.CardEffects.BT15
  7. {
  8. public class BT15_102 : CEntity_Effect
  9. {
  10. public override List<ICardEffect> CardEffects(EffectTiming timing, CardSource card)
  11. {
  12. List<ICardEffect> cardEffects = new List<ICardEffect>();
  13. #region Before Pay Cost - Condition Effect
  14. if (timing == EffectTiming.BeforePayCost)
  15. {
  16. ActivateClass activateClass = new ActivateClass();
  17. activateClass.SetUpICardEffect("Placing 1 [Dark Masters] to get Play Cost -4", CanUseCondition, card);
  18. activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, -1, false, EffectDescription());
  19. activateClass.SetHashString("PlayCost-12_BT15_102");
  20. cardEffects.Add(activateClass);
  21. string EffectDescription()
  22. {
  23. return "When this card would be played, by placing up to 3 [Dark Masters] trait cards with different names from your battle area or trash under it, reduce the play cost by 4 for each one.";
  24. }
  25. bool CardCondition(CardSource cardSource)
  26. {
  27. return cardSource == card;
  28. }
  29. bool CanNoSelect(CardSource cardSource, int placed)
  30. {
  31. if (cardSource != null
  32. && cardSource.PayingCost(SelectCardEffect.Root.Hand, null, checkAvailability: false) - (4 * placed) > cardSource.Owner.MaxMemoryCost)
  33. {
  34. return false;
  35. }
  36. return true;
  37. }
  38. bool CanUseCondition(Hashtable hashtable)
  39. {
  40. return CardEffectCommons.CanTriggerWhenPermanentWouldPlay(hashtable, CardCondition);
  41. }
  42. bool IsDarkMaster(CardSource cardSource) => cardSource.EqualsTraits("Dark Masters");
  43. bool CanActivateCondition(Hashtable hashtable)
  44. {
  45. return CardEffectCommons.HasMatchConditionOwnersCardInTrash(card, IsDarkMaster)
  46. || CardEffectCommons.HasMatchConditionOwnersPermanent(card, permanent => IsDarkMaster(permanent.TopCard));
  47. }
  48. IEnumerator ActivateCoroutine(Hashtable _hashtable)
  49. {
  50. #region Shared bool and stuff
  51. List<CardSource> digivolutionCards = new List<CardSource>();
  52. bool CanSelectCardCondition(CardSource cardSource)
  53. {
  54. if (IsDarkMaster(cardSource))
  55. {
  56. List<CardSource> chosenCards = digivolutionCards.Clone();
  57. chosenCards.Add(cardSource);
  58. return Combinations.GetUniqueNameCardCount(chosenCards) == chosenCards.Count;// If the highest unique names does not match the number of cards in the list, something shares a name
  59. }
  60. return false;
  61. }
  62. bool CanSelectPermanentCondition(Permanent permanent)
  63. {
  64. return CardEffectCommons.IsPermanentExistsOnOwnerBattleArea(permanent, card)
  65. && CanSelectCardCondition(permanent.TopCard);
  66. }
  67. int validPermanentCount = CardEffectCommons.MatchConditionOwnersPermanentCount(card, CanSelectPermanentCondition);
  68. int validTrashCardCount = card.Owner.TrashCards.Count(CanSelectCardCondition);
  69. bool noSelect() => CanNoSelect(card, digivolutionCards.Count);
  70. bool ValidPermanentCombination(List<Permanent> permanents, Permanent permanent)
  71. {
  72. List<CardSource> chosenCards = permanents.Map(perm => perm.TopCard);
  73. chosenCards.Add(permanent.TopCard);
  74. return ValidCardCombination(chosenCards);
  75. }
  76. bool ValidCardSourceCombination(List<CardSource> cardSources, CardSource cardSource)
  77. {
  78. List<CardSource> chosenCards = cardSources.Clone();
  79. chosenCards.Add(cardSource);
  80. return ValidCardCombination(chosenCards);
  81. }
  82. bool ValidCardCombination(List<CardSource> cardSources)
  83. {
  84. List<CardSource> chosenCards = digivolutionCards.Clone();
  85. chosenCards.AddRange(cardSources);
  86. return Combinations.GetUniqueNameCardCount(chosenCards) == chosenCards.Count;// If the highest unique names does not match the number of cards in the list, something shares a name
  87. }
  88. #endregion
  89. while (digivolutionCards.Count < 3
  90. && validPermanentCount + validTrashCardCount != 0)
  91. {
  92. List<SelectionElement<int>> selectionElements = new List<SelectionElement<int>>();
  93. if (validPermanentCount > 0)
  94. {
  95. selectionElements.Add(new(message: "from Battle Area", value: 1, spriteIndex: 0));
  96. }
  97. if (validTrashCardCount > 0)
  98. {
  99. selectionElements.Add(new(message: "from Trash", value: 2, spriteIndex: 0));
  100. }
  101. if (noSelect())
  102. {
  103. string message = digivolutionCards.Count > 0 ? "Finish Placing" : "Do not place";
  104. selectionElements.Add(new(message: message, value: 3, spriteIndex: 1));
  105. }
  106. GManager.instance.userSelectionManager.SetIntSelection(
  107. selectionElements: selectionElements,
  108. selectPlayer: card.Owner,
  109. selectPlayerMessage: "From which area will you select a card?",
  110. notSelectPlayerMessage: "The opponent is choosing from which area to select a card.");
  111. yield return ContinuousController.instance.StartCoroutine(GManager.instance.userSelectionManager.WaitForEndSelect());
  112. if (GManager.instance.userSelectionManager.SelectedIntValue == 3)
  113. {
  114. break;
  115. }
  116. if (GManager.instance.userSelectionManager.SelectedIntValue == 1)
  117. {
  118. bool canNoSelect = noSelect() && validTrashCardCount > 0;
  119. int maxCount = Math.Min(3 - digivolutionCards.Count, validPermanentCount);
  120. SelectPermanentEffect selectPermanentEffect = GManager.instance.GetComponent<SelectPermanentEffect>();
  121. selectPermanentEffect.SetUp(
  122. selectPlayer: card.Owner,
  123. canTargetCondition: CanSelectPermanentCondition,
  124. canTargetCondition_ByPreSelecetedList: ValidPermanentCombination,
  125. canEndSelectCondition: CanEndSelectCondition,
  126. maxCount: maxCount,
  127. canNoSelect: canNoSelect, //if need to select cards and no valid trash cards
  128. canEndNotMax: true,
  129. selectPermanentCoroutine: SelectPermanentCoroutine,
  130. afterSelectPermanentCoroutine: null,
  131. mode: SelectPermanentEffect.Mode.Custom,
  132. cardEffect: activateClass);
  133. selectPermanentEffect.SetUpCustomMessage("Select Digimon to place.", "The opponent is selecting Digimon to place.");
  134. yield return ContinuousController.instance.StartCoroutine(selectPermanentEffect.Activate());
  135. bool CanEndSelectCondition(List<Permanent> permanents)
  136. {
  137. List<CardSource> chosenCards = permanents.Map(perm => perm.TopCard);
  138. return ValidCardCombination(chosenCards);
  139. }
  140. IEnumerator SelectPermanentCoroutine(Permanent permanent)
  141. {
  142. digivolutionCards.Add(permanent.TopCard);
  143. yield return null;
  144. }
  145. validPermanentCount = CardEffectCommons.MatchConditionOwnersPermanentCount(card, CanSelectPermanentCondition);
  146. }
  147. else
  148. {
  149. bool canNoSelect = noSelect() && validPermanentCount > 0;
  150. int maxCount = Math.Min(3 - digivolutionCards.Count, validTrashCardCount);
  151. SelectCardEffect selectCardEffect = GManager.instance.GetComponent<SelectCardEffect>();
  152. selectCardEffect.SetUp(
  153. canTargetCondition: CanSelectCardCondition,
  154. canTargetCondition_ByPreSelecetedList: ValidCardSourceCombination,
  155. canEndSelectCondition: ValidCardCombination,
  156. canNoSelect: () => canNoSelect,
  157. selectCardCoroutine: SelectCardCoroutine,
  158. afterSelectCardCoroutine: null,
  159. message: "Select cards to place in Digivolution cards.",
  160. maxCount: maxCount,
  161. canEndNotMax: true,
  162. isShowOpponent: true,
  163. mode: SelectCardEffect.Mode.Custom,
  164. root: SelectCardEffect.Root.Trash,
  165. customRootCardList: null,
  166. canLookReverseCard: true,
  167. selectPlayer: card.Owner,
  168. cardEffect: activateClass);
  169. yield return ContinuousController.instance.StartCoroutine(selectCardEffect.Activate());
  170. IEnumerator SelectCardCoroutine(CardSource cardSource)
  171. {
  172. digivolutionCards.Add(cardSource);
  173. yield return null;
  174. }
  175. validTrashCardCount = card.Owner.TrashCards.Count(CanSelectCardCondition);
  176. }
  177. }
  178. if (digivolutionCards.Count >= 1)
  179. {
  180. GManager.instance.GetComponent<SelectDigiXrosClass>().AddDigivolutionCardInfos(new AddDigivolutionCardsInfo(activateClass, digivolutionCards));
  181. if (card.Owner.CanReduceCost(null, card))
  182. {
  183. ContinuousController.instance.PlaySE(GManager.instance.GetComponent<Effects>().BuffSE);
  184. }
  185. ChangeCostClass changeCostClass = new ChangeCostClass();
  186. changeCostClass.SetUpICardEffect($"Play Cost {-4 * digivolutionCards.Count}", CanUseCondition1, card);
  187. changeCostClass.SetUpChangeCostClass(changeCostFunc: ChangeCost, cardSourceCondition: CardSourceCondition, rootCondition: RootCondition, isUpDown: isUpDown, isCheckAvailability: () => false, isChangePayingCost: () => true);
  188. card.Owner.UntilCalculateFixedCostEffect.Add((_timing) => changeCostClass);
  189. bool CanUseCondition1(Hashtable hashtable)
  190. {
  191. return true;
  192. }
  193. int ChangeCost(CardSource cardSource, int Cost, SelectCardEffect.Root root, List<Permanent> targetPermanents)
  194. {
  195. if (CardSourceCondition(cardSource)
  196. && RootCondition(root)
  197. && PermanentsCondition(targetPermanents))
  198. {
  199. Cost -= digivolutionCards.Count * 4;
  200. }
  201. return Cost;
  202. }
  203. bool PermanentsCondition(List<Permanent> targetPermanents)
  204. {
  205. return targetPermanents == null
  206. || targetPermanents.Count((targetPermanent) => targetPermanent != null) == 0;
  207. }
  208. bool CardSourceCondition(CardSource cardSource)
  209. {
  210. return cardSource == card;
  211. }
  212. bool RootCondition(SelectCardEffect.Root root)
  213. {
  214. return true;
  215. }
  216. bool isUpDown()
  217. {
  218. return true;
  219. }
  220. yield return ContinuousController.instance.StartCoroutine(CardEffectCommons.ShowReducedCost(_hashtable));
  221. }
  222. }
  223. }
  224. #endregion
  225. #region Reduce Play Cost - Not Shown
  226. if (timing == EffectTiming.None)
  227. {
  228. ChangeCostClass changeCostClass = new ChangeCostClass();
  229. changeCostClass.SetUpICardEffect("Play Cost -4", CanUseCondition, card);
  230. changeCostClass.SetUpChangeCostClass(changeCostFunc: ChangeCost, cardSourceCondition: CardSourceCondition, rootCondition: RootCondition, isUpDown: isUpDown, isCheckAvailability: () => true, isChangePayingCost: () => true);
  231. changeCostClass.SetNotShowUI(true);
  232. cardEffects.Add(changeCostClass);
  233. bool CanSelectCardCondition(CardSource cardSource)
  234. {
  235. return cardSource.EqualsTraits("Dark Masters");
  236. }
  237. bool CanSelectPermanentCondition(Permanent permanent)
  238. {
  239. return CanSelectCardCondition(permanent.TopCard);
  240. }
  241. bool CanUseCondition(Hashtable hashtable)
  242. {
  243. ICardEffect activateClass = card.EffectList(EffectTiming.BeforePayCost).Find(cardEffect => cardEffect.EffectName == "Placing 1 [Dark Masters] to get Play Cost -4");
  244. return activateClass != null
  245. && (CardEffectCommons.HasMatchConditionOwnersCardInTrash(card, CanSelectCardCondition)
  246. || CardEffectCommons.HasMatchConditionOwnersPermanent(card, CanSelectPermanentCondition));
  247. }
  248. int ChangeCost(CardSource cardSource, int Cost, SelectCardEffect.Root root, List<Permanent> targetPermanents)
  249. {
  250. if (CardSourceCondition(cardSource)
  251. && RootCondition(root)
  252. && PermanentsCondition(targetPermanents))
  253. {
  254. List<CardSource> validCards = card.Owner.GetBattleAreaDigimons().Filter(CanSelectPermanentCondition).Map(permanent => permanent.TopCard);
  255. validCards.AddRange(card.Owner.TrashCards.Filter(CanSelectCardCondition));
  256. int targetCount = Math.Min(3, Combinations.GetUniqueNameCardCount(validCards));
  257. Cost -= targetCount * 4;
  258. }
  259. return Cost;
  260. }
  261. bool PermanentsCondition(List<Permanent> targetPermanents)
  262. {
  263. return targetPermanents == null
  264. || targetPermanents.Count((targetPermanent) => targetPermanent != null) == 0;
  265. }
  266. bool CardSourceCondition(CardSource cardSource)
  267. {
  268. return cardSource != null
  269. && cardSource == card;
  270. }
  271. bool RootCondition(SelectCardEffect.Root root)
  272. {
  273. return true;
  274. }
  275. bool isUpDown()
  276. {
  277. return true;
  278. }
  279. }
  280. #endregion
  281. #region End of Your Turn
  282. if (timing == EffectTiming.OnEndTurn)
  283. {
  284. ActivateClass activateClass = new ActivateClass();
  285. activateClass.SetUpICardEffect("Place 1 digimon from trash under this Digimon's digivolution cards and activate one of it's [On Play] effects", CanUseCondition, card);
  286. activateClass.SetUpActivateClass(CanActivateCondition, ActivateCoroutine, 1, false, EffectDescription());
  287. activateClass.SetIsDigimonEffect(true);
  288. cardEffects.Add(activateClass);
  289. string EffectDescription()
  290. {
  291. return "[End of Your Turn] [Once Per Turn] By placing 1 level 6 or lower card from your trash as this Digimon's bottom digivolution card, activate 1 [On Play] effect on that card as an effect. Then, trash the top 2 cards of your opponent's deck for each of this Digimon's level 6 digivolution cards.";
  292. }
  293. bool CanSelectCardCondition(CardSource cardSource)
  294. {
  295. return cardSource.HasLevel
  296. && cardSource.Level <= 6;
  297. }
  298. bool CanUseCondition(Hashtable hashtable)
  299. {
  300. return CardEffectCommons.IsExistOnBattleAreaTrigger(card, activateClass)
  301. && CardEffectCommons.IsOwnerTurn(card);
  302. }
  303. bool CanActivateCondition(Hashtable hashtable)
  304. {
  305. return CardEffectCommons.IsExistOnBattleAreaActivate(card, activateClass)
  306. && CardEffectCommons.HasMatchConditionOwnersCardInTrash(card, CanSelectCardCondition);
  307. }
  308. IEnumerator ActivateCoroutine(Hashtable _hashtable)
  309. {
  310. List<CardSource> selectedCards = new List<CardSource>();
  311. IEnumerator SelectCardCoroutine(CardSource cardSource)
  312. {
  313. selectedCards.Add(cardSource);
  314. yield return null;
  315. }
  316. SelectCardEffect selectCardEffect = GManager.instance.GetComponent<SelectCardEffect>();
  317. selectCardEffect.SetUp(
  318. canTargetCondition: CanSelectCardCondition,
  319. canTargetCondition_ByPreSelecetedList: null,
  320. canEndSelectCondition: null,
  321. canNoSelect: () => true,
  322. selectCardCoroutine: SelectCardCoroutine,
  323. afterSelectCardCoroutine: null,
  324. message: "Select 1 card to place on bottom of digivolution cards.",
  325. maxCount: 1,
  326. canEndNotMax: false,
  327. isShowOpponent: true,
  328. mode: SelectCardEffect.Mode.Custom,
  329. root: SelectCardEffect.Root.Trash,
  330. customRootCardList: null,
  331. canLookReverseCard: true,
  332. selectPlayer: card.Owner,
  333. cardEffect: activateClass);
  334. selectCardEffect.SetUpCustomMessage(
  335. "Select 1 card to place on bottom of digivolution cards.",
  336. "The opponent is selecting 1 card to place on bottom of digivolution cards.");
  337. selectCardEffect.SetUpCustomMessage_ShowCard("Digivolution Card");
  338. yield return ContinuousController.instance.StartCoroutine(selectCardEffect.Activate());
  339. CardSource selectedCard = null;
  340. if (selectedCards.Count >= 1)
  341. {
  342. yield return ContinuousController.instance.StartCoroutine(card.PermanentOfThisCard().AddDigivolutionCardsBottom(
  343. selectedCards,
  344. activateClass));
  345. selectedCard = selectedCards[0];
  346. }
  347. if (selectedCard != null)
  348. {
  349. List<ICardEffect> candidateEffects = selectedCard.EffectList_ForCard(EffectTiming.OnEnterFieldAnyone, card)
  350. .Clone()
  351. .Filter(cardEffect => cardEffect != null && cardEffect is ActivateICardEffect && !cardEffect.IsSecurityEffect && cardEffect.IsOnPlay);
  352. if (candidateEffects.Count >= 1)
  353. {
  354. ICardEffect selectedEffect = null;
  355. if (candidateEffects.Count == 1)
  356. {
  357. selectedEffect = candidateEffects[0];
  358. }
  359. else
  360. {
  361. List<SkillInfo> skillInfos = candidateEffects
  362. .Map(cardEffect => new SkillInfo(cardEffect, null, EffectTiming.None));
  363. List<CardSource> cardSources = candidateEffects
  364. .Map(cardEffect => cardEffect.EffectSourceCard);
  365. SelectCardEffect selectSourceCardEffect = GManager.instance.GetComponent<SelectCardEffect>();
  366. selectSourceCardEffect.SetUp(
  367. canTargetCondition: (cardSource) => true,
  368. canTargetCondition_ByPreSelecetedList: null,
  369. canEndSelectCondition: null,
  370. canNoSelect: () => false,
  371. selectCardCoroutine: null,
  372. afterSelectCardCoroutine: null,
  373. message: "Select 1 effect to activate.",
  374. maxCount: 1,
  375. canEndNotMax: false,
  376. isShowOpponent: false,
  377. mode: SelectCardEffect.Mode.Custom,
  378. root: SelectCardEffect.Root.Custom,
  379. customRootCardList: cardSources,
  380. canLookReverseCard: true,
  381. selectPlayer: card.Owner,
  382. cardEffect: activateClass);
  383. selectSourceCardEffect.SetNotShowCard();
  384. selectSourceCardEffect.SetUpSkillInfos(skillInfos);
  385. selectSourceCardEffect.SetUpAfterSelectIndexCoroutine(AfterSelectIndexCoroutine);
  386. yield return ContinuousController.instance.StartCoroutine(selectSourceCardEffect.Activate());
  387. IEnumerator AfterSelectIndexCoroutine(List<int> selectedIndexes)
  388. {
  389. if (selectedIndexes.Count == 1)
  390. {
  391. selectedEffect = candidateEffects[selectedIndexes[0]];
  392. yield return null;
  393. }
  394. }
  395. }
  396. if (selectedEffect != null)
  397. {
  398. Hashtable effectHashtable = CardEffectCommons.OnPlayCheckHashtableOfCard(card);
  399. if (selectedEffect.CanUse(effectHashtable))
  400. {
  401. yield return ContinuousController.instance.StartCoroutine(
  402. ((ActivateICardEffect)selectedEffect).Activate_Optional_Effect_Execute(effectHashtable));
  403. }
  404. }
  405. }
  406. }
  407. int trashCount = 2 * card.PermanentOfThisCard().cardSources.Filter(cardSource => cardSource != card && cardSource.HasLevel && cardSource.Level == 6).Count;
  408. yield return ContinuousController.instance.StartCoroutine(new IAddTrashCardsFromLibraryTop(trashCount, card.Owner.Enemy, activateClass).AddTrashCardsFromLibraryTop());
  409. }
  410. }
  411. #endregion
  412. return cardEffects;
  413. }
  414. }
  415. }